Chromium Code Reviews| Index: content/browser/renderer_host/render_process_host_browsertest.cc |
| diff --git a/content/browser/renderer_host/render_process_host_browsertest.cc b/content/browser/renderer_host/render_process_host_browsertest.cc |
| index 995addc8a90c696aae3d2b4c5c1831d29922c3de..df9b604ea1d6e4d6976eca39cd91d59789f6f21c 100644 |
| --- a/content/browser/renderer_host/render_process_host_browsertest.cc |
| +++ b/content/browser/renderer_host/render_process_host_browsertest.cc |
| @@ -6,14 +6,23 @@ |
| #include "base/bind_helpers.h" |
| #include "base/command_line.h" |
| #include "base/process.h" |
| +#include "chrome/browser/chrome_content_browser_client.h" |
|
jam
2012/03/21 23:30:12
you're going to get a checkdeps failure for this..
Charlie Reis
2012/03/21 23:44:14
Yeah, I realized that... This seems like a limita
Charlie Reis
2012/03/21 23:51:17
Actually, we've already got a render_process_host_
|
| #include "chrome/browser/ui/browser.h" |
| #include "chrome/test/base/in_process_browser_test.h" |
| #include "chrome/test/base/ui_test_utils.h" |
| #include "content/browser/renderer_host/render_process_host_impl.h" |
| #include "content/browser/tab_contents/tab_contents.h" |
| +#include "content/common/child_process_messages.h" |
| #include "content/common/test_url_constants.h" |
| +#include "content/public/browser/browser_message_filter.h" |
| #include "content/public/browser/browser_thread.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/common/content_switches.h" |
| +#include "content/public/common/referrer.h" |
| +#include "ipc/ipc_message_macros.h" |
| using content::WebContents; |
| @@ -21,6 +30,69 @@ void PostQuit(MessageLoop* loop) { |
| loop->PostTask(FROM_HERE, MessageLoop::QuitClosure()); |
| } |
| +namespace { |
| + |
| +// 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; |
| + } |
| + |
| + 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 RenderProcessHostTest : public InProcessBrowserTest { |
| public: |
| RenderProcessHostTest() { |
| @@ -56,6 +128,17 @@ class RenderProcessHostTest : public InProcessBrowserTest { |
| return wc->GetRenderProcessHost()->GetHandle(); |
| } |
| + 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_); |
| + } |
| + |
| // When we hit the max number of renderers, verify that the way we do process |
| // sharing behaves correctly. In particular, this test is verifying that even |
| // when we hit the max process limit, that renderers of each type will wind up |
| @@ -143,6 +226,12 @@ class RenderProcessHostTest : public InProcessBrowserTest { |
| EXPECT_NE(rph1, rph3); |
| EXPECT_NE(rph2, rph3); |
| } |
| + |
| + protected: |
| + RenderProcessHostTestBrowserClient browser_client_; |
| + |
| + private: |
| + content::ContentBrowserClient* old_browser_client_; |
| }; |
| @@ -257,3 +346,42 @@ IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, ProcessOverflow) { |
| IN_PROC_BROWSER_TEST_F(RenderProcessHostTestWithCommandLine, ProcessOverflow) { |
| TestProcessOverflow(); |
| } |
| + |
| +// 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(RenderProcessHostTest, DontPutNTPInDyingProcess) { |
| + // Change the first tab to be the new tab page (TYPE_WEBUI). |
| + GURL newtab(chrome::kTestNewTabURL); |
| + ui_test_utils::NavigateToURL(browser(), newtab); |
| + content::RenderProcessHost* rph = |
| + browser()->GetSelectedWebContents()->GetRenderProcessHost(); |
| + RenderProcessHostImpl* process = static_cast<RenderProcessHostImpl*>(rph); |
| + |
| + // 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); |
| + process->OnShutdownRequest(); |
| + |
| + // Wait for the NTP navigation to finish. |
| + nav_observer.Wait(); |
| + WebContents* contents = browser()->GetSelectedWebContents(); |
| + EXPECT_EQ(process, contents->GetRenderProcessHost()); |
| + EXPECT_TRUE(process->HasConnection()); |
| +} |