This source file includes following definitions.
- RenderProcessHostCount
- FindFirstDevToolsHost
- ShowSingletonTab
- OpenBackgroundTab
- WaitForLauncherThread
- TestProcessOverflow
- SetUpCommandLine
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
- tab_strip_model_
- RenderProcessGone
- IN_PROC_BROWSER_TEST_F
#include "base/command_line.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/devtools/devtools_window.h"
#include "chrome/browser/search/search.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/singleton_tabs.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/test_switches.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_iterator.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
using content::RenderViewHost;
using content::RenderWidgetHost;
using content::WebContents;
namespace {
int RenderProcessHostCount() {
content::RenderProcessHost::iterator hosts =
content::RenderProcessHost::AllHostsIterator();
int count = 0;
while (!hosts.IsAtEnd()) {
if (hosts.GetCurrentValue()->HasConnection())
count++;
hosts.Advance();
}
return count;
}
RenderViewHost* FindFirstDevToolsHost() {
scoped_ptr<content::RenderWidgetHostIterator> widgets(
RenderWidgetHost::GetRenderWidgetHosts());
while (content::RenderWidgetHost* widget = widgets->GetNextHost()) {
if (!widget->GetProcess()->HasConnection())
continue;
if (!widget->IsRenderView())
continue;
RenderViewHost* host = RenderViewHost::From(widget);
WebContents* contents = WebContents::FromRenderViewHost(host);
GURL url = contents->GetURL();
if (url.SchemeIs(content::kChromeDevToolsScheme))
return host;
}
return NULL;
}
}
class ChromeRenderProcessHostTest : public InProcessBrowserTest {
public:
ChromeRenderProcessHostTest() {}
base::ProcessHandle ShowSingletonTab(const GURL& page) {
chrome::ShowSingletonTab(browser(), page);
WebContents* wc = browser()->tab_strip_model()->GetActiveWebContents();
CHECK(wc->GetURL() == page);
WaitForLauncherThread();
return wc->GetRenderProcessHost()->GetHandle();
}
base::ProcessHandle OpenBackgroundTab(const GURL& page) {
ui_test_utils::NavigateToURLWithDisposition(browser(), page,
NEW_BACKGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
TabStripModel* tab_strip = browser()->tab_strip_model();
WebContents* wc = tab_strip->GetWebContentsAt(
tab_strip->active_index() + 1);
CHECK(wc->GetVisibleURL() == page);
WaitForLauncherThread();
return wc->GetRenderProcessHost()->GetHandle();
}
void WaitForLauncherThread() {
content::BrowserThread::PostTaskAndReply(
content::BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
base::Bind(&base::DoNothing), base::MessageLoop::QuitClosure());
base::MessageLoop::current()->Run();
}
void TestProcessOverflow() {
int tab_count = 1;
int host_count = 1;
WebContents* tab1 = NULL;
WebContents* tab2 = NULL;
content::RenderProcessHost* rph1 = NULL;
content::RenderProcessHost* rph2 = NULL;
content::RenderProcessHost* rph3 = NULL;
GURL omnibox(chrome::kChromeUIOmniboxURL);
ui_test_utils::NavigateToURL(browser(), omnibox);
EXPECT_EQ(tab_count, browser()->tab_strip_model()->count());
tab1 = browser()->tab_strip_model()->GetWebContentsAt(tab_count - 1);
rph1 = tab1->GetRenderProcessHost();
EXPECT_EQ(omnibox, tab1->GetURL());
EXPECT_EQ(host_count, RenderProcessHostCount());
GURL page1("data:text/html,hello world1");
ui_test_utils::WindowedTabAddedNotificationObserver observer1(
content::NotificationService::AllSources());
chrome::ShowSingletonTab(browser(), page1);
observer1.Wait();
tab_count++;
host_count++;
EXPECT_EQ(tab_count, browser()->tab_strip_model()->count());
tab1 = browser()->tab_strip_model()->GetWebContentsAt(tab_count - 1);
rph2 = tab1->GetRenderProcessHost();
EXPECT_EQ(tab1->GetURL(), page1);
EXPECT_EQ(host_count, RenderProcessHostCount());
EXPECT_NE(rph1, rph2);
GURL page2("data:text/html,hello world2");
ui_test_utils::WindowedTabAddedNotificationObserver observer2(
content::NotificationService::AllSources());
chrome::ShowSingletonTab(browser(), page2);
observer2.Wait();
tab_count++;
EXPECT_EQ(tab_count, browser()->tab_strip_model()->count());
tab2 = browser()->tab_strip_model()->GetWebContentsAt(tab_count - 1);
EXPECT_EQ(tab2->GetURL(), page2);
EXPECT_EQ(host_count, RenderProcessHostCount());
EXPECT_EQ(tab2->GetRenderProcessHost(), rph2);
GURL history(chrome::kChromeUIHistoryURL);
ui_test_utils::WindowedTabAddedNotificationObserver observer3(
content::NotificationService::AllSources());
chrome::ShowSingletonTab(browser(), history);
observer3.Wait();
tab_count++;
EXPECT_EQ(tab_count, browser()->tab_strip_model()->count());
tab2 = browser()->tab_strip_model()->GetWebContentsAt(tab_count - 1);
EXPECT_EQ(tab2->GetURL(), GURL(history));
EXPECT_EQ(host_count, RenderProcessHostCount());
EXPECT_EQ(tab2->GetRenderProcessHost(), rph1);
GURL bookmarks(chrome::kChromeUIBookmarksURL);
ui_test_utils::WindowedTabAddedNotificationObserver observer4(
content::NotificationService::AllSources());
chrome::ShowSingletonTab(browser(), bookmarks);
observer4.Wait();
tab_count++;
host_count++;
EXPECT_EQ(tab_count, browser()->tab_strip_model()->count());
tab1 = browser()->tab_strip_model()->GetWebContentsAt(tab_count - 1);
rph3 = tab1->GetRenderProcessHost();
EXPECT_EQ(tab1->GetURL(), bookmarks);
EXPECT_EQ(host_count, RenderProcessHostCount());
EXPECT_NE(rph1, rph3);
EXPECT_NE(rph2, rph3);
}
};
class ChromeRenderProcessHostTestWithCommandLine
: public ChromeRenderProcessHostTest {
protected:
virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
command_line->AppendSwitchASCII(switches::kRendererProcessLimit, "1");
}
};
IN_PROC_BROWSER_TEST_F(ChromeRenderProcessHostTest, ProcessPerTab) {
content::RenderProcessHost::SetMaxRendererProcessCount(1);
CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
parsed_command_line.AppendSwitch(switches::kProcessPerTab);
int tab_count = 1;
int host_count = 1;
GURL omnibox(chrome::kChromeUIOmniboxURL);
ui_test_utils::NavigateToURL(browser(), omnibox);
EXPECT_EQ(tab_count, browser()->tab_strip_model()->count());
EXPECT_EQ(host_count, RenderProcessHostCount());
GURL page1("data:text/html,hello world1");
ui_test_utils::WindowedTabAddedNotificationObserver observer1(
content::NotificationService::AllSources());
chrome::ShowSingletonTab(browser(), page1);
observer1.Wait();
tab_count++;
host_count++;
EXPECT_EQ(tab_count, browser()->tab_strip_model()->count());
EXPECT_EQ(host_count, RenderProcessHostCount());
GURL page2("data:text/html,hello world2");
ui_test_utils::WindowedTabAddedNotificationObserver observer2(
content::NotificationService::AllSources());
chrome::ShowSingletonTab(browser(), page2);
observer2.Wait();
tab_count++;
EXPECT_EQ(tab_count, browser()->tab_strip_model()->count());
EXPECT_EQ(host_count, RenderProcessHostCount());
ui_test_utils::NavigateToURLWithDisposition(
browser(), omnibox, NEW_FOREGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
tab_count++;
EXPECT_EQ(tab_count, browser()->tab_strip_model()->count());
EXPECT_EQ(host_count, RenderProcessHostCount());
ui_test_utils::NavigateToURLWithDisposition(
browser(), omnibox, NEW_FOREGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
tab_count++;
EXPECT_EQ(tab_count, browser()->tab_strip_model()->count());
EXPECT_EQ(host_count, RenderProcessHostCount());
}
#if defined(OS_WIN) || defined(OS_LINUX)
IN_PROC_BROWSER_TEST_F(ChromeRenderProcessHostTest, Backgrounding) {
if (!base::Process::CanBackgroundProcesses()) {
LOG(ERROR) << "Can't background processes";
return;
}
CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
parsed_command_line.AppendSwitch(switches::kProcessPerTab);
GURL omnibox(chrome::kChromeUIOmniboxURL);
ui_test_utils::NavigateToURL(browser(), omnibox);
GURL page1("data:text/html,hello world1");
base::ProcessHandle pid1 = ShowSingletonTab(page1);
EXPECT_FALSE(base::Process(pid1).IsProcessBackgrounded());
GURL page2("data:text/html,hello world2");
base::ProcessHandle pid2 = ShowSingletonTab(page2);
EXPECT_NE(pid1, pid2);
EXPECT_TRUE(base::Process(pid1).IsProcessBackgrounded());
EXPECT_FALSE(base::Process(pid2).IsProcessBackgrounded());
GURL page3("data:text/html,hello world3");
base::ProcessHandle pid3 = OpenBackgroundTab(page3);
EXPECT_NE(pid3, pid1);
EXPECT_NE(pid3, pid2);
EXPECT_TRUE(base::Process(pid1).IsProcessBackgrounded());
EXPECT_FALSE(base::Process(pid2).IsProcessBackgrounded());
EXPECT_TRUE(base::Process(pid3).IsProcessBackgrounded());
EXPECT_EQ(pid1, ShowSingletonTab(page1));
EXPECT_FALSE(base::Process(pid1).IsProcessBackgrounded());
EXPECT_TRUE(base::Process(pid2).IsProcessBackgrounded());
EXPECT_TRUE(base::Process(pid3).IsProcessBackgrounded());
}
#endif
#if defined(OS_WIN)
#define MAYBE_ProcessOverflow DISABLED_ProcessOverflow
#else
#define MAYBE_ProcessOverflow ProcessOverflow
#endif
IN_PROC_BROWSER_TEST_F(ChromeRenderProcessHostTest, MAYBE_ProcessOverflow) {
content::RenderProcessHost::SetMaxRendererProcessCount(1);
TestProcessOverflow();
}
IN_PROC_BROWSER_TEST_F(ChromeRenderProcessHostTestWithCommandLine,
ProcessOverflow) {
TestProcessOverflow();
}
IN_PROC_BROWSER_TEST_F(ChromeRenderProcessHostTest,
DevToolsOnSelfInOwnProcessPPT) {
#if defined(OS_WIN) && defined(USE_ASH)
if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
return;
#endif
CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
parsed_command_line.AppendSwitch(switches::kProcessPerTab);
int tab_count = 1;
int host_count = 1;
GURL page1("data:text/html,hello world1");
ui_test_utils::WindowedTabAddedNotificationObserver observer1(
content::NotificationService::AllSources());
chrome::ShowSingletonTab(browser(), page1);
observer1.Wait();
tab_count++;
host_count++;
EXPECT_EQ(tab_count, browser()->tab_strip_model()->count());
EXPECT_EQ(host_count, RenderProcessHostCount());
chrome::ToggleDevToolsWindow(browser(), DevToolsToggleAction::Inspect());
host_count++;
EXPECT_EQ(tab_count, browser()->tab_strip_model()->count());
EXPECT_EQ(host_count, RenderProcessHostCount());
RenderViewHost* devtools = FindFirstDevToolsHost();
DCHECK(devtools);
DevToolsWindow::OpenDevToolsWindow(devtools, DevToolsToggleAction::Inspect());
host_count++;
EXPECT_EQ(tab_count, browser()->tab_strip_model()->count());
EXPECT_EQ(host_count, RenderProcessHostCount());
content::WindowedNotificationObserver close_observer(
content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
content::Source<WebContents>(WebContents::FromRenderViewHost(devtools)));
chrome::ToggleDevToolsWindow(browser(), DevToolsToggleAction::Toggle());
close_observer.Wait();
}
IN_PROC_BROWSER_TEST_F(ChromeRenderProcessHostTest,
DevToolsOnSelfInOwnProcess) {
#if defined(OS_WIN) && defined(USE_ASH)
if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
return;
#endif
int tab_count = 1;
int host_count = 1;
GURL page1("data:text/html,hello world1");
ui_test_utils::WindowedTabAddedNotificationObserver observer1(
content::NotificationService::AllSources());
chrome::ShowSingletonTab(browser(), page1);
observer1.Wait();
tab_count++;
host_count++;
EXPECT_EQ(tab_count, browser()->tab_strip_model()->count());
EXPECT_EQ(host_count, RenderProcessHostCount());
chrome::ToggleDevToolsWindow(browser(), DevToolsToggleAction::Inspect());
host_count++;
EXPECT_EQ(tab_count, browser()->tab_strip_model()->count());
EXPECT_EQ(host_count, RenderProcessHostCount());
RenderViewHost* devtools = FindFirstDevToolsHost();
DCHECK(devtools);
DevToolsWindow::OpenDevToolsWindow(devtools, DevToolsToggleAction::Inspect());
host_count++;
EXPECT_EQ(tab_count, browser()->tab_strip_model()->count());
EXPECT_EQ(host_count, RenderProcessHostCount());
content::WindowedNotificationObserver close_observer(
content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
content::Source<content::WebContents>(
WebContents::FromRenderViewHost(devtools)));
chrome::ToggleDevToolsWindow(browser(), DevToolsToggleAction::Toggle());
close_observer.Wait();
}
class WindowDestroyer : public content::WebContentsObserver {
public:
WindowDestroyer(content::WebContents* web_contents, TabStripModel* model)
: content::WebContentsObserver(web_contents),
tab_strip_model_(model) {
}
virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE {
content::WindowedNotificationObserver observer(
chrome::NOTIFICATION_BROWSER_CLOSED,
content::NotificationService::AllSources());
tab_strip_model_->CloseAllTabs();
observer.Wait();
}
private:
TabStripModel* tab_strip_model_;
DISALLOW_COPY_AND_ASSIGN(WindowDestroyer);
};
IN_PROC_BROWSER_TEST_F(ChromeRenderProcessHostTest,
CloseAllTabsDuringProcessDied) {
GURL url(chrome::kChromeUIOmniboxURL);
ui_test_utils::NavigateToURL(browser(), url);
ui_test_utils::NavigateToURLWithDisposition(
browser(), url, NEW_BACKGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
EXPECT_EQ(2, browser()->tab_strip_model()->count());
WebContents* wc1 = browser()->tab_strip_model()->GetWebContentsAt(0);
WebContents* wc2 = browser()->tab_strip_model()->GetWebContentsAt(1);
EXPECT_EQ(wc1->GetRenderProcessHost(), wc2->GetRenderProcessHost());
WindowDestroyer destroyer(wc1, browser()->tab_strip_model());
content::WindowedNotificationObserver observer(
chrome::NOTIFICATION_BROWSER_CLOSED,
content::NotificationService::AllSources());
base::KillProcess(wc1->GetRenderProcessHost()->GetHandle(), -1, true);
observer.Wait();
}