ac490162e8a7b0c5dccf7005ff7763aa55fc9f9e
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / browser_browsertest.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 <string>
6
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/compiler_specific.h"
10 #include "base/files/file_path.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/prefs/pref_service.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "base/sys_info.h"
15 #include "chrome/app/chrome_command_ids.h"
16 #include "chrome/browser/chrome_content_browser_client.h"
17 #include "chrome/browser/chrome_notification_types.h"
18 #include "chrome/browser/command_updater.h"
19 #include "chrome/browser/defaults.h"
20 #include "chrome/browser/devtools/devtools_window_testing.h"
21 #include "chrome/browser/extensions/extension_browsertest.h"
22 #include "chrome/browser/extensions/extension_service.h"
23 #include "chrome/browser/extensions/tab_helper.h"
24 #include "chrome/browser/first_run/first_run.h"
25 #include "chrome/browser/lifetime/application_lifetime.h"
26 #include "chrome/browser/prefs/incognito_mode_prefs.h"
27 #include "chrome/browser/profiles/profile.h"
28 #include "chrome/browser/profiles/profile_manager.h"
29 #include "chrome/browser/search/search.h"
30 #include "chrome/browser/sessions/session_backend.h"
31 #include "chrome/browser/sessions/session_service_factory.h"
32 #include "chrome/browser/translate/chrome_translate_client.h"
33 #include "chrome/browser/translate/cld_data_harness.h"
34 #include "chrome/browser/ui/browser.h"
35 #include "chrome/browser/ui/browser_command_controller.h"
36 #include "chrome/browser/ui/browser_commands.h"
37 #include "chrome/browser/ui/browser_finder.h"
38 #include "chrome/browser/ui/browser_iterator.h"
39 #include "chrome/browser/ui/browser_navigator.h"
40 #include "chrome/browser/ui/browser_tabstrip.h"
41 #include "chrome/browser/ui/browser_ui_prefs.h"
42 #include "chrome/browser/ui/browser_window.h"
43 #include "chrome/browser/ui/extensions/application_launch.h"
44 #include "chrome/browser/ui/host_desktop.h"
45 #include "chrome/browser/ui/startup/startup_browser_creator.h"
46 #include "chrome/browser/ui/startup/startup_browser_creator_impl.h"
47 #include "chrome/browser/ui/tabs/pinned_tab_codec.h"
48 #include "chrome/browser/ui/tabs/tab_strip_model.h"
49 #include "chrome/common/chrome_switches.h"
50 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
51 #include "chrome/common/pref_names.h"
52 #include "chrome/common/url_constants.h"
53 #include "chrome/grit/chromium_strings.h"
54 #include "chrome/grit/generated_resources.h"
55 #include "chrome/test/base/in_process_browser_test.h"
56 #include "chrome/test/base/test_switches.h"
57 #include "chrome/test/base/ui_test_utils.h"
58 #include "components/app_modal_dialogs/app_modal_dialog.h"
59 #include "components/app_modal_dialogs/app_modal_dialog_queue.h"
60 #include "components/app_modal_dialogs/javascript_app_modal_dialog.h"
61 #include "components/app_modal_dialogs/native_app_modal_dialog.h"
62 #include "components/content_settings/core/browser/host_content_settings_map.h"
63 #include "components/translate/core/browser/language_state.h"
64 #include "components/translate/core/common/language_detection_details.h"
65 #include "content/public/browser/favicon_status.h"
66 #include "content/public/browser/host_zoom_map.h"
67 #include "content/public/browser/interstitial_page.h"
68 #include "content/public/browser/interstitial_page_delegate.h"
69 #include "content/public/browser/navigation_entry.h"
70 #include "content/public/browser/notification_service.h"
71 #include "content/public/browser/render_frame_host.h"
72 #include "content/public/browser/render_process_host.h"
73 #include "content/public/browser/render_view_host.h"
74 #include "content/public/browser/render_widget_host_view.h"
75 #include "content/public/browser/resource_context.h"
76 #include "content/public/browser/web_contents.h"
77 #include "content/public/browser/web_contents_observer.h"
78 #include "content/public/common/frame_navigate_params.h"
79 #include "content/public/common/renderer_preferences.h"
80 #include "content/public/common/url_constants.h"
81 #include "content/public/test/browser_test_utils.h"
82 #include "content/public/test/test_navigation_observer.h"
83 #include "extensions/browser/extension_system.h"
84 #include "extensions/browser/uninstall_reason.h"
85 #include "extensions/common/extension.h"
86 #include "extensions/common/extension_set.h"
87 #include "net/dns/mock_host_resolver.h"
88 #include "net/test/spawned_test_server/spawned_test_server.h"
89 #include "ui/base/l10n/l10n_util.h"
90 #include "ui/base/page_transition_types.h"
91
92 #if defined(OS_MACOSX)
93 #include "base/mac/mac_util.h"
94 #include "base/mac/scoped_nsautorelease_pool.h"
95 #include "chrome/browser/ui/cocoa/run_loop_testing.h"
96 #endif
97
98 #if defined(OS_WIN)
99 #include "base/i18n/rtl.h"
100 #include "chrome/browser/browser_process.h"
101 #endif
102
103 using base::ASCIIToUTF16;
104 using content::InterstitialPage;
105 using content::HostZoomMap;
106 using content::NavigationController;
107 using content::NavigationEntry;
108 using content::OpenURLParams;
109 using content::Referrer;
110 using content::WebContents;
111 using content::WebContentsObserver;
112 using extensions::Extension;
113
114 namespace {
115
116 const char* kBeforeUnloadHTML =
117     "<html><head><title>beforeunload</title></head><body>"
118     "<script>window.onbeforeunload=function(e){return 'foo'}</script>"
119     "</body></html>";
120
121 const char* kOpenNewBeforeUnloadPage =
122     "w=window.open(); w.onbeforeunload=function(e){return 'foo'};";
123
124 const base::FilePath::CharType* kBeforeUnloadFile =
125     FILE_PATH_LITERAL("beforeunload.html");
126
127 const base::FilePath::CharType* kTitle1File = FILE_PATH_LITERAL("title1.html");
128 const base::FilePath::CharType* kTitle2File = FILE_PATH_LITERAL("title2.html");
129
130 const base::FilePath::CharType kDocRoot[] =
131     FILE_PATH_LITERAL("chrome/test/data");
132
133 // Given a page title, returns the expected window caption string.
134 base::string16 WindowCaptionFromPageTitle(const base::string16& page_title) {
135 #if defined(OS_MACOSX) || defined(OS_CHROMEOS)
136   // On Mac or ChromeOS, we don't want to suffix the page title with
137   // the application name.
138   if (page_title.empty())
139     return l10n_util::GetStringUTF16(IDS_BROWSER_WINDOW_MAC_TAB_UNTITLED);
140   return page_title;
141 #else
142   if (page_title.empty())
143     return l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
144
145   return l10n_util::GetStringFUTF16(IDS_BROWSER_WINDOW_TITLE_FORMAT,
146                                     page_title);
147 #endif
148 }
149
150 // Returns the number of active RenderProcessHosts.
151 int CountRenderProcessHosts() {
152   int result = 0;
153   for (content::RenderProcessHost::iterator i(
154           content::RenderProcessHost::AllHostsIterator());
155        !i.IsAtEnd(); i.Advance())
156     ++result;
157   return result;
158 }
159
160 class MockTabStripModelObserver : public TabStripModelObserver {
161  public:
162   MockTabStripModelObserver() : closing_count_(0) {}
163
164   void TabClosingAt(TabStripModel* tab_strip_model,
165                     WebContents* contents,
166                     int index) override {
167     ++closing_count_;
168   }
169
170   int closing_count() const { return closing_count_; }
171
172  private:
173   int closing_count_;
174
175   DISALLOW_COPY_AND_ASSIGN(MockTabStripModelObserver);
176 };
177
178 // Causes the browser to swap processes on a redirect to an HTTPS URL.
179 class TransferHttpsRedirectsContentBrowserClient
180     : public chrome::ChromeContentBrowserClient {
181  public:
182   bool ShouldSwapProcessesForRedirect(
183       content::ResourceContext* resource_context,
184       const GURL& current_url,
185       const GURL& new_url) override {
186     return new_url.SchemeIs(url::kHttpsScheme);
187   }
188 };
189
190 // Used by CloseWithAppMenuOpen. Invokes CloseWindow on the supplied browser.
191 void CloseWindowCallback(Browser* browser) {
192   chrome::CloseWindow(browser);
193 }
194
195 // Used by CloseWithAppMenuOpen. Posts a CloseWindowCallback and shows the app
196 // menu.
197 void RunCloseWithAppMenuCallback(Browser* browser) {
198   // ShowAppMenu is modal under views. Schedule a task that closes the window.
199   base::MessageLoop::current()->PostTask(
200       FROM_HERE, base::Bind(&CloseWindowCallback, browser));
201   chrome::ShowAppMenu(browser);
202 }
203
204 // Displays "INTERSTITIAL" while the interstitial is attached.
205 // (InterstitialPage can be used in a test directly, but there would be no way
206 // to visually tell if it is showing or not.)
207 class TestInterstitialPage : public content::InterstitialPageDelegate {
208  public:
209   TestInterstitialPage(WebContents* tab, bool new_navigation, const GURL& url) {
210     interstitial_page_ = InterstitialPage::Create(
211         tab, new_navigation, url , this);
212     interstitial_page_->Show();
213   }
214   ~TestInterstitialPage() override {}
215   void Proceed() {
216     interstitial_page_->Proceed();
217   }
218   void DontProceed() {
219     interstitial_page_->DontProceed();
220   }
221
222   std::string GetHTMLContents() override { return "<h1>INTERSTITIAL</h1>"; }
223
224  private:
225   InterstitialPage* interstitial_page_;  // Owns us.
226 };
227
228 class RenderViewSizeObserver : public content::WebContentsObserver {
229  public:
230   RenderViewSizeObserver(content::WebContents* web_contents,
231                          BrowserWindow* browser_window)
232       : WebContentsObserver(web_contents),
233         browser_window_(browser_window) {
234   }
235
236   void GetSizeForRenderViewHost(
237       content::RenderViewHost* render_view_host,
238       gfx::Size* rwhv_create_size,
239       gfx::Size* rwhv_commit_size,
240       gfx::Size* wcv_commit_size) {
241     RenderViewSizes::const_iterator result = render_view_sizes_.end();
242     result = render_view_sizes_.find(render_view_host);
243     if (result != render_view_sizes_.end()) {
244       *rwhv_create_size = result->second.rwhv_create_size;
245       *rwhv_commit_size = result->second.rwhv_commit_size;
246       *wcv_commit_size = result->second.wcv_commit_size;
247     }
248   }
249
250   void set_wcv_resize_insets(const gfx::Size& wcv_resize_insets) {
251     wcv_resize_insets_ = wcv_resize_insets;
252   }
253
254   // Cache the size when RenderViewHost is first created.
255   void RenderViewCreated(content::RenderViewHost* render_view_host) override {
256     render_view_sizes_[render_view_host].rwhv_create_size =
257         render_view_host->GetView()->GetViewBounds().size();
258   }
259
260   // Enlarge WebContentsView by |wcv_resize_insets_| while the navigation entry
261   // is pending.
262   void DidStartNavigationToPendingEntry(
263       const GURL& url,
264       NavigationController::ReloadType reload_type) override {
265     if (wcv_resize_insets_.IsEmpty())
266       return;
267     // Resizing the main browser window by |wcv_resize_insets_| will
268     // automatically resize the WebContentsView by the same amount.
269     // Just resizing WebContentsView directly doesn't work on Linux, because the
270     // next automatic layout of the browser window will resize WebContentsView
271     // back to the previous size.  To make it consistent, resize main browser
272     // window on all platforms.
273     gfx::Rect bounds(browser_window_->GetBounds());
274     gfx::Size size(bounds.size());
275     size.Enlarge(wcv_resize_insets_.width(), wcv_resize_insets_.height());
276     bounds.set_size(size);
277     browser_window_->SetBounds(bounds);
278     // Let the message loop run so that resize actually takes effect.
279     content::RunAllPendingInMessageLoop();
280   }
281
282   // Cache the sizes of RenderWidgetHostView and WebContentsView when the
283   // navigation entry is committed, which is before
284   // WebContentsDelegate::DidNavigateMainFramePostCommit is called.
285   void NavigationEntryCommitted(
286       const content::LoadCommittedDetails& details) override {
287     content::RenderViewHost* rvh = web_contents()->GetRenderViewHost();
288     render_view_sizes_[rvh].rwhv_commit_size =
289         web_contents()->GetRenderWidgetHostView()->GetViewBounds().size();
290     render_view_sizes_[rvh].wcv_commit_size =
291         web_contents()->GetContainerBounds().size();
292   }
293
294  private:
295   struct Sizes {
296     gfx::Size rwhv_create_size;  // Size of RenderWidgetHostView when created.
297     gfx::Size rwhv_commit_size;  // Size of RenderWidgetHostView when committed.
298     gfx::Size wcv_commit_size;   // Size of WebContentsView when committed.
299   };
300
301   typedef std::map<content::RenderViewHost*, Sizes> RenderViewSizes;
302   RenderViewSizes render_view_sizes_;
303   // Enlarge WebContentsView by this size insets in
304   // DidStartNavigationToPendingEntry.
305   gfx::Size wcv_resize_insets_;
306   BrowserWindow* browser_window_;  // Weak ptr.
307
308   DISALLOW_COPY_AND_ASSIGN(RenderViewSizeObserver);
309 };
310
311 }  // namespace
312
313 class BrowserTest : public ExtensionBrowserTest {
314  protected:
315   // In RTL locales wrap the page title with RTL embedding characters so that it
316   // matches the value returned by GetWindowTitle().
317   base::string16 LocaleWindowCaptionFromPageTitle(
318       const base::string16& expected_title) {
319     base::string16 page_title = WindowCaptionFromPageTitle(expected_title);
320 #if defined(OS_WIN)
321     std::string locale = g_browser_process->GetApplicationLocale();
322     if (base::i18n::GetTextDirectionForLocale(locale.c_str()) ==
323         base::i18n::RIGHT_TO_LEFT) {
324       base::i18n::WrapStringWithLTRFormatting(&page_title);
325     }
326
327     return page_title;
328 #else
329     // Do we need to use the above code on POSIX as well?
330     return page_title;
331 #endif
332   }
333
334   // Returns the app extension aptly named "App Test".
335   const Extension* GetExtension() {
336     const extensions::ExtensionSet* extensions =
337         extensions::ExtensionSystem::Get(
338             browser()->profile())->extension_service()->extensions();
339     for (extensions::ExtensionSet::const_iterator it = extensions->begin();
340          it != extensions->end(); ++it) {
341       if ((*it)->name() == "App Test")
342         return it->get();
343     }
344     NOTREACHED();
345     return NULL;
346   }
347 };
348
349 // Launch the app on a page with no title, check that the app title was set
350 // correctly.
351 IN_PROC_BROWSER_TEST_F(BrowserTest, NoTitle) {
352 #if defined(OS_WIN) && defined(USE_ASH)
353   // Disable this test in Metro+Ash for now (http://crbug.com/262796).
354   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
355     return;
356 #endif
357
358   ui_test_utils::NavigateToURL(
359       browser(), ui_test_utils::GetTestUrl(
360                      base::FilePath(base::FilePath::kCurrentDirectory),
361                      base::FilePath(kTitle1File)));
362   EXPECT_EQ(LocaleWindowCaptionFromPageTitle(ASCIIToUTF16("title1.html")),
363             browser()->GetWindowTitleForCurrentTab());
364   base::string16 tab_title;
365   ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(), &tab_title));
366   EXPECT_EQ(ASCIIToUTF16("title1.html"), tab_title);
367 }
368
369 // Launch the app, navigate to a page with a title, check that the app title
370 // was set correctly.
371 IN_PROC_BROWSER_TEST_F(BrowserTest, Title) {
372 #if defined(OS_WIN) && defined(USE_ASH)
373   // Disable this test in Metro+Ash for now (http://crbug.com/262796).
374   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
375     return;
376 #endif
377
378   ui_test_utils::NavigateToURL(
379       browser(), ui_test_utils::GetTestUrl(
380                      base::FilePath(base::FilePath::kCurrentDirectory),
381                      base::FilePath(kTitle2File)));
382   const base::string16 test_title(ASCIIToUTF16("Title Of Awesomeness"));
383   EXPECT_EQ(LocaleWindowCaptionFromPageTitle(test_title),
384             browser()->GetWindowTitleForCurrentTab());
385   base::string16 tab_title;
386   ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(), &tab_title));
387   EXPECT_EQ(test_title, tab_title);
388 }
389
390 IN_PROC_BROWSER_TEST_F(BrowserTest, JavascriptAlertActivatesTab) {
391   GURL url(ui_test_utils::GetTestUrl(base::FilePath(
392       base::FilePath::kCurrentDirectory), base::FilePath(kTitle1File)));
393   ui_test_utils::NavigateToURL(browser(), url);
394   AddTabAtIndex(0, url, ui::PAGE_TRANSITION_TYPED);
395   EXPECT_EQ(2, browser()->tab_strip_model()->count());
396   EXPECT_EQ(0, browser()->tab_strip_model()->active_index());
397   WebContents* second_tab = browser()->tab_strip_model()->GetWebContentsAt(1);
398   ASSERT_TRUE(second_tab);
399   second_tab->GetMainFrame()->ExecuteJavaScript(
400       ASCIIToUTF16("alert('Activate!');"));
401   AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
402   alert->CloseModalDialog();
403   EXPECT_EQ(2, browser()->tab_strip_model()->count());
404   EXPECT_EQ(1, browser()->tab_strip_model()->active_index());
405 }
406
407
408 #if defined(OS_WIN) && !defined(NDEBUG)
409 // http://crbug.com/114859. Times out frequently on Windows.
410 #define MAYBE_ThirtyFourTabs DISABLED_ThirtyFourTabs
411 #else
412 #define MAYBE_ThirtyFourTabs ThirtyFourTabs
413 #endif
414
415 // Create 34 tabs and verify that a lot of processes have been created. The
416 // exact number of processes depends on the amount of memory. Previously we
417 // had a hard limit of 31 processes and this test is mainly directed at
418 // verifying that we don't crash when we pass this limit.
419 // Warning: this test can take >30 seconds when running on a slow (low
420 // memory?) Mac builder.
421 IN_PROC_BROWSER_TEST_F(BrowserTest, MAYBE_ThirtyFourTabs) {
422   GURL url(ui_test_utils::GetTestUrl(base::FilePath(
423       base::FilePath::kCurrentDirectory), base::FilePath(kTitle2File)));
424
425   // There is one initial tab.
426   const int kTabCount = 34;
427   for (int ix = 0; ix != (kTabCount - 1); ++ix) {
428     chrome::AddSelectedTabWithURL(browser(), url,
429                                   ui::PAGE_TRANSITION_TYPED);
430   }
431   EXPECT_EQ(kTabCount, browser()->tab_strip_model()->count());
432
433   // See GetMaxRendererProcessCount() in
434   // content/browser/renderer_host/render_process_host_impl.cc
435   // for the algorithm to decide how many processes to create.
436   const int kExpectedProcessCount =
437 #if defined(ARCH_CPU_64_BITS)
438       17;
439 #else
440       25;
441 #endif
442   if (base::SysInfo::AmountOfPhysicalMemoryMB() >= 2048) {
443     EXPECT_GE(CountRenderProcessHosts(), kExpectedProcessCount);
444   } else {
445     EXPECT_LT(CountRenderProcessHosts(), kExpectedProcessCount);
446   }
447 }
448
449 // Test that a browser-initiated navigation to an aborted URL load leaves around
450 // a pending entry if we start from the NTP but not from a normal page.
451 // See http://crbug.com/355537.
452 IN_PROC_BROWSER_TEST_F(BrowserTest, ClearPendingOnFailUnlessNTP) {
453   ASSERT_TRUE(test_server()->Start());
454   WebContents* web_contents =
455       browser()->tab_strip_model()->GetActiveWebContents();
456   GURL ntp_url(chrome::GetNewTabPageURL(browser()->profile()));
457   ui_test_utils::NavigateToURL(browser(), ntp_url);
458
459   // Navigate to a 204 URL (aborts with no content) on the NTP and make sure it
460   // sticks around so that the user can edit it.
461   GURL abort_url(test_server()->GetURL("nocontent"));
462   {
463     content::WindowedNotificationObserver stop_observer(
464         content::NOTIFICATION_LOAD_STOP,
465         content::Source<NavigationController>(
466             &web_contents->GetController()));
467     browser()->OpenURL(OpenURLParams(abort_url, Referrer(), CURRENT_TAB,
468                                      ui::PAGE_TRANSITION_TYPED, false));
469     stop_observer.Wait();
470     EXPECT_TRUE(web_contents->GetController().GetPendingEntry());
471     EXPECT_EQ(abort_url, web_contents->GetVisibleURL());
472   }
473
474   // Navigate to a real URL.
475   GURL real_url(test_server()->GetURL("title1.html"));
476   ui_test_utils::NavigateToURL(browser(), real_url);
477   EXPECT_EQ(real_url, web_contents->GetVisibleURL());
478
479   // Now navigating to a 204 URL should clear the pending entry.
480   {
481     content::WindowedNotificationObserver stop_observer(
482         content::NOTIFICATION_LOAD_STOP,
483         content::Source<NavigationController>(
484             &web_contents->GetController()));
485     browser()->OpenURL(OpenURLParams(abort_url, Referrer(), CURRENT_TAB,
486                                      ui::PAGE_TRANSITION_TYPED, false));
487     stop_observer.Wait();
488     EXPECT_FALSE(web_contents->GetController().GetPendingEntry());
489     EXPECT_EQ(real_url, web_contents->GetVisibleURL());
490   }
491 }
492
493 // Test for crbug.com/297289.  Ensure that modal dialogs are closed when a
494 // cross-process navigation is ready to commit.
495 IN_PROC_BROWSER_TEST_F(BrowserTest, CrossProcessNavCancelsDialogs) {
496   ASSERT_TRUE(test_server()->Start());
497   host_resolver()->AddRule("www.example.com", "127.0.0.1");
498   GURL url(test_server()->GetURL("empty.html"));
499   ui_test_utils::NavigateToURL(browser(), url);
500
501   // Test this with multiple alert dialogs to ensure that we can navigate away
502   // even if the renderer tries to synchronously create more.
503   // See http://crbug.com/312490.
504   WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
505   contents->GetMainFrame()->ExecuteJavaScript(
506       ASCIIToUTF16("alert('one'); alert('two');"));
507   AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
508   EXPECT_TRUE(alert->IsValid());
509   AppModalDialogQueue* dialog_queue = AppModalDialogQueue::GetInstance();
510   EXPECT_TRUE(dialog_queue->HasActiveDialog());
511
512   // A cross-site navigation should force the dialog to close.
513   GURL url2("http://www.example.com/empty.html");
514   ui_test_utils::NavigateToURL(browser(), url2);
515   EXPECT_FALSE(dialog_queue->HasActiveDialog());
516
517   // Make sure input events still work in the renderer process.
518   EXPECT_FALSE(contents->GetRenderProcessHost()->IgnoreInputEvents());
519 }
520
521 // Make sure that dialogs are closed after a renderer process dies, and that
522 // subsequent navigations work.  See http://crbug/com/343265.
523 IN_PROC_BROWSER_TEST_F(BrowserTest, SadTabCancelsDialogs) {
524   ASSERT_TRUE(test_server()->Start());
525   host_resolver()->AddRule("www.example.com", "127.0.0.1");
526   GURL beforeunload_url(test_server()->GetURL("files/beforeunload.html"));
527   ui_test_utils::NavigateToURL(browser(), beforeunload_url);
528
529   // Start a navigation to trigger the beforeunload dialog.
530   WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
531   contents->GetMainFrame()->ExecuteJavaScript(
532       ASCIIToUTF16("window.location.href = 'data:text/html,foo'"));
533   AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
534   EXPECT_TRUE(alert->IsValid());
535   AppModalDialogQueue* dialog_queue = AppModalDialogQueue::GetInstance();
536   EXPECT_TRUE(dialog_queue->HasActiveDialog());
537
538   // Crash the renderer process and ensure the dialog is gone.
539   content::RenderProcessHost* child_process = contents->GetRenderProcessHost();
540   content::RenderProcessHostWatcher crash_observer(
541       child_process,
542       content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
543   base::KillProcess(child_process->GetHandle(), 0, false);
544   crash_observer.Wait();
545   EXPECT_FALSE(dialog_queue->HasActiveDialog());
546
547   // Make sure subsequent navigations work.
548   GURL url2("http://www.example.com/files/empty.html");
549   ui_test_utils::NavigateToURL(browser(), url2);
550 }
551
552 // Make sure that dialogs opened by subframes are closed when the process dies.
553 // See http://crbug.com/366510.
554 IN_PROC_BROWSER_TEST_F(BrowserTest, SadTabCancelsSubframeDialogs) {
555   // Navigate to an iframe that opens an alert dialog.
556   WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
557   contents->GetMainFrame()->ExecuteJavaScript(
558       ASCIIToUTF16("window.location.href = 'data:text/html,"
559                    "<iframe srcdoc=\"<script>alert(1)</script>\">'"));
560   AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
561   EXPECT_TRUE(alert->IsValid());
562   AppModalDialogQueue* dialog_queue = AppModalDialogQueue::GetInstance();
563   EXPECT_TRUE(dialog_queue->HasActiveDialog());
564
565   // Crash the renderer process and ensure the dialog is gone.
566   content::RenderProcessHost* child_process = contents->GetRenderProcessHost();
567   content::RenderProcessHostWatcher crash_observer(
568       child_process,
569       content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
570   base::KillProcess(child_process->GetHandle(), 0, false);
571   crash_observer.Wait();
572   EXPECT_FALSE(dialog_queue->HasActiveDialog());
573
574   // Make sure subsequent navigations work.
575   GURL url2("data:text/html,foo");
576   ui_test_utils::NavigateToURL(browser(), url2);
577 }
578
579 // Test for crbug.com/22004.  Reloading a page with a before unload handler and
580 // then canceling the dialog should not leave the throbber spinning.
581 IN_PROC_BROWSER_TEST_F(BrowserTest, ReloadThenCancelBeforeUnload) {
582   GURL url(std::string("data:text/html,") + kBeforeUnloadHTML);
583   ui_test_utils::NavigateToURL(browser(), url);
584
585   // Navigate to another page, but click cancel in the dialog.  Make sure that
586   // the throbber stops spinning.
587   chrome::Reload(browser(), CURRENT_TAB);
588   AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
589   alert->CloseModalDialog();
590   EXPECT_FALSE(
591       browser()->tab_strip_model()->GetActiveWebContents()->IsLoading());
592
593   // Clear the beforeunload handler so the test can easily exit.
594   browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame()->
595       ExecuteJavaScript(ASCIIToUTF16("onbeforeunload=null;"));
596 }
597
598 class RedirectObserver : public content::WebContentsObserver {
599  public:
600   explicit RedirectObserver(content::WebContents* web_contents)
601       : WebContentsObserver(web_contents) {
602   }
603
604   void DidNavigateAnyFrame(
605       content::RenderFrameHost* render_frame_host,
606       const content::LoadCommittedDetails& details,
607       const content::FrameNavigateParams& params) override {
608     params_ = params;
609   }
610
611   void WebContentsDestroyed() override {
612     // Make sure we don't close the tab while the observer is in scope.
613     // See http://crbug.com/314036.
614     FAIL() << "WebContents closed during navigation (http://crbug.com/314036).";
615   }
616
617   const content::FrameNavigateParams& params() const {
618     return params_;
619   }
620
621  private:
622   content::FrameNavigateParams params_;
623
624   DISALLOW_COPY_AND_ASSIGN(RedirectObserver);
625 };
626
627 // Ensure that a transferred cross-process navigation does not generate
628 // DidStopLoading events until the navigation commits.  If it did, then
629 // ui_test_utils::NavigateToURL would proceed before the URL had committed.
630 // http://crbug.com/243957.
631 IN_PROC_BROWSER_TEST_F(BrowserTest, NoStopDuringTransferUntilCommit) {
632   // Create HTTP and HTTPS servers for a cross-site transition.
633   ASSERT_TRUE(test_server()->Start());
634   net::SpawnedTestServer https_test_server(net::SpawnedTestServer::TYPE_HTTPS,
635                                            net::SpawnedTestServer::kLocalhost,
636                                            base::FilePath(kDocRoot));
637   ASSERT_TRUE(https_test_server.Start());
638
639   // Temporarily replace ContentBrowserClient with one that will cause a
640   // process swap on all redirects to HTTPS URLs.
641   TransferHttpsRedirectsContentBrowserClient new_client;
642   content::ContentBrowserClient* old_client =
643       SetBrowserClientForTesting(&new_client);
644
645   GURL init_url(test_server()->GetURL("files/title1.html"));
646   ui_test_utils::NavigateToURL(browser(), init_url);
647
648   // Navigate to a same-site page that redirects, causing a transfer.
649   WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
650
651   // Create a RedirectObserver that goes away before we close the tab.
652   {
653     RedirectObserver redirect_observer(contents);
654     GURL dest_url(https_test_server.GetURL("files/title2.html"));
655     GURL redirect_url(test_server()->GetURL("server-redirect?" +
656         dest_url.spec()));
657     ui_test_utils::NavigateToURL(browser(), redirect_url);
658
659     // We should immediately see the new committed entry.
660     EXPECT_FALSE(contents->GetController().GetPendingEntry());
661     EXPECT_EQ(dest_url,
662               contents->GetController().GetLastCommittedEntry()->GetURL());
663
664     // We should keep track of the original request URL, redirect chain, and
665     // page transition type during a transfer, since these are necessary for
666     // history autocomplete to work.
667     EXPECT_EQ(redirect_url, contents->GetController().GetLastCommittedEntry()->
668                   GetOriginalRequestURL());
669     EXPECT_EQ(2U, redirect_observer.params().redirects.size());
670     EXPECT_EQ(redirect_url, redirect_observer.params().redirects.at(0));
671     EXPECT_EQ(dest_url, redirect_observer.params().redirects.at(1));
672     EXPECT_TRUE(ui::PageTransitionCoreTypeIs(
673         redirect_observer.params().transition, ui::PAGE_TRANSITION_TYPED));
674   }
675
676   // Restore previous browser client.
677   SetBrowserClientForTesting(old_client);
678 }
679
680 // Tests that a cross-process redirect will only cause the beforeunload
681 // handler to run once.
682 IN_PROC_BROWSER_TEST_F(BrowserTest, SingleBeforeUnloadAfterRedirect) {
683   // Create HTTP and HTTPS servers for a cross-site transition.
684   ASSERT_TRUE(test_server()->Start());
685   net::SpawnedTestServer https_test_server(net::SpawnedTestServer::TYPE_HTTPS,
686                                            net::SpawnedTestServer::kLocalhost,
687                                            base::FilePath(kDocRoot));
688   ASSERT_TRUE(https_test_server.Start());
689
690   // Temporarily replace ContentBrowserClient with one that will cause a
691   // process swap on all redirects to HTTPS URLs.
692   TransferHttpsRedirectsContentBrowserClient new_client;
693   content::ContentBrowserClient* old_client =
694       SetBrowserClientForTesting(&new_client);
695
696   // Navigate to a page with a beforeunload handler.
697   GURL url(test_server()->GetURL("files/beforeunload.html"));
698   ui_test_utils::NavigateToURL(browser(), url);
699
700   // Navigate to a URL that redirects to another process and approve the
701   // beforeunload dialog that pops up.
702   content::WindowedNotificationObserver nav_observer(
703       content::NOTIFICATION_NAV_ENTRY_COMMITTED,
704       content::NotificationService::AllSources());
705   GURL https_url(https_test_server.GetURL("files/title1.html"));
706   GURL redirect_url(test_server()->GetURL("server-redirect?" +
707       https_url.spec()));
708   browser()->OpenURL(OpenURLParams(redirect_url, Referrer(), CURRENT_TAB,
709                                    ui::PAGE_TRANSITION_TYPED, false));
710   AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
711   EXPECT_TRUE(
712       static_cast<JavaScriptAppModalDialog*>(alert)->is_before_unload_dialog());
713   alert->native_dialog()->AcceptAppModalDialog();
714   nav_observer.Wait();
715
716   // Restore previous browser client.
717   SetBrowserClientForTesting(old_client);
718 }
719
720 // Test for crbug.com/80401.  Canceling a before unload dialog should reset
721 // the URL to the previous page's URL.
722 IN_PROC_BROWSER_TEST_F(BrowserTest, CancelBeforeUnloadResetsURL) {
723   GURL url(ui_test_utils::GetTestUrl(base::FilePath(
724       base::FilePath::kCurrentDirectory), base::FilePath(kBeforeUnloadFile)));
725   ui_test_utils::NavigateToURL(browser(), url);
726
727   // Navigate to a page that triggers a cross-site transition.
728   ASSERT_TRUE(test_server()->Start());
729   GURL url2(test_server()->GetURL("files/title1.html"));
730   browser()->OpenURL(OpenURLParams(
731       url2, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED, false));
732
733   content::WindowedNotificationObserver host_destroyed_observer(
734       content::NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED,
735       content::NotificationService::AllSources());
736
737   // Cancel the dialog.
738   AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
739   alert->CloseModalDialog();
740   EXPECT_FALSE(
741       browser()->tab_strip_model()->GetActiveWebContents()->IsLoading());
742
743   // Verify there are no pending history items after the dialog is cancelled.
744   // (see crbug.com/93858)
745   NavigationEntry* entry = browser()->tab_strip_model()->
746       GetActiveWebContents()->GetController().GetPendingEntry();
747   EXPECT_EQ(NULL, entry);
748
749   // Wait for the ShouldClose_ACK to arrive.  We can detect it by waiting for
750   // the pending RVH to be destroyed.
751   host_destroyed_observer.Wait();
752   EXPECT_EQ(url, browser()->toolbar_model()->GetURL());
753
754   // Clear the beforeunload handler so the test can easily exit.
755   browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame()->
756       ExecuteJavaScript(ASCIIToUTF16("onbeforeunload=null;"));
757 }
758
759 // Test for crbug.com/11647.  A page closed with window.close() should not have
760 // two beforeunload dialogs shown.
761 // http://crbug.com/410891
762 IN_PROC_BROWSER_TEST_F(BrowserTest,
763                        DISABLED_SingleBeforeUnloadAfterWindowClose) {
764   browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame()->
765       ExecuteJavaScriptForTests(ASCIIToUTF16(kOpenNewBeforeUnloadPage));
766
767   // Close the new window with JavaScript, which should show a single
768   // beforeunload dialog.  Then show another alert, to make it easy to verify
769   // that a second beforeunload dialog isn't shown.
770   browser()->tab_strip_model()->GetWebContentsAt(0)->GetMainFrame()->
771       ExecuteJavaScriptForTests(ASCIIToUTF16("w.close(); alert('bar');"));
772   AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
773   alert->native_dialog()->AcceptAppModalDialog();
774
775   alert = ui_test_utils::WaitForAppModalDialog();
776   EXPECT_FALSE(static_cast<JavaScriptAppModalDialog*>(alert)->
777                    is_before_unload_dialog());
778   alert->native_dialog()->AcceptAppModalDialog();
779 }
780
781 // BrowserTest.BeforeUnloadVsBeforeReload times out on Windows.
782 // http://crbug.com/130411
783 #if defined(OS_WIN)
784 #define MAYBE_BeforeUnloadVsBeforeReload DISABLED_BeforeUnloadVsBeforeReload
785 #else
786 #define MAYBE_BeforeUnloadVsBeforeReload BeforeUnloadVsBeforeReload
787 #endif
788
789 // Test that when a page has an onunload handler, reloading a page shows a
790 // different dialog than navigating to a different page.
791 IN_PROC_BROWSER_TEST_F(BrowserTest, MAYBE_BeforeUnloadVsBeforeReload) {
792   GURL url(std::string("data:text/html,") + kBeforeUnloadHTML);
793   ui_test_utils::NavigateToURL(browser(), url);
794
795   // Reload the page, and check that we get a "before reload" dialog.
796   chrome::Reload(browser(), CURRENT_TAB);
797   AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
798   EXPECT_TRUE(static_cast<JavaScriptAppModalDialog*>(alert)->is_reload());
799
800   // Cancel the reload.
801   alert->native_dialog()->CancelAppModalDialog();
802
803   // Navigate to another url, and check that we get a "before unload" dialog.
804   GURL url2(url::kAboutBlankURL);
805   browser()->OpenURL(OpenURLParams(
806       url2, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED, false));
807
808   alert = ui_test_utils::WaitForAppModalDialog();
809   EXPECT_FALSE(static_cast<JavaScriptAppModalDialog*>(alert)->is_reload());
810
811   // Accept the navigation so we end up on a page without a beforeunload hook.
812   alert->native_dialog()->AcceptAppModalDialog();
813 }
814
815 // BeforeUnloadAtQuitWithTwoWindows is a regression test for
816 // http://crbug.com/11842. It opens two windows, one of which has a
817 // beforeunload handler and attempts to exit cleanly.
818 class BeforeUnloadAtQuitWithTwoWindows : public InProcessBrowserTest {
819  public:
820   // This test is for testing a specific shutdown behavior. This mimics what
821   // happens in InProcessBrowserTest::RunTestOnMainThread and QuitBrowsers, but
822   // ensures that it happens through the single IDC_EXIT of the test.
823   void TearDownOnMainThread() override {
824     // Cycle both the MessageLoop and the Cocoa runloop twice to flush out any
825     // Chrome work that generates Cocoa work. Do this twice since there are two
826     // Browsers that must be closed.
827     CycleRunLoops();
828     CycleRunLoops();
829
830     // Run the application event loop to completion, which will cycle the
831     // native MessagePump on all platforms.
832     base::MessageLoop::current()->PostTask(FROM_HERE,
833                                            base::MessageLoop::QuitClosure());
834     base::MessageLoop::current()->Run();
835
836     // Take care of any remaining Cocoa work.
837     CycleRunLoops();
838
839     // At this point, quit should be for real now.
840     ASSERT_EQ(0u, chrome::GetTotalBrowserCount());
841   }
842
843   // A helper function that cycles the MessageLoop, and on Mac, the Cocoa run
844   // loop. It also drains the NSAutoreleasePool.
845   void CycleRunLoops() {
846     content::RunAllPendingInMessageLoop();
847 #if defined(OS_MACOSX)
848     chrome::testing::NSRunLoopRunAllPending();
849     AutoreleasePool()->Recycle();
850 #endif
851   }
852 };
853
854 // Disabled, http://crbug.com/159214 .
855 IN_PROC_BROWSER_TEST_F(BeforeUnloadAtQuitWithTwoWindows,
856                        DISABLED_IfThisTestTimesOutItIndicatesFAILURE) {
857   // In the first browser, set up a page that has a beforeunload handler.
858   GURL url(std::string("data:text/html,") + kBeforeUnloadHTML);
859   ui_test_utils::NavigateToURL(browser(), url);
860
861   // Open a second browser window at about:blank.
862   ui_test_utils::BrowserAddedObserver browser_added_observer;
863   chrome::NewEmptyWindow(browser()->profile(), chrome::GetActiveDesktop());
864   Browser* second_window = browser_added_observer.WaitForSingleNewBrowser();
865   ui_test_utils::NavigateToURL(second_window, GURL(url::kAboutBlankURL));
866
867   // Tell the application to quit. IDC_EXIT calls AttemptUserExit, which on
868   // everything but ChromeOS allows unload handlers to block exit. On that
869   // platform, though, it exits unconditionally. See the comment and bug ID
870   // in AttemptUserExit() in application_lifetime.cc.
871 #if defined(OS_CHROMEOS)
872   chrome::AttemptExit();
873 #else
874   chrome::ExecuteCommand(second_window, IDC_EXIT);
875 #endif
876
877   // The beforeunload handler will run at exit, ensure it does, and then accept
878   // it to allow shutdown to proceed.
879   AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
880   ASSERT_TRUE(alert);
881   EXPECT_TRUE(
882       static_cast<JavaScriptAppModalDialog*>(alert)->is_before_unload_dialog());
883   alert->native_dialog()->AcceptAppModalDialog();
884
885   // But wait there's more! If this test times out, it likely means that the
886   // browser has not been able to quit correctly, indicating there's a
887   // regression of the bug noted above.
888 }
889
890 // Test that scripts can fork a new renderer process for a cross-site popup,
891 // based on http://www.google.com/chrome/intl/en/webmasters-faq.html#newtab.
892 // The script must open a new tab, set its window.opener to null, and navigate
893 // it to a cross-site URL.  It should also work for meta-refreshes.
894 // See http://crbug.com/93517.
895 IN_PROC_BROWSER_TEST_F(BrowserTest, NullOpenerRedirectForksProcess) {
896   CommandLine::ForCurrentProcess()->AppendSwitch(
897       switches::kDisablePopupBlocking);
898
899   // Create http and https servers for a cross-site transition.
900   ASSERT_TRUE(test_server()->Start());
901   net::SpawnedTestServer https_test_server(net::SpawnedTestServer::TYPE_HTTPS,
902                                            net::SpawnedTestServer::kLocalhost,
903                                            base::FilePath(kDocRoot));
904   ASSERT_TRUE(https_test_server.Start());
905   GURL http_url(test_server()->GetURL("files/title1.html"));
906   GURL https_url(https_test_server.GetURL(std::string()));
907
908   // Start with an http URL.
909   ui_test_utils::NavigateToURL(browser(), http_url);
910   WebContents* oldtab = browser()->tab_strip_model()->GetActiveWebContents();
911   content::RenderProcessHost* process = oldtab->GetRenderProcessHost();
912
913   // Now open a tab to a blank page, set its opener to null, and redirect it
914   // cross-site.
915   std::string redirect_popup = "w=window.open();";
916   redirect_popup += "w.opener=null;";
917   redirect_popup += "w.document.location=\"";
918   redirect_popup += https_url.spec();
919   redirect_popup += "\";";
920
921   content::WindowedNotificationObserver popup_observer(
922       chrome::NOTIFICATION_TAB_ADDED,
923       content::NotificationService::AllSources());
924   content::WindowedNotificationObserver nav_observer(
925       content::NOTIFICATION_NAV_ENTRY_COMMITTED,
926       content::NotificationService::AllSources());
927   oldtab->GetMainFrame()->
928       ExecuteJavaScriptForTests(ASCIIToUTF16(redirect_popup));
929
930   // Wait for popup window to appear and finish navigating.
931   popup_observer.Wait();
932   ASSERT_EQ(2, browser()->tab_strip_model()->count());
933   WebContents* newtab = browser()->tab_strip_model()->GetActiveWebContents();
934   EXPECT_TRUE(newtab);
935   EXPECT_NE(oldtab, newtab);
936   nav_observer.Wait();
937   ASSERT_TRUE(newtab->GetController().GetLastCommittedEntry());
938   EXPECT_EQ(https_url.spec(),
939             newtab->GetController().GetLastCommittedEntry()->GetURL().spec());
940
941   // Popup window should not be in the opener's process.
942   content::RenderProcessHost* popup_process =
943       newtab->GetRenderProcessHost();
944   EXPECT_NE(process, popup_process);
945
946   // Now open a tab to a blank page, set its opener to null, and use a
947   // meta-refresh to navigate it instead.
948   std::string refresh_popup = "w=window.open();";
949   refresh_popup += "w.opener=null;";
950   refresh_popup += "w.document.write(";
951   refresh_popup += "'<META HTTP-EQUIV=\"refresh\" content=\"0; url=";
952   refresh_popup += https_url.spec();
953   refresh_popup += "\">');w.document.close();";
954
955   content::WindowedNotificationObserver popup_observer2(
956       chrome::NOTIFICATION_TAB_ADDED,
957       content::NotificationService::AllSources());
958   content::WindowedNotificationObserver nav_observer2(
959       content::NOTIFICATION_NAV_ENTRY_COMMITTED,
960       content::NotificationService::AllSources());
961   oldtab->GetMainFrame()->
962       ExecuteJavaScriptForTests(ASCIIToUTF16(refresh_popup));
963
964   // Wait for popup window to appear and finish navigating.
965   popup_observer2.Wait();
966   ASSERT_EQ(3, browser()->tab_strip_model()->count());
967   WebContents* newtab2 = browser()->tab_strip_model()->GetActiveWebContents();
968   EXPECT_TRUE(newtab2);
969   EXPECT_NE(oldtab, newtab2);
970   nav_observer2.Wait();
971   ASSERT_TRUE(newtab2->GetController().GetLastCommittedEntry());
972   EXPECT_EQ(https_url.spec(),
973             newtab2->GetController().GetLastCommittedEntry()->GetURL().spec());
974
975   // This popup window should also not be in the opener's process.
976   content::RenderProcessHost* popup_process2 =
977       newtab2->GetRenderProcessHost();
978   EXPECT_NE(process, popup_process2);
979 }
980
981 // Tests that other popup navigations that do not follow the steps at
982 // http://www.google.com/chrome/intl/en/webmasters-faq.html#newtab will not
983 // fork a new renderer process.
984 IN_PROC_BROWSER_TEST_F(BrowserTest, OtherRedirectsDontForkProcess) {
985   CommandLine::ForCurrentProcess()->AppendSwitch(
986       switches::kDisablePopupBlocking);
987
988   // Create http and https servers for a cross-site transition.
989   ASSERT_TRUE(test_server()->Start());
990   net::SpawnedTestServer https_test_server(net::SpawnedTestServer::TYPE_HTTPS,
991                                            net::SpawnedTestServer::kLocalhost,
992                                            base::FilePath(kDocRoot));
993   ASSERT_TRUE(https_test_server.Start());
994   GURL http_url(test_server()->GetURL("files/title1.html"));
995   GURL https_url(https_test_server.GetURL(std::string()));
996
997   // Start with an http URL.
998   ui_test_utils::NavigateToURL(browser(), http_url);
999   WebContents* oldtab = browser()->tab_strip_model()->GetActiveWebContents();
1000   content::RenderProcessHost* process = oldtab->GetRenderProcessHost();
1001
1002   // Now open a tab to a blank page, set its opener to null, and redirect it
1003   // cross-site.
1004   std::string dont_fork_popup = "w=window.open();";
1005   dont_fork_popup += "w.document.location=\"";
1006   dont_fork_popup += https_url.spec();
1007   dont_fork_popup += "\";";
1008
1009   content::WindowedNotificationObserver popup_observer(
1010       chrome::NOTIFICATION_TAB_ADDED,
1011       content::NotificationService::AllSources());
1012   content::WindowedNotificationObserver nav_observer(
1013       content::NOTIFICATION_NAV_ENTRY_COMMITTED,
1014       content::NotificationService::AllSources());
1015   oldtab->GetMainFrame()->
1016       ExecuteJavaScriptForTests(ASCIIToUTF16(dont_fork_popup));
1017
1018   // Wait for popup window to appear and finish navigating.
1019   popup_observer.Wait();
1020   ASSERT_EQ(2, browser()->tab_strip_model()->count());
1021   WebContents* newtab = browser()->tab_strip_model()->GetActiveWebContents();
1022   EXPECT_TRUE(newtab);
1023   EXPECT_NE(oldtab, newtab);
1024   nav_observer.Wait();
1025   ASSERT_TRUE(newtab->GetController().GetLastCommittedEntry());
1026   EXPECT_EQ(https_url.spec(),
1027             newtab->GetController().GetLastCommittedEntry()->GetURL().spec());
1028
1029   // Popup window should still be in the opener's process.
1030   content::RenderProcessHost* popup_process =
1031       newtab->GetRenderProcessHost();
1032   EXPECT_EQ(process, popup_process);
1033
1034   // Same thing if the current tab tries to navigate itself.
1035   std::string navigate_str = "document.location=\"";
1036   navigate_str += https_url.spec();
1037   navigate_str += "\";";
1038
1039   content::WindowedNotificationObserver nav_observer2(
1040         content::NOTIFICATION_NAV_ENTRY_COMMITTED,
1041         content::NotificationService::AllSources());
1042   oldtab->GetMainFrame()->ExecuteJavaScriptForTests(ASCIIToUTF16(navigate_str));
1043   nav_observer2.Wait();
1044   ASSERT_TRUE(oldtab->GetController().GetLastCommittedEntry());
1045   EXPECT_EQ(https_url.spec(),
1046             oldtab->GetController().GetLastCommittedEntry()->GetURL().spec());
1047
1048   // Original window should still be in the original process.
1049   content::RenderProcessHost* new_process = newtab->GetRenderProcessHost();
1050   EXPECT_EQ(process, new_process);
1051 }
1052
1053 // Test that get_process_idle_time() returns reasonable values when compared
1054 // with time deltas measured locally.
1055 IN_PROC_BROWSER_TEST_F(BrowserTest, RenderIdleTime) {
1056   base::TimeTicks start = base::TimeTicks::Now();
1057   ui_test_utils::NavigateToURL(
1058       browser(), ui_test_utils::GetTestUrl(
1059                      base::FilePath(base::FilePath::kCurrentDirectory),
1060                      base::FilePath(kTitle1File)));
1061   content::RenderProcessHost::iterator it(
1062       content::RenderProcessHost::AllHostsIterator());
1063   for (; !it.IsAtEnd(); it.Advance()) {
1064     base::TimeDelta renderer_td =
1065         it.GetCurrentValue()->GetChildProcessIdleTime();
1066     base::TimeDelta browser_td = base::TimeTicks::Now() - start;
1067     EXPECT_TRUE(browser_td >= renderer_td);
1068   }
1069 }
1070
1071 // Test IDC_CREATE_SHORTCUTS command is enabled for url scheme file, ftp, http
1072 // and https and disabled for chrome://, about:// etc.
1073 // TODO(pinkerton): Disable app-mode in the model until we implement it
1074 // on the Mac. http://crbug.com/13148
1075 #if !defined(OS_MACOSX)
1076 IN_PROC_BROWSER_TEST_F(BrowserTest, CommandCreateAppShortcutFile) {
1077   CommandUpdater* command_updater =
1078       browser()->command_controller()->command_updater();
1079
1080   static const base::FilePath::CharType* kEmptyFile =
1081       FILE_PATH_LITERAL("empty.html");
1082   GURL file_url(ui_test_utils::GetTestUrl(base::FilePath(
1083       base::FilePath::kCurrentDirectory), base::FilePath(kEmptyFile)));
1084   ASSERT_TRUE(file_url.SchemeIs(url::kFileScheme));
1085   ui_test_utils::NavigateToURL(browser(), file_url);
1086   EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS));
1087 }
1088
1089 IN_PROC_BROWSER_TEST_F(BrowserTest, CommandCreateAppShortcutHttp) {
1090   CommandUpdater* command_updater =
1091       browser()->command_controller()->command_updater();
1092
1093   ASSERT_TRUE(test_server()->Start());
1094   GURL http_url(test_server()->GetURL(std::string()));
1095   ASSERT_TRUE(http_url.SchemeIs(url::kHttpScheme));
1096   ui_test_utils::NavigateToURL(browser(), http_url);
1097   EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS));
1098 }
1099
1100 IN_PROC_BROWSER_TEST_F(BrowserTest, CommandCreateAppShortcutHttps) {
1101   CommandUpdater* command_updater =
1102       browser()->command_controller()->command_updater();
1103
1104   net::SpawnedTestServer test_server(net::SpawnedTestServer::TYPE_HTTPS,
1105                                      net::SpawnedTestServer::kLocalhost,
1106                                      base::FilePath(kDocRoot));
1107   ASSERT_TRUE(test_server.Start());
1108   GURL https_url(test_server.GetURL("/"));
1109   ASSERT_TRUE(https_url.SchemeIs(url::kHttpsScheme));
1110   ui_test_utils::NavigateToURL(browser(), https_url);
1111   EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS));
1112 }
1113
1114 IN_PROC_BROWSER_TEST_F(BrowserTest, CommandCreateAppShortcutFtp) {
1115   CommandUpdater* command_updater =
1116       browser()->command_controller()->command_updater();
1117
1118   net::SpawnedTestServer test_server(net::SpawnedTestServer::TYPE_FTP,
1119                                      net::SpawnedTestServer::kLocalhost,
1120                                      base::FilePath(kDocRoot));
1121   ASSERT_TRUE(test_server.Start());
1122   GURL ftp_url(test_server.GetURL(std::string()));
1123   ASSERT_TRUE(ftp_url.SchemeIs(url::kFtpScheme));
1124   ui_test_utils::NavigateToURL(browser(), ftp_url);
1125   EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS));
1126 }
1127
1128 IN_PROC_BROWSER_TEST_F(BrowserTest, CommandCreateAppShortcutInvalid) {
1129   CommandUpdater* command_updater =
1130       browser()->command_controller()->command_updater();
1131
1132   // Urls that should not have shortcuts.
1133   GURL new_tab_url(chrome::kChromeUINewTabURL);
1134   ui_test_utils::NavigateToURL(browser(), new_tab_url);
1135   EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS));
1136
1137   GURL history_url(chrome::kChromeUIHistoryURL);
1138   ui_test_utils::NavigateToURL(browser(), history_url);
1139   EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS));
1140
1141   GURL downloads_url(chrome::kChromeUIDownloadsURL);
1142   ui_test_utils::NavigateToURL(browser(), downloads_url);
1143   EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS));
1144
1145   GURL blank_url(url::kAboutBlankURL);
1146   ui_test_utils::NavigateToURL(browser(), blank_url);
1147   EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS));
1148 }
1149
1150 // Change a tab into an application window.
1151 // DISABLED: http://crbug.com/72310
1152 IN_PROC_BROWSER_TEST_F(BrowserTest, DISABLED_ConvertTabToAppShortcut) {
1153   ASSERT_TRUE(test_server()->Start());
1154   GURL http_url(test_server()->GetURL(std::string()));
1155   ASSERT_TRUE(http_url.SchemeIs(url::kHttpScheme));
1156
1157   ASSERT_EQ(1, browser()->tab_strip_model()->count());
1158   WebContents* initial_tab = browser()->tab_strip_model()->GetWebContentsAt(0);
1159   WebContents* app_tab = chrome::AddSelectedTabWithURL(
1160       browser(), http_url, ui::PAGE_TRANSITION_TYPED);
1161   ASSERT_EQ(2, browser()->tab_strip_model()->count());
1162   ASSERT_EQ(1u, chrome::GetBrowserCount(browser()->profile(),
1163                                         browser()->host_desktop_type()));
1164
1165   // Normal tabs should accept load drops.
1166   EXPECT_TRUE(initial_tab->GetMutableRendererPrefs()->can_accept_load_drops);
1167   EXPECT_TRUE(app_tab->GetMutableRendererPrefs()->can_accept_load_drops);
1168
1169   // Turn |app_tab| into a tab in an app panel.
1170   chrome::ConvertTabToAppWindow(browser(), app_tab);
1171
1172   // The launch should have created a new browser.
1173   ASSERT_EQ(2u, chrome::GetBrowserCount(browser()->profile(),
1174                                         browser()->host_desktop_type()));
1175
1176   // Find the new browser.
1177   Browser* app_browser = NULL;
1178   for (chrome::BrowserIterator it; !it.done() && !app_browser; it.Next()) {
1179     if (*it != browser())
1180       app_browser = *it;
1181   }
1182   ASSERT_TRUE(app_browser);
1183
1184   // Check that the tab contents is in the new browser, and not in the old.
1185   ASSERT_EQ(1, browser()->tab_strip_model()->count());
1186   ASSERT_EQ(initial_tab, browser()->tab_strip_model()->GetWebContentsAt(0));
1187
1188   // Check that the appliaction browser has a single tab, and that tab contains
1189   // the content that we app-ified.
1190   ASSERT_EQ(1, app_browser->tab_strip_model()->count());
1191   ASSERT_EQ(app_tab, app_browser->tab_strip_model()->GetWebContentsAt(0));
1192
1193   // Normal tabs should accept load drops.
1194   EXPECT_TRUE(initial_tab->GetMutableRendererPrefs()->can_accept_load_drops);
1195
1196   // The tab in an app window should not.
1197   EXPECT_FALSE(app_tab->GetMutableRendererPrefs()->can_accept_load_drops);
1198 }
1199
1200 #endif  // !defined(OS_MACOSX)
1201
1202 // Test RenderView correctly send back favicon url for web page that redirects
1203 // to an anchor in javascript body.onload handler.
1204 IN_PROC_BROWSER_TEST_F(BrowserTest,
1205                        DISABLED_FaviconOfOnloadRedirectToAnchorPage) {
1206   ASSERT_TRUE(test_server()->Start());
1207   GURL url(test_server()->GetURL("files/onload_redirect_to_anchor.html"));
1208   GURL expected_favicon_url(test_server()->GetURL("files/test.png"));
1209
1210   ui_test_utils::NavigateToURL(browser(), url);
1211
1212   NavigationEntry* entry = browser()->tab_strip_model()->
1213       GetActiveWebContents()->GetController().GetLastCommittedEntry();
1214   EXPECT_EQ(expected_favicon_url.spec(), entry->GetFavicon().url.spec());
1215 }
1216
1217 #if defined(OS_MACOSX) || defined(OS_LINUX) || defined (OS_WIN)
1218 // http://crbug.com/83828. On Mac 10.6, the failure rate is 14%
1219 #define MAYBE_FaviconChange DISABLED_FaviconChange
1220 #else
1221 #define MAYBE_FaviconChange FaviconChange
1222 #endif
1223 // Test that an icon can be changed from JS.
1224 IN_PROC_BROWSER_TEST_F(BrowserTest, MAYBE_FaviconChange) {
1225   static const base::FilePath::CharType* kFile =
1226       FILE_PATH_LITERAL("onload_change_favicon.html");
1227   GURL file_url(ui_test_utils::GetTestUrl(base::FilePath(
1228       base::FilePath::kCurrentDirectory), base::FilePath(kFile)));
1229   ASSERT_TRUE(file_url.SchemeIs(url::kFileScheme));
1230   ui_test_utils::NavigateToURL(browser(), file_url);
1231
1232   NavigationEntry* entry = browser()->tab_strip_model()->
1233       GetActiveWebContents()->GetController().GetLastCommittedEntry();
1234   static const base::FilePath::CharType* kIcon =
1235       FILE_PATH_LITERAL("test1.png");
1236   GURL expected_favicon_url(ui_test_utils::GetTestUrl(base::FilePath(
1237       base::FilePath::kCurrentDirectory), base::FilePath(kIcon)));
1238   EXPECT_EQ(expected_favicon_url.spec(), entry->GetFavicon().url.spec());
1239 }
1240
1241 // http://crbug.com/172336
1242 #if defined(OS_WIN)
1243 #define MAYBE_TabClosingWhenRemovingExtension \
1244     DISABLED_TabClosingWhenRemovingExtension
1245 #else
1246 #define MAYBE_TabClosingWhenRemovingExtension TabClosingWhenRemovingExtension
1247 #endif
1248 // Makes sure TabClosing is sent when uninstalling an extension that is an app
1249 // tab.
1250 IN_PROC_BROWSER_TEST_F(BrowserTest, MAYBE_TabClosingWhenRemovingExtension) {
1251   ASSERT_TRUE(test_server()->Start());
1252   host_resolver()->AddRule("www.example.com", "127.0.0.1");
1253   GURL url(test_server()->GetURL("empty.html"));
1254   TabStripModel* model = browser()->tab_strip_model();
1255
1256   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("app/")));
1257
1258   const Extension* extension_app = GetExtension();
1259
1260   ui_test_utils::NavigateToURL(browser(), url);
1261
1262   WebContents* app_contents = WebContents::Create(
1263       WebContents::CreateParams(browser()->profile()));
1264   extensions::TabHelper::CreateForWebContents(app_contents);
1265   extensions::TabHelper* extensions_tab_helper =
1266       extensions::TabHelper::FromWebContents(app_contents);
1267   extensions_tab_helper->SetExtensionApp(extension_app);
1268
1269   model->AddWebContents(app_contents, 0, ui::PageTransitionFromInt(0),
1270                         TabStripModel::ADD_NONE);
1271   model->SetTabPinned(0, true);
1272   ui_test_utils::NavigateToURL(browser(), url);
1273
1274   MockTabStripModelObserver observer;
1275   model->AddObserver(&observer);
1276
1277   // Uninstall the extension and make sure TabClosing is sent.
1278   ExtensionService* service = extensions::ExtensionSystem::Get(
1279       browser()->profile())->extension_service();
1280   service->UninstallExtension(GetExtension()->id(),
1281                               extensions::UNINSTALL_REASON_FOR_TESTING,
1282                               base::Bind(&base::DoNothing),
1283                               NULL);
1284   EXPECT_EQ(1, observer.closing_count());
1285
1286   model->RemoveObserver(&observer);
1287
1288   // There should only be one tab now.
1289   ASSERT_EQ(1, browser()->tab_strip_model()->count());
1290 }
1291
1292 #if !defined(OS_MACOSX)
1293 // Open with --app-id=<id>, and see that an app window opens.
1294 IN_PROC_BROWSER_TEST_F(BrowserTest, AppIdSwitch) {
1295   ASSERT_TRUE(test_server()->Start());
1296
1297   // Load an app.
1298   host_resolver()->AddRule("www.example.com", "127.0.0.1");
1299   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("app/")));
1300   const Extension* extension_app = GetExtension();
1301
1302   CommandLine command_line(CommandLine::NO_PROGRAM);
1303   command_line.AppendSwitchASCII(switches::kAppId, extension_app->id());
1304
1305   chrome::startup::IsFirstRun first_run = first_run::IsChromeFirstRun() ?
1306       chrome::startup::IS_FIRST_RUN : chrome::startup::IS_NOT_FIRST_RUN;
1307   StartupBrowserCreatorImpl launch(base::FilePath(), command_line, first_run);
1308   ASSERT_TRUE(launch.OpenApplicationWindow(browser()->profile(), NULL));
1309
1310   // Check that the new browser has an app name.
1311   // The launch should have created a new browser.
1312   ASSERT_EQ(2u, chrome::GetBrowserCount(browser()->profile(),
1313                                         browser()->host_desktop_type()));
1314
1315   // Find the new browser.
1316   Browser* new_browser = NULL;
1317   for (chrome::BrowserIterator it; !it.done() && !new_browser; it.Next()) {
1318     if (*it != browser())
1319       new_browser = *it;
1320   }
1321   ASSERT_TRUE(new_browser);
1322   ASSERT_TRUE(new_browser != browser());
1323
1324   // The browser's app_name should include the app's ID.
1325   ASSERT_NE(
1326       new_browser->app_name_.find(extension_app->id()),
1327       std::string::npos) << new_browser->app_name_;
1328 }
1329
1330 // Open an app window and the dev tools window and ensure that the location
1331 // bar settings are correct.
1332 IN_PROC_BROWSER_TEST_F(BrowserTest, ShouldShowLocationBar) {
1333   ASSERT_TRUE(test_server()->Start());
1334
1335   // Load an app.
1336   host_resolver()->AddRule("www.example.com", "127.0.0.1");
1337   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("app/")));
1338   const Extension* extension_app = GetExtension();
1339
1340   // Launch it in a window, as AppLauncherHandler::HandleLaunchApp() would.
1341   WebContents* app_window =
1342       OpenApplication(AppLaunchParams(browser()->profile(),
1343                                       extension_app,
1344                                       extensions::LAUNCH_CONTAINER_WINDOW,
1345                                       NEW_WINDOW));
1346   ASSERT_TRUE(app_window);
1347
1348   DevToolsWindow* devtools_window =
1349       DevToolsWindowTesting::OpenDevToolsWindowSync(browser(), false);
1350
1351   // The launch should have created a new app browser and a dev tools browser.
1352   ASSERT_EQ(3u,
1353             chrome::GetBrowserCount(browser()->profile(),
1354                                     browser()->host_desktop_type()));
1355
1356   // Find the new browsers.
1357   Browser* app_browser = NULL;
1358   Browser* dev_tools_browser = NULL;
1359   for (chrome::BrowserIterator it; !it.done(); it.Next()) {
1360     if (*it == browser()) {
1361       continue;
1362     } else if ((*it)->app_name() == DevToolsWindow::kDevToolsApp) {
1363       dev_tools_browser = *it;
1364     } else {
1365       app_browser = *it;
1366     }
1367   }
1368   ASSERT_TRUE(dev_tools_browser);
1369   ASSERT_TRUE(app_browser);
1370   ASSERT_TRUE(app_browser != browser());
1371
1372   EXPECT_FALSE(
1373       dev_tools_browser->SupportsWindowFeature(Browser::FEATURE_LOCATIONBAR));
1374   EXPECT_FALSE(
1375       app_browser->SupportsWindowFeature(Browser::FEATURE_LOCATIONBAR));
1376
1377   DevToolsWindowTesting::CloseDevToolsWindowSync(devtools_window);
1378 }
1379 #endif
1380
1381 // Tests that the CLD (Compact Language Detection) works properly.
1382 IN_PROC_BROWSER_TEST_F(BrowserTest, PageLanguageDetection) {
1383   scoped_ptr<test::CldDataHarness> cld_data_harness =
1384       test::CreateCldDataHarness();
1385   ASSERT_NO_FATAL_FAILURE(cld_data_harness->Init());
1386   ASSERT_TRUE(test_server()->Start());
1387
1388   translate::LanguageDetectionDetails details;
1389
1390   // Open a new tab with a page in English.
1391   AddTabAtIndex(0, GURL(test_server()->GetURL("files/english_page.html")),
1392                 ui::PAGE_TRANSITION_TYPED);
1393
1394   WebContents* current_web_contents =
1395       browser()->tab_strip_model()->GetActiveWebContents();
1396   ChromeTranslateClient* chrome_translate_client =
1397       ChromeTranslateClient::FromWebContents(current_web_contents);
1398   content::Source<WebContents> source(current_web_contents);
1399
1400   ui_test_utils::WindowedNotificationObserverWithDetails<
1401       translate::LanguageDetectionDetails>
1402       en_language_detected_signal(chrome::NOTIFICATION_TAB_LANGUAGE_DETERMINED,
1403                                   source);
1404   EXPECT_EQ("",
1405             chrome_translate_client->GetLanguageState().original_language());
1406   en_language_detected_signal.Wait();
1407   EXPECT_TRUE(en_language_detected_signal.GetDetailsFor(
1408         source.map_key(), &details));
1409   EXPECT_EQ("en", details.adopted_language);
1410   EXPECT_EQ("en",
1411             chrome_translate_client->GetLanguageState().original_language());
1412
1413   // Now navigate to a page in French.
1414   ui_test_utils::WindowedNotificationObserverWithDetails<
1415       translate::LanguageDetectionDetails>
1416       fr_language_detected_signal(chrome::NOTIFICATION_TAB_LANGUAGE_DETERMINED,
1417                                   source);
1418   ui_test_utils::NavigateToURL(
1419       browser(), GURL(test_server()->GetURL("files/french_page.html")));
1420   fr_language_detected_signal.Wait();
1421   details.adopted_language.clear();
1422   EXPECT_TRUE(fr_language_detected_signal.GetDetailsFor(
1423         source.map_key(), &details));
1424   EXPECT_EQ("fr", details.adopted_language);
1425   EXPECT_EQ("fr",
1426             chrome_translate_client->GetLanguageState().original_language());
1427 }
1428
1429 // Chromeos defaults to restoring the last session, so this test isn't
1430 // applicable.
1431 #if !defined(OS_CHROMEOS)
1432 #if defined(OS_MACOSX)
1433 // Crashy, http://crbug.com/38522
1434 #define RestorePinnedTabs DISABLED_RestorePinnedTabs
1435 #endif
1436 // Makes sure pinned tabs are restored correctly on start.
1437 IN_PROC_BROWSER_TEST_F(BrowserTest, RestorePinnedTabs) {
1438   ASSERT_TRUE(test_server()->Start());
1439
1440   // Add an pinned app tab.
1441   host_resolver()->AddRule("www.example.com", "127.0.0.1");
1442   GURL url(test_server()->GetURL("empty.html"));
1443   TabStripModel* model = browser()->tab_strip_model();
1444   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("app/")));
1445   const Extension* extension_app = GetExtension();
1446   ui_test_utils::NavigateToURL(browser(), url);
1447   WebContents* app_contents = WebContents::Create(
1448       WebContents::CreateParams(browser()->profile()));
1449   extensions::TabHelper::CreateForWebContents(app_contents);
1450   extensions::TabHelper* extensions_tab_helper =
1451       extensions::TabHelper::FromWebContents(app_contents);
1452   extensions_tab_helper->SetExtensionApp(extension_app);
1453   model->AddWebContents(app_contents, 0, ui::PageTransitionFromInt(0),
1454                         TabStripModel::ADD_NONE);
1455   model->SetTabPinned(0, true);
1456   ui_test_utils::NavigateToURL(browser(), url);
1457
1458   // Add a non pinned tab.
1459   chrome::NewTab(browser());
1460
1461   // Add a pinned non-app tab.
1462   chrome::NewTab(browser());
1463   ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL));
1464   model->SetTabPinned(2, true);
1465
1466   // Write out the pinned tabs.
1467   PinnedTabCodec::WritePinnedTabs(browser()->profile());
1468
1469   // Simulate launching again.
1470   CommandLine dummy(CommandLine::NO_PROGRAM);
1471   chrome::startup::IsFirstRun first_run = first_run::IsChromeFirstRun() ?
1472       chrome::startup::IS_FIRST_RUN : chrome::startup::IS_NOT_FIRST_RUN;
1473   StartupBrowserCreatorImpl launch(base::FilePath(), dummy, first_run);
1474   launch.profile_ = browser()->profile();
1475   launch.ProcessStartupURLs(std::vector<GURL>(),
1476                             browser()->host_desktop_type());
1477
1478   // The launch should have created a new browser.
1479   ASSERT_EQ(2u, chrome::GetBrowserCount(browser()->profile(),
1480                                         browser()->host_desktop_type()));
1481
1482   // Find the new browser.
1483   Browser* new_browser = NULL;
1484   for (chrome::BrowserIterator it; !it.done() && !new_browser; it.Next()) {
1485     if (*it != browser())
1486       new_browser = *it;
1487   }
1488   ASSERT_TRUE(new_browser);
1489   ASSERT_TRUE(new_browser != browser());
1490
1491   // We should get back an additional tab for the app, and another for the
1492   // default home page.
1493   ASSERT_EQ(3, new_browser->tab_strip_model()->count());
1494
1495   // Make sure the state matches.
1496   TabStripModel* new_model = new_browser->tab_strip_model();
1497   EXPECT_TRUE(new_model->IsAppTab(0));
1498   EXPECT_FALSE(new_model->IsAppTab(1));
1499   EXPECT_FALSE(new_model->IsAppTab(2));
1500
1501   EXPECT_TRUE(new_model->IsTabPinned(0));
1502   EXPECT_TRUE(new_model->IsTabPinned(1));
1503   EXPECT_FALSE(new_model->IsTabPinned(2));
1504
1505   EXPECT_EQ(GURL(chrome::kChromeUINewTabURL),
1506             new_model->GetWebContentsAt(2)->GetURL());
1507
1508   EXPECT_TRUE(
1509       extensions::TabHelper::FromWebContents(
1510           new_model->GetWebContentsAt(0))->extension_app() == extension_app);
1511 }
1512 #endif  // !defined(OS_CHROMEOS)
1513
1514 // This test verifies we don't crash when closing the last window and the app
1515 // menu is showing.
1516 IN_PROC_BROWSER_TEST_F(BrowserTest, CloseWithAppMenuOpen) {
1517   if (browser_defaults::kBrowserAliveWithNoWindows)
1518     return;
1519
1520   // We need a message loop running for menus on windows.
1521   base::MessageLoop::current()->PostTask(
1522       FROM_HERE, base::Bind(&RunCloseWithAppMenuCallback, browser()));
1523 }
1524
1525 #if !defined(OS_MACOSX)
1526 IN_PROC_BROWSER_TEST_F(BrowserTest, OpenAppWindowLikeNtp) {
1527   ASSERT_TRUE(test_server()->Start());
1528
1529   // Load an app
1530   host_resolver()->AddRule("www.example.com", "127.0.0.1");
1531   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("app/")));
1532   const Extension* extension_app = GetExtension();
1533
1534   // Launch it in a window, as AppLauncherHandler::HandleLaunchApp() would.
1535   WebContents* app_window = OpenApplication(
1536       AppLaunchParams(browser()->profile(), extension_app,
1537                       extensions::LAUNCH_CONTAINER_WINDOW, NEW_WINDOW));
1538   ASSERT_TRUE(app_window);
1539
1540   // Apps launched in a window from the NTP have an extensions tab helper but
1541   // do not have extension_app set in it.
1542   ASSERT_TRUE(extensions::TabHelper::FromWebContents(app_window));
1543   EXPECT_FALSE(
1544       extensions::TabHelper::FromWebContents(app_window)->extension_app());
1545   EXPECT_EQ(extensions::AppLaunchInfo::GetFullLaunchURL(extension_app),
1546             app_window->GetURL());
1547
1548   // The launch should have created a new browser.
1549   ASSERT_EQ(2u, chrome::GetBrowserCount(browser()->profile(),
1550                                         browser()->host_desktop_type()));
1551
1552   // Find the new browser.
1553   Browser* new_browser = NULL;
1554   for (chrome::BrowserIterator it; !it.done() && !new_browser; it.Next()) {
1555     if (*it != browser())
1556       new_browser = *it;
1557   }
1558   ASSERT_TRUE(new_browser);
1559   ASSERT_TRUE(new_browser != browser());
1560
1561   EXPECT_TRUE(new_browser->is_app());
1562
1563   // The browser's app name should include the extension's id.
1564   std::string app_name = new_browser->app_name_;
1565   EXPECT_NE(app_name.find(extension_app->id()), std::string::npos)
1566       << "Name " << app_name << " should contain id "<< extension_app->id();
1567 }
1568 #endif  // !defined(OS_MACOSX)
1569
1570 // Makes sure the browser doesn't crash when
1571 // set_show_state(ui::SHOW_STATE_MAXIMIZED) has been invoked.
1572 IN_PROC_BROWSER_TEST_F(BrowserTest, StartMaximized) {
1573   Browser::Type types[] = { Browser::TYPE_TABBED, Browser::TYPE_POPUP };
1574   for (size_t i = 0; i < arraysize(types); ++i) {
1575     Browser::CreateParams params(types[i], browser()->profile(),
1576                                  browser()->host_desktop_type());
1577     params.initial_show_state = ui::SHOW_STATE_MAXIMIZED;
1578     AddBlankTabAndShow(new Browser(params));
1579   }
1580 }
1581
1582 // Aura doesn't support minimized window. crbug.com/104571.
1583 #if defined(USE_AURA)
1584 #define MAYBE_StartMinimized DISABLED_StartMinimized
1585 #else
1586 #define MAYBE_StartMinimized StartMinimized
1587 #endif
1588 // Makes sure the browser doesn't crash when
1589 // set_show_state(ui::SHOW_STATE_MINIMIZED) has been invoked.
1590 IN_PROC_BROWSER_TEST_F(BrowserTest, MAYBE_StartMinimized) {
1591   Browser::Type types[] = { Browser::TYPE_TABBED, Browser::TYPE_POPUP };
1592   for (size_t i = 0; i < arraysize(types); ++i) {
1593     Browser::CreateParams params(types[i], browser()->profile(),
1594                                  browser()->host_desktop_type());
1595     params.initial_show_state = ui::SHOW_STATE_MINIMIZED;
1596     AddBlankTabAndShow(new Browser(params));
1597   }
1598 }
1599
1600 // Makes sure the forward button is disabled immediately when navigating
1601 // forward to a slow-to-commit page.
1602 IN_PROC_BROWSER_TEST_F(BrowserTest, ForwardDisabledOnForward) {
1603   GURL blank_url(url::kAboutBlankURL);
1604   ui_test_utils::NavigateToURL(browser(), blank_url);
1605
1606   ui_test_utils::NavigateToURL(
1607       browser(), ui_test_utils::GetTestUrl(
1608                      base::FilePath(base::FilePath::kCurrentDirectory),
1609                      base::FilePath(kTitle1File)));
1610
1611   content::WindowedNotificationObserver back_nav_load_observer(
1612       content::NOTIFICATION_LOAD_STOP,
1613       content::Source<NavigationController>(
1614           &browser()->tab_strip_model()->GetActiveWebContents()->
1615               GetController()));
1616   chrome::GoBack(browser(), CURRENT_TAB);
1617   back_nav_load_observer.Wait();
1618   CommandUpdater* command_updater =
1619       browser()->command_controller()->command_updater();
1620   EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_FORWARD));
1621
1622   content::WindowedNotificationObserver forward_nav_load_observer(
1623       content::NOTIFICATION_LOAD_STOP,
1624       content::Source<NavigationController>(
1625           &browser()->tab_strip_model()->GetActiveWebContents()->
1626               GetController()));
1627   chrome::GoForward(browser(), CURRENT_TAB);
1628   // This check will happen before the navigation completes, since the browser
1629   // won't process the renderer's response until the Wait() call below.
1630   EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_FORWARD));
1631   forward_nav_load_observer.Wait();
1632 }
1633
1634 // Makes sure certain commands are disabled when Incognito mode is forced.
1635 IN_PROC_BROWSER_TEST_F(BrowserTest, DisableMenuItemsWhenIncognitoIsForced) {
1636   CommandUpdater* command_updater =
1637       browser()->command_controller()->command_updater();
1638   // At the beginning, all commands are enabled.
1639   EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_NEW_WINDOW));
1640   EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_NEW_INCOGNITO_WINDOW));
1641   EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_SHOW_BOOKMARK_MANAGER));
1642   EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_IMPORT_SETTINGS));
1643   EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_MANAGE_EXTENSIONS));
1644   EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_OPTIONS));
1645
1646   // Set Incognito to FORCED.
1647   IncognitoModePrefs::SetAvailability(browser()->profile()->GetPrefs(),
1648                                       IncognitoModePrefs::FORCED);
1649   // Bookmarks & Settings commands should get disabled.
1650   EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_NEW_WINDOW));
1651   EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_SHOW_BOOKMARK_MANAGER));
1652   EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_IMPORT_SETTINGS));
1653   EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_MANAGE_EXTENSIONS));
1654   EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_OPTIONS));
1655   // New Incognito Window command, however, should be enabled.
1656   EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_NEW_INCOGNITO_WINDOW));
1657
1658   // Create a new browser.
1659   Browser* new_browser =
1660       new Browser(Browser::CreateParams(
1661           browser()->profile()->GetOffTheRecordProfile(),
1662           browser()->host_desktop_type()));
1663   CommandUpdater* new_command_updater =
1664       new_browser->command_controller()->command_updater();
1665   // It should have Bookmarks & Settings commands disabled by default.
1666   EXPECT_FALSE(new_command_updater->IsCommandEnabled(IDC_NEW_WINDOW));
1667   EXPECT_FALSE(new_command_updater->IsCommandEnabled(
1668       IDC_SHOW_BOOKMARK_MANAGER));
1669   EXPECT_FALSE(new_command_updater->IsCommandEnabled(IDC_IMPORT_SETTINGS));
1670   EXPECT_FALSE(new_command_updater->IsCommandEnabled(IDC_MANAGE_EXTENSIONS));
1671   EXPECT_FALSE(new_command_updater->IsCommandEnabled(IDC_OPTIONS));
1672   EXPECT_TRUE(new_command_updater->IsCommandEnabled(IDC_NEW_INCOGNITO_WINDOW));
1673 }
1674
1675 // Makes sure New Incognito Window command is disabled when Incognito mode is
1676 // not available.
1677 IN_PROC_BROWSER_TEST_F(BrowserTest,
1678                        NoNewIncognitoWindowWhenIncognitoIsDisabled) {
1679   CommandUpdater* command_updater =
1680       browser()->command_controller()->command_updater();
1681   // Set Incognito to DISABLED.
1682   IncognitoModePrefs::SetAvailability(browser()->profile()->GetPrefs(),
1683                                       IncognitoModePrefs::DISABLED);
1684   // Make sure New Incognito Window command is disabled. All remaining commands
1685   // should be enabled.
1686   EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_NEW_INCOGNITO_WINDOW));
1687   EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_NEW_WINDOW));
1688   EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_SHOW_BOOKMARK_MANAGER));
1689   EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_IMPORT_SETTINGS));
1690   EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_MANAGE_EXTENSIONS));
1691   EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_OPTIONS));
1692
1693   // Create a new browser.
1694   Browser* new_browser =
1695       new Browser(Browser::CreateParams(browser()->profile(),
1696                                         browser()->host_desktop_type()));
1697   CommandUpdater* new_command_updater =
1698       new_browser->command_controller()->command_updater();
1699   EXPECT_FALSE(new_command_updater->IsCommandEnabled(IDC_NEW_INCOGNITO_WINDOW));
1700   EXPECT_TRUE(new_command_updater->IsCommandEnabled(IDC_NEW_WINDOW));
1701   EXPECT_TRUE(new_command_updater->IsCommandEnabled(IDC_SHOW_BOOKMARK_MANAGER));
1702   EXPECT_TRUE(new_command_updater->IsCommandEnabled(IDC_IMPORT_SETTINGS));
1703   EXPECT_TRUE(new_command_updater->IsCommandEnabled(IDC_MANAGE_EXTENSIONS));
1704   EXPECT_TRUE(new_command_updater->IsCommandEnabled(IDC_OPTIONS));
1705 }
1706
1707 // Makes sure Extensions and Settings commands are disabled in certain
1708 // circumstances even though normally they should stay enabled.
1709 IN_PROC_BROWSER_TEST_F(BrowserTest,
1710                        DisableExtensionsAndSettingsWhenIncognitoIsDisabled) {
1711   CommandUpdater* command_updater =
1712       browser()->command_controller()->command_updater();
1713   // Disable extensions. This should disable Extensions menu.
1714   extensions::ExtensionSystem::Get(browser()->profile())->extension_service()->
1715       set_extensions_enabled(false);
1716   // Set Incognito to DISABLED.
1717   IncognitoModePrefs::SetAvailability(browser()->profile()->GetPrefs(),
1718                                       IncognitoModePrefs::DISABLED);
1719   // Make sure Manage Extensions command is disabled.
1720   EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_MANAGE_EXTENSIONS));
1721   EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_NEW_WINDOW));
1722   EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_SHOW_BOOKMARK_MANAGER));
1723   EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_IMPORT_SETTINGS));
1724   EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_OPTIONS));
1725
1726   // Create a popup (non-main-UI-type) browser. Settings command as well
1727   // as Extensions should be disabled.
1728   Browser* popup_browser = new Browser(
1729       Browser::CreateParams(Browser::TYPE_POPUP, browser()->profile(),
1730                             browser()->host_desktop_type()));
1731   CommandUpdater* popup_command_updater =
1732       popup_browser->command_controller()->command_updater();
1733   EXPECT_FALSE(popup_command_updater->IsCommandEnabled(IDC_MANAGE_EXTENSIONS));
1734   EXPECT_FALSE(popup_command_updater->IsCommandEnabled(IDC_OPTIONS));
1735   EXPECT_TRUE(popup_command_updater->IsCommandEnabled(
1736       IDC_SHOW_BOOKMARK_MANAGER));
1737   EXPECT_FALSE(popup_command_updater->IsCommandEnabled(IDC_IMPORT_SETTINGS));
1738 }
1739
1740 // Makes sure Extensions and Settings commands are disabled in certain
1741 // circumstances even though normally they should stay enabled.
1742 IN_PROC_BROWSER_TEST_F(BrowserTest,
1743                        DisableOptionsAndImportMenuItemsConsistently) {
1744   // Create a popup browser.
1745   Browser* popup_browser = new Browser(
1746       Browser::CreateParams(Browser::TYPE_POPUP, browser()->profile(),
1747                             browser()->host_desktop_type()));
1748   CommandUpdater* command_updater =
1749       popup_browser->command_controller()->command_updater();
1750   // OPTIONS and IMPORT_SETTINGS are disabled for a non-normal UI.
1751   EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_OPTIONS));
1752   EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_IMPORT_SETTINGS));
1753
1754   // Set Incognito to FORCED.
1755   IncognitoModePrefs::SetAvailability(popup_browser->profile()->GetPrefs(),
1756                                       IncognitoModePrefs::FORCED);
1757   // OPTIONS and IMPORT_SETTINGS are disabled when Incognito is forced.
1758   EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_OPTIONS));
1759   EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_IMPORT_SETTINGS));
1760   // Set Incognito to AVAILABLE.
1761   IncognitoModePrefs::SetAvailability(popup_browser->profile()->GetPrefs(),
1762                                       IncognitoModePrefs::ENABLED);
1763   // OPTIONS and IMPORT_SETTINGS are still disabled since it is a non-normal UI.
1764   EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_OPTIONS));
1765   EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_IMPORT_SETTINGS));
1766 }
1767
1768 namespace {
1769
1770 void OnZoomLevelChanged(const base::Closure& callback,
1771                         const HostZoomMap::ZoomLevelChange& host) {
1772   callback.Run();
1773 }
1774
1775 }  // namespace
1776
1777 #if defined(OS_WIN)
1778 // Flakes regularly on Windows XP
1779 // http://crbug.com/146040
1780 #define MAYBE_PageZoom DISABLED_PageZoom
1781 #else
1782 #define MAYBE_PageZoom PageZoom
1783 #endif
1784
1785 namespace {
1786
1787 int GetZoomPercent(const content::WebContents* contents,
1788                    bool* enable_plus,
1789                    bool* enable_minus) {
1790   int percent = ZoomController::FromWebContents(contents)->GetZoomPercent();
1791   *enable_plus = percent < contents->GetMaximumZoomPercent();
1792   *enable_minus = percent > contents->GetMinimumZoomPercent();
1793   return percent;
1794 }
1795
1796 }  // namespace
1797
1798 IN_PROC_BROWSER_TEST_F(BrowserTest, MAYBE_PageZoom) {
1799   WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
1800   bool enable_plus, enable_minus;
1801
1802   {
1803     scoped_refptr<content::MessageLoopRunner> loop_runner(
1804         new content::MessageLoopRunner);
1805     content::HostZoomMap::ZoomLevelChangedCallback callback(
1806         base::Bind(&OnZoomLevelChanged, loop_runner->QuitClosure()));
1807     scoped_ptr<content::HostZoomMap::Subscription> sub =
1808         content::HostZoomMap::GetDefaultForBrowserContext(
1809             browser()->profile())->AddZoomLevelChangedCallback(callback);
1810     chrome::Zoom(browser(), content::PAGE_ZOOM_IN);
1811     loop_runner->Run();
1812     sub.reset();
1813     EXPECT_EQ(GetZoomPercent(contents, &enable_plus, &enable_minus), 110);
1814     EXPECT_TRUE(enable_plus);
1815     EXPECT_TRUE(enable_minus);
1816   }
1817
1818   {
1819     scoped_refptr<content::MessageLoopRunner> loop_runner(
1820         new content::MessageLoopRunner);
1821     content::HostZoomMap::ZoomLevelChangedCallback callback(
1822         base::Bind(&OnZoomLevelChanged, loop_runner->QuitClosure()));
1823     scoped_ptr<content::HostZoomMap::Subscription> sub =
1824         content::HostZoomMap::GetDefaultForBrowserContext(
1825             browser()->profile())->AddZoomLevelChangedCallback(callback);
1826     chrome::Zoom(browser(), content::PAGE_ZOOM_RESET);
1827     loop_runner->Run();
1828     sub.reset();
1829     EXPECT_EQ(GetZoomPercent(contents, &enable_plus, &enable_minus), 100);
1830     EXPECT_TRUE(enable_plus);
1831     EXPECT_TRUE(enable_minus);
1832   }
1833
1834   {
1835     scoped_refptr<content::MessageLoopRunner> loop_runner(
1836         new content::MessageLoopRunner);
1837     content::HostZoomMap::ZoomLevelChangedCallback callback(
1838         base::Bind(&OnZoomLevelChanged, loop_runner->QuitClosure()));
1839     scoped_ptr<content::HostZoomMap::Subscription> sub =
1840         content::HostZoomMap::GetDefaultForBrowserContext(
1841             browser()->profile())->AddZoomLevelChangedCallback(callback);
1842     chrome::Zoom(browser(), content::PAGE_ZOOM_OUT);
1843     loop_runner->Run();
1844     sub.reset();
1845     EXPECT_EQ(GetZoomPercent(contents, &enable_plus, &enable_minus), 90);
1846     EXPECT_TRUE(enable_plus);
1847     EXPECT_TRUE(enable_minus);
1848   }
1849
1850   chrome::Zoom(browser(), content::PAGE_ZOOM_RESET);
1851 }
1852
1853 IN_PROC_BROWSER_TEST_F(BrowserTest, InterstitialCommandDisable) {
1854   ASSERT_TRUE(test_server()->Start());
1855   host_resolver()->AddRule("www.example.com", "127.0.0.1");
1856   GURL url(test_server()->GetURL("empty.html"));
1857   ui_test_utils::NavigateToURL(browser(), url);
1858
1859   CommandUpdater* command_updater =
1860       browser()->command_controller()->command_updater();
1861   EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_VIEW_SOURCE));
1862   EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_PRINT));
1863   EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_SAVE_PAGE));
1864   EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_ENCODING_MENU));
1865
1866   WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
1867
1868   TestInterstitialPage* interstitial =
1869       new TestInterstitialPage(contents, false, GURL());
1870   content::WaitForInterstitialAttach(contents);
1871
1872   EXPECT_TRUE(contents->ShowingInterstitialPage());
1873
1874   EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_VIEW_SOURCE));
1875   EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_PRINT));
1876   EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_SAVE_PAGE));
1877   EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_ENCODING_MENU));
1878
1879   // Proceed and wait for interstitial to detach. This doesn't destroy
1880   // |contents|.
1881   interstitial->Proceed();
1882   content::WaitForInterstitialDetach(contents);
1883   // interstitial is deleted now.
1884
1885   EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_VIEW_SOURCE));
1886   EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_PRINT));
1887   EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_SAVE_PAGE));
1888   EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_ENCODING_MENU));
1889 }
1890
1891 // Ensure that creating an interstitial page closes any JavaScript dialogs
1892 // that were present on the previous page.  See http://crbug.com/295695.
1893 IN_PROC_BROWSER_TEST_F(BrowserTest, InterstitialClosesDialogs) {
1894   ASSERT_TRUE(test_server()->Start());
1895   host_resolver()->AddRule("www.example.com", "127.0.0.1");
1896   GURL url(test_server()->GetURL("empty.html"));
1897   ui_test_utils::NavigateToURL(browser(), url);
1898
1899   WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
1900   contents->GetMainFrame()->ExecuteJavaScript(
1901       ASCIIToUTF16("alert('Dialog showing!');"));
1902   AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
1903   EXPECT_TRUE(alert->IsValid());
1904   AppModalDialogQueue* dialog_queue = AppModalDialogQueue::GetInstance();
1905   EXPECT_TRUE(dialog_queue->HasActiveDialog());
1906
1907   TestInterstitialPage* interstitial =
1908       new TestInterstitialPage(contents, false, GURL());
1909   content::WaitForInterstitialAttach(contents);
1910
1911   // The interstitial should have closed the dialog.
1912   EXPECT_TRUE(contents->ShowingInterstitialPage());
1913   EXPECT_FALSE(dialog_queue->HasActiveDialog());
1914
1915   // Don't proceed and wait for interstitial to detach. This doesn't destroy
1916   // |contents|.
1917   interstitial->DontProceed();
1918   content::WaitForInterstitialDetach(contents);
1919   // interstitial is deleted now.
1920
1921   // Make sure input events still work in the renderer process.
1922   EXPECT_FALSE(contents->GetRenderProcessHost()->IgnoreInputEvents());
1923 }
1924
1925
1926 IN_PROC_BROWSER_TEST_F(BrowserTest, InterstitialCloseTab) {
1927   WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
1928
1929   // Interstitial will delete itself when we close the tab.
1930   new TestInterstitialPage(contents, false, GURL());
1931   content::WaitForInterstitialAttach(contents);
1932
1933   EXPECT_TRUE(contents->ShowingInterstitialPage());
1934
1935   // Close the tab and wait for interstitial detach. This destroys |contents|.
1936   content::RunTaskAndWaitForInterstitialDetach(
1937       contents, base::Bind(&chrome::CloseTab, browser()));
1938   // interstitial is deleted now.
1939 }
1940
1941 class MockWebContentsObserver : public WebContentsObserver {
1942  public:
1943   explicit MockWebContentsObserver(WebContents* web_contents)
1944       : WebContentsObserver(web_contents),
1945         got_user_gesture_(false) {
1946   }
1947
1948   void DidGetUserGesture() override { got_user_gesture_ = true; }
1949
1950   bool got_user_gesture() const {
1951     return got_user_gesture_;
1952   }
1953
1954   void set_got_user_gesture(bool got_it) {
1955     got_user_gesture_ = got_it;
1956   }
1957
1958  private:
1959   bool got_user_gesture_;
1960
1961   DISALLOW_COPY_AND_ASSIGN(MockWebContentsObserver);
1962 };
1963
1964 IN_PROC_BROWSER_TEST_F(BrowserTest, UserGesturesReported) {
1965   // Regression test for http://crbug.com/110707.  Also tests that a user
1966   // gesture is sent when a normal navigation (via e.g. the omnibox) is
1967   // performed.
1968   WebContents* web_contents =
1969       browser()->tab_strip_model()->GetActiveWebContents();
1970   MockWebContentsObserver mock_observer(web_contents);
1971
1972   ASSERT_TRUE(test_server()->Start());
1973   GURL url(test_server()->GetURL("empty.html"));
1974
1975   ui_test_utils::NavigateToURL(browser(), url);
1976   EXPECT_TRUE(mock_observer.got_user_gesture());
1977
1978   mock_observer.set_got_user_gesture(false);
1979   chrome::Reload(browser(), CURRENT_TAB);
1980   EXPECT_TRUE(mock_observer.got_user_gesture());
1981 }
1982
1983 // TODO(ben): this test was never enabled. It has bit-rotted since being added.
1984 // It originally lived in browser_unittest.cc, but has been moved here to make
1985 // room for real browser unit tests.
1986 #if 0
1987 class BrowserTest2 : public InProcessBrowserTest {
1988  public:
1989   BrowserTest2() {
1990     host_resolver_proc_ = new net::RuleBasedHostResolverProc(NULL);
1991     // Avoid making external DNS lookups. In this test we don't need this
1992     // to succeed.
1993     host_resolver_proc_->AddSimulatedFailure("*.google.com");
1994     scoped_host_resolver_proc_.Init(host_resolver_proc_.get());
1995   }
1996
1997  private:
1998   scoped_refptr<net::RuleBasedHostResolverProc> host_resolver_proc_;
1999   net::ScopedDefaultHostResolverProc scoped_host_resolver_proc_;
2000 };
2001
2002 IN_PROC_BROWSER_TEST_F(BrowserTest2, NoTabsInPopups) {
2003   chrome::RegisterAppPrefs(L"Test");
2004
2005   // We start with a normal browser with one tab.
2006   EXPECT_EQ(1, browser()->tab_strip_model()->count());
2007
2008   // Open a popup browser with a single blank foreground tab.
2009   Browser* popup_browser = new Browser(
2010       Browser::CreateParams(Browser::TYPE_POPUP, browser()->profile()));
2011   chrome::AddTabAt(popup_browser, GURL(), -1, true);
2012   EXPECT_EQ(1, popup_browser->tab_strip_model()->count());
2013
2014   // Now try opening another tab in the popup browser.
2015   AddTabWithURLParams params1(url, ui::PAGE_TRANSITION_TYPED);
2016   popup_browser->AddTabWithURL(&params1);
2017   EXPECT_EQ(popup_browser, params1.target);
2018
2019   // The popup should still only have one tab.
2020   EXPECT_EQ(1, popup_browser->tab_strip_model()->count());
2021
2022   // The normal browser should now have two.
2023   EXPECT_EQ(2, browser()->tab_strip_model()->count());
2024
2025   // Open an app frame browser with a single blank foreground tab.
2026   Browser* app_browser = new Browser(Browser::CreateParams::CreateForApp(
2027       L"Test", browser()->profile(), false));
2028   chrome::AddTabAt(app_browser, GURL(), -1, true);
2029   EXPECT_EQ(1, app_browser->tab_strip_model()->count());
2030
2031   // Now try opening another tab in the app browser.
2032   AddTabWithURLParams params2(GURL(url::kAboutBlankURL),
2033                               ui::PAGE_TRANSITION_TYPED);
2034   app_browser->AddTabWithURL(&params2);
2035   EXPECT_EQ(app_browser, params2.target);
2036
2037   // The popup should still only have one tab.
2038   EXPECT_EQ(1, app_browser->tab_strip_model()->count());
2039
2040   // The normal browser should now have three.
2041   EXPECT_EQ(3, browser()->tab_strip_model()->count());
2042
2043   // Open an app frame popup browser with a single blank foreground tab.
2044   Browser* app_popup_browser = new Browser(Browser::CreateParams::CreateForApp(
2045       L"Test", browser()->profile(), false));
2046   chrome::AddTabAt(app_popup_browser, GURL(), -1, true);
2047   EXPECT_EQ(1, app_popup_browser->tab_strip_model()->count());
2048
2049   // Now try opening another tab in the app popup browser.
2050   AddTabWithURLParams params3(GURL(url::kAboutBlankURL),
2051                               ui::PAGE_TRANSITION_TYPED);
2052   app_popup_browser->AddTabWithURL(&params3);
2053   EXPECT_EQ(app_popup_browser, params3.target);
2054
2055   // The popup should still only have one tab.
2056   EXPECT_EQ(1, app_popup_browser->tab_strip_model()->count());
2057
2058   // The normal browser should now have four.
2059   EXPECT_EQ(4, browser()->tab_strip_model()->count());
2060
2061   // Close the additional browsers.
2062   popup_browser->tab_strip_model()->CloseAllTabs();
2063   app_browser->tab_strip_model()->CloseAllTabs();
2064   app_popup_browser->tab_strip_model()->CloseAllTabs();
2065 }
2066 #endif
2067
2068 IN_PROC_BROWSER_TEST_F(BrowserTest, WindowOpenClose) {
2069   CommandLine::ForCurrentProcess()->AppendSwitch(
2070       switches::kDisablePopupBlocking);
2071   GURL url = ui_test_utils::GetTestUrl(
2072       base::FilePath(), base::FilePath().AppendASCII("window.close.html"));
2073
2074   base::string16 title = ASCIIToUTF16("Title Of Awesomeness");
2075   content::TitleWatcher title_watcher(
2076       browser()->tab_strip_model()->GetActiveWebContents(), title);
2077   ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(browser(), url, 2);
2078   EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
2079 }
2080
2081 // TODO(linux_aura) http://crbug.com/163931
2082 // Mac disabled: http://crbug.com/169820
2083 #if !defined(OS_MACOSX) && \
2084     !(defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA))
2085 IN_PROC_BROWSER_TEST_F(BrowserTest, FullscreenBookmarkBar) {
2086 #if defined(OS_WIN) && defined(USE_ASH)
2087   // Disable this test in Metro+Ash for now (http://crbug.com/262796).
2088   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
2089     return;
2090 #endif
2091
2092   chrome::ToggleBookmarkBar(browser());
2093   EXPECT_EQ(BookmarkBar::SHOW, browser()->bookmark_bar_state());
2094   chrome::ToggleFullscreenMode(browser());
2095   EXPECT_TRUE(browser()->window()->IsFullscreen());
2096 #if defined(OS_MACOSX)
2097   EXPECT_EQ(BookmarkBar::SHOW, browser()->bookmark_bar_state());
2098 #elif defined(OS_CHROMEOS)
2099   // TODO(jamescook): If immersive fullscreen is disabled by default, test
2100   // for BookmarkBar::HIDDEN.
2101   EXPECT_EQ(BookmarkBar::SHOW, browser()->bookmark_bar_state());
2102 #else
2103   EXPECT_EQ(BookmarkBar::HIDDEN, browser()->bookmark_bar_state());
2104 #endif
2105 }
2106 #endif
2107
2108 IN_PROC_BROWSER_TEST_F(BrowserTest, DisallowFileUrlUniversalAccessTest) {
2109   GURL url = ui_test_utils::GetTestUrl(
2110       base::FilePath(),
2111       base::FilePath().AppendASCII("fileurl_universalaccess.html"));
2112
2113   base::string16 expected_title(ASCIIToUTF16("Disallowed"));
2114   content::TitleWatcher title_watcher(
2115       browser()->tab_strip_model()->GetActiveWebContents(), expected_title);
2116   title_watcher.AlsoWaitForTitle(ASCIIToUTF16("Allowed"));
2117   ui_test_utils::NavigateToURL(browser(), url);
2118   ASSERT_EQ(expected_title, title_watcher.WaitAndGetTitle());
2119 }
2120
2121 class KioskModeTest : public BrowserTest {
2122  public:
2123   KioskModeTest() {}
2124
2125   void SetUpCommandLine(CommandLine* command_line) override {
2126     command_line->AppendSwitch(switches::kKioskMode);
2127   }
2128 };
2129
2130 #if defined(OS_MACOSX) || (defined(OS_LINUX) && !defined(OS_CHROMEOS))
2131 // Mac: http://crbug.com/103912
2132 // Linux: http://crbug.com/163931
2133 #define MAYBE_EnableKioskModeTest DISABLED_EnableKioskModeTest
2134 #else
2135 #define MAYBE_EnableKioskModeTest EnableKioskModeTest
2136 #endif
2137 IN_PROC_BROWSER_TEST_F(KioskModeTest, MAYBE_EnableKioskModeTest) {
2138   // Check if browser is in fullscreen mode.
2139   ASSERT_TRUE(browser()->window()->IsFullscreen());
2140   ASSERT_FALSE(browser()->window()->IsFullscreenBubbleVisible());
2141 }
2142
2143 #if defined(OS_WIN)
2144 // This test verifies that Chrome can be launched with a user-data-dir path
2145 // which contains non ASCII characters.
2146 class LaunchBrowserWithNonAsciiUserDatadir : public BrowserTest {
2147  public:
2148   LaunchBrowserWithNonAsciiUserDatadir() {}
2149
2150   virtual void SetUpCommandLine(CommandLine* command_line) override {
2151     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
2152     base::FilePath tmp_profile = temp_dir_.path().AppendASCII("tmp_profile");
2153     tmp_profile = tmp_profile.Append(L"Test Chrome G\u00E9raldine");
2154
2155     ASSERT_TRUE(base::CreateDirectory(tmp_profile));
2156     command_line->AppendSwitchPath(switches::kUserDataDir, tmp_profile);
2157   }
2158
2159   base::ScopedTempDir temp_dir_;
2160 };
2161
2162 IN_PROC_BROWSER_TEST_F(LaunchBrowserWithNonAsciiUserDatadir,
2163                        TestNonAsciiUserDataDir) {
2164   // Verify that the window is present.
2165   ASSERT_TRUE(browser());
2166 }
2167 #endif  // defined(OS_WIN)
2168
2169 // Tests to ensure that the browser continues running in the background after
2170 // the last window closes.
2171 class RunInBackgroundTest : public BrowserTest {
2172  public:
2173   RunInBackgroundTest() {}
2174
2175   void SetUpCommandLine(CommandLine* command_line) override {
2176     command_line->AppendSwitch(switches::kKeepAliveForTest);
2177   }
2178 };
2179
2180 IN_PROC_BROWSER_TEST_F(RunInBackgroundTest, RunInBackgroundBasicTest) {
2181   // Close the browser window, then open a new one - the browser should keep
2182   // running.
2183   Profile* profile = browser()->profile();
2184   EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
2185   content::WindowedNotificationObserver observer(
2186       chrome::NOTIFICATION_BROWSER_CLOSED,
2187       content::Source<Browser>(browser()));
2188   chrome::CloseWindow(browser());
2189   observer.Wait();
2190   EXPECT_EQ(0u, chrome::GetTotalBrowserCount());
2191
2192   ui_test_utils::BrowserAddedObserver browser_added_observer;
2193   chrome::NewEmptyWindow(profile, chrome::GetActiveDesktop());
2194   browser_added_observer.WaitForSingleNewBrowser();
2195
2196   EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
2197 }
2198
2199 // Tests to ensure that the browser continues running in the background after
2200 // the last window closes.
2201 class NoStartupWindowTest : public BrowserTest {
2202  public:
2203   NoStartupWindowTest() {}
2204
2205   void SetUpCommandLine(CommandLine* command_line) override {
2206     command_line->AppendSwitch(switches::kNoStartupWindow);
2207     command_line->AppendSwitch(switches::kKeepAliveForTest);
2208   }
2209
2210   // Returns true if any commands were processed.
2211   bool ProcessedAnyCommands(BaseSessionService* base_session_service) {
2212     return base_session_service->ProcessedAnyCommandsForTest();
2213   }
2214 };
2215
2216 IN_PROC_BROWSER_TEST_F(NoStartupWindowTest, NoStartupWindowBasicTest) {
2217 #if defined(OS_WIN) && defined(USE_ASH)
2218   // kNoStartupWindow doesn't make sense in Metro+Ash.
2219   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
2220     return;
2221 #endif
2222
2223   // No browser window should be started by default.
2224   EXPECT_EQ(0u, chrome::GetTotalBrowserCount());
2225
2226   // Starting a browser window should work just fine.
2227   ui_test_utils::BrowserAddedObserver browser_added_observer;
2228   CreateBrowser(ProfileManager::GetActiveUserProfile());
2229   browser_added_observer.WaitForSingleNewBrowser();
2230
2231   EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
2232 }
2233
2234 // Chromeos needs to track app windows because it considers them to be part of
2235 // session state.
2236 #if !defined(OS_CHROMEOS)
2237 IN_PROC_BROWSER_TEST_F(NoStartupWindowTest, DontInitSessionServiceForApps) {
2238 #if defined(OS_WIN) && defined(USE_ASH)
2239   // kNoStartupWindow doesn't make sense in Metro+Ash.
2240   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
2241     return;
2242 #endif
2243
2244   Profile* profile = ProfileManager::GetActiveUserProfile();
2245
2246   SessionService* session_service =
2247       SessionServiceFactory::GetForProfile(profile);
2248   BaseSessionService* base_session_service =
2249       session_service->GetBaseSessionServiceForTest();
2250   ASSERT_FALSE(ProcessedAnyCommands(base_session_service));
2251
2252   ui_test_utils::BrowserAddedObserver browser_added_observer;
2253   CreateBrowserForApp("blah", profile);
2254   browser_added_observer.WaitForSingleNewBrowser();
2255
2256   ASSERT_FALSE(ProcessedAnyCommands(base_session_service));
2257 }
2258 #endif  // !defined(OS_CHROMEOS)
2259
2260 // This test needs to be placed outside the anonymous namespace because we
2261 // need to access private type of Browser.
2262 class AppModeTest : public BrowserTest {
2263  public:
2264   AppModeTest() {}
2265
2266   void SetUpCommandLine(CommandLine* command_line) override {
2267     GURL url = ui_test_utils::GetTestUrl(
2268        base::FilePath(), base::FilePath().AppendASCII("title1.html"));
2269     command_line->AppendSwitchASCII(switches::kApp, url.spec());
2270   }
2271 };
2272
2273 IN_PROC_BROWSER_TEST_F(AppModeTest, EnableAppModeTest) {
2274 #if defined(OS_WIN) && defined(USE_ASH)
2275   // Disable this test in Metro+Ash for now (http://crbug.com/262796).
2276   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
2277     return;
2278 #endif
2279
2280   // Test that an application browser window loads correctly.
2281
2282   // Verify the browser is in application mode.
2283   EXPECT_TRUE(browser()->is_app());
2284 }
2285
2286 // Confirm chrome://version contains some expected content.
2287 IN_PROC_BROWSER_TEST_F(BrowserTest, AboutVersion) {
2288   ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIVersionURL));
2289   WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
2290   ASSERT_GT(ui_test_utils::FindInPage(tab, ASCIIToUTF16("WebKit"), true, true,
2291                                       NULL, NULL),
2292             0);
2293   ASSERT_GT(ui_test_utils::FindInPage(tab, ASCIIToUTF16("OS"), true, true,
2294                                       NULL, NULL),
2295             0);
2296   ASSERT_GT(ui_test_utils::FindInPage(tab, ASCIIToUTF16("JavaScript"), true,
2297                                       true, NULL, NULL),
2298             0);
2299 }
2300
2301 static const base::FilePath::CharType* kTestDir =
2302     FILE_PATH_LITERAL("click_modifier");
2303 static const char kFirstPageTitle[] = "First window";
2304 static const char kSecondPageTitle[] = "New window!";
2305
2306 class ClickModifierTest : public InProcessBrowserTest {
2307  public:
2308   ClickModifierTest() {
2309   }
2310
2311   // Returns a url that opens a new window or tab when clicked, via javascript.
2312   GURL GetWindowOpenURL() {
2313     return ui_test_utils::GetTestUrl(
2314       base::FilePath(kTestDir),
2315       base::FilePath(FILE_PATH_LITERAL("window_open.html")));
2316   }
2317
2318   // Returns a url that follows a simple link when clicked, unless affected by
2319   // modifiers.
2320   GURL GetHrefURL() {
2321     return ui_test_utils::GetTestUrl(
2322       base::FilePath(kTestDir),
2323       base::FilePath(FILE_PATH_LITERAL("href.html")));
2324   }
2325
2326   base::string16 getFirstPageTitle() {
2327     return ASCIIToUTF16(kFirstPageTitle);
2328   }
2329
2330   base::string16 getSecondPageTitle() {
2331     return ASCIIToUTF16(kSecondPageTitle);
2332   }
2333
2334   // Loads our test page and simulates a single click using the supplied button
2335   // and modifiers.  The click will cause either a navigation or the creation of
2336   // a new window or foreground or background tab.  We verify that the expected
2337   // disposition occurs.
2338   void RunTest(Browser* browser,
2339                const GURL& url,
2340                int modifiers,
2341                blink::WebMouseEvent::Button button,
2342                WindowOpenDisposition disposition) {
2343     ui_test_utils::NavigateToURL(browser, url);
2344     EXPECT_EQ(1u, chrome::GetBrowserCount(browser->profile(),
2345                                           browser->host_desktop_type()));
2346     EXPECT_EQ(1, browser->tab_strip_model()->count());
2347     content::WebContents* web_contents =
2348         browser->tab_strip_model()->GetActiveWebContents();
2349     EXPECT_EQ(url, web_contents->GetURL());
2350
2351     if (disposition == CURRENT_TAB) {
2352       content::WebContents* web_contents =
2353           browser->tab_strip_model()->GetActiveWebContents();
2354       content::TestNavigationObserver same_tab_observer(web_contents);
2355       SimulateMouseClick(web_contents, modifiers, button);
2356       same_tab_observer.Wait();
2357       EXPECT_EQ(1u, chrome::GetBrowserCount(browser->profile(),
2358                                             browser->host_desktop_type()));
2359       EXPECT_EQ(1, browser->tab_strip_model()->count());
2360       EXPECT_EQ(getSecondPageTitle(), web_contents->GetTitle());
2361       return;
2362     }
2363
2364     content::WindowedNotificationObserver observer(
2365         chrome::NOTIFICATION_TAB_ADDED,
2366         content::NotificationService::AllSources());
2367     SimulateMouseClick(web_contents, modifiers, button);
2368     observer.Wait();
2369
2370     if (disposition == NEW_WINDOW) {
2371       EXPECT_EQ(2u, chrome::GetBrowserCount(browser->profile(),
2372                                             browser->host_desktop_type()));
2373       return;
2374     }
2375
2376     EXPECT_EQ(1u, chrome::GetBrowserCount(browser->profile(),
2377                                           browser->host_desktop_type()));
2378     EXPECT_EQ(2, browser->tab_strip_model()->count());
2379     web_contents = browser->tab_strip_model()->GetActiveWebContents();
2380     WaitForLoadStop(web_contents);
2381     if (disposition == NEW_FOREGROUND_TAB) {
2382       EXPECT_EQ(getSecondPageTitle(), web_contents->GetTitle());
2383     } else {
2384       ASSERT_EQ(NEW_BACKGROUND_TAB, disposition);
2385       EXPECT_EQ(getFirstPageTitle(), web_contents->GetTitle());
2386     }
2387   }
2388
2389  private:
2390   DISALLOW_COPY_AND_ASSIGN(ClickModifierTest);
2391 };
2392
2393 // Tests for clicking on elements with handlers that run window.open.
2394
2395 IN_PROC_BROWSER_TEST_F(ClickModifierTest, WindowOpenBasicClickTest) {
2396   int modifiers = 0;
2397   blink::WebMouseEvent::Button button = blink::WebMouseEvent::ButtonLeft;
2398   WindowOpenDisposition disposition = NEW_FOREGROUND_TAB;
2399   RunTest(browser(), GetWindowOpenURL(), modifiers, button, disposition);
2400 }
2401
2402 // TODO(ericu): Alt-click behavior on window.open is platform-dependent and not
2403 // well defined.  Should we add tests so we know if it changes?
2404
2405 // Shift-clicks open in a new window.
2406 IN_PROC_BROWSER_TEST_F(ClickModifierTest, WindowOpenShiftClickTest) {
2407   int modifiers = blink::WebInputEvent::ShiftKey;
2408   blink::WebMouseEvent::Button button = blink::WebMouseEvent::ButtonLeft;
2409   WindowOpenDisposition disposition = NEW_WINDOW;
2410   RunTest(browser(), GetWindowOpenURL(), modifiers, button, disposition);
2411 }
2412
2413 // Control-clicks open in a background tab.
2414 // On OSX meta [the command key] takes the place of control.
2415 IN_PROC_BROWSER_TEST_F(ClickModifierTest, WindowOpenControlClickTest) {
2416 #if defined(OS_MACOSX)
2417   int modifiers = blink::WebInputEvent::MetaKey;
2418 #else
2419   int modifiers = blink::WebInputEvent::ControlKey;
2420 #endif
2421   blink::WebMouseEvent::Button button = blink::WebMouseEvent::ButtonLeft;
2422   WindowOpenDisposition disposition = NEW_BACKGROUND_TAB;
2423   RunTest(browser(), GetWindowOpenURL(), modifiers, button, disposition);
2424 }
2425
2426 // Control-shift-clicks open in a foreground tab.
2427 // On OSX meta [the command key] takes the place of control.
2428 IN_PROC_BROWSER_TEST_F(ClickModifierTest, WindowOpenControlShiftClickTest) {
2429 #if defined(OS_MACOSX)
2430   int modifiers = blink::WebInputEvent::MetaKey;
2431 #else
2432   int modifiers = blink::WebInputEvent::ControlKey;
2433 #endif
2434   modifiers |= blink::WebInputEvent::ShiftKey;
2435   blink::WebMouseEvent::Button button = blink::WebMouseEvent::ButtonLeft;
2436   WindowOpenDisposition disposition = NEW_FOREGROUND_TAB;
2437   RunTest(browser(), GetWindowOpenURL(), modifiers, button, disposition);
2438 }
2439
2440 // Middle-clicks open in a background tab.
2441 #if defined(OS_LINUX)
2442 // http://crbug.com/396347
2443 #define MAYBE_WindowOpenMiddleClickTest DISABLED_WindowOpenMiddleClickTest
2444 #else
2445 #define MAYBE_WindowOpenMiddleClickTest WindowOpenMiddleClickTest
2446 #endif
2447 IN_PROC_BROWSER_TEST_F(ClickModifierTest, MAYBE_WindowOpenMiddleClickTest) {
2448   int modifiers = 0;
2449   blink::WebMouseEvent::Button button = blink::WebMouseEvent::ButtonMiddle;
2450   WindowOpenDisposition disposition = NEW_BACKGROUND_TAB;
2451   RunTest(browser(), GetWindowOpenURL(), modifiers, button, disposition);
2452 }
2453
2454 // Shift-middle-clicks open in a foreground tab.
2455 IN_PROC_BROWSER_TEST_F(ClickModifierTest, WindowOpenShiftMiddleClickTest) {
2456   int modifiers = blink::WebInputEvent::ShiftKey;
2457   blink::WebMouseEvent::Button button = blink::WebMouseEvent::ButtonMiddle;
2458   WindowOpenDisposition disposition = NEW_FOREGROUND_TAB;
2459   RunTest(browser(), GetWindowOpenURL(), modifiers, button, disposition);
2460 }
2461
2462 // Tests for clicking on normal links.
2463
2464 IN_PROC_BROWSER_TEST_F(ClickModifierTest, HrefBasicClickTest) {
2465   int modifiers = 0;
2466   blink::WebMouseEvent::Button button = blink::WebMouseEvent::ButtonLeft;
2467   WindowOpenDisposition disposition = CURRENT_TAB;
2468   RunTest(browser(), GetHrefURL(), modifiers, button, disposition);
2469 }
2470
2471 // TODO(ericu): Alt-click behavior on links is platform-dependent and not well
2472 // defined.  Should we add tests so we know if it changes?
2473
2474 // Shift-clicks open in a new window.
2475 IN_PROC_BROWSER_TEST_F(ClickModifierTest, HrefShiftClickTest) {
2476   int modifiers = blink::WebInputEvent::ShiftKey;
2477   blink::WebMouseEvent::Button button = blink::WebMouseEvent::ButtonLeft;
2478   WindowOpenDisposition disposition = NEW_WINDOW;
2479   RunTest(browser(), GetHrefURL(), modifiers, button, disposition);
2480 }
2481
2482 // Control-clicks open in a background tab.
2483 // On OSX meta [the command key] takes the place of control.
2484 IN_PROC_BROWSER_TEST_F(ClickModifierTest, HrefControlClickTest) {
2485 #if defined(OS_MACOSX)
2486   int modifiers = blink::WebInputEvent::MetaKey;
2487 #else
2488   int modifiers = blink::WebInputEvent::ControlKey;
2489 #endif
2490   blink::WebMouseEvent::Button button = blink::WebMouseEvent::ButtonLeft;
2491   WindowOpenDisposition disposition = NEW_BACKGROUND_TAB;
2492   RunTest(browser(), GetHrefURL(), modifiers, button, disposition);
2493 }
2494
2495 // Control-shift-clicks open in a foreground tab.
2496 // On OSX meta [the command key] takes the place of control.
2497 // http://crbug.com/396347
2498 IN_PROC_BROWSER_TEST_F(ClickModifierTest, DISABLED_HrefControlShiftClickTest) {
2499 #if defined(OS_MACOSX)
2500   int modifiers = blink::WebInputEvent::MetaKey;
2501 #else
2502   int modifiers = blink::WebInputEvent::ControlKey;
2503 #endif
2504   modifiers |= blink::WebInputEvent::ShiftKey;
2505   blink::WebMouseEvent::Button button = blink::WebMouseEvent::ButtonLeft;
2506   WindowOpenDisposition disposition = NEW_FOREGROUND_TAB;
2507   RunTest(browser(), GetHrefURL(), modifiers, button, disposition);
2508 }
2509
2510 // Middle-clicks open in a background tab.
2511 IN_PROC_BROWSER_TEST_F(ClickModifierTest, HrefMiddleClickTest) {
2512   int modifiers = 0;
2513   blink::WebMouseEvent::Button button = blink::WebMouseEvent::ButtonMiddle;
2514   WindowOpenDisposition disposition = NEW_BACKGROUND_TAB;
2515   RunTest(browser(), GetHrefURL(), modifiers, button, disposition);
2516 }
2517
2518 // Shift-middle-clicks open in a foreground tab.
2519 // http://crbug.com/396347
2520 IN_PROC_BROWSER_TEST_F(ClickModifierTest, DISABLED_HrefShiftMiddleClickTest) {
2521   int modifiers = blink::WebInputEvent::ShiftKey;
2522   blink::WebMouseEvent::Button button = blink::WebMouseEvent::ButtonMiddle;
2523   WindowOpenDisposition disposition = NEW_FOREGROUND_TAB;
2524   RunTest(browser(), GetHrefURL(), modifiers, button, disposition);
2525 }
2526
2527 IN_PROC_BROWSER_TEST_F(BrowserTest, GetSizeForNewRenderView) {
2528   // The instant extended NTP has javascript that does not work with
2529   // ui_test_utils::NavigateToURL.  The NTP rvh reloads when the browser tries
2530   // to navigate away from the page, which causes the WebContents to end up in
2531   // an inconsistent state. (is_loaded = true, last_commited_url=ntp,
2532   // visible_url=title1.html)
2533   browser()->profile()->GetPrefs()->SetBoolean(prefs::kWebKitJavascriptEnabled,
2534                                                false);
2535   ASSERT_TRUE(test_server()->Start());
2536   // Create an HTTPS server for cross-site transition.
2537   net::SpawnedTestServer https_test_server(net::SpawnedTestServer::TYPE_HTTPS,
2538                                            net::SpawnedTestServer::kLocalhost,
2539                                            base::FilePath(kDocRoot));
2540   ASSERT_TRUE(https_test_server.Start());
2541
2542   // Start with NTP.
2543   ui_test_utils::NavigateToURL(browser(), GURL("chrome://newtab"));
2544   ASSERT_EQ(BookmarkBar::DETACHED, browser()->bookmark_bar_state());
2545   WebContents* web_contents =
2546       browser()->tab_strip_model()->GetActiveWebContents();
2547   content::RenderViewHost* prev_rvh = web_contents->GetRenderViewHost();
2548   const int height_inset =
2549       browser()->window()->GetRenderViewHeightInsetWithDetachedBookmarkBar();
2550   const gfx::Size initial_wcv_size =
2551       web_contents->GetContainerBounds().size();
2552   RenderViewSizeObserver observer(web_contents, browser()->window());
2553
2554   // Navigate to a non-NTP page, without resizing WebContentsView.
2555   ui_test_utils::NavigateToURL(browser(),
2556                                test_server()->GetURL("files/title1.html"));
2557   ASSERT_EQ(BookmarkBar::HIDDEN, browser()->bookmark_bar_state());
2558   // A new RenderViewHost should be created.
2559   EXPECT_NE(prev_rvh, web_contents->GetRenderViewHost());
2560   prev_rvh = web_contents->GetRenderViewHost();
2561   gfx::Size rwhv_create_size0, rwhv_commit_size0, wcv_commit_size0;
2562   observer.GetSizeForRenderViewHost(web_contents->GetRenderViewHost(),
2563                                     &rwhv_create_size0,
2564                                     &rwhv_commit_size0,
2565                                     &wcv_commit_size0);
2566   // The create height of RenderWidgetHostView should include the height inset.
2567   EXPECT_EQ(gfx::Size(initial_wcv_size.width(),
2568                       initial_wcv_size.height() + height_inset),
2569             rwhv_create_size0);
2570   // When a navigation entry is committed, the size of RenderWidgetHostView
2571   // should be the same as when it was first created.
2572   EXPECT_EQ(rwhv_create_size0, rwhv_commit_size0);
2573   // Sizes of the current RenderWidgetHostView and WebContentsView should not
2574   // change before and after WebContentsDelegate::DidNavigateMainFramePostCommit
2575   // (implemented by Browser); we obtain the sizes before PostCommit via
2576   // WebContentsObserver::NavigationEntryCommitted (implemented by
2577   // RenderViewSizeObserver).
2578   EXPECT_EQ(rwhv_commit_size0,
2579             web_contents->GetRenderWidgetHostView()->GetViewBounds().size());
2580 // The behavior differs between OSX and views.
2581 // In OSX, the wcv does not change size until after the commit, when the
2582 // bookmark bar disappears (correct).
2583 // In views, the wcv changes size at commit time.
2584 #if defined(OS_MACOSX)
2585   EXPECT_EQ(gfx::Size(wcv_commit_size0.width(),
2586                       wcv_commit_size0.height() + height_inset),
2587             web_contents->GetContainerBounds().size());
2588 #else
2589   EXPECT_EQ(wcv_commit_size0, web_contents->GetContainerBounds().size());
2590 #endif
2591
2592   // Navigate to another non-NTP page, without resizing WebContentsView.
2593   ui_test_utils::NavigateToURL(browser(),
2594                                https_test_server.GetURL("files/title2.html"));
2595   ASSERT_EQ(BookmarkBar::HIDDEN, browser()->bookmark_bar_state());
2596   // A new RenderVieHost should be created.
2597   EXPECT_NE(prev_rvh, web_contents->GetRenderViewHost());
2598   gfx::Size rwhv_create_size1, rwhv_commit_size1, wcv_commit_size1;
2599   observer.GetSizeForRenderViewHost(web_contents->GetRenderViewHost(),
2600                                     &rwhv_create_size1,
2601                                     &rwhv_commit_size1,
2602                                     &wcv_commit_size1);
2603   EXPECT_EQ(rwhv_create_size1, rwhv_commit_size1);
2604   EXPECT_EQ(rwhv_commit_size1,
2605             web_contents->GetRenderWidgetHostView()->GetViewBounds().size());
2606   EXPECT_EQ(wcv_commit_size1, web_contents->GetContainerBounds().size());
2607
2608   // Navigate from NTP to a non-NTP page, resizing WebContentsView while
2609   // navigation entry is pending.
2610   ui_test_utils::NavigateToURL(browser(), GURL("chrome://newtab"));
2611   gfx::Size wcv_resize_insets(1, 1);
2612   observer.set_wcv_resize_insets(wcv_resize_insets);
2613   ui_test_utils::NavigateToURL(browser(),
2614                                test_server()->GetURL("files/title2.html"));
2615   ASSERT_EQ(BookmarkBar::HIDDEN, browser()->bookmark_bar_state());
2616   gfx::Size rwhv_create_size2, rwhv_commit_size2, wcv_commit_size2;
2617   observer.GetSizeForRenderViewHost(web_contents->GetRenderViewHost(),
2618                                     &rwhv_create_size2,
2619                                     &rwhv_commit_size2,
2620                                     &wcv_commit_size2);
2621
2622   // The behavior on OSX and Views is incorrect in this edge case, but they are
2623   // differently incorrect.
2624   // The behavior should be:
2625   // initial wcv size: (100,100)  (to choose random numbers)
2626   // initial rwhv size: (100,140)
2627   // commit wcv size: (101, 101)
2628   // commit rwhv size: (101, 141)
2629   // final wcv size: (101, 141)
2630   // final rwhv size: (101, 141)
2631   //
2632   // On OSX, the commit rwhv size is (101, 101)
2633   // On views, the commit wcv size is (101, 141)
2634   // All other sizes are correct.
2635
2636   // The create height of RenderWidgetHostView should include the height inset.
2637   EXPECT_EQ(gfx::Size(initial_wcv_size.width(),
2638                       initial_wcv_size.height() + height_inset),
2639             rwhv_create_size2);
2640   gfx::Size exp_commit_size(initial_wcv_size);
2641
2642 #if defined(OS_MACOSX)
2643   exp_commit_size.Enlarge(wcv_resize_insets.width(),
2644                           wcv_resize_insets.height());
2645 #else
2646   exp_commit_size.Enlarge(wcv_resize_insets.width(),
2647                           wcv_resize_insets.height() + height_inset);
2648 #endif
2649   EXPECT_EQ(exp_commit_size, rwhv_commit_size2);
2650   EXPECT_EQ(exp_commit_size, wcv_commit_size2);
2651   gfx::Size exp_final_size(initial_wcv_size);
2652   exp_final_size.Enlarge(wcv_resize_insets.width(),
2653                          wcv_resize_insets.height() + height_inset);
2654   EXPECT_EQ(exp_final_size,
2655             web_contents->GetRenderWidgetHostView()->GetViewBounds().size());
2656   EXPECT_EQ(exp_final_size, web_contents->GetContainerBounds().size());
2657 }