• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
BrowserListObserverImpl()24   BrowserListObserverImpl() : did_remove_(false), running_(false) {
25     BrowserList::AddObserver(this);
26   }
27 
~BrowserListObserverImpl()28   ~BrowserListObserverImpl() {
29     BrowserList::RemoveObserver(this);
30   }
31 
32   // Returns when a browser has been removed.
Run()33   void Run() {
34     running_ = true;
35     if (!did_remove_)
36       ui_test_utils::RunMessageLoop();
37   }
38 
39   // BrowserList::Observer
OnBrowserAdded(const Browser * browser)40   virtual void OnBrowserAdded(const Browser* browser) OVERRIDE {
41   }
OnBrowserRemoved(const Browser * browser)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.
IN_PROC_BROWSER_TEST_F(SessionRestoreTest,MAYBE_RestoreOnNewWindowWithNoTabbedBrowsers)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 
IN_PROC_BROWSER_TEST_F(SessionRestoreTest,RestoreIndividualTabFromWindow)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 
IN_PROC_BROWSER_TEST_F(SessionRestoreTest,WindowWithOneTab)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.
IN_PROC_BROWSER_TEST_F(SessionRestoreTest,IncognitotoNonIncognito)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