Chromium Code Reviews| Index: content/browser/renderer_host/render_view_host_browsertest.cc |
| diff --git a/content/browser/renderer_host/render_view_host_browsertest.cc b/content/browser/renderer_host/render_view_host_browsertest.cc |
| index 32199d15c46e601e2fe907325610f30dc9ac7c92..a655ccbfa14d2dd5fed77184b0cfe853eff422e2 100644 |
| --- a/content/browser/renderer_host/render_view_host_browsertest.cc |
| +++ b/content/browser/renderer_host/render_view_host_browsertest.cc |
| @@ -5,12 +5,15 @@ |
| #include "base/time.h" |
| #include "base/utf_string_conversions.h" |
| #include "base/values.h" |
| +#include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog.h" |
| +#include "chrome/browser/ui/app_modal_dialogs/native_app_modal_dialog.h" |
| #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_view_host_impl.h" |
| #include "content/browser/tab_contents/tab_contents.h" |
| #include "content/common/view_messages.h" |
| +#include "content/public/browser/notification_service.h" |
| #include "content/public/browser/notification_types.h" |
| #include "content/public/browser/web_contents_observer.h" |
| #include "net/base/host_port_pair.h" |
| @@ -228,3 +231,169 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostTest, BaseURLParam) { |
| ui_test_utils::NavigateToURL(browser(), test_url); |
| EXPECT_EQ("http://www.google.com/", observer.base_url().spec()); |
| } |
| + |
| +// Test that a hung renderer is killed after navigating away during cross-site |
| +// navigation. |
| +IN_PROC_BROWSER_TEST_F(RenderViewHostTest, UnresponsiveCrossSiteNavigation) { |
| + WebContents* tab = NULL; |
| + WebContents* tab2 = NULL; |
| + content::RenderProcessHost* rph = NULL; |
| + base::ProcessHandle process; |
| + FilePath doc_root; |
| + |
| + doc_root = doc_root.Append(FILE_PATH_LITERAL("content")); |
| + doc_root = doc_root.Append(FILE_PATH_LITERAL("test")); |
| + doc_root = doc_root.Append(FILE_PATH_LITERAL("data")); |
| + |
| + // Start two servers to enable cross-site navigations. |
| + net::TestServer server(net::TestServer::TYPE_HTTP, |
| + net::TestServer::kLocalhost, doc_root); |
| + ASSERT_TRUE(server.Start()); |
| + net::TestServer https_server(net::TestServer::TYPE_HTTPS, |
| + net::TestServer::kLocalhost, doc_root); |
| + ASSERT_TRUE(https_server.Start()); |
| + |
| + GURL infinite_beforeunload_url( |
| + server.GetURL("files/infinite_beforeunload.html")); |
| + GURL infinite_unload_url(server.GetURL("files/infinite_unload.html")); |
| + GURL same_process_url(server.GetURL("files/english_page.html")); |
| + GURL new_process_url(https_server.GetURL("files/english_page.html")); |
| + |
| + // Navigate the tab to the page which will lock up the process when we |
| + // navigate away from it. |
| + ui_test_utils::NavigateToURL(browser(), infinite_beforeunload_url); |
| + tab = browser()->GetWebContentsAt(0); |
| + rph = tab->GetRenderProcessHost(); |
| + EXPECT_EQ(tab->GetURL(), infinite_beforeunload_url); |
| + |
| + // Remember the process prior to navigation, as we expect it to get killed. |
| + process = rph->GetHandle(); |
| + ASSERT_TRUE(process); |
| + |
| + { |
| + ui_test_utils::WindowedNotificationObserver process_exit_observer( |
| + content::NOTIFICATION_RENDERER_PROCESS_CLOSED, |
| + content::NotificationService::AllSources()); |
| + ui_test_utils::NavigateToURL(browser(), new_process_url); |
| + process_exit_observer.Wait(); |
| + } |
| + |
| + // This should fail, because the navigation to the new URL results in |
| + // the process getting killed. This is an indirect way to check for the |
| + // process having been terminated. |
| + EXPECT_FALSE(base::KillProcess(process, 1, false)); |
| + |
| + ui_test_utils::NavigateToURL(browser(), same_process_url); |
| + tab = browser()->GetWebContentsAt(0); |
| + rph = tab->GetRenderProcessHost(); |
| + ASSERT_TRUE(tab != NULL); |
| + EXPECT_EQ(tab->GetURL(), same_process_url); |
| + |
| + // Now, let's open another tab with the unresponsive page, which will cause |
| + // the previous page and the unresponsive one to use the same process. |
| + ui_test_utils::NavigateToURLWithDisposition(browser(), |
| + infinite_unload_url, NEW_FOREGROUND_TAB, |
| + ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); |
| + EXPECT_EQ(browser()->tab_count(), 2); |
| + tab2 = browser()->GetWebContentsAt(1); |
| + ASSERT_TRUE(tab2 != NULL); |
| + EXPECT_EQ(tab2->GetURL(), infinite_unload_url); |
| + EXPECT_EQ(rph, tab2->GetRenderProcessHost()); |
| + |
| + process = rph->GetHandle(); |
| + ASSERT_TRUE(process); |
| + |
| + // Navigating to the cross site URL will not kill the process, since it will |
| + // have more than one tab using it. Kill it to confirm that it is still there, |
| + // as well as finish the test faster. |
| + { |
| + ui_test_utils::WindowedNotificationObserver process_exit_observer( |
| + content::NOTIFICATION_RENDERER_PROCESS_HANG, |
| + content::NotificationService::AllSources()); |
| + ui_test_utils::NavigateToURL(browser(), new_process_url); |
| + process_exit_observer.Wait(); |
| + } |
| + |
| + EXPECT_TRUE(base::KillProcess(process, 2, false)); |
| +} |
| + |
| +// Test that a hung renderer is killed when we are closing the page. |
| +IN_PROC_BROWSER_TEST_F(RenderViewHostTest, UnresponsiveClosePage) { |
| + WebContents* tab = NULL; |
| + FilePath doc_root; |
| + |
| + doc_root = doc_root.Append(FILE_PATH_LITERAL("content")); |
| + doc_root = doc_root.Append(FILE_PATH_LITERAL("test")); |
| + doc_root = doc_root.Append(FILE_PATH_LITERAL("data")); |
| + |
| + net::TestServer server(net::TestServer::TYPE_HTTP, |
| + net::TestServer::kLocalhost, doc_root); |
| + ASSERT_TRUE(server.Start()); |
| + net::TestServer https_server(net::TestServer::TYPE_HTTPS, |
| + net::TestServer::kLocalhost, doc_root); |
| + ASSERT_TRUE(https_server.Start()); |
| + |
| + GURL infinite_beforeunload_url( |
| + server.GetURL("files/infinite_beforeunload.html")); |
| + GURL infinite_unload_url(server.GetURL("files/infinite_unload.html")); |
| + GURL new_process_url(https_server.GetURL("files/english_page.html")); |
| + GURL prompt_infinite_url(server.GetURL( |
| + "files/prompt_beforeunload_infinite_unload.html")); |
| + |
| + ui_test_utils::NavigateToURL(browser(), new_process_url); |
| + |
| + // Navigate a tab to a page which will spin into an infinite loop in the |
| + // unload handler after prompting in the beforeunload handler, tying up the |
| + // process when we navigate away from it. |
|
Charlie Reis
2012/04/10 01:19:35
nit: when we try to close it.
nasko
2012/04/10 14:31:26
Done.
|
| + ui_test_utils::NavigateToURLWithDisposition(browser(), |
| + prompt_infinite_url, NEW_FOREGROUND_TAB, |
| + ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); |
| + tab = browser()->GetWebContentsAt(1); |
| + { |
| + ui_test_utils::WindowedNotificationObserver process_exit_observer( |
| + content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, |
| + content::NotificationService::AllSources()); |
| + browser()->CloseTabContents(tab); |
| + AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog(); |
| + alert->native_dialog()->AcceptAppModalDialog(); |
| + process_exit_observer.Wait(); |
| + } |
| + |
| + // Navigate a tab to a page which will spin into an infinite loop in the |
| + // beforeunload handler, tying up the process when we navigate away from it. |
| + ui_test_utils::NavigateToURLWithDisposition(browser(), |
| + infinite_beforeunload_url, NEW_FOREGROUND_TAB, |
| + ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); |
| + tab = browser()->GetWebContentsAt(1); |
| + { |
| + ui_test_utils::WindowedNotificationObserver process_exit_observer( |
| + content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, |
| + content::NotificationService::AllSources()); |
| + browser()->CloseTabContents(tab); |
| + process_exit_observer.Wait(); |
| + } |
| + |
| + // Navigate a tab to a page which will spin into an infinite loop in the |
| + // unload handler, tying up the process when we navigate away from it. |
| + ui_test_utils::NavigateToURLWithDisposition(browser(), |
| + infinite_unload_url, NEW_FOREGROUND_TAB, |
| + ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); |
| + tab = browser()->GetWebContentsAt(1); |
| + { |
| + ui_test_utils::WindowedNotificationObserver process_exit_observer( |
| + content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, |
| + content::NotificationService::AllSources()); |
| + browser()->CloseTabContents(tab); |
| + process_exit_observer.Wait(); |
| + } |
| + |
| + ui_test_utils::NavigateToURL(browser(), infinite_unload_url); |
|
Charlie Reis
2012/04/10 01:19:35
Comment for this last one?
nasko
2012/04/10 14:31:26
Done.
|
| + tab = browser()->GetWebContentsAt(0); |
| + { |
| + ui_test_utils::WindowedNotificationObserver process_exit_observer( |
| + content::NOTIFICATION_RENDERER_PROCESS_CLOSED, |
| + content::NotificationService::AllSources()); |
| + browser()->CloseTabContents(tab); |
| + process_exit_observer.Wait(); |
| + } |
| +} |