// 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/file_path.h" #include "chrome/browser/defaults.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sessions/tab_restore_service.h" #include "chrome/browser/tabs/tab_strip_model.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/test/in_process_browser_test.h" #include "chrome/test/ui_test_utils.h" #include "content/browser/tab_contents/tab_contents.h" #include "content/common/page_transition_types.h" namespace { // BrowserList::Observer implementation that waits for a browser to be // removed. class BrowserListObserverImpl : public BrowserList::Observer { public: BrowserListObserverImpl() : did_remove_(false), running_(false) { BrowserList::AddObserver(this); } ~BrowserListObserverImpl() { BrowserList::RemoveObserver(this); } // Returns when a browser has been removed. void Run() { running_ = true; if (!did_remove_) ui_test_utils::RunMessageLoop(); } // BrowserList::Observer virtual void OnBrowserAdded(const Browser* browser) OVERRIDE { } virtual void OnBrowserRemoved(const Browser* browser) OVERRIDE { did_remove_ = true; if (running_) MessageLoop::current()->Quit(); } private: // Was OnBrowserRemoved invoked? bool did_remove_; // Was Run invoked? bool running_; DISALLOW_COPY_AND_ASSIGN(BrowserListObserverImpl); }; } // namespace typedef InProcessBrowserTest SessionRestoreTest; #if defined(OS_LINUX) && defined(TOOLKIT_VIEWS) // Crashes on Linux Views: http://crbug.com/39476 #define MAYBE_RestoreOnNewWindowWithNoTabbedBrowsers \ DISABLED_RestoreOnNewWindowWithNoTabbedBrowsers #else #define MAYBE_RestoreOnNewWindowWithNoTabbedBrowsers \ RestoreOnNewWindowWithNoTabbedBrowsers #endif // Makes sure when session restore is triggered in the same process we don't end // up with an extra tab. IN_PROC_BROWSER_TEST_F(SessionRestoreTest, MAYBE_RestoreOnNewWindowWithNoTabbedBrowsers) { if (browser_defaults::kRestorePopups) return; const FilePath::CharType* kTitle1File = FILE_PATH_LITERAL("title1.html"); GURL url(ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory), FilePath(kTitle1File))); ui_test_utils::NavigateToURL(browser(), url); // Turn on session restore. SessionStartupPref::SetStartupPref( browser()->profile(), SessionStartupPref(SessionStartupPref::LAST)); // Create a new popup. Profile* profile = browser()->profile(); Browser* popup = Browser::CreateForType(Browser::TYPE_POPUP, profile); popup->window()->Show(); // Close the browser. browser()->window()->Close(); // Create a new window, which should trigger session restore. popup->NewWindow(); Browser* new_browser = ui_test_utils::WaitForNewBrowser(); ASSERT_TRUE(new_browser != NULL); // The browser should only have one tab. ASSERT_EQ(1, new_browser->tab_count()); // And the first url should be url. EXPECT_EQ(url, new_browser->GetTabContentsAt(0)->GetURL()); } IN_PROC_BROWSER_TEST_F(SessionRestoreTest, RestoreIndividualTabFromWindow) { GURL url1(ui_test_utils::GetTestUrl( FilePath(FilePath::kCurrentDirectory), FilePath(FILE_PATH_LITERAL("title1.html")))); GURL url2(ui_test_utils::GetTestUrl( FilePath(FilePath::kCurrentDirectory), FilePath(FILE_PATH_LITERAL("title2.html")))); GURL url3(ui_test_utils::GetTestUrl( FilePath(FilePath::kCurrentDirectory), FilePath(FILE_PATH_LITERAL("title3.html")))); // Add and navigate three tabs. ui_test_utils::NavigateToURL(browser(), url1); browser()->AddSelectedTabWithURL(url2, PageTransition::LINK); ui_test_utils::WaitForNavigationInCurrentTab(browser()); browser()->AddSelectedTabWithURL(url3, PageTransition::LINK); ui_test_utils::WaitForNavigationInCurrentTab(browser()); TabRestoreService* service = browser()->profile()->GetTabRestoreService(); service->ClearEntries(); browser()->window()->Close(); // Expect a window with three tabs. EXPECT_EQ(1U, service->entries().size()); ASSERT_EQ(TabRestoreService::WINDOW, service->entries().front()->type); const TabRestoreService::Window* window = static_cast<TabRestoreService::Window*>(service->entries().front()); EXPECT_EQ(3U, window->tabs.size()); // Find the SessionID for entry2. Since the session service was destroyed, // there is no guarantee that the SessionID for the tab has remained the same. std::vector<TabRestoreService::Tab>::const_iterator it = window->tabs.begin(); for ( ; it != window->tabs.end(); ++it) { const TabRestoreService::Tab& tab = *it; // If this tab held url2, then restore this single tab. if (tab.navigations[0].virtual_url() == url2) { service->RestoreEntryById(NULL, tab.id, false); break; } } // Make sure that the Window got updated. EXPECT_EQ(1U, service->entries().size()); ASSERT_EQ(TabRestoreService::WINDOW, service->entries().front()->type); window = static_cast<TabRestoreService::Window*>(service->entries().front()); EXPECT_EQ(2U, window->tabs.size()); } IN_PROC_BROWSER_TEST_F(SessionRestoreTest, WindowWithOneTab) { GURL url(ui_test_utils::GetTestUrl( FilePath(FilePath::kCurrentDirectory), FilePath(FILE_PATH_LITERAL("title1.html")))); // Add a single tab. ui_test_utils::NavigateToURL(browser(), url); TabRestoreService* service = browser()->profile()->GetTabRestoreService(); service->ClearEntries(); EXPECT_EQ(0U, service->entries().size()); // Close the window. browser()->window()->Close(); // Expect the window to be converted to a tab by the TRS. EXPECT_EQ(1U, service->entries().size()); ASSERT_EQ(TabRestoreService::TAB, service->entries().front()->type); const TabRestoreService::Tab* tab = static_cast<TabRestoreService::Tab*>(service->entries().front()); // Restore the tab. service->RestoreEntryById(NULL, tab->id, false); // Make sure the restore was successful. EXPECT_EQ(0U, service->entries().size()); } // Verifies we remember the last browser window when closing the last // non-incognito window while an incognito window is open. IN_PROC_BROWSER_TEST_F(SessionRestoreTest, IncognitotoNonIncognito) { // Turn on session restore. SessionStartupPref pref(SessionStartupPref::LAST); SessionStartupPref::SetStartupPref(browser()->profile(), pref); GURL url(ui_test_utils::GetTestUrl( FilePath(FilePath::kCurrentDirectory), FilePath(FILE_PATH_LITERAL("title1.html")))); // Add a single tab. ui_test_utils::NavigateToURL(browser(), url); // Create a new incognito window. Browser* incognito_browser = CreateIncognitoBrowser(); incognito_browser->AddBlankTab(true); incognito_browser->window()->Show(); // Close the normal browser. After this we only have the incognito window // open. We wait until the window closes as window closing is async. { BrowserListObserverImpl observer; browser()->window()->Close(); observer.Run(); } // Create a new window, which should trigger session restore. incognito_browser->NewWindow(); // The first tab should have 'url' as its url. Browser* new_browser = ui_test_utils::WaitForNewBrowser(); ASSERT_TRUE(new_browser); EXPECT_EQ(url, new_browser->GetTabContentsAt(0)->GetURL()); }