summaryrefslogtreecommitdiffstats
path: root/chrome/browser/lifetime/browser_close_manager_browsertest.cc
diff options
context:
space:
mode:
authorsammc@chromium.org <sammc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-16 05:45:56 +0000
committersammc@chromium.org <sammc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-16 05:45:56 +0000
commit2e9d79f5f464c68f5f5d957fa32ffc2c72ef3881 (patch)
tree31c76e43c68306b0035cd1d13433b322b12f458d /chrome/browser/lifetime/browser_close_manager_browsertest.cc
parent1e7ed9716c2c13cd2d74a62879370d0d8cd6dc84 (diff)
downloadchromium_src-2e9d79f5f464c68f5f5d957fa32ffc2c72ef3881.zip
chromium_src-2e9d79f5f464c68f5f5d957fa32ffc2c72ef3881.tar.gz
chromium_src-2e9d79f5f464c68f5f5d957fa32ffc2c72ef3881.tar.bz2
Don't close tabs at shutdown until all beforeunload handlers have run.
Previously, when Chrome shuts down, each window independently runs its beforeunload handlers and aborts closing if the user decides to stay on the current page; there is no communication between windows and only windows containing tabs that the user chose to keep open remain open. The session manager is disabled when the shutdown begins so any tabs opened after shutdown is aborted won't be noticed by the session manager. With this change, all beforeunload handlers across all windows are run before any windows start closing, so the browser will return to its pre-shutdown state if a shutdown is aborted due to a beforeunload dialog. BUG=265764 Review URL: https://chromiumcodereview.appspot.com/21143003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@217949 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/lifetime/browser_close_manager_browsertest.cc')
-rw-r--r--chrome/browser/lifetime/browser_close_manager_browsertest.cc541
1 files changed, 541 insertions, 0 deletions
diff --git a/chrome/browser/lifetime/browser_close_manager_browsertest.cc b/chrome/browser/lifetime/browser_close_manager_browsertest.cc
new file mode 100644
index 0000000..34c97742
--- /dev/null
+++ b/chrome/browser/lifetime/browser_close_manager_browsertest.cc
@@ -0,0 +1,541 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <vector>
+
+#include "base/command_line.h"
+#include "chrome/browser/browser_shutdown.h"
+#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/lifetime/application_lifetime.h"
+#include "chrome/browser/lifetime/browser_close_manager.h"
+#include "chrome/browser/prefs/session_startup_pref.h"
+#include "chrome/browser/ui/app_modal_dialogs/javascript_app_modal_dialog.h"
+#include "chrome/browser/ui/app_modal_dialogs/native_app_modal_dialog.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_iterator.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/url_constants.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/test/test_navigation_observer.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+
+namespace {
+
+class AppModalDialogObserver {
+ public:
+ AppModalDialogObserver() {}
+
+ void Start() {
+ observer_.reset(new content::WindowedNotificationObserver(
+ chrome::NOTIFICATION_APP_MODAL_DIALOG_SHOWN,
+ content::NotificationService::AllSources()));
+ }
+
+ void AcceptClose() {
+ NativeAppModalDialog* dialog = GetNextDialog();
+ ASSERT_TRUE(dialog);
+ dialog->AcceptAppModalDialog();
+ }
+
+ void CancelClose() {
+ NativeAppModalDialog* dialog = GetNextDialog();
+ ASSERT_TRUE(dialog);
+ dialog->CancelAppModalDialog();
+ }
+
+ private:
+ NativeAppModalDialog* GetNextDialog() {
+ DCHECK(observer_);
+ observer_->Wait();
+ if (observer_->source() == content::NotificationService::AllSources())
+ return NULL;
+
+ AppModalDialog* dialog =
+ content::Source<AppModalDialog>(observer_->source()).ptr();
+ EXPECT_TRUE(dialog->IsJavaScriptModalDialog());
+ JavaScriptAppModalDialog* js_dialog =
+ static_cast<JavaScriptAppModalDialog*>(dialog);
+ observer_.reset(new content::WindowedNotificationObserver(
+ chrome::NOTIFICATION_APP_MODAL_DIALOG_SHOWN,
+ content::NotificationService::AllSources()));
+ return js_dialog->native_dialog();
+ }
+
+ scoped_ptr<content::WindowedNotificationObserver> observer_;
+
+ DISALLOW_COPY_AND_ASSIGN(AppModalDialogObserver);
+};
+
+class RepeatedNotificationObserver : public content::NotificationObserver {
+ public:
+ explicit RepeatedNotificationObserver(int type, int count)
+ : num_outstanding_(count), running_(false) {
+ registrar_.Add(this, type, content::NotificationService::AllSources());
+ }
+
+ virtual void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) OVERRIDE {
+ ASSERT_GT(num_outstanding_, 0);
+ if (!--num_outstanding_ && running_) {
+ content::BrowserThread::PostTask(
+ content::BrowserThread::UI, FROM_HERE, run_loop_.QuitClosure());
+ }
+ }
+
+ void Wait() {
+ if (num_outstanding_ <= 0)
+ return;
+
+ running_ = true;
+ run_loop_.Run();
+ running_ = false;
+ }
+
+ private:
+ int num_outstanding_;
+ content::NotificationRegistrar registrar_;
+ bool running_;
+ base::RunLoop run_loop_;
+
+ DISALLOW_COPY_AND_ASSIGN(RepeatedNotificationObserver);
+};
+
+} // namespace
+
+class BrowserCloseManagerBrowserTest
+ : public InProcessBrowserTest,
+ public testing::WithParamInterface<bool> {
+ protected:
+ virtual void SetUpOnMainThread() OVERRIDE {
+ InProcessBrowserTest::SetUpOnMainThread();
+ SessionStartupPref::SetStartupPref(
+ browser()->profile(), SessionStartupPref(SessionStartupPref::LAST));
+ browsers_.push_back(browser());
+ dialogs_.Start();
+ }
+
+ virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+ command_line->AppendSwitch(switches::kEnableBatchedShutdown);
+ if (GetParam())
+ command_line->AppendSwitch(switches::kEnableFastUnload);
+ }
+
+ std::vector<Browser*> browsers_;
+ AppModalDialogObserver dialogs_;
+};
+
+IN_PROC_BROWSER_TEST_P(BrowserCloseManagerBrowserTest, TestSingleTabShutdown) {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(
+ browser(), embedded_test_server()->GetURL("/beforeunload.html")));
+ RepeatedNotificationObserver cancel_observer(
+ chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED, 1);
+ chrome::CloseAllBrowsers();
+ ASSERT_NO_FATAL_FAILURE(dialogs_.CancelClose());
+ cancel_observer.Wait();
+ EXPECT_FALSE(browser_shutdown::IsTryingToQuit());
+ EXPECT_EQ(1, browser()->tab_strip_model()->count());
+
+ RepeatedNotificationObserver close_observer(
+ chrome::NOTIFICATION_BROWSER_CLOSED, 1);
+ chrome::CloseAllBrowsers();
+ ASSERT_NO_FATAL_FAILURE(dialogs_.AcceptClose());
+ close_observer.Wait();
+ EXPECT_TRUE(browser_shutdown::IsTryingToQuit());
+ EXPECT_TRUE(chrome::BrowserIterator().done());
+}
+
+IN_PROC_BROWSER_TEST_P(BrowserCloseManagerBrowserTest,
+ TestShutdownMoreThanOnce) {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(
+ browser(), embedded_test_server()->GetURL("/beforeunload.html")));
+ RepeatedNotificationObserver cancel_observer(
+ chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED, 1);
+ chrome::CloseAllBrowsers();
+ chrome::CloseAllBrowsers();
+ ASSERT_NO_FATAL_FAILURE(dialogs_.CancelClose());
+ cancel_observer.Wait();
+ EXPECT_FALSE(browser_shutdown::IsTryingToQuit());
+ EXPECT_EQ(1, browser()->tab_strip_model()->count());
+
+ RepeatedNotificationObserver close_observer(
+ chrome::NOTIFICATION_BROWSER_CLOSED, 1);
+ chrome::CloseAllBrowsers();
+ chrome::CloseAllBrowsers();
+ ASSERT_NO_FATAL_FAILURE(dialogs_.AcceptClose());
+ close_observer.Wait();
+ EXPECT_TRUE(browser_shutdown::IsTryingToQuit());
+ EXPECT_TRUE(chrome::BrowserIterator().done());
+}
+
+IN_PROC_BROWSER_TEST_P(BrowserCloseManagerBrowserTest, PRE_TestSessionRestore) {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(
+ browser(), embedded_test_server()->GetURL("/beforeunload.html")));
+ AddBlankTabAndShow(browser());
+ ASSERT_NO_FATAL_FAILURE(
+ ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIAboutURL)));
+ RepeatedNotificationObserver cancel_observer(
+ chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED, 1);
+ chrome::CloseAllBrowsers();
+ ASSERT_NO_FATAL_FAILURE(dialogs_.CancelClose());
+ cancel_observer.Wait();
+ EXPECT_FALSE(browser_shutdown::IsTryingToQuit());
+
+ browser()->tab_strip_model()
+ ->CloseWebContentsAt(1, TabStripModel::CLOSE_USER_GESTURE);
+ content::TestNavigationObserver navigation_observer(
+ browser()->tab_strip_model()->GetActiveWebContents(), 1);
+ ASSERT_NO_FATAL_FAILURE(
+ NavigateToURLWithDisposition(browser(),
+ GURL(chrome::kChromeUIVersionURL),
+ CURRENT_TAB,
+ ui_test_utils::BROWSER_TEST_NONE));
+ ASSERT_NO_FATAL_FAILURE(dialogs_.AcceptClose());
+ navigation_observer.Wait();
+
+ RepeatedNotificationObserver close_observer(
+ chrome::NOTIFICATION_BROWSER_CLOSED, 1);
+ chrome::CloseAllBrowsers();
+ close_observer.Wait();
+ EXPECT_TRUE(browser_shutdown::IsTryingToQuit());
+ EXPECT_TRUE(chrome::BrowserIterator().done());
+}
+
+// Test that the tab closed after the aborted shutdown attempt is not re-opened
+// when restoring the session.
+IN_PROC_BROWSER_TEST_P(BrowserCloseManagerBrowserTest, TestSessionRestore) {
+ // The testing framework launches Chrome with about:blank as args.
+ EXPECT_EQ(2, browser()->tab_strip_model()->count());
+ EXPECT_EQ(GURL(chrome::kChromeUIVersionURL),
+ browser()->tab_strip_model()->GetWebContentsAt(0)->GetURL());
+ EXPECT_EQ(GURL("about:blank"),
+ browser()->tab_strip_model()->GetWebContentsAt(1)->GetURL());
+}
+
+// Test that browser windows are only closed if all browsers are ready to close
+// and that all beforeunload dialogs are shown again after a cancel.
+IN_PROC_BROWSER_TEST_P(BrowserCloseManagerBrowserTest, TestMultipleWindows) {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ browsers_.push_back(CreateBrowser(browser()->profile()));
+ ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(
+ browsers_[0], embedded_test_server()->GetURL("/beforeunload.html")));
+ ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(
+ browsers_[1], embedded_test_server()->GetURL("/beforeunload.html")));
+
+ // Cancel shutdown on the first beforeunload event.
+ {
+ RepeatedNotificationObserver cancel_observer(
+ chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED, 1);
+ chrome::CloseAllBrowsers();
+ ASSERT_NO_FATAL_FAILURE(dialogs_.CancelClose());
+ cancel_observer.Wait();
+ }
+ EXPECT_FALSE(browser_shutdown::IsTryingToQuit());
+ EXPECT_EQ(1, browsers_[0]->tab_strip_model()->count());
+ EXPECT_EQ(1, browsers_[1]->tab_strip_model()->count());
+
+ // Cancel shutdown on the second beforeunload event.
+ {
+ RepeatedNotificationObserver cancel_observer(
+ chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED, 2);
+ chrome::CloseAllBrowsers();
+ ASSERT_NO_FATAL_FAILURE(dialogs_.AcceptClose());
+ ASSERT_NO_FATAL_FAILURE(dialogs_.CancelClose());
+ cancel_observer.Wait();
+ }
+ EXPECT_FALSE(browser_shutdown::IsTryingToQuit());
+ EXPECT_EQ(1, browsers_[0]->tab_strip_model()->count());
+ EXPECT_EQ(1, browsers_[1]->tab_strip_model()->count());
+
+ // Allow shutdown for both beforeunload events.
+ RepeatedNotificationObserver close_observer(
+ chrome::NOTIFICATION_BROWSER_CLOSED, 2);
+ chrome::CloseAllBrowsers();
+ ASSERT_NO_FATAL_FAILURE(dialogs_.AcceptClose());
+ close_observer.Wait();
+ EXPECT_TRUE(browser_shutdown::IsTryingToQuit());
+ EXPECT_TRUE(chrome::BrowserIterator().done());
+}
+
+// Test that tabs in the same window with a beforeunload event that hangs are
+// treated the same as the user accepting the close, but do not close the tab
+// early.
+IN_PROC_BROWSER_TEST_P(BrowserCloseManagerBrowserTest,
+ TestHangInBeforeUnloadMultipleTabs) {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(
+ browsers_[0], embedded_test_server()->GetURL("/beforeunload_hang.html")));
+ AddBlankTabAndShow(browsers_[0]);
+ ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(
+ browsers_[0], embedded_test_server()->GetURL("/beforeunload.html")));
+ AddBlankTabAndShow(browsers_[0]);
+ ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(
+ browsers_[0], embedded_test_server()->GetURL("/beforeunload_hang.html")));
+
+ RepeatedNotificationObserver cancel_observer(
+ chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED, 1);
+ chrome::CloseAllBrowsers();
+ ASSERT_NO_FATAL_FAILURE(dialogs_.CancelClose());
+ cancel_observer.Wait();
+ EXPECT_FALSE(browser_shutdown::IsTryingToQuit());
+ // All tabs should still be open.
+ EXPECT_EQ(3, browsers_[0]->tab_strip_model()->count());
+
+ RepeatedNotificationObserver close_observer(
+ chrome::NOTIFICATION_BROWSER_CLOSED, 1);
+ chrome::CloseAllBrowsers();
+ ASSERT_NO_FATAL_FAILURE(dialogs_.AcceptClose());
+ close_observer.Wait();
+ EXPECT_TRUE(browser_shutdown::IsTryingToQuit());
+ EXPECT_TRUE(chrome::BrowserIterator().done());
+}
+
+// Test that tabs in different windows with a beforeunload event that hangs are
+// treated the same as the user accepting the close, but do not close the tab
+// early.
+IN_PROC_BROWSER_TEST_P(BrowserCloseManagerBrowserTest,
+ TestHangInBeforeUnloadMultipleWindows) {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ browsers_.push_back(CreateBrowser(browser()->profile()));
+ browsers_.push_back(CreateBrowser(browser()->profile()));
+ ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(
+ browsers_[0], embedded_test_server()->GetURL("/beforeunload_hang.html")));
+ ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(
+ browsers_[1], embedded_test_server()->GetURL("/beforeunload.html")));
+ ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(
+ browsers_[2], embedded_test_server()->GetURL("/beforeunload_hang.html")));
+
+ RepeatedNotificationObserver cancel_observer(
+ chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED, 2);
+ chrome::CloseAllBrowsers();
+ ASSERT_NO_FATAL_FAILURE(dialogs_.CancelClose());
+ cancel_observer.Wait();
+ EXPECT_FALSE(browser_shutdown::IsTryingToQuit());
+ // All windows should still be open.
+ EXPECT_EQ(1, browsers_[0]->tab_strip_model()->count());
+ EXPECT_EQ(1, browsers_[1]->tab_strip_model()->count());
+ EXPECT_EQ(1, browsers_[2]->tab_strip_model()->count());
+
+ RepeatedNotificationObserver close_observer(
+ chrome::NOTIFICATION_BROWSER_CLOSED, 3);
+ chrome::CloseAllBrowsers();
+ ASSERT_NO_FATAL_FAILURE(dialogs_.AcceptClose());
+ close_observer.Wait();
+ EXPECT_TRUE(browser_shutdown::IsTryingToQuit());
+ EXPECT_TRUE(chrome::BrowserIterator().done());
+}
+
+// Test that a window created during shutdown is closed.
+IN_PROC_BROWSER_TEST_P(BrowserCloseManagerBrowserTest,
+ TestAddWindowDuringShutdown) {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(
+ browsers_[0], embedded_test_server()->GetURL("/beforeunload.html")));
+
+ RepeatedNotificationObserver close_observer(
+ chrome::NOTIFICATION_BROWSER_CLOSED, 2);
+ chrome::CloseAllBrowsers();
+ browsers_.push_back(CreateBrowser(browser()->profile()));
+ ASSERT_NO_FATAL_FAILURE(dialogs_.AcceptClose());
+ close_observer.Wait();
+ EXPECT_TRUE(browser_shutdown::IsTryingToQuit());
+ EXPECT_TRUE(chrome::BrowserIterator().done());
+}
+
+// Test that a window created during shutdown with a beforeunload handler can
+// cancel the shutdown.
+IN_PROC_BROWSER_TEST_P(BrowserCloseManagerBrowserTest,
+ TestAddWindowWithBeforeUnloadDuringShutdown) {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(
+ browsers_[0], embedded_test_server()->GetURL("/beforeunload.html")));
+
+ RepeatedNotificationObserver cancel_observer(
+ chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED, 2);
+ chrome::CloseAllBrowsers();
+ browsers_.push_back(CreateBrowser(browser()->profile()));
+ ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(
+ browsers_[1], embedded_test_server()->GetURL("/beforeunload.html")));
+ ASSERT_NO_FATAL_FAILURE(dialogs_.AcceptClose());
+ ASSERT_NO_FATAL_FAILURE(dialogs_.CancelClose());
+ cancel_observer.Wait();
+ EXPECT_FALSE(browser_shutdown::IsTryingToQuit());
+ EXPECT_EQ(1, browsers_[0]->tab_strip_model()->count());
+ EXPECT_EQ(1, browsers_[1]->tab_strip_model()->count());
+
+ // Allow shutdown for both beforeunload dialogs.
+ RepeatedNotificationObserver close_observer(
+ chrome::NOTIFICATION_BROWSER_CLOSED, 2);
+ chrome::CloseAllBrowsers();
+ ASSERT_NO_FATAL_FAILURE(dialogs_.AcceptClose());
+ close_observer.Wait();
+ EXPECT_TRUE(browser_shutdown::IsTryingToQuit());
+ EXPECT_TRUE(chrome::BrowserIterator().done());
+}
+
+// Test that tabs added during shutdown are closed.
+IN_PROC_BROWSER_TEST_P(BrowserCloseManagerBrowserTest,
+ TestAddTabDuringShutdown) {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ browsers_.push_back(CreateBrowser(browser()->profile()));
+ ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(
+ browsers_[0], embedded_test_server()->GetURL("/beforeunload.html")));
+ ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(
+ browsers_[1], embedded_test_server()->GetURL("/beforeunload.html")));
+
+ RepeatedNotificationObserver close_observer(
+ chrome::NOTIFICATION_BROWSER_CLOSED, 2);
+ chrome::CloseAllBrowsers();
+ ASSERT_NO_FATAL_FAILURE(dialogs_.AcceptClose());
+ AddBlankTabAndShow(browsers_[0]);
+ AddBlankTabAndShow(browsers_[1]);
+ ASSERT_NO_FATAL_FAILURE(dialogs_.AcceptClose());
+ close_observer.Wait();
+ EXPECT_TRUE(browser_shutdown::IsTryingToQuit());
+ EXPECT_TRUE(chrome::BrowserIterator().done());
+}
+
+// Test that tabs created during shutdown with beforeunload handlers can cancel
+// the shutdown.
+IN_PROC_BROWSER_TEST_P(BrowserCloseManagerBrowserTest,
+ TestAddTabWithBeforeUnloadDuringShutdown) {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ browsers_.push_back(CreateBrowser(browser()->profile()));
+ ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(
+ browsers_[0], embedded_test_server()->GetURL("/beforeunload.html")));
+ ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(
+ browsers_[1], embedded_test_server()->GetURL("/beforeunload.html")));
+ RepeatedNotificationObserver cancel_observer(
+ chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED, 2);
+ chrome::CloseAllBrowsers();
+ ASSERT_NO_FATAL_FAILURE(dialogs_.AcceptClose());
+ AddBlankTabAndShow(browsers_[0]);
+ ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(
+ browsers_[0], embedded_test_server()->GetURL("/beforeunload.html")));
+ AddBlankTabAndShow(browsers_[1]);
+ ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(
+ browsers_[1], embedded_test_server()->GetURL("/beforeunload.html")));
+ ASSERT_NO_FATAL_FAILURE(dialogs_.AcceptClose());
+ ASSERT_NO_FATAL_FAILURE(dialogs_.CancelClose());
+ cancel_observer.Wait();
+ EXPECT_FALSE(browser_shutdown::IsTryingToQuit());
+ EXPECT_EQ(2, browsers_[0]->tab_strip_model()->count());
+ EXPECT_EQ(2, browsers_[1]->tab_strip_model()->count());
+
+ RepeatedNotificationObserver close_observer(
+ chrome::NOTIFICATION_BROWSER_CLOSED, 2);
+ chrome::CloseAllBrowsers();
+ ASSERT_NO_FATAL_FAILURE(dialogs_.AcceptClose());
+ ASSERT_NO_FATAL_FAILURE(dialogs_.AcceptClose());
+
+ close_observer.Wait();
+ EXPECT_TRUE(browser_shutdown::IsTryingToQuit());
+ EXPECT_TRUE(chrome::BrowserIterator().done());
+}
+
+IN_PROC_BROWSER_TEST_P(BrowserCloseManagerBrowserTest,
+ TestCloseTabDuringShutdown) {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(
+ browsers_[0], embedded_test_server()->GetURL("/beforeunload.html")));
+ RepeatedNotificationObserver cancel_observer(
+ chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED, 1);
+ chrome::CloseAllBrowsers();
+
+ browsers_.push_back(CreateBrowser(browser()->profile()));
+ ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(
+ browsers_[1], embedded_test_server()->GetURL("/beforeunload.html")));
+ browsers_[1]->tab_strip_model()->CloseAllTabs();
+ ASSERT_NO_FATAL_FAILURE(dialogs_.CancelClose());
+ ASSERT_NO_FATAL_FAILURE(dialogs_.CancelClose());
+ cancel_observer.Wait();
+ EXPECT_FALSE(browser_shutdown::IsTryingToQuit());
+ EXPECT_EQ(1, browsers_[0]->tab_strip_model()->count());
+ EXPECT_EQ(1, browsers_[1]->tab_strip_model()->count());
+
+ RepeatedNotificationObserver close_observer(
+ chrome::NOTIFICATION_BROWSER_CLOSED, 2);
+ chrome::CloseAllBrowsers();
+ browsers_[1]->tab_strip_model()->CloseAllTabs();
+ ASSERT_NO_FATAL_FAILURE(dialogs_.AcceptClose());
+ ASSERT_NO_FATAL_FAILURE(dialogs_.AcceptClose());
+
+ close_observer.Wait();
+ EXPECT_TRUE(browser_shutdown::IsTryingToQuit());
+ EXPECT_TRUE(chrome::BrowserIterator().done());
+}
+
+IN_PROC_BROWSER_TEST_P(BrowserCloseManagerBrowserTest,
+ TestOpenAndCloseWindowDuringShutdown) {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(
+ browsers_[0], embedded_test_server()->GetURL("/beforeunload.html")));
+ RepeatedNotificationObserver cancel_observer(
+ chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED, 2);
+ chrome::CloseAllBrowsers();
+
+ browsers_.push_back(CreateBrowser(browser()->profile()));
+ ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(
+ browsers_[1], embedded_test_server()->GetURL("/beforeunload.html")));
+ ASSERT_FALSE(browsers_[1]->ShouldCloseWindow());
+ ASSERT_NO_FATAL_FAILURE(dialogs_.CancelClose());
+ ASSERT_NO_FATAL_FAILURE(dialogs_.CancelClose());
+ cancel_observer.Wait();
+ EXPECT_FALSE(browser_shutdown::IsTryingToQuit());
+ EXPECT_EQ(1, browsers_[0]->tab_strip_model()->count());
+ EXPECT_EQ(1, browsers_[1]->tab_strip_model()->count());
+
+ RepeatedNotificationObserver close_observer(
+ chrome::NOTIFICATION_BROWSER_CLOSED, 2);
+ chrome::CloseAllBrowsers();
+ ASSERT_FALSE(browsers_[1]->ShouldCloseWindow());
+ ASSERT_NO_FATAL_FAILURE(dialogs_.AcceptClose());
+ ASSERT_NO_FATAL_FAILURE(dialogs_.AcceptClose());
+
+ close_observer.Wait();
+ EXPECT_TRUE(browser_shutdown::IsTryingToQuit());
+ EXPECT_TRUE(chrome::BrowserIterator().done());
+}
+
+IN_PROC_BROWSER_TEST_P(BrowserCloseManagerBrowserTest,
+ TestCloseWindowDuringShutdown) {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(
+ browsers_[0], embedded_test_server()->GetURL("/beforeunload.html")));
+ browsers_.push_back(CreateBrowser(browser()->profile()));
+ ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(
+ browsers_[1], embedded_test_server()->GetURL("/beforeunload.html")));
+ RepeatedNotificationObserver cancel_observer(
+ chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED, 1);
+ chrome::CloseAllBrowsers();
+
+ ASSERT_FALSE(browsers_[0]->ShouldCloseWindow());
+ ASSERT_NO_FATAL_FAILURE(dialogs_.CancelClose());
+ cancel_observer.Wait();
+ EXPECT_FALSE(browser_shutdown::IsTryingToQuit());
+ EXPECT_EQ(1, browsers_[0]->tab_strip_model()->count());
+ EXPECT_EQ(1, browsers_[1]->tab_strip_model()->count());
+
+ RepeatedNotificationObserver close_observer(
+ chrome::NOTIFICATION_BROWSER_CLOSED, 2);
+ chrome::CloseAllBrowsers();
+ ASSERT_FALSE(browsers_[0]->ShouldCloseWindow());
+ ASSERT_NO_FATAL_FAILURE(dialogs_.AcceptClose());
+ ASSERT_NO_FATAL_FAILURE(dialogs_.AcceptClose());
+
+ close_observer.Wait();
+ EXPECT_TRUE(browser_shutdown::IsTryingToQuit());
+ EXPECT_TRUE(chrome::BrowserIterator().done());
+}
+
+INSTANTIATE_TEST_CASE_P(BrowserCloseManagerBrowserTest,
+ BrowserCloseManagerBrowserTest,
+ testing::Bool());