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