Chromium Code Reviews| Index: chrome/browser/unload_browsertest.cc |
| diff --git a/chrome/browser/unload_browsertest.cc b/chrome/browser/unload_browsertest.cc |
| index 9552d0a6039708c4149598a4c8c579ee1ff5d10d..b39cb8ee1c896b9c1a83eb3b739fb0b4def82945 100644 |
| --- a/chrome/browser/unload_browsertest.cc |
| +++ b/chrome/browser/unload_browsertest.cc |
| @@ -411,5 +411,214 @@ IN_PROC_BROWSER_TEST_F(UnloadTest, BrowserCloseTabWhenOtherTabHasListener) { |
| CheckTitle("only_one_unload"); |
| } |
| +class FastUnloadTest : public UnloadTest { |
| + public: |
| + virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { |
| + UnloadTest::SetUpCommandLine(command_line); |
| + command_line->AppendSwitch(switches::kEnableFastUnload); |
| + } |
| + |
| + 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()); |
|
Avi (use Gerrit)
2013/10/11 17:58:07
You cannot use WindowedNotificationObserver like t
|
| + 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. |