Chromium Code Reviews| Index: chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc |
| diff --git a/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc b/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc |
| index 633119038913d0b032568f39e18790466f7b8309..02915e5658ba4a20ff947e75c1925a99ce037ef3 100644 |
| --- a/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc |
| +++ b/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc |
| @@ -3,63 +3,152 @@ |
| // found in the LICENSE file. |
| #include "base/command_line.h" |
| +#include "chrome/browser/chrome_content_browser_client.h" |
| #include "chrome/browser/debugger/devtools_window.h" |
| #include "chrome/browser/ui/browser.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/ui_test_utils.h" |
| +#include "content/common/child_process_messages.h" |
|
Charlie Reis
2012/03/22 00:27:13
Drat. I was able to get all of it to work in chro
|
| +#include "content/public/browser/browser_message_filter.h" |
| +#include "content/public/browser/content_browser_client.h" |
| +#include "content/public/browser/notification_service.h" |
| +#include "content/public/browser/notification_types.h" |
| +#include "content/public/browser/page_navigator.h" |
| #include "content/public/browser/render_process_host.h" |
| #include "content/public/browser/render_view_host.h" |
| #include "content/public/browser/render_view_host_delegate.h" |
| +#include "content/public/browser/web_contents.h" |
| +#include "content/public/common/referrer.h" |
| +#include "ipc/ipc_message_macros.h" |
| using content::RenderViewHost; |
| using content::RenderWidgetHost; |
| namespace { |
| -int RenderProcessHostCount() { |
| - content::RenderProcessHost::iterator hosts = |
| - content::RenderProcessHost::AllHostsIterator(); |
| - int count = 0; |
| - while (!hosts.IsAtEnd()) { |
| - if (hosts.GetCurrentValue()->HasConnection()) |
| - count++; |
| - hosts.Advance(); |
| +// Custom message filter to consume shutdown messages on demand. |
| +class RenderProcessHostTestMessageFilter |
| + : public content::BrowserMessageFilter { |
| + public: |
| + RenderProcessHostTestMessageFilter() : |
| + should_filter_shutdown_requests_(false) {} |
| + virtual ~RenderProcessHostTestMessageFilter() {} |
| + |
| + void set_should_filter_shutdown_requests(bool should_filter) { |
| + should_filter_shutdown_requests_ = should_filter; |
| } |
| - return count; |
| -} |
| -RenderViewHost* FindFirstDevToolsHost() { |
| - content::RenderProcessHost::iterator hosts = |
| - content::RenderProcessHost::AllHostsIterator(); |
| - for (; !hosts.IsAtEnd(); hosts.Advance()) { |
| - content::RenderProcessHost* render_process_host = hosts.GetCurrentValue(); |
| - DCHECK(render_process_host); |
| - if (!render_process_host->HasConnection()) |
| - continue; |
| - content::RenderProcessHost::RenderWidgetHostsIterator iter( |
| - render_process_host->GetRenderWidgetHostsIterator()); |
| - for (; !iter.IsAtEnd(); iter.Advance()) { |
| - const RenderWidgetHost* widget = iter.GetCurrentValue(); |
| - DCHECK(widget); |
| - if (!widget || !widget->IsRenderView()) |
| + bool OnMessageReceived(const IPC::Message& message, |
| + bool* message_was_ok) OVERRIDE { |
| + if (!should_filter_shutdown_requests_) |
| + return false; |
| + |
| + bool handled = true; |
| + IPC_BEGIN_MESSAGE_MAP_EX(RenderProcessHostTestMessageFilter, |
| + message, *message_was_ok) |
| + IPC_MESSAGE_HANDLER(ChildProcessHostMsg_ShutdownRequest, |
| + OnShutdownRequest) |
| + IPC_MESSAGE_UNHANDLED(handled = false) |
| + IPC_END_MESSAGE_MAP() |
| + return handled; |
| + } |
| + |
| + void OnShutdownRequest() { |
| + // Discard the message so the browser doesn't see it. |
| + } |
| + |
| + private: |
| + bool should_filter_shutdown_requests_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(RenderProcessHostTestMessageFilter); |
| +}; |
| + |
| +class RenderProcessHostTestBrowserClient |
| + : public chrome::ChromeContentBrowserClient { |
| + public: |
| + RenderProcessHostTestBrowserClient() : |
| + message_filter_(new RenderProcessHostTestMessageFilter()) {} |
| + virtual ~RenderProcessHostTestBrowserClient() {} |
| + |
| + // ChromeContentBrowserClient implementation. |
| + virtual void RenderProcessHostCreated(content::RenderProcessHost* host) |
| + OVERRIDE { |
| + // Install our custom filter first. |
| + host->GetChannel()->AddFilter(message_filter_); |
| + |
| + // Install the remaining message filters. |
| + ChromeContentBrowserClient::RenderProcessHostCreated(host); |
| + } |
| + |
| + scoped_refptr<RenderProcessHostTestMessageFilter> message_filter_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(RenderProcessHostTestBrowserClient); |
| +}; |
| + |
| +} // namespace |
| + |
| +class ChromeRenderProcessHostTest : public InProcessBrowserTest { |
| + public: |
| + ChromeRenderProcessHostTest() {} |
| + |
| + 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() { |
| + content::RenderProcessHost::iterator hosts = |
| + content::RenderProcessHost::AllHostsIterator(); |
| + for (; !hosts.IsAtEnd(); hosts.Advance()) { |
| + content::RenderProcessHost* render_process_host = hosts.GetCurrentValue(); |
| + DCHECK(render_process_host); |
| + if (!render_process_host->HasConnection()) |
| continue; |
| - RenderViewHost* host = |
| - RenderViewHost::From(const_cast<RenderWidgetHost*>(widget)); |
| + content::RenderProcessHost::RenderWidgetHostsIterator iter( |
| + render_process_host->GetRenderWidgetHostsIterator()); |
| + for (; !iter.IsAtEnd(); iter.Advance()) { |
| + const RenderWidgetHost* widget = iter.GetCurrentValue(); |
| + DCHECK(widget); |
| + if (!widget || !widget->IsRenderView()) |
| + continue; |
| + RenderViewHost* host = |
| + RenderViewHost::From(const_cast<RenderWidgetHost*>(widget)); |
| - content::RenderViewHostDelegate* host_delegate = host->GetDelegate(); |
| - GURL url = host_delegate->GetURL(); |
| - if (url.SchemeIs(chrome::kChromeDevToolsScheme)) |
| - return host; |
| + content::RenderViewHostDelegate* host_delegate = host->GetDelegate(); |
| + GURL url = host_delegate->GetURL(); |
| + if (url.SchemeIs(chrome::kChromeDevToolsScheme)) |
| + return host; |
| + } |
| } |
| + return NULL; |
| } |
| - return NULL; |
| -} |
| -} // namespace |
| + virtual void SetUp() OVERRIDE { |
| + old_browser_client_ = content::GetContentClient()->browser(); |
| + content::GetContentClient()->set_browser(&browser_client_); |
| + InProcessBrowserTest::SetUp(); |
| + } |
| + |
| + virtual void TearDown() OVERRIDE { |
| + InProcessBrowserTest::TearDown(); |
| + content::GetContentClient()->set_browser(old_browser_client_); |
| + } |
| + |
| + protected: |
| + RenderProcessHostTestBrowserClient browser_client_; |
| -typedef InProcessBrowserTest ChromeRenderProcessHostTest; |
| + private: |
| + content::ContentBrowserClient* old_browser_client_; |
| +}; |
| // Ensure that DevTools opened to debug DevTools is launched in a separate |
| // process when --process-per-tab is set. See crbug.com/69873. |
| @@ -137,3 +226,40 @@ IN_PROC_BROWSER_TEST_F(ChromeRenderProcessHostTest, |
| EXPECT_EQ(tab_count, browser()->tab_count()); |
| EXPECT_EQ(host_count, RenderProcessHostCount()); |
| } |
| + |
| +// Ensure that if a second NTP is opened as the first one is exiting, we don't |
| +// end up killing the second NTP as well. http://crbug.com/87176. |
| +IN_PROC_BROWSER_TEST_F(ChromeRenderProcessHostTest, DontPutNTPInDyingProcess) { |
| + // Change the first tab to be the new tab page (TYPE_WEBUI). |
| + GURL newtab(chrome::kChromeUINewTabURL); |
| + ui_test_utils::NavigateToURL(browser(), newtab); |
| + content::RenderProcessHost* rph = |
| + browser()->GetSelectedWebContents()->GetRenderProcessHost(); |
| + |
| + // Before navigating away, make sure the ShutdownRequest message is "delayed" |
| + // by consuming it and sending a new one later. |
| + browser_client_.message_filter_->set_should_filter_shutdown_requests(true); |
| + |
| + // Now navigate to a page that causes a process swap, causing the NTP's |
| + // process to send a ShutdownRequest message (which we "delay"). |
| + GURL page1("data:text/html,hello world1"); |
| + ui_test_utils::NavigateToURL(browser(), page1); |
| + |
| + // Before the ShutdownRequest message arrives, open a new tab with the NTP. |
| + ui_test_utils::WindowedNotificationObserver nav_observer( |
| + content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
| + content::NotificationService::AllSources()); |
| + ui_test_utils::NavigateToURLWithDisposition( |
| + browser(), newtab, NEW_FOREGROUND_TAB, |
| + ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB); |
| + |
| + // After the tab opens but before the navigation completes, simulate the |
| + // ShutdownRequest message arriving. |
| + browser_client_.message_filter_->set_should_filter_shutdown_requests(false); |
| + rph->OnMessageReceived(ChildProcessHostMsg_ShutdownRequest()); |
| + |
| + // Wait for the NTP navigation to finish. |
| + nav_observer.Wait(); |
| + EXPECT_EQ(rph, browser()->GetSelectedWebContents()->GetRenderProcessHost()); |
| + EXPECT_TRUE(rph->HasConnection()); |
| +} |