ui_test_utils.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/base/ui_test_utils.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_path.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_reader.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/message_loop.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/test/test_timeouts.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/time.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/utf_string_conversions.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/autocomplete/autocomplete_controller.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/bookmarks/bookmark_model.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/browser_process.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_action.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/history_service_factory.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/prefs/pref_service.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/search_engines/template_url_service.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/search_engines/template_url_service_test_util.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/thumbnails/render_widget_snapshot_taker.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_commands.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_finder.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_list.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_navigator.h"
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_tabstrip.h"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_window.h"
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/find_bar/find_notification_details.h"
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/find_bar/find_tab_helper.h"
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/host_desktop.h"
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/omnibox/location_bar.h"
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/omnibox/omnibox_view.h"
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_notification_types.h"
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_paths.h"
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h"
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/base/bookmark_load_observer.h"
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/dom_operation_notification_details.h"
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/download_item.h"
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/download_manager.h"
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/geolocation.h"
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/navigation_controller.h"
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/navigation_entry.h"
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h"
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_process_host.h"
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_view_host.h"
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h"
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents_observer.h"
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents_view.h"
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/geoposition.h"
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/test/browser_test_utils.h"
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/test/download_test_observer.h"
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/test/test_navigation_observer.h"
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/test/test_utils.h"
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h"
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/test/python_utils.h"
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h"
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkColor.h"
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/size.h"
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/ui_controls/ui_controls.h"
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_AURA)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/shell.h"
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/root_window.h"
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::DomOperationNotificationDetails;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::NativeWebKeyboardEvent;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::NavigationController;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::NavigationEntry;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::OpenURLParams;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::RenderViewHost;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::RenderWidgetHost;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::Referrer;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebContents;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ui_test_utils {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class FindInPageNotificationObserver : public content::NotificationObserver {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit FindInPageNotificationObserver(WebContents* parent_tab)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : active_match_ordinal_(-1),
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        number_of_matches_(0) {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FindTabHelper* find_tab_helper =
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FindTabHelper::FromWebContents(parent_tab);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    current_find_request_id_ = find_tab_helper->current_find_request_id();
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    registrar_.Add(this, chrome::NOTIFICATION_FIND_RESULT_AVAILABLE,
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   content::Source<WebContents>(parent_tab));
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    message_loop_runner_ = new content::MessageLoopRunner;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    message_loop_runner_->Run();
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int active_match_ordinal() const { return active_match_ordinal_; }
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int number_of_matches() const { return number_of_matches_; }
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect selection_rect() const { return selection_rect_; }
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Observe(int type, const content::NotificationSource& source,
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const content::NotificationDetails& details) {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (type == chrome::NOTIFICATION_FIND_RESULT_AVAILABLE) {
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::Details<FindNotificationDetails> find_details(details);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (find_details->request_id() == current_find_request_id_) {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // We get multiple responses and one of those will contain the ordinal.
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // This message comes to us before the final update is sent.
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (find_details->active_match_ordinal() > -1) {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          active_match_ordinal_ = find_details->active_match_ordinal();
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          selection_rect_ = find_details->selection_rect();
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (find_details->final_update()) {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          number_of_matches_ = find_details->number_of_matches();
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          message_loop_runner_->Quit();
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          DVLOG(1) << "Ignoring, since we only care about the final message";
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::NotificationRegistrar registrar_;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We will at some point (before final update) be notified of the ordinal and
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we need to preserve it so we can send it later.
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int active_match_ordinal_;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int number_of_matches_;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect selection_rect_;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The id of the current find request, obtained from WebContents. Allows us
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to monitor when the search completes.
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int current_find_request_id_;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(FindInPageNotificationObserver);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetCurrentTabTitle(const Browser* browser, string16* title) {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebContents* web_contents = chrome::GetActiveWebContents(browser);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!web_contents)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NavigationEntry* last_entry = web_contents->GetController().GetActiveEntry();
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!last_entry)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  title->assign(last_entry->GetTitleForDisplay(""));
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WaitForNavigations(NavigationController* controller,
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        int number_of_navigations) {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::TestNavigationObserver observer(
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::Source<NavigationController>(controller), NULL,
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      number_of_navigations);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::RunLoop run_loop;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observer.WaitForObservation(
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&content::RunThisRunLoop, base::Unretained(&run_loop)),
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::GetQuitTaskForRunLoop(&run_loop));
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WaitForNewTab(Browser* browser) {
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::WindowedNotificationObserver observer(
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      chrome::NOTIFICATION_TAB_ADDED,
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::Source<content::WebContentsDelegate>(browser));
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observer.Wait();
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Browser* WaitForBrowserNotInSet(std::set<Browser*> excluded_browsers) {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Browser* new_browser = GetBrowserNotInSet(excluded_browsers);
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (new_browser == NULL) {
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserAddedObserver observer;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    new_browser = observer.WaitForSingleNewBrowser();
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The new browser should never be in |excluded_browsers|.
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!ContainsKey(excluded_browsers, new_browser));
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new_browser;
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Browser* OpenURLOffTheRecord(Profile* profile, const GURL& url) {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  chrome::OpenURLOffTheRecord(profile, url, chrome::HOST_DESKTOP_TYPE_NATIVE);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Browser* browser = browser::FindTabbedBrowser(
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      profile->GetOffTheRecordProfile(),
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      false,
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      chrome::HOST_DESKTOP_TYPE_NATIVE);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForNavigations(&chrome::GetActiveWebContents(browser)->GetController(),
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     1);
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return browser;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NavigateToURL(chrome::NavigateParams* params) {
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::TestNavigationObserver observer(
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::NotificationService::AllSources(), NULL, 1);
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  chrome::Navigate(params);
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::RunLoop run_loop;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observer.WaitForObservation(
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&content::RunThisRunLoop, base::Unretained(&run_loop)),
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::GetQuitTaskForRunLoop(&run_loop));
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NavigateToURL(Browser* browser, const GURL& url) {
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NavigateToURLWithDisposition(browser, url, CURRENT_TAB,
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               BROWSER_TEST_WAIT_FOR_NAVIGATION);
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Navigates the specified tab (via |disposition|) of |browser| to |url|,
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// blocking until the |number_of_navigations| specified complete.
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |disposition| indicates what tab the download occurs in, and
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |browser_test_flags| controls what to wait for before continuing.
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void NavigateToURLWithDispositionBlockUntilNavigationsComplete(
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Browser* browser,
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& url,
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int number_of_navigations,
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WindowOpenDisposition disposition,
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int browser_test_flags) {
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (disposition == CURRENT_TAB && chrome::GetActiveWebContents(browser))
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::WaitForLoadStop(chrome::GetActiveWebContents(browser));
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NavigationController* controller =
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      chrome::GetActiveWebContents(browser) ?
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &chrome::GetActiveWebContents(browser)->GetController() : NULL;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::TestNavigationObserver same_tab_observer(
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::Source<NavigationController>(controller),
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NULL,
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      number_of_navigations);
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set<Browser*> initial_browsers;
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::vector<Browser*>::const_iterator iter = BrowserList::begin();
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != BrowserList::end();
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++iter) {
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    initial_browsers.insert(*iter);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::WindowedNotificationObserver tab_added_observer(
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      chrome::NOTIFICATION_TAB_ADDED,
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::NotificationService::AllSources());
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  browser->OpenURL(OpenURLParams(
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      url, Referrer(), disposition, content::PAGE_TRANSITION_TYPED, false));
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (browser_test_flags & BROWSER_TEST_WAIT_FOR_BROWSER)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    browser = WaitForBrowserNotInSet(initial_browsers);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (browser_test_flags & BROWSER_TEST_WAIT_FOR_TAB)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tab_added_observer.Wait();
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!(browser_test_flags & BROWSER_TEST_WAIT_FOR_NAVIGATION)) {
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Some other flag caused the wait prior to this.
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebContents* web_contents = NULL;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (disposition == NEW_BACKGROUND_TAB) {
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We've opened up a new tab, but not selected it.
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    web_contents =
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        chrome::GetWebContentsAt(browser, browser->active_index() + 1);
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(web_contents != NULL)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << " Unable to wait for navigation to \"" << url.spec()
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << "\" because the new tab is not available yet";
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!web_contents)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if ((disposition == CURRENT_TAB) ||
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (disposition == NEW_FOREGROUND_TAB) ||
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (disposition == SINGLETON_TAB)) {
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The currently selected tab is the right one.
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    web_contents = chrome::GetActiveWebContents(browser);
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (disposition == CURRENT_TAB) {
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::RunLoop run_loop;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    same_tab_observer.WaitForObservation(
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&content::RunThisRunLoop, base::Unretained(&run_loop)),
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        content::GetQuitTaskForRunLoop(&run_loop));
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (web_contents) {
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NavigationController* controller = &web_contents->GetController();
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WaitForNavigations(controller, number_of_navigations);
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(NULL != web_contents) << " Unable to wait for navigation to \""
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    << url.spec() << "\""
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    << " because we can't get the tab contents";
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NavigateToURLWithDisposition(Browser* browser,
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  const GURL& url,
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  WindowOpenDisposition disposition,
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  int browser_test_flags) {
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NavigateToURLWithDispositionBlockUntilNavigationsComplete(
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      browser,
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      url,
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      1,
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      disposition,
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      browser_test_flags);
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NavigateToURLBlockUntilNavigationsComplete(Browser* browser,
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                const GURL& url,
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                int number_of_navigations) {
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NavigateToURLWithDispositionBlockUntilNavigationsComplete(
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      browser,
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      url,
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      number_of_navigations,
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CURRENT_TAB,
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BROWSER_TEST_WAIT_FOR_NAVIGATION);
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FilePath GetTestFilePath(const FilePath& dir, const FilePath& file) {
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FilePath path;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PathService::Get(chrome::DIR_TEST_DATA, &path);
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return path.Append(dir).Append(file);
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GURL GetTestUrl(const FilePath& dir, const FilePath& file) {
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return net::FilePathToFileURL(GetTestFilePath(dir, file));
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetRelativeBuildDirectory(FilePath* build_dir) {
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This function is used to find the build directory so TestServer can serve
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // built files (nexes, etc).  TestServer expects a path relative to the source
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // root.
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FilePath exe_dir = CommandLine::ForCurrentProcess()->GetProgram().DirName();
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FilePath src_dir;
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!PathService::Get(base::DIR_SOURCE_ROOT, &src_dir))
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We must first generate absolute paths to SRC and EXE and from there
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // generate a relative path.
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!exe_dir.IsAbsolute())
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file_util::AbsolutePath(&exe_dir);
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!src_dir.IsAbsolute())
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file_util::AbsolutePath(&src_dir);
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!exe_dir.IsAbsolute())
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!src_dir.IsAbsolute())
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t match, exe_size, src_size;
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<FilePath::StringType> src_parts, exe_parts;
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Determine point at which src and exe diverge.
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  exe_dir.GetComponents(&exe_parts);
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  src_dir.GetComponents(&src_parts);
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  exe_size = exe_parts.size();
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  src_size = src_parts.size();
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (match = 0; match < exe_size && match < src_size; ++match) {
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (exe_parts[match] != src_parts[match])
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a relative path.
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *build_dir = FilePath();
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t tmp_itr = match; tmp_itr < src_size; ++tmp_itr)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *build_dir = build_dir->Append(FILE_PATH_LITERAL(".."));
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (; match < exe_size; ++match)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *build_dir = build_dir->Append(exe_parts[match]);
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AppModalDialog* WaitForAppModalDialog() {
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::WindowedNotificationObserver observer(
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      chrome::NOTIFICATION_APP_MODAL_DIALOG_SHOWN,
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::NotificationService::AllSources());
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observer.Wait();
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return content::Source<AppModalDialog>(observer.source()).ptr();
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int FindInPage(WebContents* tab, const string16& search_string,
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               bool forward, bool match_case, int* ordinal,
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               gfx::Rect* selection_rect) {
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FindTabHelper* find_tab_helper = FindTabHelper::FromWebContents(tab);
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  find_tab_helper->StartFinding(search_string, forward, match_case);
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FindInPageNotificationObserver observer(tab);
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ordinal)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *ordinal = observer.active_match_ordinal();
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (selection_rect)
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *selection_rect = observer.selection_rect();
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return observer.number_of_matches();
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RegisterAndWait(content::NotificationObserver* observer,
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     int type,
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     const content::NotificationSource& source) {
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::NotificationRegistrar registrar;
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar.Add(observer, type, source);
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::RunMessageLoop();
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WaitForBookmarkModelToLoad(BookmarkModel* model) {
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (model->IsLoaded())
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::RunLoop run_loop;
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BookmarkLoadObserver observer(content::GetQuitTaskForRunLoop(&run_loop));
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  model->AddObserver(&observer);
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::RunThisRunLoop(&run_loop);
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  model->RemoveObserver(&observer);
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(model->IsLoaded());
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WaitForTemplateURLServiceToLoad(TemplateURLService* service) {
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (service->loaded())
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  service->Load();
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TemplateURLServiceTestUtil::BlockTillServiceProcessesRequests();
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(service->loaded());
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WaitForHistoryToLoad(HistoryService* history_service) {
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::WindowedNotificationObserver history_loaded_observer(
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      chrome::NOTIFICATION_HISTORY_LOADED,
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::NotificationService::AllSources());
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!history_service->BackendLoaded())
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    history_loaded_observer.Wait();
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DownloadURL(Browser* browser, const GURL& download_url) {
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedTempDir downloads_directory;
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(downloads_directory.CreateUniqueTempDir());
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  browser->profile()->GetPrefs()->SetFilePath(
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      prefs::kDownloadDefaultDirectory, downloads_directory.path());
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::DownloadManager* download_manager =
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::BrowserContext::GetDownloadManager(browser->profile());
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<content::DownloadTestObserver> observer(
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new content::DownloadTestObserverTerminal(
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          download_manager, 1,
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_ACCEPT));
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ui_test_utils::NavigateToURL(browser, download_url);
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observer->WaitForFinished();
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SendToOmniboxAndSubmit(LocationBar* location_bar,
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const std::string& input) {
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OmniboxView* omnibox = location_bar->GetLocationEntry();
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  omnibox->model()->OnSetFocus(false);
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  omnibox->SetUserText(ASCIIToUTF16(input));
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  location_bar->AcceptInput();
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (!omnibox->model()->autocomplete_controller()->done()) {
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::WindowedNotificationObserver observer(
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        chrome::NOTIFICATION_AUTOCOMPLETE_CONTROLLER_RESULT_READY,
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        content::NotificationService::AllSources());
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    observer.Wait();
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetNativeWindow(const Browser* browser, gfx::NativeWindow* native_window) {
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserWindow* window = browser->window();
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!window)
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *native_window = window->GetNativeWindow();
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return *native_window;
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BringBrowserWindowToFront(const Browser* browser) {
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::NativeWindow window = NULL;
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!GetNativeWindow(browser, &window))
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ui_test_utils::ShowAndFocusNativeWindow(window);
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Browser* GetBrowserNotInSet(std::set<Browser*> excluded_browsers) {
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (BrowserList::const_iterator iter = BrowserList::begin();
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != BrowserList::end();
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++iter) {
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (excluded_browsers.find(*iter) == excluded_browsers.end())
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return *iter;
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SendKeyPressSync(const Browser* browser,
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      ui::KeyboardCode key,
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      bool control,
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      bool shift,
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      bool alt,
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      bool command) {
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::NativeWindow window = NULL;
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!GetNativeWindow(browser, &window))
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<content::MessageLoopRunner> runner =
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new content::MessageLoopRunner;
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool result;
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = ui_controls::SendKeyPressNotifyWhenDone(
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      window, key, control, shift, alt, command, runner->QuitClosure());
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!result && BringBrowserWindowToFront(browser)) {
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = ui_controls::SendKeyPressNotifyWhenDone(
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        window, key, control, shift, alt, command, runner->QuitClosure());
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!result) {
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "ui_controls::SendKeyPressNotifyWhenDone failed";
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Run the message loop. It'll stop running when either the key was received
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // or the test timed out (in which case testing::Test::HasFatalFailure should
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // be set).
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  runner->Run();
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !testing::Test::HasFatalFailure();
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SendKeyPressAndWait(const Browser* browser,
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         ui::KeyboardCode key,
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         bool control,
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         bool shift,
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         bool alt,
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         bool command,
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         int type,
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         const content::NotificationSource& source) {
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::WindowedNotificationObserver observer(type, source);
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!SendKeyPressSync(browser, key, control, shift, alt, command))
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observer.Wait();
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !testing::Test::HasFatalFailure();
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SendMouseMoveSync(const gfx::Point& location) {
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<content::MessageLoopRunner> runner =
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new content::MessageLoopRunner;
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ui_controls::SendMouseMoveNotifyWhenDone(
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          location.x(), location.y(), runner->QuitClosure())) {
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  runner->Run();
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !testing::Test::HasFatalFailure();
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SendMouseEventsSync(ui_controls::MouseButton type, int state) {
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<content::MessageLoopRunner> runner =
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new content::MessageLoopRunner;
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ui_controls::SendMouseEventsNotifyWhenDone(
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          type, state, runner->QuitClosure())) {
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  runner->Run();
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !testing::Test::HasFatalFailure();
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WindowedTabAddedNotificationObserver::WindowedTabAddedNotificationObserver(
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::NotificationSource& source)
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : WindowedNotificationObserver(chrome::NOTIFICATION_TAB_ADDED, source),
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      added_tab_(NULL) {
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WindowedTabAddedNotificationObserver::Observe(
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int type,
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::NotificationSource& source,
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::NotificationDetails& details) {
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  added_tab_ = content::Details<WebContents>(details).ptr();
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::WindowedNotificationObserver::Observe(type, source, details);
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UrlLoadObserver::UrlLoadObserver(const GURL& url,
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const content::NotificationSource& source)
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : WindowedNotificationObserver(content::NOTIFICATION_LOAD_STOP, source),
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      url_(url) {
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UrlLoadObserver::~UrlLoadObserver() {}
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UrlLoadObserver::Observe(
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int type,
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::NotificationSource& source,
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::NotificationDetails& details) {
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NavigationController* controller =
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::Source<NavigationController>(source).ptr();
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (controller->GetWebContents()->GetURL() != url_)
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WindowedNotificationObserver::Observe(type, source, details);
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BrowserAddedObserver::BrowserAddedObserver()
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : notification_observer_(
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          chrome::NOTIFICATION_BROWSER_OPENED,
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          content::NotificationService::AllSources()) {
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  original_browsers_.insert(BrowserList::begin(), BrowserList::end());
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BrowserAddedObserver::~BrowserAddedObserver() {
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Browser* BrowserAddedObserver::WaitForSingleNewBrowser() {
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notification_observer_.Wait();
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that only a single new browser has appeared.
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(original_browsers_.size() + 1, BrowserList::size());
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetBrowserNotInSet(original_browsers_);
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Coordinates taking snapshots of a |RenderWidget|.
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SnapshotTaker {
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SnapshotTaker() : bitmap_(NULL) {}
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool TakeRenderWidgetSnapshot(RenderWidgetHost* rwh,
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const gfx::Size& page_size,
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const gfx::Size& desired_size,
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                SkBitmap* bitmap) WARN_UNUSED_RESULT {
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bitmap_ = bitmap;
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    snapshot_taken_ = false;
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_browser_process->GetRenderWidgetSnapshotTaker()->AskForSnapshot(
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rwh,
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&SnapshotTaker::OnSnapshotTaken, base::Unretained(this)),
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        page_size,
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        desired_size);
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    message_loop_runner_ = new content::MessageLoopRunner;
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    message_loop_runner_->Run();
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return snapshot_taken_;
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool TakeEntirePageSnapshot(RenderViewHost* rvh,
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              SkBitmap* bitmap) WARN_UNUSED_RESULT {
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const wchar_t* script =
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        L"window.domAutomationController.send("
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        L"    JSON.stringify([document.width, document.height]))";
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string json;
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!content::ExecuteJavaScriptAndExtractString(rvh, L"", script, &json))
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Parse the JSON.
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<int> dimensions;
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<Value> value(
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::JSONReader::Read(json, base::JSON_ALLOW_TRAILING_COMMAS));
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!value->IsType(Value::TYPE_LIST))
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ListValue* list = static_cast<ListValue*>(value.get());
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int width, height;
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!list->GetInteger(0, &width) || !list->GetInteger(1, &height))
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Take the snapshot.
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Size page_size(width, height);
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TakeRenderWidgetSnapshot(rvh, page_size, page_size, bitmap);
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called when the RenderWidgetSnapshotTaker has taken the snapshot.
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnSnapshotTaken(const SkBitmap& bitmap) {
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *bitmap_ = bitmap;
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    snapshot_taken_ = true;
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    message_loop_runner_->Quit();
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkBitmap* bitmap_;
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Whether the snapshot was actually taken and received by this SnapshotTaker.
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This will be false if the test times out.
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool snapshot_taken_;
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SnapshotTaker);
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TakeRenderWidgetSnapshot(RenderWidgetHost* rwh,
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const gfx::Size& page_size,
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              SkBitmap* bitmap) {
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(bitmap);
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SnapshotTaker taker;
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return taker.TakeRenderWidgetSnapshot(rwh, page_size, page_size, bitmap);
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TakeEntirePageSnapshot(RenderViewHost* rvh, SkBitmap* bitmap) {
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(bitmap);
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SnapshotTaker taker;
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return taker.TakeEntirePageSnapshot(rvh, bitmap);
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OverrideGeolocation(double latitude, double longitude) {
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::Geoposition position;
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  position.latitude = latitude;
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  position.longitude = longitude;
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  position.altitude = 0.;
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  position.accuracy = 0.;
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  position.timestamp = base::Time::Now();
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<content::MessageLoopRunner> runner =
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new content::MessageLoopRunner;
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::OverrideLocationForTesting(position, runner->QuitClosure());
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  runner->Run();
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace internal {
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ClickTask(ui_controls::MouseButton button,
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               int state,
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               const base::Closure& followup) {
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!followup.is_null())
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui_controls::SendMouseEventsNotifyWhenDone(button, state, followup);
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui_controls::SendMouseEvents(button, state);
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace internal
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HistoryEnumerator::HistoryEnumerator(Profile* profile) {
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<content::MessageLoopRunner> message_loop_runner =
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new content::MessageLoopRunner;
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HistoryService* hs = HistoryServiceFactory::GetForProfile(
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      profile, Profile::EXPLICIT_ACCESS);
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hs->QueryHistory(
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      string16(),
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      history::QueryOptions(),
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &consumer_,
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&HistoryEnumerator::HistoryQueryComplete,
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this), message_loop_runner->QuitClosure()));
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_loop_runner->Run();
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HistoryEnumerator::~HistoryEnumerator() {}
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryEnumerator::HistoryQueryComplete(
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::Closure& quit_task,
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HistoryService::Handle request_handle,
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    history::QueryResults* results) {
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < results->size(); ++i)
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    urls_.push_back((*results)[i].url());
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  quit_task.Run();
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ui_test_utils
736