render_process_host_chrome_browsertest.cc revision f2477e01787aa58f445919b809d89e252beef54f
1551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer// Copyright (c) 2012 The Chromium Authors. All rights reserved.
263b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman// Use of this source code is governed by a BSD-style license that can be
36c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke// found in the LICENSE file.
46c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke
57ed47a13356daed2a34cd2209a31f92552e3bdd8Chris Lattner#include "base/command_line.h"
67ed47a13356daed2a34cd2209a31f92552e3bdd8Chris Lattner#include "chrome/browser/chrome_notification_types.h"
763b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman#include "chrome/browser/devtools/devtools_window.h"
86c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke#include "chrome/browser/search/search.h"
96c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke#include "chrome/browser/ui/browser.h"
106c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke#include "chrome/browser/ui/browser_commands.h"
116c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke#include "chrome/browser/ui/singleton_tabs.h"
1263b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman#include "chrome/browser/ui/tabs/tab_strip_model.h"
139a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson#include "chrome/common/chrome_switches.h"
149a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson#include "chrome/common/url_constants.h"
159a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson#include "chrome/test/base/in_process_browser_test.h"
169a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson#include "chrome/test/base/test_switches.h"
176c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke#include "chrome/test/base/ui_test_utils.h"
186c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke#include "content/public/browser/notification_service.h"
196c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke#include "content/public/browser/render_process_host.h"
20551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer#include "content/public/browser/render_view_host.h"
21551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer#include "content/public/browser/render_widget_host_iterator.h"
22551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer#include "content/public/browser/web_contents.h"
238b67f774e9c38b7718b2b300b628388f966df4e0Chandler Carruth#include "content/public/browser/web_contents_observer.h"
246c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke
256c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaekeusing content::RenderViewHost;
266c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaekeusing content::RenderWidgetHost;
276c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaekeusing content::WebContents;
286c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke
296c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaekenamespace {
306c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke
316c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaekeint RenderProcessHostCount() {
326c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  content::RenderProcessHost::iterator hosts =
336c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke      content::RenderProcessHost::AllHostsIterator();
346c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  int count = 0;
356c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  while (!hosts.IsAtEnd()) {
36620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke    if (hosts.GetCurrentValue()->HasConnection())
37620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke      count++;
38620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke    hosts.Advance();
39620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke  }
40620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke  return count;
41620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke}
42620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke
43620ee02353d8b65959dc01a66b073adfcdef9eacBrian GaekeRenderViewHost* FindFirstDevToolsHost() {
44620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke  scoped_ptr<content::RenderWidgetHostIterator> widgets(
45620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke      RenderWidgetHost::GetRenderWidgetHosts());
466c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  while (content::RenderWidgetHost* widget = widgets->GetNextHost()) {
47757c1f9d87b516a1e3bc4cd678245b207ae9c559Brian Gaeke    if (!widget->GetProcess()->HasConnection())
486c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke      continue;
499a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson    if (!widget->IsRenderView())
509a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson      continue;
519a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson    RenderViewHost* host = RenderViewHost::From(widget);
529a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson    WebContents* contents = WebContents::FromRenderViewHost(host);
539a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson    GURL url = contents->GetURL();
549a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson    if (url.SchemeIs(chrome::kChromeDevToolsScheme))
559a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson      return host;
569a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson  }
579a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson  return NULL;
589a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson}
599a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson
609a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson}  // namespace
619a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson
629a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilsonclass ChromeRenderProcessHostTest : public InProcessBrowserTest {
639a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson public:
646c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  ChromeRenderProcessHostTest() {}
659a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson
666c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  // Show a tab, activating the current one if there is one, and wait for
676c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  // the renderer process to be created or foregrounded, returning the process
686c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  // handle.
696c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  base::ProcessHandle ShowSingletonTab(const GURL& page) {
706c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    chrome::ShowSingletonTab(browser(), page);
716c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    WebContents* wc = browser()->tab_strip_model()->GetActiveWebContents();
726c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    CHECK(wc->GetURL() == page);
736c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke
746c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    // Ensure that the backgrounding / foregrounding gets a chance to run.
756c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    content::BrowserThread::PostTaskAndReply(
766c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke        content::BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
776c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke        base::Bind(&base::DoNothing), base::MessageLoop::QuitClosure());
786c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    base::MessageLoop::current()->Run();
79fe4591bfc2b147c10d6a7b1a5af56454fb78daceStephen Wilson
80314451326ad1ef89241b240a704e104897e4ee81Stephen Wilson    return wc->GetRenderProcessHost()->GetHandle();
816c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  }
829a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson
839a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson  // When we hit the max number of renderers, verify that the way we do process
846c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  // sharing behaves correctly.  In particular, this test is verifying that even
856c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  // when we hit the max process limit, that renderers of each type will wind up
86620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke  // in a process of that type, even if that means creating a new process.
87620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke  void TestProcessOverflow() {
88e9f6f2c0492af8097166f1b7d62f131f20ca5714Brian Gaeke    int tab_count = 1;
899a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson    int host_count = 1;
90620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke    WebContents* tab1 = NULL;
91620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke    WebContents* tab2 = NULL;
92620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke    content::RenderProcessHost* rph1 = NULL;
93620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke    content::RenderProcessHost* rph2 = NULL;
94620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke    content::RenderProcessHost* rph3 = NULL;
95620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke
96620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke    // Change the first tab to be the omnibox page (TYPE_WEBUI).
97620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke    GURL omnibox(chrome::kChromeUIOmniboxURL);
98620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke    ui_test_utils::NavigateToURL(browser(), omnibox);
99620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke    EXPECT_EQ(tab_count, browser()->tab_strip_model()->count());
100620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke    tab1 = browser()->tab_strip_model()->GetWebContentsAt(tab_count - 1);
101620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke    rph1 = tab1->GetRenderProcessHost();
102620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke    EXPECT_EQ(omnibox, tab1->GetURL());
1039a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson    EXPECT_EQ(host_count, RenderProcessHostCount());
1049a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson
1059a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson    // Create a new TYPE_TABBED tab.  It should be in its own process.
1069a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson    GURL page1("data:text/html,hello world1");
1079a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson
108e9f6f2c0492af8097166f1b7d62f131f20ca5714Brian Gaeke    ui_test_utils::WindowedTabAddedNotificationObserver observer1(
109620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke        content::NotificationService::AllSources());
1106c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    chrome::ShowSingletonTab(browser(), page1);
1116c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    observer1.Wait();
1126c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke
1136c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    tab_count++;
1146c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    host_count++;
1156c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    EXPECT_EQ(tab_count, browser()->tab_strip_model()->count());
1166c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    tab1 = browser()->tab_strip_model()->GetWebContentsAt(tab_count - 1);
1176c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    rph2 = tab1->GetRenderProcessHost();
1186c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    EXPECT_EQ(tab1->GetURL(), page1);
1196c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    EXPECT_EQ(host_count, RenderProcessHostCount());
1206c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    EXPECT_NE(rph1, rph2);
1215af8f421b6412e52530608097e39d2602195629fDan Gohman
1225af8f421b6412e52530608097e39d2602195629fDan Gohman    // Create another TYPE_TABBED tab.  It should share the previous process.
1235af8f421b6412e52530608097e39d2602195629fDan Gohman    GURL page2("data:text/html,hello world2");
1245af8f421b6412e52530608097e39d2602195629fDan Gohman    ui_test_utils::WindowedTabAddedNotificationObserver observer2(
1255af8f421b6412e52530608097e39d2602195629fDan Gohman        content::NotificationService::AllSources());
1265af8f421b6412e52530608097e39d2602195629fDan Gohman    chrome::ShowSingletonTab(browser(), page2);
1276c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    observer2.Wait();
1286c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    tab_count++;
1296c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    EXPECT_EQ(tab_count, browser()->tab_strip_model()->count());
1306c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    tab2 = browser()->tab_strip_model()->GetWebContentsAt(tab_count - 1);
1316c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    EXPECT_EQ(tab2->GetURL(), page2);
1326c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    EXPECT_EQ(host_count, RenderProcessHostCount());
1336c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    EXPECT_EQ(tab2->GetRenderProcessHost(), rph2);
1346c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke
135620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke    // Create another TYPE_WEBUI tab.  It should share the process with omnibox.
1366c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    // Note: intentionally create this tab after the TYPE_TABBED tabs to
137620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke    // exercise bug 43448 where extension and WebUI tabs could get combined into
138620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke    // normal renderers.
1399a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson    GURL history(chrome::kChromeUIHistoryURL);
140620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke    ui_test_utils::WindowedTabAddedNotificationObserver observer3(
141620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke        content::NotificationService::AllSources());
142cc5fc60468a1915049ef19a549fe4a6ae8708a00Bruno Cardoso Lopes    chrome::ShowSingletonTab(browser(), history);
143cc5fc60468a1915049ef19a549fe4a6ae8708a00Bruno Cardoso Lopes    observer3.Wait();
1446c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    tab_count++;
1456c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    EXPECT_EQ(tab_count, browser()->tab_strip_model()->count());
1466c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    tab2 = browser()->tab_strip_model()->GetWebContentsAt(tab_count - 1);
1476c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    EXPECT_EQ(tab2->GetURL(), GURL(history));
1486c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    EXPECT_EQ(host_count, RenderProcessHostCount());
1496c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    EXPECT_EQ(tab2->GetRenderProcessHost(), rph1);
1506c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke
1516c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    // Create a TYPE_EXTENSION tab.  It should be in its own process.
1526c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    // (the bookmark manager is implemented as an extension)
1536c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    GURL bookmarks(chrome::kChromeUIBookmarksURL);
1549a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson    ui_test_utils::WindowedTabAddedNotificationObserver observer4(
1556c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke        content::NotificationService::AllSources());
1566c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    chrome::ShowSingletonTab(browser(), bookmarks);
1576c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    observer4.Wait();
1586c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    tab_count++;
159e07cc5dab102c0f8c3f66c2703c95e547d6bf1c6Matt Fleming    host_count++;
1605af8f421b6412e52530608097e39d2602195629fDan Gohman    EXPECT_EQ(tab_count, browser()->tab_strip_model()->count());
161e07cc5dab102c0f8c3f66c2703c95e547d6bf1c6Matt Fleming    tab1 = browser()->tab_strip_model()->GetWebContentsAt(tab_count - 1);
162e07cc5dab102c0f8c3f66c2703c95e547d6bf1c6Matt Fleming    rph3 = tab1->GetRenderProcessHost();
163e07cc5dab102c0f8c3f66c2703c95e547d6bf1c6Matt Fleming    EXPECT_EQ(tab1->GetURL(), bookmarks);
164e07cc5dab102c0f8c3f66c2703c95e547d6bf1c6Matt Fleming    EXPECT_EQ(host_count, RenderProcessHostCount());
165e07cc5dab102c0f8c3f66c2703c95e547d6bf1c6Matt Fleming    EXPECT_NE(rph1, rph3);
166e07cc5dab102c0f8c3f66c2703c95e547d6bf1c6Matt Fleming    EXPECT_NE(rph2, rph3);
167e07cc5dab102c0f8c3f66c2703c95e547d6bf1c6Matt Fleming  }
168e07cc5dab102c0f8c3f66c2703c95e547d6bf1c6Matt Fleming};
169e07cc5dab102c0f8c3f66c2703c95e547d6bf1c6Matt Fleming
170e07cc5dab102c0f8c3f66c2703c95e547d6bf1c6Matt Fleming
171e07cc5dab102c0f8c3f66c2703c95e547d6bf1c6Matt Flemingclass ChromeRenderProcessHostTestWithCommandLine
172e07cc5dab102c0f8c3f66c2703c95e547d6bf1c6Matt Fleming    : public ChromeRenderProcessHostTest {
173e07cc5dab102c0f8c3f66c2703c95e547d6bf1c6Matt Fleming protected:
174e07cc5dab102c0f8c3f66c2703c95e547d6bf1c6Matt Fleming  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
175e07cc5dab102c0f8c3f66c2703c95e547d6bf1c6Matt Fleming    command_line->AppendSwitchASCII(switches::kRendererProcessLimit, "1");
176e07cc5dab102c0f8c3f66c2703c95e547d6bf1c6Matt Fleming  }
177e07cc5dab102c0f8c3f66c2703c95e547d6bf1c6Matt Fleming};
178e07cc5dab102c0f8c3f66c2703c95e547d6bf1c6Matt Fleming
179e07cc5dab102c0f8c3f66c2703c95e547d6bf1c6Matt FlemingIN_PROC_BROWSER_TEST_F(ChromeRenderProcessHostTest, ProcessPerTab) {
180e07cc5dab102c0f8c3f66c2703c95e547d6bf1c6Matt Fleming  // Set max renderers to 1 to force running out of processes.
1815af8f421b6412e52530608097e39d2602195629fDan Gohman  content::RenderProcessHost::SetMaxRendererProcessCount(1);
1825af8f421b6412e52530608097e39d2602195629fDan Gohman
183004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming  CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
184004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming  parsed_command_line.AppendSwitch(switches::kProcessPerTab);
185004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming
186004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming  int tab_count = 1;
187004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming  int host_count = 1;
188004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming
189004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming  // Change the first tab to be the new tab page (TYPE_WEBUI).
190004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming  GURL omnibox(chrome::kChromeUIOmniboxURL);
191004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming  ui_test_utils::NavigateToURL(browser(), omnibox);
192004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming  EXPECT_EQ(tab_count, browser()->tab_strip_model()->count());
193004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming  EXPECT_EQ(host_count, RenderProcessHostCount());
194004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming
195004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming  // Create a new TYPE_TABBED tab.  It should be in its own process.
196004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming  GURL page1("data:text/html,hello world1");
197004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming  ui_test_utils::WindowedTabAddedNotificationObserver observer1(
198004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming      content::NotificationService::AllSources());
199004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming  chrome::ShowSingletonTab(browser(), page1);
200004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming  observer1.Wait();
201004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming  tab_count++;
202004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming  host_count++;
203004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming  EXPECT_EQ(tab_count, browser()->tab_strip_model()->count());
204004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming  EXPECT_EQ(host_count, RenderProcessHostCount());
205004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming
206004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming  // Create another TYPE_TABBED tab.  It should share the previous process.
207004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming  GURL page2("data:text/html,hello world2");
208004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming  ui_test_utils::WindowedTabAddedNotificationObserver observer2(
209004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming      content::NotificationService::AllSources());
210004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming  chrome::ShowSingletonTab(browser(), page2);
211004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming  observer2.Wait();
212004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming  tab_count++;
213004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming  EXPECT_EQ(tab_count, browser()->tab_strip_model()->count());
214004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming  EXPECT_EQ(host_count, RenderProcessHostCount());
215004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming
216004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming  // Create another omnibox tab.  It should share the process with the other
217004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming  // WebUI.
218004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming  ui_test_utils::NavigateToURLWithDisposition(
2196c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke      browser(), omnibox, NEW_FOREGROUND_TAB,
2206c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
2216c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  tab_count++;
2226c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  EXPECT_EQ(tab_count, browser()->tab_strip_model()->count());
2236c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  EXPECT_EQ(host_count, RenderProcessHostCount());
2246c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke
2256c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  // Create another omnibox tab.  It should share the process with the other
2266c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  // WebUI.
22763b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman  ui_test_utils::NavigateToURLWithDisposition(
2286c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke      browser(), omnibox, NEW_FOREGROUND_TAB,
2296c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
2306c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  tab_count++;
2316c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  EXPECT_EQ(tab_count, browser()->tab_strip_model()->count());
2326c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  EXPECT_EQ(host_count, RenderProcessHostCount());
233620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke}
234e9f6f2c0492af8097166f1b7d62f131f20ca5714Brian Gaeke
235620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke// We don't change process priorities on Mac or Posix because the user lacks the
236620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke// permission to raise a process' priority even after lowering it.
237620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke#if defined(OS_WIN) || defined(OS_LINUX)
238620ee02353d8b65959dc01a66b073adfcdef9eacBrian GaekeIN_PROC_BROWSER_TEST_F(ChromeRenderProcessHostTest, Backgrounding) {
239620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke  if (!base::Process::CanBackgroundProcesses()) {
240620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke    LOG(ERROR) << "Can't background processes";
241620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke    return;
242620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke  }
243620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke  CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
244620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke  parsed_command_line.AppendSwitch(switches::kProcessPerTab);
245e9f6f2c0492af8097166f1b7d62f131f20ca5714Brian Gaeke
246620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke  // Change the first tab to be the omnibox page (TYPE_WEBUI).
2476c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  GURL omnibox(chrome::kChromeUIOmniboxURL);
2486c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  ui_test_utils::NavigateToURL(browser(), omnibox);
2496c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke
2506c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  // Create a new tab. It should be foreground.
2516c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  GURL page1("data:text/html,hello world1");
2526c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  base::ProcessHandle pid1 = ShowSingletonTab(page1);
2536c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  EXPECT_FALSE(base::Process(pid1).IsProcessBackgrounded());
2546c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke
2556c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  // Create another tab. It should be foreground, and the first tab should
2566c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  // now be background.
2576c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  GURL page2("data:text/html,hello world2");
2586c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  base::ProcessHandle pid2 = ShowSingletonTab(page2);
2596c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  EXPECT_NE(pid1, pid2);
2606c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  EXPECT_TRUE(base::Process(pid1).IsProcessBackgrounded());
2616c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  EXPECT_FALSE(base::Process(pid2).IsProcessBackgrounded());
2626c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke
2636c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  // Navigate back to first page. It should be foreground again, and the second
2646c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  // tab should be background.
2656c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  EXPECT_EQ(pid1, ShowSingletonTab(page1));
2666c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  EXPECT_FALSE(base::Process(pid1).IsProcessBackgrounded());
2676c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  EXPECT_TRUE(base::Process(pid2).IsProcessBackgrounded());
2686c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke}
2696c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke#endif
2706c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke
2716c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke// TODO(nasko): crbug.com/173137
2726c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke#if defined(OS_WIN)
2736c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke#define MAYBE_ProcessOverflow DISABLED_ProcessOverflow
2746c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke#else
2756c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke#define MAYBE_ProcessOverflow ProcessOverflow
2766c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke#endif
2776c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke
2786c39a42b5c93b6d0af008dbafed6134d1deaa848Brian GaekeIN_PROC_BROWSER_TEST_F(ChromeRenderProcessHostTest, MAYBE_ProcessOverflow) {
2796c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  // Set max renderers to 1 to force running out of processes.
2806c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  content::RenderProcessHost::SetMaxRendererProcessCount(1);
2816c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  TestProcessOverflow();
2826c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke}
2836c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke
2846c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke// Variation of the ProcessOverflow test, which is driven through command line
2856c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke// parameter instead of direct function call into the class.
2869a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen WilsonIN_PROC_BROWSER_TEST_F(ChromeRenderProcessHostTestWithCommandLine,
2876c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke                       ProcessOverflow) {
2886c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  TestProcessOverflow();
2896c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke}
2906c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke
2916c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke// Ensure that DevTools opened to debug DevTools is launched in a separate
2926c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke// process when --process-per-tab is set. See crbug.com/69873.
2936c39a42b5c93b6d0af008dbafed6134d1deaa848Brian GaekeIN_PROC_BROWSER_TEST_F(ChromeRenderProcessHostTest,
29463b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman                       DevToolsOnSelfInOwnProcessPPT) {
2956c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke#if defined(OS_WIN) && defined(USE_ASH)
2966c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  // Disable this test in Metro+Ash for now (http://crbug.com/262796).
297314451326ad1ef89241b240a704e104897e4ee81Stephen Wilson  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
298314451326ad1ef89241b240a704e104897e4ee81Stephen Wilson    return;
299314451326ad1ef89241b240a704e104897e4ee81Stephen Wilson#endif
300314451326ad1ef89241b240a704e104897e4ee81Stephen Wilson
301314451326ad1ef89241b240a704e104897e4ee81Stephen Wilson  CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
3026c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  parsed_command_line.AppendSwitch(switches::kProcessPerTab);
3036c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke
3046c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  int tab_count = 1;
3056c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  int host_count = 1;
3069a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson
3079a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson  GURL page1("data:text/html,hello world1");
3089a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson  ui_test_utils::WindowedTabAddedNotificationObserver observer1(
3099a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson      content::NotificationService::AllSources());
3109a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson  chrome::ShowSingletonTab(browser(), page1);
3119a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson  observer1.Wait();
3129a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson  tab_count++;
3139a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson  host_count++;
3149a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson  EXPECT_EQ(tab_count, browser()->tab_strip_model()->count());
3159a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson  EXPECT_EQ(host_count, RenderProcessHostCount());
3169a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson
3179a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson  // DevTools start in docked mode (no new tab), in a separate process.
3189a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson  chrome::ToggleDevToolsWindow(browser(), DevToolsToggleAction::Inspect());
3199a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson  host_count++;
3209a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson  EXPECT_EQ(tab_count, browser()->tab_strip_model()->count());
3219a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson  EXPECT_EQ(host_count, RenderProcessHostCount());
3229a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson
3239a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson  RenderViewHost* devtools = FindFirstDevToolsHost();
3249a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson  DCHECK(devtools);
3259a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson
3266c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  // DevTools start in a separate process.
3276c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  DevToolsWindow::ToggleDevToolsWindow(
3286c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke      devtools, true, DevToolsToggleAction::Inspect());
3296c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  host_count++;
3306c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  EXPECT_EQ(tab_count, browser()->tab_strip_model()->count());
3316c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  EXPECT_EQ(host_count, RenderProcessHostCount());
3326c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke
3336c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  // close docked devtools
3346c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  content::WindowedNotificationObserver close_observer(
3356c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke      content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
3366c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke      content::Source<WebContents>(WebContents::FromRenderViewHost(devtools)));
3376c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke
3386c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  chrome::ToggleDevToolsWindow(browser(), DevToolsToggleAction::Toggle());
3396c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  close_observer.Wait();
3406c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke}
3416c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke
34253621a1a7376cba5d0a22c12a171933eb8c6d3f6Eli Friedman// Ensure that DevTools opened to debug DevTools is launched in a separate
34353621a1a7376cba5d0a22c12a171933eb8c6d3f6Eli Friedman// process. See crbug.com/69873.
3446c39a42b5c93b6d0af008dbafed6134d1deaa848Brian GaekeIN_PROC_BROWSER_TEST_F(ChromeRenderProcessHostTest,
3456c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke                       DevToolsOnSelfInOwnProcess) {
3466c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke#if defined(OS_WIN) && defined(USE_ASH)
3476c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  // Disable this test in Metro+Ash for now (http://crbug.com/262796).
34853621a1a7376cba5d0a22c12a171933eb8c6d3f6Eli Friedman  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
34953621a1a7376cba5d0a22c12a171933eb8c6d3f6Eli Friedman    return;
35053621a1a7376cba5d0a22c12a171933eb8c6d3f6Eli Friedman#endif
35153621a1a7376cba5d0a22c12a171933eb8c6d3f6Eli Friedman
35253621a1a7376cba5d0a22c12a171933eb8c6d3f6Eli Friedman  int tab_count = 1;
35353621a1a7376cba5d0a22c12a171933eb8c6d3f6Eli Friedman  int host_count = 1;
35453621a1a7376cba5d0a22c12a171933eb8c6d3f6Eli Friedman
3556c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  GURL page1("data:text/html,hello world1");
3566c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  ui_test_utils::WindowedTabAddedNotificationObserver observer1(
35763b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman      content::NotificationService::AllSources());
3586c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  chrome::ShowSingletonTab(browser(), page1);
35963b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman  observer1.Wait();
3606c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  tab_count++;
3616c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  host_count++;
362314451326ad1ef89241b240a704e104897e4ee81Stephen Wilson  EXPECT_EQ(tab_count, browser()->tab_strip_model()->count());
363314451326ad1ef89241b240a704e104897e4ee81Stephen Wilson  EXPECT_EQ(host_count, RenderProcessHostCount());
364314451326ad1ef89241b240a704e104897e4ee81Stephen Wilson
365314451326ad1ef89241b240a704e104897e4ee81Stephen Wilson  // DevTools start in docked mode (no new tab), in a separate process.
366314451326ad1ef89241b240a704e104897e4ee81Stephen Wilson  chrome::ToggleDevToolsWindow(browser(), DevToolsToggleAction::Inspect());
3676c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  host_count++;
3686c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  EXPECT_EQ(tab_count, browser()->tab_strip_model()->count());
3696c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  EXPECT_EQ(host_count, RenderProcessHostCount());
3706c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke
3716c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  RenderViewHost* devtools = FindFirstDevToolsHost();
3726c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  DCHECK(devtools);
37363b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman
3746c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  // DevTools start in a separate process.
3756c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  DevToolsWindow::ToggleDevToolsWindow(
37663b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman      devtools, true, DevToolsToggleAction::Inspect());
3776c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  host_count++;
3786c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  EXPECT_EQ(tab_count, browser()->tab_strip_model()->count());
379314451326ad1ef89241b240a704e104897e4ee81Stephen Wilson  EXPECT_EQ(host_count, RenderProcessHostCount());
380314451326ad1ef89241b240a704e104897e4ee81Stephen Wilson
381314451326ad1ef89241b240a704e104897e4ee81Stephen Wilson  // close docked devtools
382314451326ad1ef89241b240a704e104897e4ee81Stephen Wilson  content::WindowedNotificationObserver close_observer(
383314451326ad1ef89241b240a704e104897e4ee81Stephen Wilson      content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
3846c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke      content::Source<content::WebContents>(
3856c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke          WebContents::FromRenderViewHost(devtools)));
3866c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  chrome::ToggleDevToolsWindow(browser(), DevToolsToggleAction::Toggle());
3876c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  close_observer.Wait();
388004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming}
389004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming
390004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming// This class's goal is to close the browser window when a renderer process has
391004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming// crashed. It does so by monitoring WebContents for RenderProcessGone event and
392004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming// closing the passed in TabStripModel. This is used in the following test case.
393004c82ad7c0d2da761726f063373c28ffd18e66dMatt Flemingclass WindowDestroyer : public content::WebContentsObserver {
394004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming public:
395314451326ad1ef89241b240a704e104897e4ee81Stephen Wilson  WindowDestroyer(content::WebContents* web_contents, TabStripModel* model)
396314451326ad1ef89241b240a704e104897e4ee81Stephen Wilson      : content::WebContentsObserver(web_contents),
397004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming        tab_strip_model_(model) {
398004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming  }
399314451326ad1ef89241b240a704e104897e4ee81Stephen Wilson
400314451326ad1ef89241b240a704e104897e4ee81Stephen Wilson  virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE {
401314451326ad1ef89241b240a704e104897e4ee81Stephen Wilson    // Wait for the window to be destroyed, which will ensure all other
402004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming    // RenderViewHost objects are deleted before we return and proceed with
403004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming    // the next iteration of notifications.
404004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming    content::WindowedNotificationObserver observer(
405004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming        chrome::NOTIFICATION_BROWSER_CLOSED,
406004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming        content::NotificationService::AllSources());
407004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming    tab_strip_model_->CloseAllTabs();
408004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming    observer.Wait();
409004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming  }
410004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming
411004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming private:
412004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming  TabStripModel* tab_strip_model_;
413004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming
414314451326ad1ef89241b240a704e104897e4ee81Stephen Wilson  DISALLOW_COPY_AND_ASSIGN(WindowDestroyer);
415314451326ad1ef89241b240a704e104897e4ee81Stephen Wilson};
416004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming
417004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming// Test to ensure that while iterating through all listeners in
418314451326ad1ef89241b240a704e104897e4ee81Stephen Wilson// RenderProcessHost and invalidating them, we remove them properly and don't
419314451326ad1ef89241b240a704e104897e4ee81Stephen Wilson// access already freed objects. See http://crbug.com/255524.
420314451326ad1ef89241b240a704e104897e4ee81Stephen WilsonIN_PROC_BROWSER_TEST_F(ChromeRenderProcessHostTest,
421004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming                       CloseAllTabsDuringProcessDied) {
422004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming  GURL url(chrome::kChromeUIOmniboxURL);
423004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming
424004c82ad7c0d2da761726f063373c28ffd18e66dMatt Fleming  ui_test_utils::NavigateToURL(browser(), url);
4259a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson  ui_test_utils::NavigateToURLWithDisposition(
4266c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke      browser(), url, NEW_BACKGROUND_TAB,
4276c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
4286c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke
4296c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  EXPECT_EQ(2, browser()->tab_strip_model()->count());
4306c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke
4316c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  WebContents* wc1 = browser()->tab_strip_model()->GetWebContentsAt(0);
4326c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  WebContents* wc2 = browser()->tab_strip_model()->GetWebContentsAt(1);
4336c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  EXPECT_EQ(wc1->GetRenderProcessHost(), wc2->GetRenderProcessHost());
4346c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke
4356c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  // Create an object that will close the window on a process crash.
4366c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  WindowDestroyer destroyer(wc1, browser()->tab_strip_model());
4379a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson
4389a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson  // Use NOTIFICATION_BROWSER_CLOSED instead of NOTIFICATION_WINDOW_CLOSED,
4399a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson  // since the latter is not implemented on OSX and the test will timeout,
4409a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson  // causing it to fail.
4419a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson  content::WindowedNotificationObserver observer(
4429a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson      chrome::NOTIFICATION_BROWSER_CLOSED,
4439a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson      content::NotificationService::AllSources());
4449a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson
4459a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson  // Kill the renderer process, simulating a crash. This should the ProcessDied
4469a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson  // method to be called. Alternatively, RenderProcessHost::OnChannelError can
4479a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson  // be called to directly force a call to ProcessDied.
4489a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson  base::KillProcess(wc1->GetRenderProcessHost()->GetHandle(), -1, true);
4494e9ca339b56f082c6b2d7dd7d91f704801c0d4fdMikhail Glushenkov
4506c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  observer.Wait();
4516c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke}
4526c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke