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