1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CONTENT_PUBLIC_TEST_CONTENT_BROWSER_TEST_UTILS_H_ 6 #define CONTENT_PUBLIC_TEST_CONTENT_BROWSER_TEST_UTILS_H_ 7 8 #include <map> 9 #include <string> 10 11 #include "base/callback.h" 12 #include "base/macros.h" 13 #include "base/run_loop.h" 14 #include "content/public/common/page_type.h" 15 #include "ui/gfx/native_widget_types.h" 16 #include "url/gurl.h" 17 18 namespace base { 19 class FilePath; 20 21 namespace mac { 22 class ScopedObjCClassSwizzler; 23 } // namespace mac 24 } // namespace base 25 26 namespace gfx { 27 class Point; 28 class Range; 29 class Rect; 30 } // namespace gfx 31 32 namespace net { 33 namespace test_server { 34 class EmbeddedTestServer; 35 } // namespace test_server 36 } // namespace net 37 38 // A collections of functions designed for use with content_shell based browser 39 // tests. 40 // Note: if a function here also works with browser_tests, it should be in 41 // content\public\test\browser_test_utils.h 42 43 namespace content { 44 class RenderFrameHost; 45 class RenderWidgetHost; 46 class Shell; 47 class ToRenderFrameHost; 48 class WebContents; 49 50 // Generate the file path for testing a particular test. 51 // The file for the tests is all located in 52 // content/test/data/dir/<file> 53 // The returned path is FilePath format. 54 // 55 // A null |dir| indicates the root directory - i.e. 56 // content/test/data/<file> 57 base::FilePath GetTestFilePath(const char* dir, const char* file); 58 59 // Generate the URL for testing a particular test. 60 // HTML for the tests is all located in 61 // test_root_directory/dir/<file> 62 // The returned path is GURL format. 63 // 64 // A null |dir| indicates the root directory - i.e. 65 // content/test/data/<file> 66 GURL GetTestUrl(const char* dir, const char* file); 67 68 // Navigates |window| to |url|, blocking until the navigation finishes. Returns 69 // true if the page was loaded successfully and the last committed URL matches 70 // |url|. This is a browser-initiated navigation that simulates a user typing 71 // |url| into the address bar. 72 // 73 // Tests should ensure that NavigateToURL succeeds. If the URL that will 74 // eventually commit is different from |url|, such as with redirects, use the 75 // version below which also takes the expected commit URL. If the navigation 76 // will not result in a commit, such as a download or a 204 response, use 77 // NavigateToURLAndExpectNoCommit() instead. 78 WARN_UNUSED_RESULT bool NavigateToURL(Shell* window, const GURL& url); 79 80 // Same as above, but takes in an additional URL, |expected_commit_url|, to 81 // which the navigation should eventually commit. This is useful for cases 82 // like redirects, where navigation starts on one URL but ends up committing a 83 // different URL. This function will return true if navigating to |url| 84 // results in a successful commit to |expected_commit_url|. 85 WARN_UNUSED_RESULT bool NavigateToURL(Shell* window, 86 const GURL& url, 87 const GURL& expected_commit_url); 88 89 // Navigates |window| to |url|, blocking until the given number of navigations 90 // finishes. 91 void NavigateToURLBlockUntilNavigationsComplete(Shell* window, 92 const GURL& url, 93 int number_of_navigations); 94 95 // Navigates |window| to |url|, blocks until the navigation finishes, and 96 // checks that the navigation did not commit (e.g., due to a crash or 97 // download). 98 WARN_UNUSED_RESULT bool NavigateToURLAndExpectNoCommit(Shell* window, 99 const GURL& url); 100 101 // Reloads |window|, blocking until the given number of navigations finishes. 102 void ReloadBlockUntilNavigationsComplete(Shell* window, 103 int number_of_navigations); 104 105 // Reloads |window| with bypassing cache flag, and blocks until the given number 106 // of navigations finishes. 107 void ReloadBypassingCacheBlockUntilNavigationsComplete( 108 Shell* window, 109 int number_of_navigations); 110 111 // A class to help with waiting for at least one javascript dialog to be 112 // requested. 113 // 114 // On creation or Restart, it uses set_dialog_request_callback to 115 // capture any future dialog request. Calling Wait() will 116 // either return immediately because a dialog has already been called or it will 117 // wait, processing events until one is requested. 118 // 119 // That means, object should be constructed, or Restart() called, before section 120 // that could request a modal dialog. 121 class AppModalDialogWaiter { 122 public: 123 explicit AppModalDialogWaiter(Shell* shell); 124 void Restart(); 125 void Wait(); 126 WasDialogRequestedCallbackCalled()127 bool WasDialogRequestedCallbackCalled() { 128 return was_dialog_request_callback_called_; 129 } 130 131 private: 132 void EarlyCallback(); 133 bool was_dialog_request_callback_called_ = false; 134 Shell* shell_; 135 }; 136 137 // Extends the ToRenderFrameHost mechanism to content::Shells. 138 RenderFrameHost* ConvertToRenderFrameHost(Shell* shell); 139 140 // Writes an entry with the name and id of the first camera to the logs or 141 // an entry indicating that no camera is available. This must be invoked from 142 // the test method body, because at the time of invocation of 143 // testing::Test::SetUp() the BrowserMainLoop does not yet exist. 144 void LookupAndLogNameAndIdOfFirstCamera(); 145 146 // Used to wait for a new Shell window to be created. Instantiate this object 147 // before the operation that will create the window. 148 class ShellAddedObserver { 149 public: 150 ShellAddedObserver(); 151 ~ShellAddedObserver(); 152 153 // Will run a message loop to wait for the new window if it hasn't been 154 // created since the constructor. 155 Shell* GetShell(); 156 157 private: 158 void ShellCreated(Shell* shell); 159 160 Shell* shell_ = nullptr; 161 std::unique_ptr<base::RunLoop> runner_; 162 163 DISALLOW_COPY_AND_ASSIGN(ShellAddedObserver); 164 }; 165 166 #if defined(OS_MAC) 167 // An observer of the RenderWidgetHostViewCocoa which is the NSView 168 // corresponding to the page. 169 class RenderWidgetHostViewCocoaObserver { 170 public: 171 // The method name for 'didAddSubview'. 172 static constexpr char kDidAddSubview[] = "didAddSubview:"; 173 static constexpr char kShowDefinitionForAttributedString[] = 174 "showDefinitionForAttributedString:atPoint:"; 175 176 // Returns the method swizzler for the given |method_name|. This is useful 177 // when the original implementation of the method is needed. 178 static base::mac::ScopedObjCClassSwizzler* GetSwizzler( 179 const std::string& method_name); 180 181 // Returns the unique RenderWidgetHostViewCocoaObserver instance (if any) for 182 // the given WebContents. There can be at most one observer per WebContents 183 // and to create a new observer the older one has to be deleted first. 184 static RenderWidgetHostViewCocoaObserver* GetObserver( 185 WebContents* web_contents); 186 187 explicit RenderWidgetHostViewCocoaObserver(WebContents* web_contents); 188 virtual ~RenderWidgetHostViewCocoaObserver(); 189 190 // Called when a new NSView is added as a subview of RWHVCocoa. 191 // |rect_in_root_view| represents the bounds of the NSView in RWHVCocoa 192 // coordinates. The view will be dismissed shortly after this call. DidAddSubviewWillBeDismissed(const gfx::Rect & rect_in_root_view)193 virtual void DidAddSubviewWillBeDismissed( 194 const gfx::Rect& rect_in_root_view) {} 195 // Called when RenderWidgeHostViewCocoa is asked to show definition of 196 // |for_word| using Mac's dictionary popup. OnShowDefinitionForAttributedString(const std::string & for_word)197 virtual void OnShowDefinitionForAttributedString( 198 const std::string& for_word) {} 199 web_contents()200 WebContents* web_contents() const { return web_contents_; } 201 202 private: 203 static void SetUpSwizzlers(); 204 205 static std::map<std::string, 206 std::unique_ptr<base::mac::ScopedObjCClassSwizzler>> 207 rwhvcocoa_swizzlers_; 208 static std::map<WebContents*, RenderWidgetHostViewCocoaObserver*> observers_; 209 210 WebContents* const web_contents_; 211 212 DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewCocoaObserver); 213 }; 214 215 void SetWindowBounds(gfx::NativeWindow window, const gfx::Rect& bounds); 216 217 // This method will request the string (word) at |point| inside the |rwh| where 218 // |point| is with respect to the |rwh| coordinates. |result_callback| is called 219 // with the word as well as |baselinePoint| when the result comes back from the 220 // renderer. The baseline point is the position of the pop-up in AppKit 221 // coordinate system (inverted y-axis). 222 void GetStringAtPointForRenderWidget( 223 RenderWidgetHost* rwh, 224 const gfx::Point& point, 225 base::OnceCallback<void(const std::string&, const gfx::Point&)> 226 result_callback); 227 228 // This method will request the string identified by |range| inside the |rwh|. 229 // When the result comes back, |result_callback| is invoked with the given text 230 // and its position in AppKit coordinates (inverted-y axis). 231 void GetStringFromRangeForRenderWidget( 232 RenderWidgetHost* rwh, 233 const gfx::Range& range, 234 base::OnceCallback<void(const std::string&, const gfx::Point&)> 235 result_callback); 236 237 #endif 238 239 // Adds http://<hostname_to_isolate>/ to the list of origins that require 240 // isolation (for each of the hostnames in the |hostnames_to_isolate| vector). 241 // 242 // To ensure that the isolation applies to subsequent navigations in 243 // |web_contents|, this function forces a BrowsingInstance swap by performing 244 // one or two browser-initiated navigations in |web_contents| to another, 245 // random, guid-based hostname. 246 void IsolateOriginsForTesting( 247 net::test_server::EmbeddedTestServer* embedded_test_server, 248 WebContents* web_contents, 249 std::vector<std::string> hostnames_to_isolate); 250 251 #if defined(OS_WIN) 252 253 void SetMockCursorPositionForTesting(WebContents* web_contents, 254 const gfx::Point& position); 255 256 #endif // defined(OS_WIN) 257 258 } // namespace content 259 260 #endif // CONTENT_PUBLIC_TEST_CONTENT_BROWSER_TEST_UTILS_H_ 261