// Copyright (c) 2011 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 "base/bind.h" #include "base/file_path.h" #include "base/stl_util.h" #include "base/test/thread_test_helper.h" #include "chrome/browser/net/sqlite_persistent_cookie_store.h" #include "chrome/common/chrome_constants.h" #include "chrome/test/automation/automation_proxy.h" #include "chrome/test/automation/browser_proxy.h" #include "chrome/test/automation/tab_proxy.h" #include "chrome/test/base/ui_test_utils.h" #include "chrome/test/ui/ui_test.h" #include "content/test/test_browser_thread.h" using content::BrowserThread; class FastShutdown : public UITest { protected: FastShutdown() : db_thread_(BrowserThread::DB), io_thread_(BrowserThread::IO), thread_helper_(new base::ThreadTestHelper( BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB))) { dom_automation_enabled_ = true; } void Init() { ASSERT_TRUE(db_thread_.Start()); ASSERT_TRUE(io_thread_.Start()); // Cache this, so that we can still access it after the browser exits. user_data_dir_ = user_data_dir(); } // Looks for the given |cookie| in the cookie store. If it exists, puts the // cookie's value in |cookie_value| and sets |has_cookie| to true. Sets // |has_cookie| to false if the |cookie| wasn't found. void GetCookie(const net::CookieMonster::CanonicalCookie& cookie, bool* has_cookie, std::string* cookie_value) { scoped_refptr cookie_store( new SQLitePersistentCookieStore( user_data_dir_.AppendASCII(chrome::kInitialProfile) .Append(chrome::kCookieFilename), false)); std::vector cookies; cookie_store->Load( base::Bind(&FastShutdown::LoadCookiesCallback, base::Unretained(this), MessageLoop::current(), base::Unretained(&cookies))); // Will receive a QuitTask when LoadCookiesCallback is invoked. MessageLoop::current()->Run(); *has_cookie = false; for (size_t i = 0; i < cookies.size(); ++i) { if (cookies[i]->IsEquivalent(cookie)) { *has_cookie = true; *cookie_value = cookies[i]->Value(); } } cookie_store = NULL; ASSERT_TRUE(thread_helper_->Run()); STLDeleteElements(&cookies); } private: void LoadCookiesCallback( MessageLoop* to_notify, std::vector* cookies, const std::vector& cookies_get) { *cookies = cookies_get; to_notify->PostTask(FROM_HERE, MessageLoop::QuitClosure()); } content::TestBrowserThread db_thread_; content::TestBrowserThread io_thread_; scoped_refptr thread_helper_; FilePath user_data_dir_; DISALLOW_COPY_AND_ASSIGN(FastShutdown); }; // This tests for a previous error where uninstalling an onbeforeunload handler // would enable fast shutdown even if an onunload handler still existed. // Flaky on all platforms, http://crbug.com/89173 TEST_F(FastShutdown, FLAKY_SlowTermination) { Init(); // Only the name, domain and path are used in IsEquivalent(), so we don't care // what the other fields have. net::CookieMonster::CanonicalCookie cookie( GURL(), // url "unloaded", // name "", // value "", // domain "/", // path "", // mac_key "", // mac_algorithm base::Time(), // creation base::Time(), // expiration base::Time(), // last_access false, // secure false, // httponly false, // has_expires false); // is_persistent // This page has an unload handler. const FilePath dir(FILE_PATH_LITERAL("fast_shutdown")); const FilePath file(FILE_PATH_LITERAL("on_unloader.html")); NavigateToURL(ui_test_utils::GetTestUrl(dir, file)); scoped_refptr browser(automation()->GetBrowserWindow(0)); // This page has a beforeunload handler. ASSERT_TRUE(browser->GetTab(0)->ExecuteJavaScript( "open('on_before_unloader.html')")); WaitUntilTabCount(2); // Close the tab, removing the one and only beforeunload handler. ASSERT_TRUE(browser->GetTab(1)->Close(true)); // Close the browser. This should launch the unload handler, which sets a // cookie that's stored to disk. QuitBrowser(); bool has_cookie = false; std::string cookie_value; // Read the cookie and check that it has the expected value. GetCookie(cookie, &has_cookie, &cookie_value); EXPECT_TRUE(has_cookie); EXPECT_EQ("ohyeah", cookie_value); }