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 CHROME_TEST_BASE_UI_TEST_UTILS_H_
6#define CHROME_TEST_BASE_UI_TEST_UTILS_H_
7
8#include <map>
9#include <queue>
10#include <set>
11#include <string>
12#include <vector>
13
14#include "base/basictypes.h"
15#include "base/memory/ref_counted.h"
16#include "base/strings/string16.h"
17#include "chrome/browser/history/history_service.h"
18#include "content/public/browser/notification_details.h"
19#include "content/public/browser/notification_observer.h"
20#include "content/public/browser/notification_registrar.h"
21#include "content/public/browser/notification_source.h"
22#include "content/public/test/test_utils.h"
23#include "testing/gtest/include/gtest/gtest.h"
24#include "ui/base/window_open_disposition.h"
25#include "ui/events/keycodes/keyboard_codes.h"
26#include "ui/gfx/native_widget_types.h"
27#include "url/gurl.h"
28
29class AppModalDialog;
30class Browser;
31class LocationBar;
32class Profile;
33class SkBitmap;
34class TemplateURLService;
35
36namespace base {
37class FilePath;
38}
39
40namespace chrome {
41struct NavigateParams;
42}
43
44namespace content {
45class MessageLoopRunner;
46class RenderViewHost;
47class RenderWidgetHost;
48class WebContents;
49}
50
51namespace gfx {
52class Rect;
53class Size;
54}
55
56// A collections of functions designed for use with InProcessBrowserTest.
57namespace ui_test_utils {
58
59// Flags to indicate what to wait for in a navigation test.
60// They can be ORed together.
61// The order in which the waits happen when more than one is selected, is:
62//    Browser
63//    Tab
64//    Navigation
65enum BrowserTestWaitFlags {
66  BROWSER_TEST_NONE = 0,                      // Don't wait for anything.
67  BROWSER_TEST_WAIT_FOR_BROWSER = 1 << 0,     // Wait for a new browser.
68  BROWSER_TEST_WAIT_FOR_TAB = 1 << 1,         // Wait for a new tab.
69  BROWSER_TEST_WAIT_FOR_NAVIGATION = 1 << 2,  // Wait for navigation to finish.
70
71  BROWSER_TEST_MASK = BROWSER_TEST_WAIT_FOR_BROWSER |
72                      BROWSER_TEST_WAIT_FOR_TAB |
73                      BROWSER_TEST_WAIT_FOR_NAVIGATION
74};
75
76// Puts the current tab title in |title|. Returns true on success.
77bool GetCurrentTabTitle(const Browser* browser, base::string16* title);
78
79// Opens |url| in an incognito browser window with the incognito profile of
80// |profile|, blocking until the navigation finishes. This will create a new
81// browser if a browser with the incognito profile does not exist. Returns the
82// incognito window Browser.
83Browser* OpenURLOffTheRecord(Profile* profile, const GURL& url);
84
85// Performs the provided navigation process, blocking until the navigation
86// finishes. May change the params in some cases (i.e. if the navigation
87// opens a new browser window). Uses chrome::Navigate.
88void NavigateToURL(chrome::NavigateParams* params);
89
90// Navigates the selected tab of |browser| to |url|, blocking until the
91// navigation finishes. Simulates a POST and uses chrome::Navigate.
92void NavigateToURLWithPost(Browser* browser, const GURL& url);
93
94// Navigates the selected tab of |browser| to |url|, blocking until the
95// navigation finishes. Uses Browser::OpenURL --> chrome::Navigate.
96void NavigateToURL(Browser* browser, const GURL& url);
97
98// Navigates the specified tab of |browser| to |url|, blocking until the
99// navigation finishes.
100// |disposition| indicates what tab the navigation occurs in, and
101// |browser_test_flags| controls what to wait for before continuing.
102void NavigateToURLWithDisposition(Browser* browser,
103                                  const GURL& url,
104                                  WindowOpenDisposition disposition,
105                                  int browser_test_flags);
106
107// Navigates the selected tab of |browser| to |url|, blocking until the
108// number of navigations specified complete.
109void NavigateToURLBlockUntilNavigationsComplete(Browser* browser,
110                                                const GURL& url,
111                                                int number_of_navigations);
112
113// Generate the file path for testing a particular test.
114// The file for the tests is all located in
115// test_root_directory/dir/<file>
116// The returned path is base::FilePath format.
117base::FilePath GetTestFilePath(const base::FilePath& dir,
118                               const base::FilePath& file);
119
120// Generate the URL for testing a particular test.
121// HTML for the tests is all located in
122// test_root_directory/dir/<file>
123// The returned path is GURL format.
124GURL GetTestUrl(const base::FilePath& dir, const base::FilePath& file);
125
126// Generate the path of the build directory, relative to the source root.
127bool GetRelativeBuildDirectory(base::FilePath* build_dir);
128
129// Blocks until an application modal dialog is showns and returns it.
130AppModalDialog* WaitForAppModalDialog();
131
132// Performs a find in the page of the specified tab. Returns the number of
133// matches found.  |ordinal| is an optional parameter which is set to the index
134// of the current match. |selection_rect| is an optional parameter which is set
135// to the location of the current match.
136int FindInPage(content::WebContents* tab,
137               const base::string16& search_string,
138               bool forward,
139               bool case_sensitive,
140               int* ordinal,
141               gfx::Rect* selection_rect);
142
143// Blocks until |service| finishes loading.
144void WaitForTemplateURLServiceToLoad(TemplateURLService* service);
145
146// Blocks until the |history_service|'s history finishes loading.
147void WaitForHistoryToLoad(HistoryService* history_service);
148
149// Download the given file and waits for the download to complete.
150void DownloadURL(Browser* browser, const GURL& download_url);
151
152// Send the given text to the omnibox and wait until it's updated.
153void SendToOmniboxAndSubmit(LocationBar* location_bar,
154                            const std::string& input);
155
156// Gets the first browser that is not in the specified set.
157Browser* GetBrowserNotInSet(std::set<Browser*> excluded_browsers);
158
159// Gets the size and value of the cookie string for |url| in the given tab.
160// Can be called from any thread.
161void GetCookies(const GURL& url,
162                content::WebContents* contents,
163                int* value_size,
164                std::string* value);
165
166// A WindowedNotificationObserver hard-wired to observe
167// chrome::NOTIFICATION_TAB_ADDED.
168class WindowedTabAddedNotificationObserver
169    : public content::WindowedNotificationObserver {
170 public:
171  // Register to listen for notifications of NOTIFICATION_TAB_ADDED from either
172  // a specific source, or from all sources if |source| is
173  // NotificationService::AllSources().
174  explicit WindowedTabAddedNotificationObserver(
175      const content::NotificationSource& source);
176
177  // Returns the added tab, or NULL if no notification was observed yet.
178  content::WebContents* GetTab() { return added_tab_; }
179
180  virtual void Observe(int type,
181                       const content::NotificationSource& source,
182                       const content::NotificationDetails& details) OVERRIDE;
183
184 private:
185  content::WebContents* added_tab_;
186
187  DISALLOW_COPY_AND_ASSIGN(WindowedTabAddedNotificationObserver);
188};
189
190// Similar to WindowedNotificationObserver but also provides a way of retrieving
191// the details associated with the notification.
192// Note that in order to use that class the details class should be copiable,
193// which is the case with most notifications.
194template <class U>
195class WindowedNotificationObserverWithDetails
196    : public content::WindowedNotificationObserver {
197 public:
198  WindowedNotificationObserverWithDetails(
199      int notification_type,
200      const content::NotificationSource& source)
201      : content::WindowedNotificationObserver(notification_type, source) {}
202
203  // Fills |details| with the details of the notification received for |source|.
204  bool GetDetailsFor(uintptr_t source, U* details) {
205    typename std::map<uintptr_t, U>::const_iterator iter =
206        details_.find(source);
207    if (iter == details_.end())
208      return false;
209    *details = iter->second;
210    return true;
211  }
212
213  virtual void Observe(int type,
214                       const content::NotificationSource& source,
215                       const content::NotificationDetails& details) OVERRIDE {
216    const U* details_ptr = content::Details<U>(details).ptr();
217    if (details_ptr)
218      details_[source.map_key()] = *details_ptr;
219    content::WindowedNotificationObserver::Observe(type, source, details);
220  }
221
222 private:
223  std::map<uintptr_t, U> details_;
224
225  DISALLOW_COPY_AND_ASSIGN(WindowedNotificationObserverWithDetails);
226};
227
228// Notification observer which waits for navigation events and blocks until
229// a specific URL is loaded. The URL must be an exact match.
230class UrlLoadObserver : public content::WindowedNotificationObserver {
231 public:
232  // Register to listen for notifications of the given type from either a
233  // specific source, or from all sources if |source| is
234  // NotificationService::AllSources().
235  UrlLoadObserver(const GURL& url, const content::NotificationSource& source);
236  virtual ~UrlLoadObserver();
237
238  // content::NotificationObserver:
239  virtual void Observe(int type,
240                       const content::NotificationSource& source,
241                       const content::NotificationDetails& details) OVERRIDE;
242
243 private:
244  GURL url_;
245
246  DISALLOW_COPY_AND_ASSIGN(UrlLoadObserver);
247};
248
249// Convenience class for waiting for a new browser to be created.
250// Like WindowedNotificationObserver, this class provides a safe, non-racey
251// way to wait for a new browser to be created.
252class BrowserAddedObserver {
253 public:
254  BrowserAddedObserver();
255  ~BrowserAddedObserver();
256
257  // Wait for a new browser to be created, and return a pointer to it.
258  Browser* WaitForSingleNewBrowser();
259
260 private:
261  content::WindowedNotificationObserver notification_observer_;
262  std::set<Browser*> original_browsers_;
263
264  DISALLOW_COPY_AND_ASSIGN(BrowserAddedObserver);
265};
266
267// Takes a snapshot of the entire page, according to the width and height
268// properties of the DOM's document. Returns true on success. DOMAutomation
269// must be enabled.
270bool TakeEntirePageSnapshot(content::RenderViewHost* rvh,
271                            SkBitmap* bitmap) WARN_UNUSED_RESULT;
272
273#if defined(OS_WIN)
274// Saves a snapshot of the entire screen to a file named
275// ChromiumSnapshotYYYYMMDDHHMMSS.png to |directory|, returning true on success.
276// The path to the file produced is returned in |screenshot_path| if non-NULL.
277bool SaveScreenSnapshotToDirectory(const base::FilePath& directory,
278                                   base::FilePath* screenshot_path);
279
280// Saves a snapshot of the entire screen as above to the current user's desktop.
281// The Chrome path provider must be registered prior to calling this function.
282bool SaveScreenSnapshotToDesktop(base::FilePath* screenshot_path);
283#endif
284
285// Configures the geolocation provider to always return the given position.
286void OverrideGeolocation(double latitude, double longitude);
287
288// Enumerates all history contents on the backend thread. Returns them in
289// descending order by time.
290class HistoryEnumerator {
291 public:
292  explicit HistoryEnumerator(Profile* profile);
293  ~HistoryEnumerator();
294
295  std::vector<GURL>& urls() { return urls_; }
296
297 private:
298  void HistoryQueryComplete(
299      const base::Closure& quit_task,
300      history::QueryResults* results);
301
302  std::vector<GURL> urls_;
303
304  base::CancelableTaskTracker tracker_;
305
306  DISALLOW_COPY_AND_ASSIGN(HistoryEnumerator);
307};
308
309}  // namespace ui_test_utils
310
311#endif  // CHROME_TEST_BASE_UI_TEST_UTILS_H_
312