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