Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / test / base / ui_test_utils.cc
blob4b4d488c225abb0efacb883c2b23017e5c734d6c
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.
5 #include "chrome/test/base/ui_test_utils.h"
7 #if defined(OS_WIN)
8 #include <windows.h>
9 #endif
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/files/file_path.h"
16 #include "base/files/file_util.h"
17 #include "base/memory/ref_counted.h"
18 #include "base/memory/scoped_ptr.h"
19 #include "base/path_service.h"
20 #include "base/prefs/pref_service.h"
21 #include "base/strings/stringprintf.h"
22 #include "base/strings/utf_string_conversions.h"
23 #include "base/test/test_timeouts.h"
24 #include "base/time/time.h"
25 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
26 #include "chrome/browser/chrome_notification_types.h"
27 #include "chrome/browser/history/history_service_factory.h"
28 #include "chrome/browser/profiles/profile.h"
29 #include "chrome/browser/ui/browser.h"
30 #include "chrome/browser/ui/browser_commands.h"
31 #include "chrome/browser/ui/browser_finder.h"
32 #include "chrome/browser/ui/browser_iterator.h"
33 #include "chrome/browser/ui/browser_list.h"
34 #include "chrome/browser/ui/browser_navigator.h"
35 #include "chrome/browser/ui/browser_window.h"
36 #include "chrome/browser/ui/find_bar/find_notification_details.h"
37 #include "chrome/browser/ui/find_bar/find_tab_helper.h"
38 #include "chrome/browser/ui/host_desktop.h"
39 #include "chrome/browser/ui/location_bar/location_bar.h"
40 #include "chrome/browser/ui/omnibox/omnibox_view.h"
41 #include "chrome/browser/ui/tabs/tab_strip_model.h"
42 #include "chrome/common/chrome_paths.h"
43 #include "chrome/common/pref_names.h"
44 #include "chrome/test/base/find_in_page_observer.h"
45 #include "components/app_modal/app_modal_dialog.h"
46 #include "components/app_modal/app_modal_dialog_queue.h"
47 #include "components/bookmarks/browser/bookmark_model.h"
48 #include "components/history/core/browser/history_service_observer.h"
49 #include "components/omnibox/browser/autocomplete_controller.h"
50 #include "components/search_engines/template_url_service.h"
51 #include "content/public/browser/dom_operation_notification_details.h"
52 #include "content/public/browser/download_item.h"
53 #include "content/public/browser/download_manager.h"
54 #include "content/public/browser/geolocation_provider.h"
55 #include "content/public/browser/navigation_controller.h"
56 #include "content/public/browser/navigation_entry.h"
57 #include "content/public/browser/notification_service.h"
58 #include "content/public/browser/render_process_host.h"
59 #include "content/public/browser/web_contents.h"
60 #include "content/public/browser/web_contents_observer.h"
61 #include "content/public/common/geoposition.h"
62 #include "content/public/test/browser_test_utils.h"
63 #include "content/public/test/download_test_observer.h"
64 #include "content/public/test/test_navigation_observer.h"
65 #include "content/public/test/test_utils.h"
66 #include "net/base/filename_util.h"
67 #include "net/cookies/cookie_constants.h"
68 #include "net/cookies/cookie_monster.h"
69 #include "net/cookies/cookie_store.h"
70 #include "net/test/python_utils.h"
71 #include "net/url_request/url_request_context.h"
72 #include "net/url_request/url_request_context_getter.h"
73 #include "ui/gfx/geometry/rect.h"
75 #if defined(USE_AURA)
76 #include "ash/shell.h"
77 #include "ui/aura/window_event_dispatcher.h"
78 #endif
80 using content::DomOperationNotificationDetails;
81 using content::NativeWebKeyboardEvent;
82 using content::NavigationController;
83 using content::NavigationEntry;
84 using content::OpenURLParams;
85 using content::Referrer;
86 using content::WebContents;
88 namespace ui_test_utils {
90 namespace {
92 Browser* WaitForBrowserNotInSet(std::set<Browser*> excluded_browsers) {
93 Browser* new_browser = GetBrowserNotInSet(excluded_browsers);
94 if (new_browser == NULL) {
95 BrowserAddedObserver observer;
96 new_browser = observer.WaitForSingleNewBrowser();
97 // The new browser should never be in |excluded_browsers|.
98 DCHECK(!ContainsKey(excluded_browsers, new_browser));
100 return new_browser;
103 class AppModalDialogWaiter : public app_modal::AppModalDialogObserver {
104 public:
105 AppModalDialogWaiter()
106 : dialog_(NULL) {
108 ~AppModalDialogWaiter() override {
111 app_modal::AppModalDialog* Wait() {
112 if (dialog_)
113 return dialog_;
114 message_loop_runner_ = new content::MessageLoopRunner;
115 message_loop_runner_->Run();
116 EXPECT_TRUE(dialog_);
117 return dialog_;
120 // AppModalDialogWaiter:
121 void Notify(app_modal::AppModalDialog* dialog) override {
122 DCHECK(!dialog_);
123 dialog_ = dialog;
124 if (message_loop_runner_.get() && message_loop_runner_->loop_running())
125 message_loop_runner_->Quit();
128 private:
129 app_modal::AppModalDialog* dialog_;
130 scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
132 DISALLOW_COPY_AND_ASSIGN(AppModalDialogWaiter);
135 } // namespace
137 bool GetCurrentTabTitle(const Browser* browser, base::string16* title) {
138 WebContents* web_contents =
139 browser->tab_strip_model()->GetActiveWebContents();
140 if (!web_contents)
141 return false;
142 NavigationEntry* last_entry = web_contents->GetController().GetActiveEntry();
143 if (!last_entry)
144 return false;
145 title->assign(last_entry->GetTitleForDisplay(std::string()));
146 return true;
149 void NavigateToURL(chrome::NavigateParams* params) {
150 chrome::Navigate(params);
151 content::WaitForLoadStop(params->target_contents);
155 void NavigateToURLWithPost(Browser* browser, const GURL& url) {
156 chrome::NavigateParams params(browser, url,
157 ui::PAGE_TRANSITION_FORM_SUBMIT);
158 params.uses_post = true;
159 NavigateToURL(&params);
162 void NavigateToURL(Browser* browser, const GURL& url) {
163 NavigateToURLWithDisposition(browser, url, CURRENT_TAB,
164 BROWSER_TEST_WAIT_FOR_NAVIGATION);
167 void NavigateToURLWithDispositionBlockUntilNavigationsComplete(
168 Browser* browser,
169 const GURL& url,
170 int number_of_navigations,
171 WindowOpenDisposition disposition,
172 int browser_test_flags) {
173 TabStripModel* tab_strip = browser->tab_strip_model();
174 if (disposition == CURRENT_TAB && tab_strip->GetActiveWebContents())
175 content::WaitForLoadStop(tab_strip->GetActiveWebContents());
176 content::TestNavigationObserver same_tab_observer(
177 tab_strip->GetActiveWebContents(),
178 number_of_navigations);
180 std::set<Browser*> initial_browsers;
181 for (chrome::BrowserIterator it; !it.done(); it.Next())
182 initial_browsers.insert(*it);
184 content::WindowedNotificationObserver tab_added_observer(
185 chrome::NOTIFICATION_TAB_ADDED,
186 content::NotificationService::AllSources());
188 browser->OpenURL(OpenURLParams(
189 url, Referrer(), disposition, ui::PAGE_TRANSITION_TYPED, false));
190 if (browser_test_flags & BROWSER_TEST_WAIT_FOR_BROWSER)
191 browser = WaitForBrowserNotInSet(initial_browsers);
192 if (browser_test_flags & BROWSER_TEST_WAIT_FOR_TAB)
193 tab_added_observer.Wait();
194 if (!(browser_test_flags & BROWSER_TEST_WAIT_FOR_NAVIGATION)) {
195 // Some other flag caused the wait prior to this.
196 return;
198 WebContents* web_contents = NULL;
199 if (disposition == NEW_BACKGROUND_TAB) {
200 // We've opened up a new tab, but not selected it.
201 TabStripModel* tab_strip = browser->tab_strip_model();
202 web_contents = tab_strip->GetWebContentsAt(tab_strip->active_index() + 1);
203 EXPECT_TRUE(web_contents != NULL)
204 << " Unable to wait for navigation to \"" << url.spec()
205 << "\" because the new tab is not available yet";
206 if (!web_contents)
207 return;
208 } else if ((disposition == CURRENT_TAB) ||
209 (disposition == NEW_FOREGROUND_TAB) ||
210 (disposition == SINGLETON_TAB)) {
211 // The currently selected tab is the right one.
212 web_contents = browser->tab_strip_model()->GetActiveWebContents();
214 if (disposition == CURRENT_TAB) {
215 same_tab_observer.Wait();
216 return;
217 } else if (web_contents) {
218 content::TestNavigationObserver observer(web_contents,
219 number_of_navigations);
220 observer.Wait();
221 return;
223 EXPECT_TRUE(NULL != web_contents) << " Unable to wait for navigation to \""
224 << url.spec() << "\""
225 << " because we can't get the tab contents";
228 void NavigateToURLWithDisposition(Browser* browser,
229 const GURL& url,
230 WindowOpenDisposition disposition,
231 int browser_test_flags) {
232 NavigateToURLWithDispositionBlockUntilNavigationsComplete(
233 browser,
234 url,
236 disposition,
237 browser_test_flags);
240 void NavigateToURLBlockUntilNavigationsComplete(Browser* browser,
241 const GURL& url,
242 int number_of_navigations) {
243 NavigateToURLWithDispositionBlockUntilNavigationsComplete(
244 browser,
245 url,
246 number_of_navigations,
247 CURRENT_TAB,
248 BROWSER_TEST_WAIT_FOR_NAVIGATION);
251 base::FilePath GetTestFilePath(const base::FilePath& dir,
252 const base::FilePath& file) {
253 base::FilePath path;
254 PathService::Get(chrome::DIR_TEST_DATA, &path);
255 return path.Append(dir).Append(file);
258 GURL GetTestUrl(const base::FilePath& dir, const base::FilePath& file) {
259 return net::FilePathToFileURL(GetTestFilePath(dir, file));
262 bool GetRelativeBuildDirectory(base::FilePath* build_dir) {
263 // This function is used to find the build directory so TestServer can serve
264 // built files (nexes, etc). TestServer expects a path relative to the source
265 // root.
266 base::FilePath exe_dir =
267 base::CommandLine::ForCurrentProcess()->GetProgram().DirName();
268 base::FilePath src_dir;
269 if (!PathService::Get(base::DIR_SOURCE_ROOT, &src_dir))
270 return false;
272 // We must first generate absolute paths to SRC and EXE and from there
273 // generate a relative path.
274 if (!exe_dir.IsAbsolute())
275 exe_dir = base::MakeAbsoluteFilePath(exe_dir);
276 if (!src_dir.IsAbsolute())
277 src_dir = base::MakeAbsoluteFilePath(src_dir);
278 if (!exe_dir.IsAbsolute())
279 return false;
280 if (!src_dir.IsAbsolute())
281 return false;
283 size_t match, exe_size, src_size;
284 std::vector<base::FilePath::StringType> src_parts, exe_parts;
286 // Determine point at which src and exe diverge.
287 exe_dir.GetComponents(&exe_parts);
288 src_dir.GetComponents(&src_parts);
289 exe_size = exe_parts.size();
290 src_size = src_parts.size();
291 for (match = 0; match < exe_size && match < src_size; ++match) {
292 if (exe_parts[match] != src_parts[match])
293 break;
296 // Create a relative path.
297 *build_dir = base::FilePath();
298 for (size_t tmp_itr = match; tmp_itr < src_size; ++tmp_itr)
299 *build_dir = build_dir->Append(FILE_PATH_LITERAL(".."));
300 for (; match < exe_size; ++match)
301 *build_dir = build_dir->Append(exe_parts[match]);
302 return true;
305 app_modal::AppModalDialog* WaitForAppModalDialog() {
306 app_modal::AppModalDialogQueue* dialog_queue =
307 app_modal::AppModalDialogQueue::GetInstance();
308 if (dialog_queue->HasActiveDialog())
309 return dialog_queue->active_dialog();
310 AppModalDialogWaiter waiter;
311 return waiter.Wait();
314 int FindInPage(WebContents* tab,
315 const base::string16& search_string,
316 bool forward,
317 bool match_case,
318 int* ordinal,
319 gfx::Rect* selection_rect) {
320 FindTabHelper* find_tab_helper = FindTabHelper::FromWebContents(tab);
321 find_tab_helper->StartFinding(search_string, forward, match_case);
322 FindInPageNotificationObserver observer(tab);
323 observer.Wait();
324 if (ordinal)
325 *ordinal = observer.active_match_ordinal();
326 if (selection_rect)
327 *selection_rect = observer.selection_rect();
328 return observer.number_of_matches();
331 void WaitForTemplateURLServiceToLoad(TemplateURLService* service) {
332 if (service->loaded())
333 return;
334 scoped_refptr<content::MessageLoopRunner> message_loop_runner =
335 new content::MessageLoopRunner;
336 scoped_ptr<TemplateURLService::Subscription> subscription =
337 service->RegisterOnLoadedCallback(
338 message_loop_runner->QuitClosure());
339 service->Load();
340 message_loop_runner->Run();
342 ASSERT_TRUE(service->loaded());
345 void DownloadURL(Browser* browser, const GURL& download_url) {
346 base::ScopedTempDir downloads_directory;
347 ASSERT_TRUE(downloads_directory.CreateUniqueTempDir());
348 browser->profile()->GetPrefs()->SetFilePath(
349 prefs::kDownloadDefaultDirectory, downloads_directory.path());
351 content::DownloadManager* download_manager =
352 content::BrowserContext::GetDownloadManager(browser->profile());
353 scoped_ptr<content::DownloadTestObserver> observer(
354 new content::DownloadTestObserverTerminal(
355 download_manager, 1,
356 content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_ACCEPT));
358 ui_test_utils::NavigateToURL(browser, download_url);
359 observer->WaitForFinished();
362 void SendToOmniboxAndSubmit(LocationBar* location_bar,
363 const std::string& input) {
364 OmniboxView* omnibox = location_bar->GetOmniboxView();
365 omnibox->model()->OnSetFocus(false);
366 omnibox->SetUserText(base::ASCIIToUTF16(input));
367 location_bar->AcceptInput();
368 while (!omnibox->model()->autocomplete_controller()->done()) {
369 content::WindowedNotificationObserver observer(
370 chrome::NOTIFICATION_AUTOCOMPLETE_CONTROLLER_RESULT_READY,
371 content::NotificationService::AllSources());
372 observer.Wait();
376 Browser* GetBrowserNotInSet(std::set<Browser*> excluded_browsers) {
377 for (chrome::BrowserIterator it; !it.done(); it.Next()) {
378 if (excluded_browsers.find(*it) == excluded_browsers.end())
379 return *it;
381 return NULL;
384 namespace {
386 void GetCookiesCallback(base::WaitableEvent* event,
387 std::string* cookies,
388 const std::string& cookie_line) {
389 *cookies = cookie_line;
390 event->Signal();
393 void GetCookiesOnIOThread(
394 const GURL& url,
395 const scoped_refptr<net::URLRequestContextGetter>& context_getter,
396 base::WaitableEvent* event,
397 std::string* cookies) {
398 context_getter->GetURLRequestContext()->cookie_store()->
399 GetCookiesWithOptionsAsync(
400 url, net::CookieOptions(),
401 base::Bind(&GetCookiesCallback, event, cookies));
404 } // namespace
406 void GetCookies(const GURL& url,
407 WebContents* contents,
408 int* value_size,
409 std::string* value) {
410 *value_size = -1;
411 if (url.is_valid() && contents) {
412 scoped_refptr<net::URLRequestContextGetter> context_getter =
413 contents->GetBrowserContext()->GetRequestContextForRenderProcess(
414 contents->GetRenderProcessHost()->GetID());
415 base::WaitableEvent event(true /* manual reset */,
416 false /* not initially signaled */);
417 CHECK(content::BrowserThread::PostTask(
418 content::BrowserThread::IO, FROM_HERE,
419 base::Bind(&GetCookiesOnIOThread, url, context_getter, &event, value)));
420 event.Wait();
422 *value_size = static_cast<int>(value->size());
426 WindowedTabAddedNotificationObserver::WindowedTabAddedNotificationObserver(
427 const content::NotificationSource& source)
428 : WindowedNotificationObserver(chrome::NOTIFICATION_TAB_ADDED, source),
429 added_tab_(NULL) {
432 void WindowedTabAddedNotificationObserver::Observe(
433 int type,
434 const content::NotificationSource& source,
435 const content::NotificationDetails& details) {
436 added_tab_ = content::Details<WebContents>(details).ptr();
437 content::WindowedNotificationObserver::Observe(type, source, details);
440 UrlLoadObserver::UrlLoadObserver(const GURL& url,
441 const content::NotificationSource& source)
442 : WindowedNotificationObserver(content::NOTIFICATION_LOAD_STOP, source),
443 url_(url) {
446 UrlLoadObserver::~UrlLoadObserver() {}
448 void UrlLoadObserver::Observe(
449 int type,
450 const content::NotificationSource& source,
451 const content::NotificationDetails& details) {
452 NavigationController* controller =
453 content::Source<NavigationController>(source).ptr();
454 if (controller->GetWebContents()->GetURL() != url_)
455 return;
457 WindowedNotificationObserver::Observe(type, source, details);
460 BrowserAddedObserver::BrowserAddedObserver()
461 : notification_observer_(
462 chrome::NOTIFICATION_BROWSER_OPENED,
463 content::NotificationService::AllSources()) {
464 for (chrome::BrowserIterator it; !it.done(); it.Next())
465 original_browsers_.insert(*it);
468 BrowserAddedObserver::~BrowserAddedObserver() {
471 Browser* BrowserAddedObserver::WaitForSingleNewBrowser() {
472 notification_observer_.Wait();
473 // Ensure that only a single new browser has appeared.
474 EXPECT_EQ(original_browsers_.size() + 1, chrome::GetTotalBrowserCount());
475 return GetBrowserNotInSet(original_browsers_);
478 void OverrideGeolocation(double latitude, double longitude) {
479 content::Geoposition position;
480 position.latitude = latitude;
481 position.longitude = longitude;
482 position.altitude = 0.;
483 position.accuracy = 0.;
484 position.timestamp = base::Time::Now();
485 content::GeolocationProvider::GetInstance()->OverrideLocationForTesting(
486 position);
489 HistoryEnumerator::HistoryEnumerator(Profile* profile) {
490 scoped_refptr<content::MessageLoopRunner> message_loop_runner =
491 new content::MessageLoopRunner;
493 history::HistoryService* hs = HistoryServiceFactory::GetForProfile(
494 profile, ServiceAccessType::EXPLICIT_ACCESS);
495 hs->QueryHistory(base::string16(),
496 history::QueryOptions(),
497 base::Bind(&HistoryEnumerator::HistoryQueryComplete,
498 base::Unretained(this),
499 message_loop_runner->QuitClosure()),
500 &tracker_);
501 message_loop_runner->Run();
504 HistoryEnumerator::~HistoryEnumerator() {}
506 void HistoryEnumerator::HistoryQueryComplete(
507 const base::Closure& quit_task,
508 history::QueryResults* results) {
509 for (size_t i = 0; i < results->size(); ++i)
510 urls_.push_back((*results)[i].url());
511 quit_task.Run();
514 // Wait for HistoryService to load.
515 class WaitHistoryLoadedObserver : public history::HistoryServiceObserver {
516 public:
517 explicit WaitHistoryLoadedObserver(content::MessageLoopRunner* runner);
518 ~WaitHistoryLoadedObserver() override;
520 // history::HistoryServiceObserver:
521 void OnHistoryServiceLoaded(history::HistoryService* service) override;
523 private:
524 // weak
525 content::MessageLoopRunner* runner_;
528 WaitHistoryLoadedObserver::WaitHistoryLoadedObserver(
529 content::MessageLoopRunner* runner)
530 : runner_(runner) {
533 WaitHistoryLoadedObserver::~WaitHistoryLoadedObserver() {
536 void WaitHistoryLoadedObserver::OnHistoryServiceLoaded(
537 history::HistoryService* service) {
538 runner_->Quit();
541 void WaitForHistoryToLoad(history::HistoryService* history_service) {
542 if (!history_service->BackendLoaded()) {
543 scoped_refptr<content::MessageLoopRunner> runner =
544 new content::MessageLoopRunner;
545 WaitHistoryLoadedObserver observer(runner.get());
546 ScopedObserver<history::HistoryService, history::HistoryServiceObserver>
547 scoped_observer(&observer);
548 scoped_observer.Add(history_service);
549 runner->Run();
553 } // namespace ui_test_utils