Index: chrome/browser/unload_browsertest.cc |
diff --git a/chrome/browser/unload_browsertest.cc b/chrome/browser/unload_browsertest.cc |
index b07c8f8e71c422587b20291873695fe01ec15a71..83bf458ae121271f72144314d1e1be92df0af8b0 100644 |
--- a/chrome/browser/unload_browsertest.cc |
+++ b/chrome/browser/unload_browsertest.cc |
@@ -412,5 +412,210 @@ IN_PROC_BROWSER_TEST_F(UnloadTest, BrowserCloseTabWhenOtherTabHasListener) { |
CheckTitle("only_one_unload"); |
} |
+ |
+class FastUnloadTest : public UnloadTest { |
+ public: |
+ virtual void SetUpInProcessBrowserTestFixture() OVERRIDE { |
+ ASSERT_TRUE(test_server()->Start()); |
+ } |
+ |
+ virtual void TearDownInProcessBrowserTestFixture() OVERRIDE { |
+ test_server()->Stop(); |
+ } |
+ |
+ GURL GetUrl(const std::string& name) { |
+ return GURL(test_server()->GetURL( |
+ "files/fast_tab_close/" + name + ".html")); |
+ } |
+ |
+ void NavigateToPage(const char* name) { |
+ ui_test_utils::NavigateToURL(browser(), GetUrl(name)); |
+ CheckTitle(name); |
+ } |
+ |
+ void NavigateToPageInNewTab(const char* name) { |
+ ui_test_utils::NavigateToURLWithDisposition( |
+ browser(), GetUrl(name), NEW_FOREGROUND_TAB, |
+ ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); |
+ CheckTitle(name); |
+ } |
+ |
+ std::string GetCookies(const char* name) { |
+ content::WebContents* contents = |
+ browser()->tab_strip_model()->GetActiveWebContents(); |
+ return content::GetCookies(contents->GetBrowserContext(), GetUrl(name)); |
+ } |
+}; |
+ |
+class FastTabCloseTabStripModelObserver : public TabStripModelObserver { |
+ public: |
+ FastTabCloseTabStripModelObserver(TabStripModel* model, |
+ base::RunLoop* run_loop) |
+ : model_(model), |
+ run_loop_(run_loop) { |
+ model_->AddObserver(this); |
+ } |
+ |
+ virtual ~FastTabCloseTabStripModelObserver() { |
+ model_->RemoveObserver(this); |
+ } |
+ |
+ // TabStripModelObserver: |
+ virtual void TabDetachedAt(content::WebContents* contents, |
+ int index) OVERRIDE { |
+ run_loop_->Quit(); |
+ } |
+ |
+ private: |
+ TabStripModel* const model_; |
+ base::RunLoop* const run_loop_; |
+}; |
+ |
+ |
+// Test that fast-tab-close works when closing a tab with an unload handler |
+// (http://crbug.com/142458). |
+IN_PROC_BROWSER_TEST_F(FastUnloadTest, UnloadHidden) { |
+ NavigateToPage("no_listeners"); |
+ NavigateToPageInNewTab("unload_sets_cookie"); |
+ EXPECT_EQ("", GetCookies("no_listeners")); |
+ |
+ { |
+ base::RunLoop run_loop; |
+ FastTabCloseTabStripModelObserver observer( |
+ browser()->tab_strip_model(), &run_loop); |
+ chrome::CloseTab(browser()); |
+ run_loop.Run(); |
+ } |
+ |
+ // Check that the browser only has the original tab. |
+ CheckTitle("no_listeners"); |
+ EXPECT_EQ(1, browser()->tab_strip_model()->count()); |
+ |
+ // Show that the web contents to go away after the was removed. |
+ // Without unload-detached, this times-out because it happens earlier. |
+ content::WindowedNotificationObserver contents_destroyed_observer( |
+ content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
+ content::NotificationService::AllSources()); |
+ contents_destroyed_observer.Wait(); |
+ |
+ // Browser still has the same tab. |
+ CheckTitle("no_listeners"); |
+ EXPECT_EQ(1, browser()->tab_strip_model()->count()); |
+ EXPECT_EQ("unloaded=ohyeah", GetCookies("no_listeners")); |
+} |
+ |
+// Test that fast-tab-close does not break a solo tab. |
+IN_PROC_BROWSER_TEST_F(FastUnloadTest, PRE_ClosingLastTabFinishesUnload) { |
+ // The unload handler sleeps before setting the cookie to catch cases when |
+ // unload handlers are not allowed to run to completion. (For example, |
+ // using the detached handler for the tab and then closing the browser.) |
+ NavigateToPage("unload_sleep_before_cookie"); |
+ EXPECT_EQ(1, browser()->tab_strip_model()->count()); |
+ EXPECT_EQ("", GetCookies("unload_sleep_before_cookie")); |
+ |
+ content::WindowedNotificationObserver window_observer( |
+ chrome::NOTIFICATION_BROWSER_CLOSED, |
+ content::NotificationService::AllSources()); |
+ chrome::CloseTab(browser()); |
+ window_observer.Wait(); |
+} |
+IN_PROC_BROWSER_TEST_F(FastUnloadTest, ClosingLastTabFinishesUnload) { |
+ // Check for cookie set in unload handler of PRE_ test. |
+ NavigateToPage("no_listeners"); |
+ EXPECT_EQ("unloaded=ohyeah", GetCookies("no_listeners")); |
+} |
+ |
+// Test that fast-tab-close does not break window close. |
+IN_PROC_BROWSER_TEST_F(FastUnloadTest, PRE_WindowCloseFinishesUnload) { |
+ NavigateToPage("no_listeners"); |
+ |
+ // The unload handler sleeps before setting the cookie to catch cases when |
+ // unload handlers are not allowed to run to completion. Without the sleep, |
+ // the cookie can get set even if the browser does not wait for |
+ // the unload handler to finish. |
+ NavigateToPageInNewTab("unload_sleep_before_cookie"); |
+ EXPECT_EQ(2, browser()->tab_strip_model()->count()); |
+ EXPECT_EQ("", GetCookies("no_listeners")); |
+ |
+ content::WindowedNotificationObserver window_observer( |
+ chrome::NOTIFICATION_BROWSER_CLOSED, |
+ content::NotificationService::AllSources()); |
+ chrome::CloseWindow(browser()); |
+ window_observer.Wait(); |
+} |
+IN_PROC_BROWSER_TEST_F(FastUnloadTest, WindowCloseFinishesUnload) { |
+ // Check for cookie set in unload during PRE_ test. |
+ NavigateToPage("no_listeners"); |
+ EXPECT_EQ("unloaded=ohyeah", GetCookies("no_listeners")); |
+} |
+ |
+// Test that a tab crash during unload does not break window close. |
+// |
+// Hits assertion on Linux and Mac: |
+// [FATAL:profile_destroyer.cc(46)] Check failed: |
+// hosts.empty() || |
+// profile->IsOffTheRecord() || |
+// content::RenderProcessHost::run_renderer_in_process(). |
+// More details: The renderer process host matches the closed, crashed tab. |
+// The |UnloadController| receives |NOTIFICATION_WEB_CONTENTS_DISCONNECTED| |
+// and proceeds with the close. |
+IN_PROC_BROWSER_TEST_F(FastUnloadTest, DISABLED_WindowCloseAfterUnloadCrash) { |
+ NavigateToPage("no_listeners"); |
+ NavigateToPageInNewTab("unload_sets_cookie"); |
+ content::WebContents* unload_contents = |
+ browser()->tab_strip_model()->GetActiveWebContents(); |
+ EXPECT_EQ("", GetCookies("no_listeners")); |
+ |
+ { |
+ base::RunLoop run_loop; |
+ FastTabCloseTabStripModelObserver observer( |
+ browser()->tab_strip_model(), &run_loop); |
+ chrome::CloseTab(browser()); |
+ run_loop.Run(); |
+ } |
+ |
+ // Check that the browser only has the original tab. |
+ CheckTitle("no_listeners"); |
+ EXPECT_EQ(1, browser()->tab_strip_model()->count()); |
+ |
+ CrashTab(unload_contents); |
+ |
+ // Check that the browser only has the original tab. |
+ CheckTitle("no_listeners"); |
+ EXPECT_EQ(1, browser()->tab_strip_model()->count()); |
+ |
+ content::WindowedNotificationObserver window_observer( |
+ chrome::NOTIFICATION_BROWSER_CLOSED, |
+ content::NotificationService::AllSources()); |
+ chrome::CloseWindow(browser()); |
+ window_observer.Wait(); |
+} |
+ |
+// Times out on Windows and Linux. |
+#if defined(OS_WIN) || defined(OS_LINUX) |
+#define MAYBE_WindowCloseAfterBeforeUnloadCrash \ |
+ DISABLED_WindowCloseAfterBeforeUnloadCrash |
+#else |
+#define MAYBE_WindowCloseAfterBeforeUnloadCrash \ |
+ WindowCloseAfterBeforeUnloadCrash |
+#endif |
+IN_PROC_BROWSER_TEST_F(FastUnloadTest, |
+ MAYBE_WindowCloseAfterBeforeUnloadCrash) { |
+ // Tests makes no sense in single-process mode since the renderer is hung. |
+ if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess)) |
+ return; |
+ |
+ NavigateToDataURL(BEFORE_UNLOAD_HTML, "beforeunload"); |
+ content::WebContents* beforeunload_contents = |
+ browser()->tab_strip_model()->GetActiveWebContents(); |
+ |
+ content::WindowedNotificationObserver window_observer( |
+ chrome::NOTIFICATION_BROWSER_CLOSED, |
+ content::NotificationService::AllSources()); |
+ chrome::CloseWindow(browser()); |
+ CrashTab(beforeunload_contents); |
+ window_observer.Wait(); |
+} |
+ |
// TODO(ojan): Add tests for unload/beforeunload that have multiple tabs |
// and multiple windows. |