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