Home | History | Annotate | Download | only in sessions
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "base/file_path.h"
      6 #include "chrome/browser/defaults.h"
      7 #include "chrome/browser/profiles/profile.h"
      8 #include "chrome/browser/sessions/tab_restore_service.h"
      9 #include "chrome/browser/tabs/tab_strip_model.h"
     10 #include "chrome/browser/ui/browser.h"
     11 #include "chrome/browser/ui/browser_list.h"
     12 #include "chrome/browser/ui/browser_window.h"
     13 #include "chrome/test/in_process_browser_test.h"
     14 #include "chrome/test/ui_test_utils.h"
     15 #include "content/browser/tab_contents/tab_contents.h"
     16 #include "content/common/page_transition_types.h"
     17 
     18 namespace {
     19 
     20 // BrowserList::Observer implementation that waits for a browser to be
     21 // removed.
     22 class BrowserListObserverImpl : public BrowserList::Observer {
     23  public:
     24   BrowserListObserverImpl() : did_remove_(false), running_(false) {
     25     BrowserList::AddObserver(this);
     26   }
     27 
     28   ~BrowserListObserverImpl() {
     29     BrowserList::RemoveObserver(this);
     30   }
     31 
     32   // Returns when a browser has been removed.
     33   void Run() {
     34     running_ = true;
     35     if (!did_remove_)
     36       ui_test_utils::RunMessageLoop();
     37   }
     38 
     39   // BrowserList::Observer
     40   virtual void OnBrowserAdded(const Browser* browser) OVERRIDE {
     41   }
     42   virtual void OnBrowserRemoved(const Browser* browser) OVERRIDE {
     43     did_remove_ = true;
     44     if (running_)
     45       MessageLoop::current()->Quit();
     46   }
     47 
     48  private:
     49   // Was OnBrowserRemoved invoked?
     50   bool did_remove_;
     51 
     52   // Was Run invoked?
     53   bool running_;
     54 
     55   DISALLOW_COPY_AND_ASSIGN(BrowserListObserverImpl);
     56 };
     57 
     58 }  // namespace
     59 
     60 typedef InProcessBrowserTest SessionRestoreTest;
     61 
     62 #if defined(OS_LINUX) && defined(TOOLKIT_VIEWS)
     63 // Crashes on Linux Views: http://crbug.com/39476
     64 #define MAYBE_RestoreOnNewWindowWithNoTabbedBrowsers \
     65         DISABLED_RestoreOnNewWindowWithNoTabbedBrowsers
     66 #else
     67 #define MAYBE_RestoreOnNewWindowWithNoTabbedBrowsers \
     68         RestoreOnNewWindowWithNoTabbedBrowsers
     69 #endif
     70 
     71 // Makes sure when session restore is triggered in the same process we don't end
     72 // up with an extra tab.
     73 IN_PROC_BROWSER_TEST_F(SessionRestoreTest,
     74                        MAYBE_RestoreOnNewWindowWithNoTabbedBrowsers) {
     75   if (browser_defaults::kRestorePopups)
     76     return;
     77 
     78   const FilePath::CharType* kTitle1File = FILE_PATH_LITERAL("title1.html");
     79   GURL url(ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory),
     80                                      FilePath(kTitle1File)));
     81   ui_test_utils::NavigateToURL(browser(), url);
     82 
     83   // Turn on session restore.
     84   SessionStartupPref::SetStartupPref(
     85       browser()->profile(),
     86       SessionStartupPref(SessionStartupPref::LAST));
     87 
     88   // Create a new popup.
     89   Profile* profile = browser()->profile();
     90   Browser* popup = Browser::CreateForType(Browser::TYPE_POPUP, profile);
     91   popup->window()->Show();
     92 
     93   // Close the browser.
     94   browser()->window()->Close();
     95 
     96   // Create a new window, which should trigger session restore.
     97   popup->NewWindow();
     98 
     99   Browser* new_browser = ui_test_utils::WaitForNewBrowser();
    100 
    101   ASSERT_TRUE(new_browser != NULL);
    102 
    103   // The browser should only have one tab.
    104   ASSERT_EQ(1, new_browser->tab_count());
    105 
    106   // And the first url should be url.
    107   EXPECT_EQ(url, new_browser->GetTabContentsAt(0)->GetURL());
    108 }
    109 
    110 IN_PROC_BROWSER_TEST_F(SessionRestoreTest, RestoreIndividualTabFromWindow) {
    111   GURL url1(ui_test_utils::GetTestUrl(
    112       FilePath(FilePath::kCurrentDirectory),
    113       FilePath(FILE_PATH_LITERAL("title1.html"))));
    114   GURL url2(ui_test_utils::GetTestUrl(
    115       FilePath(FilePath::kCurrentDirectory),
    116       FilePath(FILE_PATH_LITERAL("title2.html"))));
    117   GURL url3(ui_test_utils::GetTestUrl(
    118       FilePath(FilePath::kCurrentDirectory),
    119       FilePath(FILE_PATH_LITERAL("title3.html"))));
    120 
    121   // Add and navigate three tabs.
    122   ui_test_utils::NavigateToURL(browser(), url1);
    123   browser()->AddSelectedTabWithURL(url2, PageTransition::LINK);
    124   ui_test_utils::WaitForNavigationInCurrentTab(browser());
    125 
    126   browser()->AddSelectedTabWithURL(url3, PageTransition::LINK);
    127   ui_test_utils::WaitForNavigationInCurrentTab(browser());
    128 
    129   TabRestoreService* service = browser()->profile()->GetTabRestoreService();
    130   service->ClearEntries();
    131 
    132   browser()->window()->Close();
    133 
    134   // Expect a window with three tabs.
    135   EXPECT_EQ(1U, service->entries().size());
    136   ASSERT_EQ(TabRestoreService::WINDOW, service->entries().front()->type);
    137   const TabRestoreService::Window* window =
    138       static_cast<TabRestoreService::Window*>(service->entries().front());
    139   EXPECT_EQ(3U, window->tabs.size());
    140 
    141   // Find the SessionID for entry2. Since the session service was destroyed,
    142   // there is no guarantee that the SessionID for the tab has remained the same.
    143   std::vector<TabRestoreService::Tab>::const_iterator it = window->tabs.begin();
    144   for ( ; it != window->tabs.end(); ++it) {
    145     const TabRestoreService::Tab& tab = *it;
    146     // If this tab held url2, then restore this single tab.
    147     if (tab.navigations[0].virtual_url() == url2) {
    148       service->RestoreEntryById(NULL, tab.id, false);
    149       break;
    150     }
    151   }
    152 
    153   // Make sure that the Window got updated.
    154   EXPECT_EQ(1U, service->entries().size());
    155   ASSERT_EQ(TabRestoreService::WINDOW, service->entries().front()->type);
    156   window = static_cast<TabRestoreService::Window*>(service->entries().front());
    157   EXPECT_EQ(2U, window->tabs.size());
    158 }
    159 
    160 IN_PROC_BROWSER_TEST_F(SessionRestoreTest, WindowWithOneTab) {
    161   GURL url(ui_test_utils::GetTestUrl(
    162       FilePath(FilePath::kCurrentDirectory),
    163       FilePath(FILE_PATH_LITERAL("title1.html"))));
    164 
    165   // Add a single tab.
    166   ui_test_utils::NavigateToURL(browser(), url);
    167 
    168   TabRestoreService* service = browser()->profile()->GetTabRestoreService();
    169   service->ClearEntries();
    170   EXPECT_EQ(0U, service->entries().size());
    171 
    172   // Close the window.
    173   browser()->window()->Close();
    174 
    175   // Expect the window to be converted to a tab by the TRS.
    176   EXPECT_EQ(1U, service->entries().size());
    177   ASSERT_EQ(TabRestoreService::TAB, service->entries().front()->type);
    178   const TabRestoreService::Tab* tab =
    179       static_cast<TabRestoreService::Tab*>(service->entries().front());
    180 
    181   // Restore the tab.
    182   service->RestoreEntryById(NULL, tab->id, false);
    183 
    184   // Make sure the restore was successful.
    185   EXPECT_EQ(0U, service->entries().size());
    186 }
    187 
    188 // Verifies we remember the last browser window when closing the last
    189 // non-incognito window while an incognito window is open.
    190 IN_PROC_BROWSER_TEST_F(SessionRestoreTest, IncognitotoNonIncognito) {
    191   // Turn on session restore.
    192   SessionStartupPref pref(SessionStartupPref::LAST);
    193   SessionStartupPref::SetStartupPref(browser()->profile(), pref);
    194 
    195   GURL url(ui_test_utils::GetTestUrl(
    196       FilePath(FilePath::kCurrentDirectory),
    197       FilePath(FILE_PATH_LITERAL("title1.html"))));
    198 
    199   // Add a single tab.
    200   ui_test_utils::NavigateToURL(browser(), url);
    201 
    202   // Create a new incognito window.
    203   Browser* incognito_browser = CreateIncognitoBrowser();
    204   incognito_browser->AddBlankTab(true);
    205   incognito_browser->window()->Show();
    206 
    207   // Close the normal browser. After this we only have the incognito window
    208   // open. We wait until the window closes as window closing is async.
    209   {
    210     BrowserListObserverImpl observer;
    211     browser()->window()->Close();
    212     observer.Run();
    213   }
    214 
    215   // Create a new window, which should trigger session restore.
    216   incognito_browser->NewWindow();
    217 
    218   // The first tab should have 'url' as its url.
    219   Browser* new_browser = ui_test_utils::WaitForNewBrowser();
    220   ASSERT_TRUE(new_browser);
    221   EXPECT_EQ(url, new_browser->GetTabContentsAt(0)->GetURL());
    222 }
    223