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