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()); |
+} |