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_BROWSER_TEST_UTILS_H_ 6 #define CONTENT_PUBLIC_TEST_BROWSER_TEST_UTILS_H_ 7 8 #include <queue> 9 #include <string> 10 #include <vector> 11 12 #include "base/callback_forward.h" 13 #include "base/compiler_specific.h" 14 #include "base/files/scoped_temp_dir.h" 15 #include "base/memory/ref_counted.h" 16 #include "base/process/process.h" 17 #include "base/strings/string16.h" 18 #include "content/public/browser/notification_observer.h" 19 #include "content/public/browser/notification_registrar.h" 20 #include "content/public/browser/render_process_host_observer.h" 21 #include "content/public/browser/web_contents_observer.h" 22 #include "third_party/WebKit/public/web/WebInputEvent.h" 23 #include "ui/events/keycodes/keyboard_codes.h" 24 #include "url/gurl.h" 25 26 #if defined(OS_WIN) 27 #include "base/win/scoped_handle.h" 28 #endif 29 30 namespace base { 31 class RunLoop; 32 } 33 34 namespace gfx { 35 class Point; 36 } 37 38 // A collections of functions designed for use with content_browsertests and 39 // browser_tests. 40 // TO BE CLEAR: any function here must work against both binaries. If it only 41 // works with browser_tests, it should be in chrome\test\base\ui_test_utils.h. 42 // If it only works with content_browsertests, it should be in 43 // content\test\content_browser_test_utils.h. 44 45 namespace content { 46 47 class BrowserContext; 48 class MessageLoopRunner; 49 class RenderViewHost; 50 class WebContents; 51 52 // Generate a URL for a file path including a query string. 53 GURL GetFileUrlWithQuery(const base::FilePath& path, 54 const std::string& query_string); 55 56 // Waits for a load stop for the specified |web_contents|'s controller, if the 57 // tab is currently web_contents. Otherwise returns immediately. 58 void WaitForLoadStop(WebContents* web_contents); 59 60 #if defined(USE_AURA) 61 // If WebContent's view is currently being resized, this will wait for the ack 62 // from the renderer that the resize is complete and for the 63 // WindowEventDispatcher to release the pointer moves. If there's no resize in 64 // progress, the method will return right away. 65 void WaitForResizeComplete(WebContents* web_contents); 66 #endif // USE_AURA 67 68 // Causes the specified web_contents to crash. Blocks until it is crashed. 69 void CrashTab(WebContents* web_contents); 70 71 // Simulates clicking at the center of the given tab asynchronously; modifiers 72 // may contain bits from WebInputEvent::Modifiers. 73 void SimulateMouseClick(WebContents* web_contents, 74 int modifiers, 75 blink::WebMouseEvent::Button button); 76 77 // Simulates clicking at the point |point| of the given tab asynchronously; 78 // modifiers may contain bits from WebInputEvent::Modifiers. 79 void SimulateMouseClickAt(WebContents* web_contents, 80 int modifiers, 81 blink::WebMouseEvent::Button button, 82 const gfx::Point& point); 83 84 // Simulates asynchronously a mouse enter/move/leave event. 85 void SimulateMouseEvent(WebContents* web_contents, 86 blink::WebInputEvent::Type type, 87 const gfx::Point& point); 88 89 // Taps the screen at |point|. 90 void SimulateTapAt(WebContents* web_contents, const gfx::Point& point); 91 92 // Sends a key press asynchronously. 93 // The native code of the key event will be set to InvalidNativeKeycode(). 94 // |key_code| alone is good enough for scenarios that only need the char 95 // value represented by a key event and not the physical key on the keyboard 96 // or the keyboard layout. 97 // For scenarios such as chromoting that need the native code, 98 // SimulateKeyPressWithCode should be used. 99 void SimulateKeyPress(WebContents* web_contents, 100 ui::KeyboardCode key_code, 101 bool control, 102 bool shift, 103 bool alt, 104 bool command); 105 106 // Sends a key press asynchronously. 107 // |code| specifies the UIEvents (aka: DOM4Events) value of the key: 108 // https://dvcs.w3.org/hg/d4e/raw-file/tip/source_respec.htm 109 // The native code of the key event will be set based on |code|. 110 // See ui/base/keycodes/vi usb_keycode_map.h for mappings between |code| 111 // and the native code. 112 // Examples of the various codes: 113 // key_code: VKEY_A 114 // code: "KeyA" 115 // native key code: 0x001e (for Windows). 116 // native key code: 0x0026 (for Linux). 117 void SimulateKeyPressWithCode(WebContents* web_contents, 118 ui::KeyboardCode key_code, 119 const char* code, 120 bool control, 121 bool shift, 122 bool alt, 123 bool command); 124 125 namespace internal { 126 // Allow ExecuteScript* methods to target either a WebContents or a 127 // RenderFrameHost. Targetting a WebContents means executing the script in the 128 // RenderFrameHost returned by WebContents::GetMainFrame(), which is the 129 // main frame. Pass a specific RenderFrameHost to target it. 130 class ToRenderFrameHost { 131 public: 132 ToRenderFrameHost(WebContents* web_contents); 133 ToRenderFrameHost(RenderViewHost* render_view_host); 134 ToRenderFrameHost(RenderFrameHost* render_frame_host); 135 136 RenderFrameHost* render_frame_host() const { return render_frame_host_; } 137 138 private: 139 RenderFrameHost* render_frame_host_; 140 }; 141 } // namespace internal 142 143 // Executes the passed |script| in the specified frame. The |script| should not 144 // invoke domAutomationController.send(); otherwise, your test will hang or be 145 // flaky. If you want to extract a result, use one of the below functions. 146 // Returns true on success. 147 bool ExecuteScript(const internal::ToRenderFrameHost& adapter, 148 const std::string& script) WARN_UNUSED_RESULT; 149 150 // The following methods executes the passed |script| in the specified frame and 151 // sets |result| to the value passed to "window.domAutomationController.send" by 152 // the executed script. They return true on success, false if the script 153 // execution failed or did not evaluate to the expected type. 154 bool ExecuteScriptAndExtractInt(const internal::ToRenderFrameHost& adapter, 155 const std::string& script, 156 int* result) WARN_UNUSED_RESULT; 157 bool ExecuteScriptAndExtractBool(const internal::ToRenderFrameHost& adapter, 158 const std::string& script, 159 bool* result) WARN_UNUSED_RESULT; 160 bool ExecuteScriptAndExtractString(const internal::ToRenderFrameHost& adapter, 161 const std::string& script, 162 std::string* result) WARN_UNUSED_RESULT; 163 164 // Walks the frame tree of the specified WebContents and returns the sole frame 165 // that matches the specified predicate function. This function will DCHECK if 166 // no frames match the specified predicate, or if more than one frame matches. 167 RenderFrameHost* FrameMatchingPredicate( 168 WebContents* web_contents, 169 const base::Callback<bool(RenderFrameHost*)>& predicate); 170 171 // Predicates for use with FrameMatchingPredicate. 172 bool FrameMatchesName(const std::string& name, RenderFrameHost* frame); 173 bool FrameIsChildOfMainFrame(RenderFrameHost* frame); 174 bool FrameHasSourceUrl(const GURL& url, RenderFrameHost* frame); 175 176 // Executes the WebUI resource test runner injecting each resource ID in 177 // |js_resource_ids| prior to executing the tests. 178 // 179 // Returns true if tests ran successfully, false otherwise. 180 bool ExecuteWebUIResourceTest(WebContents* web_contents, 181 const std::vector<int>& js_resource_ids); 182 183 // Returns the cookies for the given url. 184 std::string GetCookies(BrowserContext* browser_context, const GURL& url); 185 186 // Sets a cookie for the given url. Returns true on success. 187 bool SetCookie(BrowserContext* browser_context, 188 const GURL& url, 189 const std::string& value); 190 191 // Fetch the histograms data from other processes. This should be called after 192 // the test code has been executed but before performing assertions. 193 void FetchHistogramsFromChildProcesses(); 194 195 // Watches title changes on a WebContents, blocking until an expected title is 196 // set. 197 class TitleWatcher : public WebContentsObserver { 198 public: 199 // |web_contents| must be non-NULL and needs to stay alive for the 200 // entire lifetime of |this|. |expected_title| is the title that |this| 201 // will wait for. 202 TitleWatcher(WebContents* web_contents, 203 const base::string16& expected_title); 204 virtual ~TitleWatcher(); 205 206 // Adds another title to watch for. 207 void AlsoWaitForTitle(const base::string16& expected_title); 208 209 // Waits until the title matches either expected_title or one of the titles 210 // added with AlsoWaitForTitle. Returns the value of the most recently 211 // observed matching title. 212 const base::string16& WaitAndGetTitle() WARN_UNUSED_RESULT; 213 214 private: 215 // Overridden WebContentsObserver methods. 216 virtual void DidStopLoading(RenderViewHost* render_view_host) OVERRIDE; 217 virtual void TitleWasSet(NavigationEntry* entry, bool explicit_set) OVERRIDE; 218 219 void TestTitle(); 220 221 std::vector<base::string16> expected_titles_; 222 scoped_refptr<MessageLoopRunner> message_loop_runner_; 223 224 // The most recently observed expected title, if any. 225 base::string16 observed_title_; 226 227 DISALLOW_COPY_AND_ASSIGN(TitleWatcher); 228 }; 229 230 // Watches a WebContents and blocks until it is destroyed. 231 class WebContentsDestroyedWatcher : public WebContentsObserver { 232 public: 233 explicit WebContentsDestroyedWatcher(WebContents* web_contents); 234 virtual ~WebContentsDestroyedWatcher(); 235 236 // Waits until the WebContents is destroyed. 237 void Wait(); 238 239 private: 240 // Overridden WebContentsObserver methods. 241 virtual void WebContentsDestroyed() OVERRIDE; 242 243 scoped_refptr<MessageLoopRunner> message_loop_runner_; 244 245 DISALLOW_COPY_AND_ASSIGN(WebContentsDestroyedWatcher); 246 }; 247 248 // Watches a RenderProcessHost and waits for specified destruction events. 249 class RenderProcessHostWatcher : public RenderProcessHostObserver { 250 public: 251 enum WatchType { 252 WATCH_FOR_PROCESS_EXIT, 253 WATCH_FOR_HOST_DESTRUCTION 254 }; 255 256 RenderProcessHostWatcher(RenderProcessHost* render_process_host, 257 WatchType type); 258 // Waits for the render process that contains the specified web contents. 259 RenderProcessHostWatcher(WebContents* web_contents, WatchType type); 260 virtual ~RenderProcessHostWatcher(); 261 262 // Waits until the renderer process exits. 263 void Wait(); 264 265 private: 266 // Overridden RenderProcessHost::LifecycleObserver methods. 267 virtual void RenderProcessExited(RenderProcessHost* host, 268 base::ProcessHandle handle, 269 base::TerminationStatus status, 270 int exit_code) OVERRIDE; 271 virtual void RenderProcessHostDestroyed(RenderProcessHost* host) OVERRIDE; 272 273 RenderProcessHost* render_process_host_; 274 WatchType type_; 275 276 scoped_refptr<MessageLoopRunner> message_loop_runner_; 277 278 DISALLOW_COPY_AND_ASSIGN(RenderProcessHostWatcher); 279 }; 280 281 // Watches for responses from the DOMAutomationController and keeps them in a 282 // queue. Useful for waiting for a message to be received. 283 class DOMMessageQueue : public NotificationObserver { 284 public: 285 // Constructs a DOMMessageQueue and begins listening for messages from the 286 // DOMAutomationController. Do not construct this until the browser has 287 // started. 288 DOMMessageQueue(); 289 virtual ~DOMMessageQueue(); 290 291 // Removes all messages in the message queue. 292 void ClearQueue(); 293 294 // Wait for the next message to arrive. |message| will be set to the next 295 // message. Returns true on success. 296 bool WaitForMessage(std::string* message) WARN_UNUSED_RESULT; 297 298 // Overridden NotificationObserver methods. 299 virtual void Observe(int type, 300 const NotificationSource& source, 301 const NotificationDetails& details) OVERRIDE; 302 303 private: 304 NotificationRegistrar registrar_; 305 std::queue<std::string> message_queue_; 306 scoped_refptr<MessageLoopRunner> message_loop_runner_; 307 308 DISALLOW_COPY_AND_ASSIGN(DOMMessageQueue); 309 }; 310 311 } // namespace content 312 313 #endif // CONTENT_PUBLIC_TEST_BROWSER_TEST_UTILS_H_ 314