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 29 class AppModalDialog; 30 class Browser; 31 class DevToolsWindow; 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, base::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. Simulates a POST and uses chrome::Navigate. 93 void NavigateToURLWithPost(Browser* browser, const GURL& url); 94 95 // Navigates the selected tab of |browser| to |url|, blocking until the 96 // navigation finishes. Uses Browser::OpenURL --> chrome::Navigate. 97 void NavigateToURL(Browser* browser, const GURL& url); 98 99 // Navigates the specified tab of |browser| to |url|, blocking until the 100 // navigation finishes. 101 // |disposition| indicates what tab the navigation occurs in, and 102 // |browser_test_flags| controls what to wait for before continuing. 103 void NavigateToURLWithDisposition(Browser* browser, 104 const GURL& url, 105 WindowOpenDisposition disposition, 106 int browser_test_flags); 107 108 // Navigates the selected tab of |browser| to |url|, blocking until the 109 // number of navigations specified complete. 110 void NavigateToURLBlockUntilNavigationsComplete(Browser* browser, 111 const GURL& url, 112 int number_of_navigations); 113 114 // Blocks until DevTools window is loaded. 115 void WaitUntilDevToolsWindowLoaded(DevToolsWindow* window); 116 117 // Generate the file path for testing a particular test. 118 // The file for the tests is all located in 119 // test_root_directory/dir/<file> 120 // The returned path is base::FilePath format. 121 base::FilePath GetTestFilePath(const base::FilePath& dir, 122 const base::FilePath& file); 123 124 // Generate the URL for testing a particular test. 125 // HTML for the tests is all located in 126 // test_root_directory/dir/<file> 127 // The returned path is GURL format. 128 GURL GetTestUrl(const base::FilePath& dir, const base::FilePath& file); 129 130 // Generate the path of the build directory, relative to the source root. 131 bool GetRelativeBuildDirectory(base::FilePath* build_dir); 132 133 // Blocks until an application modal dialog is showns and returns it. 134 AppModalDialog* WaitForAppModalDialog(); 135 136 // Performs a find in the page of the specified tab. Returns the number of 137 // matches found. |ordinal| is an optional parameter which is set to the index 138 // of the current match. |selection_rect| is an optional parameter which is set 139 // to the location of the current match. 140 int FindInPage(content::WebContents* tab, 141 const base::string16& search_string, 142 bool forward, 143 bool case_sensitive, 144 int* ordinal, 145 gfx::Rect* selection_rect); 146 147 // Blocks until |service| finishes loading. 148 void WaitForTemplateURLServiceToLoad(TemplateURLService* service); 149 150 // Blocks until the |history_service|'s history finishes loading. 151 void WaitForHistoryToLoad(HistoryService* history_service); 152 153 // Download the given file and waits for the download to complete. 154 void DownloadURL(Browser* browser, const GURL& download_url); 155 156 // Send the given text to the omnibox and wait until it's updated. 157 void SendToOmniboxAndSubmit(LocationBar* location_bar, 158 const std::string& input); 159 160 // Gets the first browser that is not in the specified set. 161 Browser* GetBrowserNotInSet(std::set<Browser*> excluded_browsers); 162 163 // Gets the size and value of the cookie string for |url| in the given tab. 164 // Can be called from any thread. 165 void GetCookies(const GURL& url, 166 content::WebContents* contents, 167 int* value_size, 168 std::string* value); 169 170 // A WindowedNotificationObserver hard-wired to observe 171 // chrome::NOTIFICATION_TAB_ADDED. 172 class WindowedTabAddedNotificationObserver 173 : public content::WindowedNotificationObserver { 174 public: 175 // Register to listen for notifications of NOTIFICATION_TAB_ADDED from either 176 // a specific source, or from all sources if |source| is 177 // NotificationService::AllSources(). 178 explicit WindowedTabAddedNotificationObserver( 179 const content::NotificationSource& source); 180 181 // Returns the added tab, or NULL if no notification was observed yet. GetTab()182 content::WebContents* GetTab() { return added_tab_; } 183 184 virtual void Observe(int type, 185 const content::NotificationSource& source, 186 const content::NotificationDetails& details) OVERRIDE; 187 188 private: 189 content::WebContents* added_tab_; 190 191 DISALLOW_COPY_AND_ASSIGN(WindowedTabAddedNotificationObserver); 192 }; 193 194 // Similar to WindowedNotificationObserver but also provides a way of retrieving 195 // the details associated with the notification. 196 // Note that in order to use that class the details class should be copiable, 197 // which is the case with most notifications. 198 template <class U> 199 class WindowedNotificationObserverWithDetails 200 : public content::WindowedNotificationObserver { 201 public: WindowedNotificationObserverWithDetails(int notification_type,const content::NotificationSource & source)202 WindowedNotificationObserverWithDetails( 203 int notification_type, 204 const content::NotificationSource& source) 205 : content::WindowedNotificationObserver(notification_type, source) {} 206 207 // Fills |details| with the details of the notification received for |source|. GetDetailsFor(uintptr_t source,U * details)208 bool GetDetailsFor(uintptr_t source, U* details) { 209 typename std::map<uintptr_t, U>::const_iterator iter = 210 details_.find(source); 211 if (iter == details_.end()) 212 return false; 213 *details = iter->second; 214 return true; 215 } 216 Observe(int type,const content::NotificationSource & source,const content::NotificationDetails & details)217 virtual void Observe(int type, 218 const content::NotificationSource& source, 219 const content::NotificationDetails& details) OVERRIDE { 220 const U* details_ptr = content::Details<U>(details).ptr(); 221 if (details_ptr) 222 details_[source.map_key()] = *details_ptr; 223 content::WindowedNotificationObserver::Observe(type, source, details); 224 } 225 226 private: 227 std::map<uintptr_t, U> details_; 228 229 DISALLOW_COPY_AND_ASSIGN(WindowedNotificationObserverWithDetails); 230 }; 231 232 // Notification observer which waits for navigation events and blocks until 233 // a specific URL is loaded. The URL must be an exact match. 234 class UrlLoadObserver : public content::WindowedNotificationObserver { 235 public: 236 // Register to listen for notifications of the given type from either a 237 // specific source, or from all sources if |source| is 238 // NotificationService::AllSources(). 239 UrlLoadObserver(const GURL& url, const content::NotificationSource& source); 240 virtual ~UrlLoadObserver(); 241 242 // content::NotificationObserver: 243 virtual void Observe(int type, 244 const content::NotificationSource& source, 245 const content::NotificationDetails& details) OVERRIDE; 246 247 private: 248 GURL url_; 249 250 DISALLOW_COPY_AND_ASSIGN(UrlLoadObserver); 251 }; 252 253 // Convenience class for waiting for a new browser to be created. 254 // Like WindowedNotificationObserver, this class provides a safe, non-racey 255 // way to wait for a new browser to be created. 256 class BrowserAddedObserver { 257 public: 258 BrowserAddedObserver(); 259 ~BrowserAddedObserver(); 260 261 // Wait for a new browser to be created, and return a pointer to it. 262 Browser* WaitForSingleNewBrowser(); 263 264 private: 265 content::WindowedNotificationObserver notification_observer_; 266 std::set<Browser*> original_browsers_; 267 268 DISALLOW_COPY_AND_ASSIGN(BrowserAddedObserver); 269 }; 270 271 // Takes a snapshot of the entire page, according to the width and height 272 // properties of the DOM's document. Returns true on success. DOMAutomation 273 // must be enabled. 274 bool TakeEntirePageSnapshot(content::RenderViewHost* rvh, 275 SkBitmap* bitmap) WARN_UNUSED_RESULT; 276 277 #if defined(OS_WIN) 278 // Saves a snapshot of the entire screen to a file named 279 // ChromiumSnapshotYYYYMMDDHHMMSS.png to |directory|, returning true on success. 280 // The path to the file produced is returned in |screenshot_path| if non-NULL. 281 bool SaveScreenSnapshotToDirectory(const base::FilePath& directory, 282 base::FilePath* screenshot_path); 283 284 // Saves a snapshot of the entire screen as above to the current user's desktop. 285 // The Chrome path provider must be registered prior to calling this function. 286 bool SaveScreenSnapshotToDesktop(base::FilePath* screenshot_path); 287 #endif 288 289 // Configures the geolocation provider to always return the given position. 290 void OverrideGeolocation(double latitude, double longitude); 291 292 // Enumerates all history contents on the backend thread. Returns them in 293 // descending order by time. 294 class HistoryEnumerator { 295 public: 296 explicit HistoryEnumerator(Profile* profile); 297 ~HistoryEnumerator(); 298 urls()299 std::vector<GURL>& urls() { return urls_; } 300 301 private: 302 void HistoryQueryComplete( 303 const base::Closure& quit_task, 304 HistoryService::Handle request_handle, 305 history::QueryResults* results); 306 307 std::vector<GURL> urls_; 308 309 CancelableRequestConsumer consumer_; 310 311 DISALLOW_COPY_AND_ASSIGN(HistoryEnumerator); 312 }; 313 314 } // namespace ui_test_utils 315 316 #endif // CHROME_TEST_BASE_UI_TEST_UTILS_H_ 317