Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(90)

Unified Diff: chrome/browser/unload_browsertest.cc

Issue 11016023: Quickly close tabs/window with long-running unload handlers. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Patch for landing Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/ui/views/frame/browser_view.cc ('k') | chrome/test/data/fast_tab_close/no_listeners.html » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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.
« no previous file with comments | « chrome/browser/ui/views/frame/browser_view.cc ('k') | chrome/test/data/fast_tab_close/no_listeners.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698