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