This source file includes following definitions.
- SetUpCommandLine
- SetUpOnMainThread
- CheckTitle
- NavigateToDataURL
- NavigateToNolistenersFileTwice
- NavigateToNolistenersFileTwiceAsync
- LoadUrlAndQuitBrowser
- ClickModalDialogButton
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
- SetUpCommandLine
- SetUpInProcessBrowserTestFixture
- TearDownInProcessBrowserTestFixture
- GetUrl
- NavigateToPage
- NavigateToPageInNewTab
- GetCookies
- run_loop_
- TabDetachedAt
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
#if defined(OS_POSIX)
#include <signal.h>
#endif
#include "base/command_line.h"
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/net/url_request_mock_util.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_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 "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test_utils.h"
#include "content/test/net/url_request_mock_http_job.h"
#include "net/url_request/url_request_test_util.h"
#if defined(OS_WIN)
#include "base/win/windows_version.h"
#endif
using base::TimeDelta;
using content::BrowserThread;
const std::string NOLISTENERS_HTML =
"<html><head><title>nolisteners</title></head><body></body></html>";
const std::string UNLOAD_HTML =
"<html><head><title>unload</title></head><body>"
"<script>window.onunload=function(e){}</script></body></html>";
const std::string BEFORE_UNLOAD_HTML =
"<html><head><title>beforeunload</title></head><body>"
"<script>window.onbeforeunload=function(e){"
"setTimeout('document.title=\"cancelled\"', 0);return 'foo'}</script>"
"</body></html>";
const std::string INNER_FRAME_WITH_FOCUS_HTML =
"<html><head><title>innerframewithfocus</title></head><body>"
"<script>window.onbeforeunload=function(e){return 'foo'}</script>"
"<iframe src=\"data:text/html,<html><head><script>window.onload="
"function(){document.getElementById('box').focus()}</script>"
"<body><input id='box'></input></body></html>\"></iframe>"
"</body></html>";
const std::string TWO_SECOND_BEFORE_UNLOAD_HTML =
"<html><head><title>twosecondbeforeunload</title></head><body>"
"<script>window.onbeforeunload=function(e){"
"var start = new Date().getTime();"
"while(new Date().getTime() - start < 2000){}"
"return 'foo';"
"}</script></body></html>";
const std::string INFINITE_UNLOAD_HTML =
"<html><head><title>infiniteunload</title></head><body>"
"<script>window.onunload=function(e){while(true){}}</script>"
"</body></html>";
const std::string INFINITE_BEFORE_UNLOAD_HTML =
"<html><head><title>infinitebeforeunload</title></head><body>"
"<script>window.onbeforeunload=function(e){while(true){}}</script>"
"</body></html>";
const std::string INFINITE_UNLOAD_ALERT_HTML =
"<html><head><title>infiniteunloadalert</title></head><body>"
"<script>window.onunload=function(e){"
"while(true){}"
"alert('foo');"
"}</script></body></html>";
const std::string INFINITE_BEFORE_UNLOAD_ALERT_HTML =
"<html><head><title>infinitebeforeunloadalert</title></head><body>"
"<script>window.onbeforeunload=function(e){"
"while(true){}"
"alert('foo');"
"}</script></body></html>";
const std::string TWO_SECOND_UNLOAD_ALERT_HTML =
"<html><head><title>twosecondunloadalert</title></head><body>"
"<script>window.onunload=function(e){"
"var start = new Date().getTime();"
"while(new Date().getTime() - start < 2000){}"
"alert('foo');"
"}</script></body></html>";
const std::string TWO_SECOND_BEFORE_UNLOAD_ALERT_HTML =
"<html><head><title>twosecondbeforeunloadalert</title></head><body>"
"<script>window.onbeforeunload=function(e){"
"var start = new Date().getTime();"
"while(new Date().getTime() - start < 2000){}"
"alert('foo');"
"}</script></body></html>";
const std::string CLOSE_TAB_WHEN_OTHER_TAB_HAS_LISTENER =
"<html><head><title>only_one_unload</title></head>"
"<body onclick=\"window.open('data:text/html,"
"<html><head><title>popup</title></head></body>')\" "
"onbeforeunload='return;'>"
"</body></html>";
class UnloadTest : public InProcessBrowserTest {
public:
virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
const testing::TestInfo* const test_info =
testing::UnitTest::GetInstance()->current_test_info();
if (strcmp(test_info->name(),
"BrowserCloseTabWhenOtherTabHasListener") == 0) {
command_line->AppendSwitch(switches::kDisablePopupBlocking);
} else if (strcmp(test_info->name(), "BrowserTerminateBeforeUnload") == 0) {
#if defined(OS_POSIX)
DisableSIGTERMHandling();
#endif
}
}
virtual void SetUpOnMainThread() OVERRIDE {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&chrome_browser_net::SetUrlRequestMocksEnabled, true));
}
void CheckTitle(const char* expected_title) {
base::string16 expected = base::ASCIIToUTF16(expected_title);
EXPECT_EQ(expected,
browser()->tab_strip_model()->GetActiveWebContents()->GetTitle());
}
void NavigateToDataURL(const std::string& html_content,
const char* expected_title) {
ui_test_utils::NavigateToURL(browser(),
GURL("data:text/html," + html_content));
CheckTitle(expected_title);
}
void NavigateToNolistenersFileTwice() {
GURL url(content::URLRequestMockHTTPJob::GetMockUrl(
base::FilePath(FILE_PATH_LITERAL("title2.html"))));
ui_test_utils::NavigateToURL(browser(), url);
CheckTitle("Title Of Awesomeness");
ui_test_utils::NavigateToURL(browser(), url);
CheckTitle("Title Of Awesomeness");
}
void NavigateToNolistenersFileTwiceAsync() {
GURL url(content::URLRequestMockHTTPJob::GetMockUrl(
base::FilePath(FILE_PATH_LITERAL("title2.html"))));
ui_test_utils::NavigateToURLWithDisposition(browser(), url, CURRENT_TAB, 0);
ui_test_utils::NavigateToURL(browser(), url);
CheckTitle("Title Of Awesomeness");
}
void LoadUrlAndQuitBrowser(const std::string& html_content,
const char* expected_title) {
NavigateToDataURL(html_content, expected_title);
content::WindowedNotificationObserver window_observer(
chrome::NOTIFICATION_BROWSER_CLOSED,
content::NotificationService::AllSources());
chrome::CloseWindow(browser());
window_observer.Wait();
}
void ClickModalDialogButton(bool accept) {
AppModalDialog* dialog = ui_test_utils::WaitForAppModalDialog();
ASSERT_TRUE(dialog->IsJavaScriptModalDialog());
JavaScriptAppModalDialog* js_dialog =
static_cast<JavaScriptAppModalDialog*>(dialog);
if (accept)
js_dialog->native_dialog()->AcceptAppModalDialog();
else
js_dialog->native_dialog()->CancelAppModalDialog();
}
};
IN_PROC_BROWSER_TEST_F(UnloadTest, CrossSiteInfiniteUnloadAsync) {
if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess))
return;
NavigateToDataURL(INFINITE_UNLOAD_HTML, "infiniteunload");
NavigateToNolistenersFileTwiceAsync();
}
IN_PROC_BROWSER_TEST_F(UnloadTest, CrossSiteInfiniteUnloadSync) {
if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess))
return;
NavigateToDataURL(INFINITE_UNLOAD_HTML, "infiniteunload");
NavigateToNolistenersFileTwice();
}
IN_PROC_BROWSER_TEST_F(UnloadTest, CrossSiteInfiniteBeforeUnloadAsync) {
if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess))
return;
NavigateToDataURL(INFINITE_BEFORE_UNLOAD_HTML, "infinitebeforeunload");
NavigateToNolistenersFileTwiceAsync();
}
IN_PROC_BROWSER_TEST_F(UnloadTest, CrossSiteInfiniteBeforeUnloadSync) {
if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess))
return;
NavigateToDataURL(INFINITE_BEFORE_UNLOAD_HTML, "infinitebeforeunload");
NavigateToNolistenersFileTwice();
}
IN_PROC_BROWSER_TEST_F(UnloadTest, BrowserCloseNoUnloadListeners) {
LoadUrlAndQuitBrowser(NOLISTENERS_HTML, "nolisteners");
}
IN_PROC_BROWSER_TEST_F(UnloadTest, DISABLED_BrowserCloseUnload) {
LoadUrlAndQuitBrowser(UNLOAD_HTML, "unload");
}
IN_PROC_BROWSER_TEST_F(UnloadTest, BrowserCloseBeforeUnloadOK) {
NavigateToDataURL(BEFORE_UNLOAD_HTML, "beforeunload");
content::WindowedNotificationObserver window_observer(
chrome::NOTIFICATION_BROWSER_CLOSED,
content::NotificationService::AllSources());
chrome::CloseWindow(browser());
ClickModalDialogButton(true);
window_observer.Wait();
}
IN_PROC_BROWSER_TEST_F(UnloadTest, BrowserCloseBeforeUnloadCancel) {
NavigateToDataURL(BEFORE_UNLOAD_HTML, "beforeunload");
chrome::CloseWindow(browser());
base::string16 expected_title = base::ASCIIToUTF16("cancelled");
content::TitleWatcher title_watcher(
browser()->tab_strip_model()->GetActiveWebContents(), expected_title);
ClickModalDialogButton(false);
ASSERT_EQ(expected_title, title_watcher.WaitAndGetTitle());
content::WindowedNotificationObserver window_observer(
chrome::NOTIFICATION_BROWSER_CLOSED,
content::NotificationService::AllSources());
chrome::CloseWindow(browser());
ClickModalDialogButton(true);
window_observer.Wait();
}
#if defined(OS_CHROMEOS)
IN_PROC_BROWSER_TEST_F(UnloadTest, BrowserTerminateBeforeUnload) {
NavigateToDataURL(BEFORE_UNLOAD_HTML, "beforeunload");
EXPECT_EQ(kill(base::GetCurrentProcessHandle(), SIGTERM), 0);
}
#endif
IN_PROC_BROWSER_TEST_F(UnloadTest, BrowserCloseWithInnerFocusedFrame) {
NavigateToDataURL(INNER_FRAME_WITH_FOCUS_HTML, "innerframewithfocus");
content::WindowedNotificationObserver window_observer(
chrome::NOTIFICATION_BROWSER_CLOSED,
content::NotificationService::AllSources());
chrome::CloseWindow(browser());
ClickModalDialogButton(true);
window_observer.Wait();
}
IN_PROC_BROWSER_TEST_F(UnloadTest, BrowserCloseTwoSecondBeforeUnload) {
LoadUrlAndQuitBrowser(TWO_SECOND_BEFORE_UNLOAD_HTML,
"twosecondbeforeunload");
}
IN_PROC_BROWSER_TEST_F(UnloadTest, BrowserCloseInfiniteUnload) {
if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess))
return;
LoadUrlAndQuitBrowser(INFINITE_UNLOAD_HTML, "infiniteunload");
}
IN_PROC_BROWSER_TEST_F(UnloadTest, DISABLED_BrowserCloseInfiniteBeforeUnload) {
if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess))
return;
LoadUrlAndQuitBrowser(INFINITE_BEFORE_UNLOAD_HTML, "infinitebeforeunload");
}
IN_PROC_BROWSER_TEST_F(UnloadTest, BrowserCloseInfiniteUnloadAlert) {
if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess))
return;
LoadUrlAndQuitBrowser(INFINITE_UNLOAD_ALERT_HTML, "infiniteunloadalert");
}
IN_PROC_BROWSER_TEST_F(UnloadTest,
DISABLED_BrowserCloseInfiniteBeforeUnloadAlert) {
if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess))
return;
LoadUrlAndQuitBrowser(INFINITE_BEFORE_UNLOAD_ALERT_HTML,
"infinitebeforeunloadalert");
}
IN_PROC_BROWSER_TEST_F(UnloadTest, BrowserCloseTwoSecondUnloadAlert) {
LoadUrlAndQuitBrowser(TWO_SECOND_UNLOAD_ALERT_HTML, "twosecondunloadalert");
}
IN_PROC_BROWSER_TEST_F(UnloadTest, BrowserCloseTwoSecondBeforeUnloadAlert) {
LoadUrlAndQuitBrowser(TWO_SECOND_BEFORE_UNLOAD_ALERT_HTML,
"twosecondbeforeunloadalert");
}
IN_PROC_BROWSER_TEST_F(UnloadTest, BrowserCloseTabWhenOtherTabHasListener) {
NavigateToDataURL(CLOSE_TAB_WHEN_OTHER_TAB_HAS_LISTENER, "only_one_unload");
content::WindowedNotificationObserver observer(
chrome::NOTIFICATION_TAB_ADDED,
content::NotificationService::AllSources());
content::WindowedNotificationObserver load_stop_observer(
content::NOTIFICATION_LOAD_STOP,
content::NotificationService::AllSources());
content::SimulateMouseClick(
browser()->tab_strip_model()->GetActiveWebContents(), 0,
blink::WebMouseEvent::ButtonLeft);
observer.Wait();
load_stop_observer.Wait();
CheckTitle("popup");
content::WebContentsDestroyedWatcher destroyed_watcher(
browser()->tab_strip_model()->GetActiveWebContents());
chrome::CloseTab(browser());
destroyed_watcher.Wait();
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);
}
virtual void TabDetachedAt(content::WebContents* contents,
int index) OVERRIDE {
run_loop_->Quit();
}
private:
TabStripModel* const model_;
base::RunLoop* const run_loop_;
};
#if defined(OS_WIN)
#define MAYBE_UnloadHidden \
DISABLED_UnloadHidden
#else
#define MAYBE_UnloadHidden \
UnloadHidden
#endif
IN_PROC_BROWSER_TEST_F(FastUnloadTest, MAYBE_UnloadHidden) {
NavigateToPage("no_listeners");
NavigateToPageInNewTab("unload_sets_cookie");
EXPECT_EQ("", GetCookies("no_listeners"));
content::WebContentsDestroyedWatcher destroyed_watcher(
browser()->tab_strip_model()->GetActiveWebContents());
{
base::RunLoop run_loop;
FastTabCloseTabStripModelObserver observer(
browser()->tab_strip_model(), &run_loop);
chrome::CloseTab(browser());
run_loop.Run();
}
CheckTitle("no_listeners");
EXPECT_EQ(1, browser()->tab_strip_model()->count());
destroyed_watcher.Wait();
EXPECT_EQ("unloaded=ohyeah", GetCookies("no_listeners"));
}
IN_PROC_BROWSER_TEST_F(FastUnloadTest, PRE_ClosingLastTabFinishesUnload) {
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, DISABLED_ClosingLastTabFinishesUnload) {
#if defined(OS_WIN)
if (base::win::GetVersion() >= base::win::VERSION_WIN7)
return;
#endif
NavigateToPage("no_listeners");
EXPECT_EQ("unloaded=ohyeah", GetCookies("no_listeners"));
}
IN_PROC_BROWSER_TEST_F(FastUnloadTest, PRE_WindowCloseFinishesUnload) {
NavigateToPage("no_listeners");
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, DISABLED_WindowCloseFinishesUnload) {
NavigateToPage("no_listeners");
EXPECT_EQ("unloaded=ohyeah", GetCookies("no_listeners"));
}
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();
}
CheckTitle("no_listeners");
EXPECT_EQ(1, browser()->tab_strip_model()->count());
CrashTab(unload_contents);
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();
}
#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) {
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();
}