• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "chrome/test/base/ui_test_utils.h"
6 
7 #if defined(OS_WIN)
8 #include <windows.h>
9 #endif
10 
11 #include "base/bind.h"
12 #include "base/bind_helpers.h"
13 #include "base/callback.h"
14 #include "base/command_line.h"
15 #include "base/file_util.h"
16 #include "base/files/file_path.h"
17 #include "base/json/json_reader.h"
18 #include "base/memory/ref_counted.h"
19 #include "base/memory/scoped_ptr.h"
20 #include "base/path_service.h"
21 #include "base/prefs/pref_service.h"
22 #include "base/strings/stringprintf.h"
23 #include "base/strings/utf_string_conversions.h"
24 #include "base/test/test_timeouts.h"
25 #include "base/time/time.h"
26 #include "base/values.h"
27 #include "chrome/browser/autocomplete/autocomplete_controller.h"
28 #include "chrome/browser/bookmarks/bookmark_model.h"
29 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
30 #include "chrome/browser/browser_process.h"
31 #include "chrome/browser/chrome_notification_types.h"
32 #include "chrome/browser/extensions/extension_action.h"
33 #include "chrome/browser/history/history_service_factory.h"
34 #include "chrome/browser/profiles/profile.h"
35 #include "chrome/browser/search_engines/template_url_service.h"
36 #include "chrome/browser/search_engines/template_url_service_test_util.h"
37 #include "chrome/browser/thumbnails/render_widget_snapshot_taker.h"
38 #include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog.h"
39 #include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog_queue.h"
40 #include "chrome/browser/ui/browser.h"
41 #include "chrome/browser/ui/browser_commands.h"
42 #include "chrome/browser/ui/browser_finder.h"
43 #include "chrome/browser/ui/browser_iterator.h"
44 #include "chrome/browser/ui/browser_list.h"
45 #include "chrome/browser/ui/browser_navigator.h"
46 #include "chrome/browser/ui/browser_window.h"
47 #include "chrome/browser/ui/find_bar/find_notification_details.h"
48 #include "chrome/browser/ui/find_bar/find_tab_helper.h"
49 #include "chrome/browser/ui/host_desktop.h"
50 #include "chrome/browser/ui/omnibox/location_bar.h"
51 #include "chrome/browser/ui/omnibox/omnibox_view.h"
52 #include "chrome/browser/ui/tabs/tab_strip_model.h"
53 #include "chrome/common/chrome_paths.h"
54 #include "chrome/common/pref_names.h"
55 #include "chrome/test/base/find_in_page_observer.h"
56 #include "content/public/browser/browser_thread.h"
57 #include "content/public/browser/dom_operation_notification_details.h"
58 #include "content/public/browser/download_item.h"
59 #include "content/public/browser/download_manager.h"
60 #include "content/public/browser/geolocation_provider.h"
61 #include "content/public/browser/navigation_controller.h"
62 #include "content/public/browser/navigation_entry.h"
63 #include "content/public/browser/notification_service.h"
64 #include "content/public/browser/render_process_host.h"
65 #include "content/public/browser/render_view_host.h"
66 #include "content/public/browser/web_contents.h"
67 #include "content/public/browser/web_contents_observer.h"
68 #include "content/public/browser/web_contents_view.h"
69 #include "content/public/common/geoposition.h"
70 #include "content/public/test/browser_test_utils.h"
71 #include "content/public/test/download_test_observer.h"
72 #include "content/public/test/test_navigation_observer.h"
73 #include "content/public/test/test_utils.h"
74 #include "net/base/net_util.h"
75 #include "net/test/python_utils.h"
76 #include "third_party/skia/include/core/SkBitmap.h"
77 #include "third_party/skia/include/core/SkColor.h"
78 #include "ui/gfx/size.h"
79 #include "ui/snapshot/test/snapshot_desktop.h"
80 
81 #if defined(USE_AURA)
82 #include "ash/shell.h"
83 #include "ui/aura/root_window.h"
84 #endif
85 
86 using content::BrowserThread;
87 using content::DomOperationNotificationDetails;
88 using content::NativeWebKeyboardEvent;
89 using content::NavigationController;
90 using content::NavigationEntry;
91 using content::OpenURLParams;
92 using content::RenderViewHost;
93 using content::RenderWidgetHost;
94 using content::Referrer;
95 using content::WebContents;
96 
97 namespace ui_test_utils {
98 
99 namespace {
100 
101 #if defined(OS_WIN)
102 const char kSnapshotBaseName[] = "ChromiumSnapshot";
103 const char kSnapshotExtension[] = ".png";
104 
GetSnapshotFileName(const base::FilePath & snapshot_directory)105 base::FilePath GetSnapshotFileName(const base::FilePath& snapshot_directory) {
106   base::Time::Exploded the_time;
107 
108   base::Time::Now().LocalExplode(&the_time);
109   std::string filename(base::StringPrintf("%s%04d%02d%02d%02d%02d%02d%s",
110       kSnapshotBaseName, the_time.year, the_time.month, the_time.day_of_month,
111       the_time.hour, the_time.minute, the_time.second, kSnapshotExtension));
112 
113   base::FilePath snapshot_file = snapshot_directory.AppendASCII(filename);
114   if (base::PathExists(snapshot_file)) {
115     int index = 0;
116     std::string suffix;
117     base::FilePath trial_file;
118     do {
119       suffix = base::StringPrintf(" (%d)", ++index);
120       trial_file = snapshot_file.InsertBeforeExtensionASCII(suffix);
121     } while (base::PathExists(trial_file));
122     snapshot_file = trial_file;
123   }
124   return snapshot_file;
125 }
126 #endif  // defined(OS_WIN)
127 
WaitForBrowserNotInSet(std::set<Browser * > excluded_browsers)128 Browser* WaitForBrowserNotInSet(std::set<Browser*> excluded_browsers) {
129   Browser* new_browser = GetBrowserNotInSet(excluded_browsers);
130   if (new_browser == NULL) {
131     BrowserAddedObserver observer;
132     new_browser = observer.WaitForSingleNewBrowser();
133     // The new browser should never be in |excluded_browsers|.
134     DCHECK(!ContainsKey(excluded_browsers, new_browser));
135   }
136   return new_browser;
137 }
138 
139 }  // namespace
140 
GetCurrentTabTitle(const Browser * browser,string16 * title)141 bool GetCurrentTabTitle(const Browser* browser, string16* title) {
142   WebContents* web_contents =
143       browser->tab_strip_model()->GetActiveWebContents();
144   if (!web_contents)
145     return false;
146   NavigationEntry* last_entry = web_contents->GetController().GetActiveEntry();
147   if (!last_entry)
148     return false;
149   title->assign(last_entry->GetTitleForDisplay(std::string()));
150   return true;
151 }
152 
OpenURLOffTheRecord(Profile * profile,const GURL & url)153 Browser* OpenURLOffTheRecord(Profile* profile, const GURL& url) {
154   chrome::HostDesktopType active_desktop = chrome::GetActiveDesktop();
155   chrome::OpenURLOffTheRecord(profile, url, active_desktop);
156   Browser* browser = chrome::FindTabbedBrowser(
157       profile->GetOffTheRecordProfile(), false, active_desktop);
158   content::TestNavigationObserver observer(
159       browser->tab_strip_model()->GetActiveWebContents());
160   observer.Wait();
161   return browser;
162 }
163 
NavigateToURL(chrome::NavigateParams * params)164 void NavigateToURL(chrome::NavigateParams* params) {
165   chrome::Navigate(params);
166   content::WaitForLoadStop(params->target_contents);
167 }
168 
169 
NavigateToURLWithPost(Browser * browser,const GURL & url)170 void NavigateToURLWithPost(Browser* browser, const GURL& url) {
171   chrome::NavigateParams params(browser, url,
172                                 content::PAGE_TRANSITION_FORM_SUBMIT);
173   params.uses_post = true;
174   NavigateToURL(&params);
175 }
176 
NavigateToURL(Browser * browser,const GURL & url)177 void NavigateToURL(Browser* browser, const GURL& url) {
178   NavigateToURLWithDisposition(browser, url, CURRENT_TAB,
179                                BROWSER_TEST_WAIT_FOR_NAVIGATION);
180 }
181 
182 // Navigates the specified tab (via |disposition|) of |browser| to |url|,
183 // blocking until the |number_of_navigations| specified complete.
184 // |disposition| indicates what tab the download occurs in, and
185 // |browser_test_flags| controls what to wait for before continuing.
NavigateToURLWithDispositionBlockUntilNavigationsComplete(Browser * browser,const GURL & url,int number_of_navigations,WindowOpenDisposition disposition,int browser_test_flags)186 static void NavigateToURLWithDispositionBlockUntilNavigationsComplete(
187     Browser* browser,
188     const GURL& url,
189     int number_of_navigations,
190     WindowOpenDisposition disposition,
191     int browser_test_flags) {
192   TabStripModel* tab_strip = browser->tab_strip_model();
193   if (disposition == CURRENT_TAB && tab_strip->GetActiveWebContents())
194       content::WaitForLoadStop(tab_strip->GetActiveWebContents());
195   content::TestNavigationObserver same_tab_observer(
196       tab_strip->GetActiveWebContents(),
197       number_of_navigations);
198 
199   std::set<Browser*> initial_browsers;
200   for (chrome::BrowserIterator it; !it.done(); it.Next())
201     initial_browsers.insert(*it);
202 
203   content::WindowedNotificationObserver tab_added_observer(
204       chrome::NOTIFICATION_TAB_ADDED,
205       content::NotificationService::AllSources());
206 
207   browser->OpenURL(OpenURLParams(
208       url, Referrer(), disposition, content::PAGE_TRANSITION_TYPED, false));
209   if (browser_test_flags & BROWSER_TEST_WAIT_FOR_BROWSER)
210     browser = WaitForBrowserNotInSet(initial_browsers);
211   if (browser_test_flags & BROWSER_TEST_WAIT_FOR_TAB)
212     tab_added_observer.Wait();
213   if (!(browser_test_flags & BROWSER_TEST_WAIT_FOR_NAVIGATION)) {
214     // Some other flag caused the wait prior to this.
215     return;
216   }
217   WebContents* web_contents = NULL;
218   if (disposition == NEW_BACKGROUND_TAB) {
219     // We've opened up a new tab, but not selected it.
220     TabStripModel* tab_strip = browser->tab_strip_model();
221     web_contents = tab_strip->GetWebContentsAt(tab_strip->active_index() + 1);
222     EXPECT_TRUE(web_contents != NULL)
223         << " Unable to wait for navigation to \"" << url.spec()
224         << "\" because the new tab is not available yet";
225     if (!web_contents)
226       return;
227   } else if ((disposition == CURRENT_TAB) ||
228       (disposition == NEW_FOREGROUND_TAB) ||
229       (disposition == SINGLETON_TAB)) {
230     // The currently selected tab is the right one.
231     web_contents = browser->tab_strip_model()->GetActiveWebContents();
232   }
233   if (disposition == CURRENT_TAB) {
234     same_tab_observer.Wait();
235     return;
236   } else if (web_contents) {
237     content::TestNavigationObserver observer(web_contents,
238                                              number_of_navigations);
239     observer.Wait();
240     return;
241   }
242   EXPECT_TRUE(NULL != web_contents) << " Unable to wait for navigation to \""
243                                     << url.spec() << "\""
244                                     << " because we can't get the tab contents";
245 }
246 
NavigateToURLWithDisposition(Browser * browser,const GURL & url,WindowOpenDisposition disposition,int browser_test_flags)247 void NavigateToURLWithDisposition(Browser* browser,
248                                   const GURL& url,
249                                   WindowOpenDisposition disposition,
250                                   int browser_test_flags) {
251   NavigateToURLWithDispositionBlockUntilNavigationsComplete(
252       browser,
253       url,
254       1,
255       disposition,
256       browser_test_flags);
257 }
258 
NavigateToURLBlockUntilNavigationsComplete(Browser * browser,const GURL & url,int number_of_navigations)259 void NavigateToURLBlockUntilNavigationsComplete(Browser* browser,
260                                                 const GURL& url,
261                                                 int number_of_navigations) {
262   NavigateToURLWithDispositionBlockUntilNavigationsComplete(
263       browser,
264       url,
265       number_of_navigations,
266       CURRENT_TAB,
267       BROWSER_TEST_WAIT_FOR_NAVIGATION);
268 }
269 
GetTestFilePath(const base::FilePath & dir,const base::FilePath & file)270 base::FilePath GetTestFilePath(const base::FilePath& dir,
271                                const base::FilePath& file) {
272   base::FilePath path;
273   PathService::Get(chrome::DIR_TEST_DATA, &path);
274   return path.Append(dir).Append(file);
275 }
276 
GetTestUrl(const base::FilePath & dir,const base::FilePath & file)277 GURL GetTestUrl(const base::FilePath& dir, const base::FilePath& file) {
278   return net::FilePathToFileURL(GetTestFilePath(dir, file));
279 }
280 
GetRelativeBuildDirectory(base::FilePath * build_dir)281 bool GetRelativeBuildDirectory(base::FilePath* build_dir) {
282   // This function is used to find the build directory so TestServer can serve
283   // built files (nexes, etc).  TestServer expects a path relative to the source
284   // root.
285   base::FilePath exe_dir =
286       CommandLine::ForCurrentProcess()->GetProgram().DirName();
287   base::FilePath src_dir;
288   if (!PathService::Get(base::DIR_SOURCE_ROOT, &src_dir))
289     return false;
290 
291   // We must first generate absolute paths to SRC and EXE and from there
292   // generate a relative path.
293   if (!exe_dir.IsAbsolute())
294     exe_dir = base::MakeAbsoluteFilePath(exe_dir);
295   if (!src_dir.IsAbsolute())
296     src_dir = base::MakeAbsoluteFilePath(src_dir);
297   if (!exe_dir.IsAbsolute())
298     return false;
299   if (!src_dir.IsAbsolute())
300     return false;
301 
302   size_t match, exe_size, src_size;
303   std::vector<base::FilePath::StringType> src_parts, exe_parts;
304 
305   // Determine point at which src and exe diverge.
306   exe_dir.GetComponents(&exe_parts);
307   src_dir.GetComponents(&src_parts);
308   exe_size = exe_parts.size();
309   src_size = src_parts.size();
310   for (match = 0; match < exe_size && match < src_size; ++match) {
311     if (exe_parts[match] != src_parts[match])
312       break;
313   }
314 
315   // Create a relative path.
316   *build_dir = base::FilePath();
317   for (size_t tmp_itr = match; tmp_itr < src_size; ++tmp_itr)
318     *build_dir = build_dir->Append(FILE_PATH_LITERAL(".."));
319   for (; match < exe_size; ++match)
320     *build_dir = build_dir->Append(exe_parts[match]);
321   return true;
322 }
323 
WaitForAppModalDialog()324 AppModalDialog* WaitForAppModalDialog() {
325   AppModalDialogQueue* dialog_queue = AppModalDialogQueue::GetInstance();
326   if (dialog_queue->HasActiveDialog())
327     return dialog_queue->active_dialog();
328 
329   content::WindowedNotificationObserver observer(
330       chrome::NOTIFICATION_APP_MODAL_DIALOG_SHOWN,
331       content::NotificationService::AllSources());
332   observer.Wait();
333   return content::Source<AppModalDialog>(observer.source()).ptr();
334 }
335 
FindInPage(WebContents * tab,const string16 & search_string,bool forward,bool match_case,int * ordinal,gfx::Rect * selection_rect)336 int FindInPage(WebContents* tab, const string16& search_string,
337                bool forward, bool match_case, int* ordinal,
338                gfx::Rect* selection_rect) {
339   FindTabHelper* find_tab_helper = FindTabHelper::FromWebContents(tab);
340   find_tab_helper->StartFinding(search_string, forward, match_case);
341   FindInPageNotificationObserver observer(tab);
342   observer.Wait();
343   if (ordinal)
344     *ordinal = observer.active_match_ordinal();
345   if (selection_rect)
346     *selection_rect = observer.selection_rect();
347   return observer.number_of_matches();
348 }
349 
WaitForTemplateURLServiceToLoad(TemplateURLService * service)350 void WaitForTemplateURLServiceToLoad(TemplateURLService* service) {
351   if (service->loaded())
352     return;
353   scoped_refptr<content::MessageLoopRunner> message_loop_runner =
354       new content::MessageLoopRunner;
355   scoped_ptr<TemplateURLService::Subscription> subscription =
356       service->RegisterOnLoadedCallback(
357           message_loop_runner->QuitClosure());
358   service->Load();
359   message_loop_runner->Run();
360 
361   ASSERT_TRUE(service->loaded());
362 }
363 
WaitForHistoryToLoad(HistoryService * history_service)364 void WaitForHistoryToLoad(HistoryService* history_service) {
365   content::WindowedNotificationObserver history_loaded_observer(
366       chrome::NOTIFICATION_HISTORY_LOADED,
367       content::NotificationService::AllSources());
368   if (!history_service->BackendLoaded())
369     history_loaded_observer.Wait();
370 }
371 
DownloadURL(Browser * browser,const GURL & download_url)372 void DownloadURL(Browser* browser, const GURL& download_url) {
373   base::ScopedTempDir downloads_directory;
374   ASSERT_TRUE(downloads_directory.CreateUniqueTempDir());
375   browser->profile()->GetPrefs()->SetFilePath(
376       prefs::kDownloadDefaultDirectory, downloads_directory.path());
377 
378   content::DownloadManager* download_manager =
379       content::BrowserContext::GetDownloadManager(browser->profile());
380   scoped_ptr<content::DownloadTestObserver> observer(
381       new content::DownloadTestObserverTerminal(
382           download_manager, 1,
383           content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_ACCEPT));
384 
385   ui_test_utils::NavigateToURL(browser, download_url);
386   observer->WaitForFinished();
387 }
388 
SendToOmniboxAndSubmit(LocationBar * location_bar,const std::string & input)389 void SendToOmniboxAndSubmit(LocationBar* location_bar,
390                             const std::string& input) {
391   OmniboxView* omnibox = location_bar->GetOmniboxView();
392   omnibox->model()->OnSetFocus(false);
393   omnibox->SetUserText(ASCIIToUTF16(input));
394   location_bar->AcceptInput();
395   while (!omnibox->model()->autocomplete_controller()->done()) {
396     content::WindowedNotificationObserver observer(
397         chrome::NOTIFICATION_AUTOCOMPLETE_CONTROLLER_RESULT_READY,
398         content::NotificationService::AllSources());
399     observer.Wait();
400   }
401 }
402 
GetBrowserNotInSet(std::set<Browser * > excluded_browsers)403 Browser* GetBrowserNotInSet(std::set<Browser*> excluded_browsers) {
404   for (chrome::BrowserIterator it; !it.done(); it.Next()) {
405     if (excluded_browsers.find(*it) == excluded_browsers.end())
406       return *it;
407   }
408   return NULL;
409 }
410 
WindowedTabAddedNotificationObserver(const content::NotificationSource & source)411 WindowedTabAddedNotificationObserver::WindowedTabAddedNotificationObserver(
412     const content::NotificationSource& source)
413     : WindowedNotificationObserver(chrome::NOTIFICATION_TAB_ADDED, source),
414       added_tab_(NULL) {
415 }
416 
Observe(int type,const content::NotificationSource & source,const content::NotificationDetails & details)417 void WindowedTabAddedNotificationObserver::Observe(
418     int type,
419     const content::NotificationSource& source,
420     const content::NotificationDetails& details) {
421   added_tab_ = content::Details<WebContents>(details).ptr();
422   content::WindowedNotificationObserver::Observe(type, source, details);
423 }
424 
UrlLoadObserver(const GURL & url,const content::NotificationSource & source)425 UrlLoadObserver::UrlLoadObserver(const GURL& url,
426                                  const content::NotificationSource& source)
427     : WindowedNotificationObserver(content::NOTIFICATION_LOAD_STOP, source),
428       url_(url) {
429 }
430 
~UrlLoadObserver()431 UrlLoadObserver::~UrlLoadObserver() {}
432 
Observe(int type,const content::NotificationSource & source,const content::NotificationDetails & details)433 void UrlLoadObserver::Observe(
434     int type,
435     const content::NotificationSource& source,
436     const content::NotificationDetails& details) {
437   NavigationController* controller =
438       content::Source<NavigationController>(source).ptr();
439   if (controller->GetWebContents()->GetURL() != url_)
440     return;
441 
442   WindowedNotificationObserver::Observe(type, source, details);
443 }
444 
BrowserAddedObserver()445 BrowserAddedObserver::BrowserAddedObserver()
446     : notification_observer_(
447           chrome::NOTIFICATION_BROWSER_OPENED,
448           content::NotificationService::AllSources()) {
449   for (chrome::BrowserIterator it; !it.done(); it.Next())
450     original_browsers_.insert(*it);
451 }
452 
~BrowserAddedObserver()453 BrowserAddedObserver::~BrowserAddedObserver() {
454 }
455 
WaitForSingleNewBrowser()456 Browser* BrowserAddedObserver::WaitForSingleNewBrowser() {
457   notification_observer_.Wait();
458   // Ensure that only a single new browser has appeared.
459   EXPECT_EQ(original_browsers_.size() + 1, chrome::GetTotalBrowserCount());
460   return GetBrowserNotInSet(original_browsers_);
461 }
462 
463 #if defined(OS_WIN)
464 
SaveScreenSnapshotToDirectory(const base::FilePath & directory,base::FilePath * screenshot_path)465 bool SaveScreenSnapshotToDirectory(const base::FilePath& directory,
466                                    base::FilePath* screenshot_path) {
467   bool succeeded = false;
468   base::FilePath out_path(GetSnapshotFileName(directory));
469 
470   MONITORINFO monitor_info = {};
471   monitor_info.cbSize = sizeof(monitor_info);
472   HMONITOR main_monitor = MonitorFromWindow(NULL, MONITOR_DEFAULTTOPRIMARY);
473   if (GetMonitorInfo(main_monitor, &monitor_info)) {
474     RECT& rect = monitor_info.rcMonitor;
475 
476     std::vector<unsigned char> png_data;
477     gfx::Rect bounds(
478         gfx::Size(rect.right - rect.left, rect.bottom - rect.top));
479     if (ui::GrabDesktopSnapshot(bounds, &png_data) &&
480         png_data.size() <= INT_MAX) {
481       int bytes = static_cast<int>(png_data.size());
482       int written = file_util::WriteFile(
483           out_path, reinterpret_cast<char*>(&png_data[0]), bytes);
484       succeeded = (written == bytes);
485     }
486   }
487 
488   if (succeeded && screenshot_path != NULL)
489     *screenshot_path = out_path;
490 
491   return succeeded;
492 }
493 
SaveScreenSnapshotToDesktop(base::FilePath * screenshot_path)494 bool SaveScreenSnapshotToDesktop(base::FilePath* screenshot_path) {
495   base::FilePath desktop;
496 
497   return PathService::Get(base::DIR_USER_DESKTOP, &desktop) &&
498       SaveScreenSnapshotToDirectory(desktop, screenshot_path);
499 }
500 
501 #endif  // defined(OS_WIN)
502 
OverrideGeolocation(double latitude,double longitude)503 void OverrideGeolocation(double latitude, double longitude) {
504   content::Geoposition position;
505   position.latitude = latitude;
506   position.longitude = longitude;
507   position.altitude = 0.;
508   position.accuracy = 0.;
509   position.timestamp = base::Time::Now();
510   scoped_refptr<content::MessageLoopRunner> runner =
511       new content::MessageLoopRunner;
512 
513   content::GeolocationProvider::OverrideLocationForTesting(
514       position, runner->QuitClosure());
515 
516   runner->Run();
517 }
518 
HistoryEnumerator(Profile * profile)519 HistoryEnumerator::HistoryEnumerator(Profile* profile) {
520   scoped_refptr<content::MessageLoopRunner> message_loop_runner =
521       new content::MessageLoopRunner;
522 
523   HistoryService* hs = HistoryServiceFactory::GetForProfile(
524       profile, Profile::EXPLICIT_ACCESS);
525   hs->QueryHistory(
526       string16(),
527       history::QueryOptions(),
528       &consumer_,
529       base::Bind(&HistoryEnumerator::HistoryQueryComplete,
530                  base::Unretained(this), message_loop_runner->QuitClosure()));
531   message_loop_runner->Run();
532 }
533 
~HistoryEnumerator()534 HistoryEnumerator::~HistoryEnumerator() {}
535 
HistoryQueryComplete(const base::Closure & quit_task,HistoryService::Handle request_handle,history::QueryResults * results)536 void HistoryEnumerator::HistoryQueryComplete(
537     const base::Closure& quit_task,
538     HistoryService::Handle request_handle,
539     history::QueryResults* results) {
540   for (size_t i = 0; i < results->size(); ++i)
541     urls_.push_back((*results)[i].url());
542   quit_task.Run();
543 }
544 
545 }  // namespace ui_test_utils
546