// Copyright 2012 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/command_line.h" #include "base/functional/bind.h" #include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" #include "components/embedder_support/switches.h" #include "components/javascript_dialogs/app_modal_dialog_controller.h" #include "components/javascript_dialogs/app_modal_dialog_view.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" #include "content/public/common/content_switches.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" #include "content/public/test/test_navigation_observer.h" #include "net/dns/mock_host_resolver.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "third_party/blink/public/common/features.h" BrowserThread; const char NOLISTENERS_HTML[] = …; const char UNLOAD_HTML[] = …; const char BEFORE_UNLOAD_HTML[] = …; const char INNER_FRAME_WITH_FOCUS_HTML[] = …; const char INFINITE_UNLOAD_HTML[] = …; const char INFINITE_BEFORE_UNLOAD_HTML[] = …; const char INFINITE_UNLOAD_ALERT_HTML[] = …; const char INFINITE_BEFORE_UNLOAD_ALERT_HTML[] = …; const char TWO_SECOND_UNLOAD_ALERT_HTML[] = …; const char TWO_SECOND_BEFORE_UNLOAD_ALERT_HTML[] = …; const char CLOSE_TAB_WHEN_OTHER_TAB_HAS_LISTENER[] = …; class UnloadResults { … }; class UnloadTest : public InProcessBrowserTest { … }; // Navigate to a page with an infinite unload handler. // Then two async crosssite requests to ensure // we don't get confused and think we're closing the tab. // // This test is flaky on the valgrind UI bots. http://crbug.com/39057 IN_PROC_BROWSER_TEST_F(UnloadTest, CrossSiteInfiniteUnloadAsync) { … } // Navigate to a page with an infinite unload handler. // Then two sync crosssite requests to ensure // we correctly nav to each one. IN_PROC_BROWSER_TEST_F(UnloadTest, CrossSiteInfiniteUnloadSync) { … } // Navigate to a page with an infinite beforeunload handler. // Then two two async crosssite requests to ensure // we don't get confused and think we're closing the tab. // This test is flaky on the valgrind UI bots. http://crbug.com/39057 and // http://crbug.com/86469 IN_PROC_BROWSER_TEST_F(UnloadTest, CrossSiteInfiniteBeforeUnloadAsync) { … } // Navigate to a page with an infinite beforeunload handler. // Then two two sync crosssite requests to ensure // we correctly nav to each one. // Flaky on Win, Linux, and Mac; http://crbug.com/462671. IN_PROC_BROWSER_TEST_F(UnloadTest, DISABLED_CrossSiteInfiniteBeforeUnloadSync) { … } // Tests closing the browser on a page with no unload listeners registered. IN_PROC_BROWSER_TEST_F(UnloadTest, BrowserCloseNoUnloadListeners) { … } // Tests closing the browser on a page with an unload listener registered. // Test marked as flaky in http://crbug.com/51698 IN_PROC_BROWSER_TEST_F(UnloadTest, DISABLED_BrowserCloseUnload) { … } // Tests closing the browser with a beforeunload handler and clicking // OK in the beforeunload confirm dialog. IN_PROC_BROWSER_TEST_F(UnloadTest, BrowserCloseBeforeUnloadOK) { … } // Tests closing the browser with a beforeunload handler and clicking // CANCEL in the beforeunload confirm dialog. // If this test flakes, reopen http://crbug.com/123110 IN_PROC_BROWSER_TEST_F(UnloadTest, BrowserCloseBeforeUnloadCancel) { … } // Tests closing the browser by BrowserList::CloseAllBrowsersWithProfile, // on a page with no unload listeners registered. IN_PROC_BROWSER_TEST_F(UnloadTest, BrowserListCloseNoUnloadListeners) { … } // Tests closing the browser by BrowserList::CloseAllBrowsersWithProfile, with a // beforeunload handler and clicking Leave in the beforeunload confirm dialog. IN_PROC_BROWSER_TEST_F(UnloadTest, BrowserListCloseBeforeUnloadOK) { … } IN_PROC_BROWSER_TEST_F(UnloadTest, BrowserListForceCloseNoUnloadListeners) { … } IN_PROC_BROWSER_TEST_F(UnloadTest, BrowserListForceCloseWithBeforeUnload) { … } // Tests closing the browser by BrowserList::CloseAllBrowsersWithProfile, with a // beforeunload handler and clicking Stay in the beforeunload confirm dialog. // TODO(crbug.com/40241736): Flaky on Mac. #if BUILDFLAG(IS_MAC) #define MAYBE_BrowserListCloseBeforeUnloadCancel … #else #define MAYBE_BrowserListCloseBeforeUnloadCancel … #endif IN_PROC_BROWSER_TEST_F(UnloadTest, MAYBE_BrowserListCloseBeforeUnloadCancel) { … } // Tests double calls to BrowserList::CloseAllBrowsersWithProfile, with a // beforeunload handler and clicking Leave in the beforeunload confirm dialog. IN_PROC_BROWSER_TEST_F(UnloadTest, BrowserListDoubleCloseBeforeUnloadOK) { … } // Tests double calls to BrowserList::CloseAllBrowsersWithProfile, with a // beforeunload handler and clicking Stay in the beforeunload confirm dialog. IN_PROC_BROWSER_TEST_F(UnloadTest, BrowserListDoubleCloseBeforeUnloadCancel) { … } // Tests closing the browser by BrowserList::CloseAllBrowsersWithProfile, with // a null success callback, a beforeunload handler and clicking Leave in the // beforeunload confirm dialog. The test succeed if no crash happens. IN_PROC_BROWSER_TEST_F(UnloadTest, BrowserListCloseBeforeUnloadNullCallbackOk) { … } // Tests closing the browser by BrowserList::CloseAllBrowsersWithProfile, with // a null failure callback, a beforeunload handler and clicking Stay in the // beforeunload confirm dialog. The test succeed if no crash happens. IN_PROC_BROWSER_TEST_F(UnloadTest, BrowserListCloseBeforeUnloadNullCallbackCancel) { … } // Tests terminating the browser with a beforeunload handler. // Currently only ChromeOS shuts down gracefully. #if BUILDFLAG(IS_CHROMEOS_ASH) IN_PROC_BROWSER_TEST_F(UnloadTest, BrowserTerminateBeforeUnload) { NavigateToDataURL(BEFORE_UNLOAD_HTML, "beforeunload"); EXPECT_EQ(kill(base::GetCurrentProcessHandle(), SIGTERM), 0); } #endif // Tests closing the browser and clicking OK in the beforeunload confirm dialog // if an inner frame has the focus. // If this flakes, use http://crbug.com/32615 and http://crbug.com/45675 IN_PROC_BROWSER_TEST_F(UnloadTest, BrowserCloseWithInnerFocusedFrame) { … } // Tests closing the browser with a beforeunload handler that takes forever // by running an infinite loop. IN_PROC_BROWSER_TEST_F(UnloadTest, BrowserCloseInfiniteBeforeUnload) { … } // Tests closing the browser on a page with an unload listener registered where // the unload handler has an infinite loop. IN_PROC_BROWSER_TEST_F(UnloadTest, BrowserCloseInfiniteUnload) { … } // Tests closing the browser on a page with an unload listener registered where // the unload handler has an infinite loop followed by an alert. // If this flakes, use http://crbug.com/86469 IN_PROC_BROWSER_TEST_F(UnloadTest, BrowserCloseInfiniteUnloadAlert) { … } // Tests closing the browser with a beforeunload handler that hangs then // pops up an alert. // If this flakes, use http://crbug.com/78803 and http://crbug.com/86469. IN_PROC_BROWSER_TEST_F(UnloadTest, DISABLED_BrowserCloseInfiniteBeforeUnloadAlert) { … } // Tests closing the browser on a page with an unload listener registered where // the unload handler has an 2 second long loop followed by an alert. IN_PROC_BROWSER_TEST_F(UnloadTest, BrowserCloseTwoSecondUnloadAlert) { … } // Tests closing the browser with a beforeunload handler that takes // two seconds to run then pops up an alert. IN_PROC_BROWSER_TEST_F(UnloadTest, BrowserCloseTwoSecondBeforeUnloadAlert) { … } // Tests that if there's a renderer process with two tabs, one of which has an // unload handler, and the other doesn't, the tab that doesn't have an unload // handler can be closed. // If this flakes, see http://crbug.com/45162, http://crbug.com/45281 and // http://crbug.com/86769. IN_PROC_BROWSER_TEST_F(UnloadTest, BrowserCloseTabWhenOtherTabHasListener) { … } // Tests that visibilitychange is only dispatched once on tab close. IN_PROC_BROWSER_TEST_F(UnloadTest, VisibilityChangeOnlyDispatchedOnce) { … } IN_PROC_BROWSER_TEST_F(UnloadTest, BrowserListForceCloseAfterNormalClose) { … } // Tests that a cross-site iframe runs its beforeunload handler when closing // the browser. See https://crbug.com/853021. IN_PROC_BROWSER_TEST_F(UnloadTest, BrowserCloseWithCrossSiteIframe) { … } // Tests that a same-site iframe runs its beforeunload handler when closing the // browser. See https://crbug.com/1010456. IN_PROC_BROWSER_TEST_F(UnloadTest, BrowserCloseWithSameSiteIframe) { … } // Tests closing the browser with onbeforeunload handler and // event.preventDefault() will prompt confirmation dialog IN_PROC_BROWSER_TEST_F(UnloadTest, OnBeforeUnloadCancelByPreventDefault) { … } // Tests closing the browser with onbeforeunload handler and // setting returnValue will prompt confirmation dialog IN_PROC_BROWSER_TEST_F(UnloadTest, OnBeforeUnloadCancelByReturnValue) { … } // Tests closing the browser with onbeforeunload handler and // setting returnValue empty string will not prompt confirmation dialog IN_PROC_BROWSER_TEST_F(UnloadTest, OnBeforeUnloadCancelByReturnValueEmpty) { … } // Tests closing the browser with onbeforeunload handler and // having return value will prompt confirmation dialog IN_PROC_BROWSER_TEST_F(UnloadTest, OnBeforeUnloadCancelByReturn) { … } // Tests closing the browser with onbeforeunload handler and // returning empty string will prompt confirmation dialog IN_PROC_BROWSER_TEST_F(UnloadTest, OnBeforeUnloadCancelByReturnEmpty) { … } // Tests closing the browser with addEventListener('beforeunload') handler and // event.preventDefault() will prompt confirmation dialog IN_PROC_BROWSER_TEST_F(UnloadTest, BeforeUnloadListenerCancelByPreventDefault) { … } // Tests closing the browser with addEventListener('beforeunload') handler and // setting returnValue will prompt confirmation dialog IN_PROC_BROWSER_TEST_F(UnloadTest, BeforeUnloadListenerCancelByReturnValue) { … } // Tests closing the browser with addEventListener('beforeunload') handler and // setting returnValue empty string will not prompt confirmation dialog IN_PROC_BROWSER_TEST_F(UnloadTest, BeforeUnloadListenerCancelByReturnValueEmpty) { … } // Tests closing the browser with addEventListener('beforeunload') handler and // having return value will _not_ prompt confirmation dialog // TODO(crbug.com/41368941) Change this test if spec changes IN_PROC_BROWSER_TEST_F(UnloadTest, BeforeUnloadListenerCancelByReturn) { … } // Tests closing the browser with addEventListener('beforeunload') handler and // returning empty string will not prompt confirmation dialog IN_PROC_BROWSER_TEST_F(UnloadTest, BeforeUnloadListenerCancelByReturnEmpty) { … } // TODO(crbug.com/40586353): Remove below test when feature // BeforeunloadEventCancelByPreventDefault is fully stable. class UnloadTestCancelByPreventDefaultDisabled : public UnloadTest { … }; // Tests closing the browser with onbeforeunload handler and // event.preventDefault() will not prompt confirmation dialog when // BeforeunloadEventCancelByPreventDefault is disabled. IN_PROC_BROWSER_TEST_F(UnloadTestCancelByPreventDefaultDisabled, OnBeforeUnloadPreventDefault) { … } // Tests closing the browser with onbeforeunload handler and // event.returnValue = "" will prompt confirmation dialog when // BeforeunloadEventCancelByPreventDefault is disabled. IN_PROC_BROWSER_TEST_F(UnloadTestCancelByPreventDefaultDisabled, OnBeforeUnloadEmptyString) { … } // Tests closing the browser with addEventListener('beforeunload') handler and // event.preventDefault() will not prompt confirmation dialog when // BeforeunloadEventCancelByPreventDefault is disabled. IN_PROC_BROWSER_TEST_F(UnloadTestCancelByPreventDefaultDisabled, BeforeUnloadPreventDefault) { … } // Tests closing the browser with addEventListener('beforeunload') handler and // event.returnValue = "" will prompt confirmation dialog when // BeforeunloadEventCancelByPreventDefault is disabled. IN_PROC_BROWSER_TEST_F(UnloadTestCancelByPreventDefaultDisabled, BeforeUnloadEmptyString) { … } // TODO(ojan): Add tests for unload/beforeunload that have multiple tabs // and multiple windows.