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 "base/command_line.h"
6#include "chrome/browser/ui/browser.h"
7#include "chrome/browser/ui/browser_commands.h"
8#include "chrome/browser/ui/tabs/tab_strip_model.h"
9#include "chrome/common/chrome_switches.h"
10#include "chrome/common/url_constants.h"
11#include "chrome/test/base/in_process_browser_test.h"
12#include "chrome/test/base/ui_test_utils.h"
13#include "content/public/browser/render_process_host.h"
14#include "content/public/browser/web_contents.h"
15#include "content/public/test/browser_test_utils.h"
16#include "content/public/test/test_navigation_observer.h"
17#include "url/gurl.h"
18
19using content::OpenURLParams;
20using content::Referrer;
21
22class NewTabUIBrowserTest : public InProcessBrowserTest {
23 public:
24  NewTabUIBrowserTest() {}
25};
26
27// TODO(samarth): delete along with rest of NTP4 code.
28// #if defined(OS_WIN)
29// // Flaky on Windows (http://crbug.com/174819)
30// #define MAYBE_LoadNTPInExistingProcess DISABLED_LoadNTPInExistingProcess
31// #else
32// #define MAYBE_LoadNTPInExistingProcess LoadNTPInExistingProcess
33// #endif
34
35// Ensure loading a NTP with an existing SiteInstance in a reused process
36// doesn't cause us to kill the process.  See http://crbug.com/104258.
37IN_PROC_BROWSER_TEST_F(NewTabUIBrowserTest, DISABLED_LoadNTPInExistingProcess) {
38  // Set max renderers to 1 to force running out of processes.
39  content::RenderProcessHost::SetMaxRendererProcessCount(1);
40
41  // Start server for simple page.
42  ASSERT_TRUE(test_server()->Start());
43
44  // Load a NTP in a new tab.
45  ui_test_utils::NavigateToURLWithDisposition(
46      browser(), GURL(chrome::kChromeUINewTabURL), NEW_FOREGROUND_TAB,
47      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
48  EXPECT_EQ(1,
49            browser()->tab_strip_model()->GetWebContentsAt(1)->GetMaxPageID());
50
51  // Navigate that tab to another site.  This allows the NTP process to exit,
52  // but it keeps the NTP SiteInstance (and its max_page_id) alive in history.
53  {
54    // Wait not just for the navigation to finish, but for the NTP process to
55    // exit as well.
56    content::RenderProcessHostWatcher process_exited_observer(
57        browser()->tab_strip_model()->GetActiveWebContents(),
58        content::RenderProcessHostWatcher::WATCH_FOR_HOST_DESTRUCTION);
59    browser()->OpenURL(OpenURLParams(
60        test_server()->GetURL("files/title1.html"), Referrer(), CURRENT_TAB,
61        ui::PAGE_TRANSITION_TYPED, false));
62    process_exited_observer.Wait();
63  }
64
65  // Creating a NTP in another tab should not be affected, since page IDs
66  // are now specific to a tab.
67  ui_test_utils::NavigateToURLWithDisposition(
68      browser(), GURL(chrome::kChromeUINewTabURL), NEW_FOREGROUND_TAB,
69      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
70  EXPECT_EQ(1,
71            browser()->tab_strip_model()->GetWebContentsAt(2)->GetMaxPageID());
72  chrome::CloseTab(browser());
73
74  // Open another Web UI page in a new tab.
75  ui_test_utils::NavigateToURLWithDisposition(
76      browser(), GURL(chrome::kChromeUISettingsURL), NEW_FOREGROUND_TAB,
77      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
78  EXPECT_EQ(1,
79            browser()->tab_strip_model()->GetWebContentsAt(2)->GetMaxPageID());
80
81  // At this point, opening another NTP will use the existing WebUI process
82  // but its own SiteInstance, so the page IDs shouldn't affect each other.
83  ui_test_utils::NavigateToURLWithDisposition(
84      browser(), GURL(chrome::kChromeUINewTabURL), NEW_FOREGROUND_TAB,
85      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
86  EXPECT_EQ(1,
87            browser()->tab_strip_model()->GetWebContentsAt(3)->GetMaxPageID());
88
89  // Navigating to the NTP in the original tab causes a BrowsingInstance
90  // swap, so it gets a new SiteInstance starting with page ID 1 again.
91  browser()->tab_strip_model()->ActivateTabAt(1, true);
92  ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL));
93  EXPECT_EQ(1,
94            browser()->tab_strip_model()->GetWebContentsAt(1)->GetMaxPageID());
95}
96
97// TODO(samarth): delete along with rest of NTP4 code.
98// Loads chrome://hang/ into two NTP tabs, ensuring we don't crash.
99// See http://crbug.com/59859.
100// If this flakes, use http://crbug.com/87200.
101IN_PROC_BROWSER_TEST_F(NewTabUIBrowserTest, DISABLED_ChromeHangInNTP) {
102  // Bring up a new tab page.
103  ui_test_utils::NavigateToURLWithDisposition(
104      browser(), GURL(chrome::kChromeUINewTabURL), NEW_FOREGROUND_TAB,
105      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
106
107  // Navigate to chrome://hang/ to stall the process.
108  ui_test_utils::NavigateToURLWithDisposition(
109      browser(), GURL(content::kChromeUIHangURL), CURRENT_TAB, 0);
110
111  // Visit chrome://hang/ again in another NTP. Don't bother waiting for the
112  // NTP to load, because it's hung.
113  chrome::NewTab(browser());
114  browser()->OpenURL(OpenURLParams(
115      GURL(content::kChromeUIHangURL), Referrer(), CURRENT_TAB,
116      ui::PAGE_TRANSITION_TYPED, false));
117}
118
119class NewTabUIProcessPerTabTest : public NewTabUIBrowserTest {
120 public:
121   NewTabUIProcessPerTabTest() {}
122
123   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
124     command_line->AppendSwitch(switches::kProcessPerTab);
125   }
126};
127
128// Navigates away from NTP before it commits, in process-per-tab mode.
129// Ensures that we don't load the normal page in the NTP process (and thus
130// crash), as in http://crbug.com/69224.
131// If this flakes, use http://crbug.com/87200
132IN_PROC_BROWSER_TEST_F(NewTabUIProcessPerTabTest, NavBeforeNTPCommits) {
133  // Bring up a new tab page.
134  ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL));
135
136  // Navigate to chrome://hang/ to stall the process.
137  ui_test_utils::NavigateToURLWithDisposition(
138      browser(), GURL(content::kChromeUIHangURL), CURRENT_TAB, 0);
139
140  // Visit a normal URL in another NTP that hasn't committed.
141  ui_test_utils::NavigateToURLWithDisposition(
142      browser(), GURL(chrome::kChromeUINewTabURL), NEW_FOREGROUND_TAB, 0);
143
144  // We don't use ui_test_utils::NavigateToURLWithDisposition because that waits
145  // for current loading to stop.
146  content::TestNavigationObserver observer(
147      browser()->tab_strip_model()->GetActiveWebContents());
148  browser()->OpenURL(OpenURLParams(
149      GURL("data:text/html,hello world"), Referrer(), CURRENT_TAB,
150      ui::PAGE_TRANSITION_TYPED, false));
151  observer.Wait();
152}
153