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/keycodes/keyboard_codes.h" 25 #include "ui/base/window_open_disposition.h" 26 #include "ui/gfx/native_widget_types.h" 27 #include "url/gurl.h" 28 29 class AppModalDialog; 30 class BookmarkModel; 31 class Browser; 32 class LocationBar; 33 class Profile; 34 class SkBitmap; 35 class TemplateURLService; 36 37 namespace base { 38 class FilePath; 39 } 40 41 namespace chrome { 42 struct NavigateParams; 43 } 44 45 namespace content { 46 class MessageLoopRunner; 47 class RenderViewHost; 48 class RenderWidgetHost; 49 class WebContents; 50 } 51 52 namespace gfx { 53 class Rect; 54 class Size; 55 } 56 57 // A collections of functions designed for use with InProcessBrowserTest. 58 namespace ui_test_utils { 59 60 // Flags to indicate what to wait for in a navigation test. 61 // They can be ORed together. 62 // The order in which the waits happen when more than one is selected, is: 63 // Browser 64 // Tab 65 // Navigation 66 enum BrowserTestWaitFlags { 67 BROWSER_TEST_NONE = 0, // Don't wait for anything. 68 BROWSER_TEST_WAIT_FOR_BROWSER = 1 << 0, // Wait for a new browser. 69 BROWSER_TEST_WAIT_FOR_TAB = 1 << 1, // Wait for a new tab. 70 BROWSER_TEST_WAIT_FOR_NAVIGATION = 1 << 2, // Wait for navigation to finish. 71 72 BROWSER_TEST_MASK = BROWSER_TEST_WAIT_FOR_BROWSER | 73 BROWSER_TEST_WAIT_FOR_TAB | 74 BROWSER_TEST_WAIT_FOR_NAVIGATION 75 }; 76 77 // Puts the current tab title in |title|. Returns true on success. 78 bool GetCurrentTabTitle(const Browser* browser, string16* title); 79 80 // Opens |url| in an incognito browser window with the incognito profile of 81 // |profile|, blocking until the navigation finishes. This will create a new 82 // browser if a browser with the incognito profile does not exist. Returns the 83 // incognito window Browser. 84 Browser* OpenURLOffTheRecord(Profile* profile, const GURL& url); 85 86 // Performs the provided navigation process, blocking until the navigation 87 // finishes. May change the params in some cases (i.e. if the navigation 88 // opens a new browser window). Uses chrome::Navigate. 89 void NavigateToURL(chrome::NavigateParams* params); 90 91 // Navigates the selected tab of |browser| to |url|, blocking until the 92 // navigation finishes. Uses Browser::OpenURL --> chrome::Navigate. 93 void NavigateToURL(Browser* browser, const GURL& url); 94 95 // Navigates the specified tab of |browser| to |url|, blocking until the 96 // navigation finishes. 97 // |disposition| indicates what tab the navigation occurs in, and 98 // |browser_test_flags| controls what to wait for before continuing. 99 void NavigateToURLWithDisposition(Browser* browser, 100 const GURL& url, 101 WindowOpenDisposition disposition, 102 int browser_test_flags); 103 104 // Navigates the selected tab of |browser| to |url|, blocking until the 105 // number of navigations specified complete. 106 void NavigateToURLBlockUntilNavigationsComplete(Browser* browser, 107 const GURL& url, 108 int number_of_navigations); 109 110 // Generate the file path for testing a particular test. 111 // The file for the tests is all located in 112 // test_root_directory/dir/<file> 113 // The returned path is base::FilePath format. 114 base::FilePath GetTestFilePath(const base::FilePath& dir, 115 const base::FilePath& file); 116 117 // Generate the URL for testing a particular test. 118 // HTML for the tests is all located in 119 // test_root_directory/dir/<file> 120 // The returned path is GURL format. 121 GURL GetTestUrl(const base::FilePath& dir, const base::FilePath& file); 122 123 // Generate the path of the build directory, relative to the source root. 124 bool GetRelativeBuildDirectory(base::FilePath* build_dir); 125 126 // Blocks until an application modal dialog is showns and returns it. 127 AppModalDialog* WaitForAppModalDialog(); 128 129 // Performs a find in the page of the specified tab. Returns the number of 130 // matches found. |ordinal| is an optional parameter which is set to the index 131 // of the current match. |selection_rect| is an optional parameter which is set 132 // to the location of the current match. 133 int FindInPage(content::WebContents* tab, 134 const string16& search_string, 135 bool forward, 136 bool case_sensitive, 137 int* ordinal, 138 gfx::Rect* selection_rect); 139 140 // Register |observer| for the given |type| and |source| and run 141 // the message loop until the observer posts a quit task. 142 void RegisterAndWait(content::NotificationObserver* observer, 143 int type, 144 const content::NotificationSource& source); 145 146 // Blocks until |model| finishes loading. 147 void WaitForBookmarkModelToLoad(BookmarkModel* model); 148 void WaitForBookmarkModelToLoad(Profile* profile); 149 150 // Blocks until |service| finishes loading. 151 void WaitForTemplateURLServiceToLoad(TemplateURLService* service); 152 153 // Blocks until the |history_service|'s history finishes loading. 154 void WaitForHistoryToLoad(HistoryService* history_service); 155 156 // Download the given file and waits for the download to complete. 157 void DownloadURL(Browser* browser, const GURL& download_url); 158 159 // Send the given text to the omnibox and wait until it's updated. 160 void SendToOmniboxAndSubmit(LocationBar* location_bar, 161 const std::string& input); 162 163 // Gets the first browser that is not in the specified set. 164 Browser* GetBrowserNotInSet(std::set<Browser*> excluded_browsers); 165 166 // A WindowedNotificationObserver hard-wired to observe 167 // chrome::NOTIFICATION_TAB_ADDED. 168 class 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. 194 template <class U> 195 class 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. 230 class 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. 252 class 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 given render widget, rendered at |page_size|. The 268 // snapshot is set to |bitmap|. Returns true on success. 269 bool TakeRenderWidgetSnapshot(content::RenderWidgetHost* rwh, 270 const gfx::Size& page_size, 271 SkBitmap* bitmap) WARN_UNUSED_RESULT; 272 273 // Takes a snapshot of the entire page, according to the width and height 274 // properties of the DOM's document. Returns true on success. DOMAutomation 275 // must be enabled. 276 bool TakeEntirePageSnapshot(content::RenderViewHost* rvh, 277 SkBitmap* bitmap) WARN_UNUSED_RESULT; 278 279 #if defined(OS_WIN) 280 // Saves a snapshot of the entire screen to a file named 281 // ChromiumSnapshotYYYYMMDDHHMMSS.png to |directory|, returning true on success. 282 // The path to the file produced is returned in |screenshot_path| if non-NULL. 283 bool SaveScreenSnapshotToDirectory(const base::FilePath& directory, 284 base::FilePath* screenshot_path); 285 286 // Saves a snapshot of the entire screen as above to the current user's desktop. 287 // The Chrome path provider must be registered prior to calling this function. 288 bool SaveScreenSnapshotToDesktop(base::FilePath* screenshot_path); 289 #endif 290 291 // Configures the geolocation provider to always return the given position. 292 void OverrideGeolocation(double latitude, double longitude); 293 294 // Enumerates all history contents on the backend thread. Returns them in 295 // descending order by time. 296 class HistoryEnumerator { 297 public: 298 explicit HistoryEnumerator(Profile* profile); 299 ~HistoryEnumerator(); 300 301 std::vector<GURL>& urls() { return urls_; } 302 303 private: 304 void HistoryQueryComplete( 305 const base::Closure& quit_task, 306 HistoryService::Handle request_handle, 307 history::QueryResults* results); 308 309 std::vector<GURL> urls_; 310 311 CancelableRequestConsumer consumer_; 312 313 DISALLOW_COPY_AND_ASSIGN(HistoryEnumerator); 314 }; 315 316 } // namespace ui_test_utils 317 318 #endif // CHROME_TEST_BASE_UI_TEST_UTILS_H_ 319