Index: chrome/browser/ui/browser_browsertest.cc |
diff --git a/chrome/browser/ui/browser_browsertest.cc b/chrome/browser/ui/browser_browsertest.cc |
index 7325b7d8142d4da2c9bb710e9571ca56bb2166e7..d13afe820d0e1af53b02553350e7559f6e82d23c 100644 |
--- a/chrome/browser/ui/browser_browsertest.cc |
+++ b/chrome/browser/ui/browser_browsertest.cc |
@@ -7,9 +7,6 @@ |
#include "base/bind.h" |
#include "base/compiler_specific.h" |
#include "base/file_path.h" |
-#if defined(OS_MACOSX) |
-#include "base/mac/mac_util.h" |
-#endif |
#include "base/sys_info.h" |
#include "base/utf_string_conversions.h" |
#include "chrome/app/chrome_command_ids.h" |
@@ -69,6 +66,12 @@ |
#include "net/test/test_server.h" |
#include "ui/base/l10n/l10n_util.h" |
+#if defined(OS_MACOSX) |
+#include "base/mac/mac_util.h" |
+#include "base/mac/scoped_nsautorelease_pool.h" |
+#include "chrome/browser/ui/cocoa/run_loop_testing.h" |
+#endif |
+ |
#if defined(OS_WIN) |
#include "base/i18n/rtl.h" |
#include "chrome/browser/browser_process.h" |
@@ -429,6 +432,79 @@ IN_PROC_BROWSER_TEST_F(BrowserTest, MAYBE_BeforeUnloadVsBeforeReload) { |
alert->native_dialog()->AcceptAppModalDialog(); |
} |
+// BeforeUnloadAtQuitWithTwoWindows is a regression test for |
+// http://crbug.com/11842. It opens two windows, one of which has a |
+// beforeunload handler and attempts to exit cleanly. |
+class BeforeUnloadAtQuitWithTwoWindows : public InProcessBrowserTest { |
+ public: |
+ // This test is for testing a specific shutdown behavior. This mimics what |
+ // happens in InProcessBrowserTest::RunTestOnMainThread and QuitBrowsers, but |
+ // ensures that it happens through the single IDC_EXIT of the test. |
+ virtual void CleanUpOnMainThread() OVERRIDE { |
+ // Cycle both the MessageLoop and the Cocoa runloop twice to flush out any |
+ // Chrome work that generates Cocoa work. Do this twice since there are two |
+ // Browsers that must be closed. |
+ CycleRunLoops(); |
+ CycleRunLoops(); |
+ |
+ // Run the application event loop to completion, which will cycle the |
+ // native MessagePump on all platforms. |
+ MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure()); |
+ MessageLoop::current()->Run(); |
+ |
+ // Take care of any remaining Cocoa work. |
+ CycleRunLoops(); |
+ |
+ // At this point, quit should be for real now. |
+ ASSERT_EQ(0u, BrowserList::size()); |
+ } |
+ |
+ // A helper function that cycles the MessageLoop, and on Mac, the Cocoa run |
+ // loop. It also drains the NSAutoreleasePool. |
+ void CycleRunLoops() { |
+ content::RunAllPendingInMessageLoop(); |
+#if defined(OS_MACOSX) |
+ chrome::testing::NSRunLoopRunAllPending(); |
+ AutoreleasePool()->Recycle(); |
+#endif |
+ } |
+}; |
+ |
+IN_PROC_BROWSER_TEST_F(BeforeUnloadAtQuitWithTwoWindows, |
+ IfThisTestTimesOutItIndicatesFAILURE) { |
+ // In the first browser, set up a page that has a beforeunload handler. |
+ GURL url(std::string("data:text/html,") + kBeforeUnloadHTML); |
+ ui_test_utils::NavigateToURL(browser(), url); |
+ |
+ // Open a second browser window at about:blank. |
+ ui_test_utils::BrowserAddedObserver browser_added_observer; |
+ chrome::NewEmptyWindow(browser()->profile()); |
+ Browser* second_window = browser_added_observer.WaitForSingleNewBrowser(); |
+ ui_test_utils::NavigateToURL(second_window, GURL("about:blank")); |
+ |
+ // Tell the application to quit. IDC_EXIT calls AttemptUserExit, which on |
+ // everything but ChromeOS allows unload handlers to block exit. On that |
+ // platform, though, it exits unconditionally. See the comment and bug ID |
+ // in AttemptUserExit() in application_lifetime.cc. |
+#if defined(OS_CHROMEOS) |
+ browser::AttemptExit(); |
+#else |
+ chrome::ExecuteCommand(second_window, IDC_EXIT); |
+#endif |
+ |
+ // The beforeunload handler will run at exit, ensure it does, and then accept |
+ // it to allow shutdown to proceed. |
+ AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog(); |
+ ASSERT_TRUE(alert); |
+ EXPECT_TRUE( |
+ static_cast<JavaScriptAppModalDialog*>(alert)->is_before_unload_dialog()); |
+ alert->native_dialog()->AcceptAppModalDialog(); |
+ |
+ // But wait there's more! If this test times out, it likely means that the |
+ // browser has not been able to quit correctly, indicating there's a |
+ // regression of the bug noted above. |
+} |
+ |
// Test that scripts can fork a new renderer process for a cross-site popup, |
// based on http://www.google.com/chrome/intl/en/webmasters-faq.html#newtab. |
// The script must open a new tab, set its window.opener to null, and navigate |