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