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 LocationBar; 32 class Profile; 33 class SkBitmap; 34 class TemplateURLService; 35 36 namespace base { 37 class FilePath; 38 } 39 40 namespace chrome { 41 struct NavigateParams; 42 } 43 44 namespace content { 45 class MessageLoopRunner; 46 class RenderViewHost; 47 class RenderWidgetHost; 48 class WebContents; 49 } 50 51 namespace gfx { 52 class Rect; 53 class Size; 54 } 55 56 // A collections of functions designed for use with InProcessBrowserTest. 57 namespace 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 65 enum 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. 77 bool GetCurrentTabTitle(const Browser* browser, 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. 83 Browser* 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. 88 void 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. 92 void 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. 96 void 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. 102 void 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. 109 void 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. 117 base::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. 124 GURL GetTestUrl(const base::FilePath& dir, const base::FilePath& file); 125 126 // Generate the path of the build directory, relative to the source root. 127 bool GetRelativeBuildDirectory(base::FilePath* build_dir); 128 129 // Blocks until an application modal dialog is showns and returns it. 130 AppModalDialog* 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. 136 int FindInPage(content::WebContents* tab, 137 const 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. 144 void WaitForTemplateURLServiceToLoad(TemplateURLService* service); 145 146 // Blocks until the |history_service|'s history finishes loading. 147 void WaitForHistoryToLoad(HistoryService* history_service); 148 149 // Download the given file and waits for the download to complete. 150 void DownloadURL(Browser* browser, const GURL& download_url); 151 152 // Send the given text to the omnibox and wait until it's updated. 153 void SendToOmniboxAndSubmit(LocationBar* location_bar, 154 const std::string& input); 155 156 // Gets the first browser that is not in the specified set. 157 Browser* GetBrowserNotInSet(std::set<Browser*> excluded_browsers); 158 159 // A WindowedNotificationObserver hard-wired to observe 160 // chrome::NOTIFICATION_TAB_ADDED. 161 class WindowedTabAddedNotificationObserver 162 : public content::WindowedNotificationObserver { 163 public: 164 // Register to listen for notifications of NOTIFICATION_TAB_ADDED from either 165 // a specific source, or from all sources if |source| is 166 // NotificationService::AllSources(). 167 explicit WindowedTabAddedNotificationObserver( 168 const content::NotificationSource& source); 169 170 // Returns the added tab, or NULL if no notification was observed yet. GetTab()171 content::WebContents* GetTab() { return added_tab_; } 172 173 virtual void Observe(int type, 174 const content::NotificationSource& source, 175 const content::NotificationDetails& details) OVERRIDE; 176 177 private: 178 content::WebContents* added_tab_; 179 180 DISALLOW_COPY_AND_ASSIGN(WindowedTabAddedNotificationObserver); 181 }; 182 183 // Similar to WindowedNotificationObserver but also provides a way of retrieving 184 // the details associated with the notification. 185 // Note that in order to use that class the details class should be copiable, 186 // which is the case with most notifications. 187 template <class U> 188 class WindowedNotificationObserverWithDetails 189 : public content::WindowedNotificationObserver { 190 public: WindowedNotificationObserverWithDetails(int notification_type,const content::NotificationSource & source)191 WindowedNotificationObserverWithDetails( 192 int notification_type, 193 const content::NotificationSource& source) 194 : content::WindowedNotificationObserver(notification_type, source) {} 195 196 // Fills |details| with the details of the notification received for |source|. GetDetailsFor(uintptr_t source,U * details)197 bool GetDetailsFor(uintptr_t source, U* details) { 198 typename std::map<uintptr_t, U>::const_iterator iter = 199 details_.find(source); 200 if (iter == details_.end()) 201 return false; 202 *details = iter->second; 203 return true; 204 } 205 Observe(int type,const content::NotificationSource & source,const content::NotificationDetails & details)206 virtual void Observe(int type, 207 const content::NotificationSource& source, 208 const content::NotificationDetails& details) OVERRIDE { 209 const U* details_ptr = content::Details<U>(details).ptr(); 210 if (details_ptr) 211 details_[source.map_key()] = *details_ptr; 212 content::WindowedNotificationObserver::Observe(type, source, details); 213 } 214 215 private: 216 std::map<uintptr_t, U> details_; 217 218 DISALLOW_COPY_AND_ASSIGN(WindowedNotificationObserverWithDetails); 219 }; 220 221 // Notification observer which waits for navigation events and blocks until 222 // a specific URL is loaded. The URL must be an exact match. 223 class UrlLoadObserver : public content::WindowedNotificationObserver { 224 public: 225 // Register to listen for notifications of the given type from either a 226 // specific source, or from all sources if |source| is 227 // NotificationService::AllSources(). 228 UrlLoadObserver(const GURL& url, const content::NotificationSource& source); 229 virtual ~UrlLoadObserver(); 230 231 // content::NotificationObserver: 232 virtual void Observe(int type, 233 const content::NotificationSource& source, 234 const content::NotificationDetails& details) OVERRIDE; 235 236 private: 237 GURL url_; 238 239 DISALLOW_COPY_AND_ASSIGN(UrlLoadObserver); 240 }; 241 242 // Convenience class for waiting for a new browser to be created. 243 // Like WindowedNotificationObserver, this class provides a safe, non-racey 244 // way to wait for a new browser to be created. 245 class BrowserAddedObserver { 246 public: 247 BrowserAddedObserver(); 248 ~BrowserAddedObserver(); 249 250 // Wait for a new browser to be created, and return a pointer to it. 251 Browser* WaitForSingleNewBrowser(); 252 253 private: 254 content::WindowedNotificationObserver notification_observer_; 255 std::set<Browser*> original_browsers_; 256 257 DISALLOW_COPY_AND_ASSIGN(BrowserAddedObserver); 258 }; 259 260 // Takes a snapshot of the given render widget, rendered at |page_size|. The 261 // snapshot is set to |bitmap|. Returns true on success. 262 bool TakeRenderWidgetSnapshot(content::RenderWidgetHost* rwh, 263 const gfx::Size& page_size, 264 SkBitmap* bitmap) WARN_UNUSED_RESULT; 265 266 // Takes a snapshot of the entire page, according to the width and height 267 // properties of the DOM's document. Returns true on success. DOMAutomation 268 // must be enabled. 269 bool TakeEntirePageSnapshot(content::RenderViewHost* rvh, 270 SkBitmap* bitmap) WARN_UNUSED_RESULT; 271 272 #if defined(OS_WIN) 273 // Saves a snapshot of the entire screen to a file named 274 // ChromiumSnapshotYYYYMMDDHHMMSS.png to |directory|, returning true on success. 275 // The path to the file produced is returned in |screenshot_path| if non-NULL. 276 bool SaveScreenSnapshotToDirectory(const base::FilePath& directory, 277 base::FilePath* screenshot_path); 278 279 // Saves a snapshot of the entire screen as above to the current user's desktop. 280 // The Chrome path provider must be registered prior to calling this function. 281 bool SaveScreenSnapshotToDesktop(base::FilePath* screenshot_path); 282 #endif 283 284 // Configures the geolocation provider to always return the given position. 285 void OverrideGeolocation(double latitude, double longitude); 286 287 // Enumerates all history contents on the backend thread. Returns them in 288 // descending order by time. 289 class HistoryEnumerator { 290 public: 291 explicit HistoryEnumerator(Profile* profile); 292 ~HistoryEnumerator(); 293 urls()294 std::vector<GURL>& urls() { return urls_; } 295 296 private: 297 void HistoryQueryComplete( 298 const base::Closure& quit_task, 299 HistoryService::Handle request_handle, 300 history::QueryResults* results); 301 302 std::vector<GURL> urls_; 303 304 CancelableRequestConsumer consumer_; 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