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/web_contents_observer.h"
21#include "third_party/WebKit/public/web/WebInputEvent.h"
22#include "ui/events/keycodes/keyboard_codes.h"
23#include "url/gurl.h"
24
25#if defined(OS_WIN)
26#include "base/win/scoped_handle.h"
27#endif
28
29class CommandLine;
30
31namespace base {
32class RunLoop;
33}
34
35namespace gfx {
36class Point;
37}
38
39// A collections of functions designed for use with content_browsertests and
40// browser_tests.
41// TO BE CLEAR: any function here must work against both binaries. If it only
42// works with browser_tests, it should be in chrome\test\base\ui_test_utils.h.
43// If it only works with content_browsertests, it should be in
44// content\test\content_browser_test_utils.h.
45
46namespace content {
47
48class BrowserContext;
49class MessageLoopRunner;
50class RenderViewHost;
51class WebContents;
52
53// Generate a URL for a file path including a query string.
54GURL GetFileUrlWithQuery(const base::FilePath& path,
55                         const std::string& query_string);
56
57// Waits for a load stop for the specified |web_contents|'s controller, if the
58// tab is currently web_contents.  Otherwise returns immediately.
59void WaitForLoadStop(WebContents* web_contents);
60
61// Causes the specified web_contents to crash. Blocks until it is crashed.
62void CrashTab(WebContents* web_contents);
63
64// Simulates clicking at the center of the given tab asynchronously; modifiers
65// may contain bits from WebInputEvent::Modifiers.
66void SimulateMouseClick(WebContents* web_contents,
67                        int modifiers,
68                        blink::WebMouseEvent::Button button);
69
70// Simulates clicking at the point |point| of the given tab asynchronously;
71// modifiers may contain bits from WebInputEvent::Modifiers.
72void SimulateMouseClickAt(WebContents* web_contents,
73                          int modifiers,
74                          blink::WebMouseEvent::Button button,
75                          const gfx::Point& point);
76
77// Simulates asynchronously a mouse enter/move/leave event.
78void SimulateMouseEvent(WebContents* web_contents,
79                        blink::WebInputEvent::Type type,
80                        const gfx::Point& point);
81
82// Sends a key press asynchronously.
83// The native code of the key event will be set to InvalidNativeKeycode().
84// |key_code| alone is good enough for scenarios that only need the char
85// value represented by a key event and not the physical key on the keyboard
86// or the keyboard layout.
87// For scenarios such as chromoting that need the native code,
88// SimulateKeyPressWithCode should be used.
89void SimulateKeyPress(WebContents* web_contents,
90                      ui::KeyboardCode key_code,
91                      bool control,
92                      bool shift,
93                      bool alt,
94                      bool command);
95
96// Sends a key press asynchronously.
97// |code| specifies the UIEvents (aka: DOM4Events) value of the key:
98// https://dvcs.w3.org/hg/d4e/raw-file/tip/source_respec.htm
99// The native code of the key event will be set based on |code|.
100// See ui/base/keycodes/vi usb_keycode_map.h for mappings between |code|
101// and the native code.
102// Examples of the various codes:
103//   key_code: VKEY_A
104//   code: "KeyA"
105//   native key code: 0x001e (for Windows).
106//   native key code: 0x0026 (for Linux).
107void SimulateKeyPressWithCode(WebContents* web_contents,
108                              ui::KeyboardCode key_code,
109                              const char* code,
110                              bool control,
111                              bool shift,
112                              bool alt,
113                              bool command);
114
115// Allow ExecuteScript* methods to target either a WebContents or a
116// RenderViewHost.  Targetting a WebContents means executing script in the
117// RenderViewHost returned by WebContents::GetRenderViewHost(), which is the
118// "current" RenderViewHost.  Pass a specific RenderViewHost to target, for
119// example, a "swapped-out" RenderViewHost.
120namespace internal {
121class ToRenderViewHost {
122 public:
123  ToRenderViewHost(WebContents* web_contents);
124  ToRenderViewHost(RenderViewHost* render_view_host);
125
126  RenderViewHost* render_view_host() const { return render_view_host_; }
127
128 private:
129  RenderViewHost* render_view_host_;
130};
131}  // namespace internal
132
133// Executes the passed |script| in the frame pointed to by |frame_xpath| (use
134// empty string for main frame).  The |script| should not invoke
135// domAutomationController.send(); otherwise, your test will hang or be flaky.
136// If you want to extract a result, use one of the below functions.
137// Returns true on success.
138bool ExecuteScriptInFrame(const internal::ToRenderViewHost& adapter,
139                          const std::string& frame_xpath,
140                          const std::string& script) WARN_UNUSED_RESULT;
141
142// The following methods executes the passed |script| in the frame pointed to by
143// |frame_xpath| (use empty string for main frame) and sets |result| to the
144// value passed to "window.domAutomationController.send" by the executed script.
145// They return true on success, false if the script execution failed or did not
146// evaluate to the expected type.
147bool ExecuteScriptInFrameAndExtractInt(
148    const internal::ToRenderViewHost& adapter,
149    const std::string& frame_xpath,
150    const std::string& script,
151    int* result) WARN_UNUSED_RESULT;
152bool ExecuteScriptInFrameAndExtractBool(
153    const internal::ToRenderViewHost& adapter,
154    const std::string& frame_xpath,
155    const std::string& script,
156    bool* result) WARN_UNUSED_RESULT;
157bool ExecuteScriptInFrameAndExtractString(
158    const internal::ToRenderViewHost& adapter,
159    const std::string& frame_xpath,
160    const std::string& script,
161    std::string* result) WARN_UNUSED_RESULT;
162
163// Top-frame script execution helpers (a.k.a., the common case):
164bool ExecuteScript(const internal::ToRenderViewHost& adapter,
165                   const std::string& script) WARN_UNUSED_RESULT;
166bool ExecuteScriptAndExtractInt(const internal::ToRenderViewHost& adapter,
167                                const std::string& script,
168                                int* result) WARN_UNUSED_RESULT;
169bool ExecuteScriptAndExtractBool(const internal::ToRenderViewHost& adapter,
170                                 const std::string& script,
171                                 bool* result) WARN_UNUSED_RESULT;
172bool ExecuteScriptAndExtractString(const internal::ToRenderViewHost& adapter,
173                                   const std::string& script,
174                                   std::string* result) WARN_UNUSED_RESULT;
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(const internal::ToRenderViewHost& adapter,
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// Watches title changes on a WebContents, blocking until an expected title is
192// set.
193class TitleWatcher : public WebContentsObserver {
194 public:
195  // |web_contents| must be non-NULL and needs to stay alive for the
196  // entire lifetime of |this|. |expected_title| is the title that |this|
197  // will wait for.
198  TitleWatcher(WebContents* web_contents,
199               const base::string16& expected_title);
200  virtual ~TitleWatcher();
201
202  // Adds another title to watch for.
203  void AlsoWaitForTitle(const base::string16& expected_title);
204
205  // Waits until the title matches either expected_title or one of the titles
206  // added with AlsoWaitForTitle. Returns the value of the most recently
207  // observed matching title.
208  const base::string16& WaitAndGetTitle() WARN_UNUSED_RESULT;
209
210 private:
211  // Overridden WebContentsObserver methods.
212  virtual void DidStopLoading(RenderViewHost* render_view_host) OVERRIDE;
213  virtual void TitleWasSet(NavigationEntry* entry, bool explicit_set) OVERRIDE;
214
215  void TestTitle();
216
217  std::vector<base::string16> expected_titles_;
218  scoped_refptr<MessageLoopRunner> message_loop_runner_;
219
220  // The most recently observed expected title, if any.
221  base::string16 observed_title_;
222
223  DISALLOW_COPY_AND_ASSIGN(TitleWatcher);
224};
225
226// Watches a WebContents and blocks until it is destroyed.
227class WebContentsDestroyedWatcher : public WebContentsObserver {
228 public:
229  explicit WebContentsDestroyedWatcher(WebContents* web_contents);
230  virtual ~WebContentsDestroyedWatcher();
231
232  // Waits until the WebContents is destroyed.
233  void Wait();
234
235 private:
236  // Overridden WebContentsObserver methods.
237  virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE;
238
239  scoped_refptr<MessageLoopRunner> message_loop_runner_;
240
241  DISALLOW_COPY_AND_ASSIGN(WebContentsDestroyedWatcher);
242};
243
244// Watches for responses from the DOMAutomationController and keeps them in a
245// queue. Useful for waiting for a message to be received.
246class DOMMessageQueue : public NotificationObserver {
247 public:
248  // Constructs a DOMMessageQueue and begins listening for messages from the
249  // DOMAutomationController. Do not construct this until the browser has
250  // started.
251  DOMMessageQueue();
252  virtual ~DOMMessageQueue();
253
254  // Removes all messages in the message queue.
255  void ClearQueue();
256
257  // Wait for the next message to arrive. |message| will be set to the next
258  // message, if not null. Returns true on success.
259  bool WaitForMessage(std::string* message) WARN_UNUSED_RESULT;
260
261  // Overridden NotificationObserver methods.
262  virtual void Observe(int type,
263                       const NotificationSource& source,
264                       const NotificationDetails& details) OVERRIDE;
265
266 private:
267  NotificationRegistrar registrar_;
268  std::queue<std::string> message_queue_;
269  bool waiting_for_message_;
270  scoped_refptr<MessageLoopRunner> message_loop_runner_;
271
272  DISALLOW_COPY_AND_ASSIGN(DOMMessageQueue);
273};
274
275}  // namespace content
276
277#endif  // CONTENT_PUBLIC_TEST_BROWSER_TEST_UTILS_H_
278