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
30namespace base {
31class RunLoop;
32}
33
34namespace gfx {
35class 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
45namespace content {
46
47class BrowserContext;
48class MessageLoopRunner;
49class RenderViewHost;
50class WebContents;
51
52// Generate a URL for a file path including a query string.
53GURL 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.
58void 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.
65void WaitForResizeComplete(WebContents* web_contents);
66#endif  // USE_AURA
67
68// Causes the specified web_contents to crash. Blocks until it is crashed.
69void CrashTab(WebContents* web_contents);
70
71// Simulates clicking at the center of the given tab asynchronously; modifiers
72// may contain bits from WebInputEvent::Modifiers.
73void 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.
79void 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.
85void SimulateMouseEvent(WebContents* web_contents,
86                        blink::WebInputEvent::Type type,
87                        const gfx::Point& point);
88
89// Taps the screen at |point|.
90void 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.
99void 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).
117void 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
125namespace 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.
130class 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.
147bool 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.
154bool ExecuteScriptAndExtractInt(const internal::ToRenderFrameHost& adapter,
155                                const std::string& script,
156                                int* result) WARN_UNUSED_RESULT;
157bool ExecuteScriptAndExtractBool(const internal::ToRenderFrameHost& adapter,
158                                 const std::string& script,
159                                 bool* result) WARN_UNUSED_RESULT;
160bool 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.
167RenderFrameHost* FrameMatchingPredicate(
168    WebContents* web_contents,
169    const base::Callback<bool(RenderFrameHost*)>& predicate);
170
171// Predicates for use with FrameMatchingPredicate.
172bool FrameMatchesName(const std::string& name, RenderFrameHost* frame);
173bool FrameIsChildOfMainFrame(RenderFrameHost* frame);
174bool 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.
180bool ExecuteWebUIResourceTest(WebContents* web_contents,
181                              const std::vector<int>& js_resource_ids);
182
183// Returns the cookies for the given url.
184std::string GetCookies(BrowserContext* browser_context, const GURL& url);
185
186// Sets a cookie for the given url. Returns true on success.
187bool 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.
193void FetchHistogramsFromChildProcesses();
194
195// Watches title changes on a WebContents, blocking until an expected title is
196// set.
197class 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.
231class 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.
249class 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.
283class 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