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