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/command_line.h"
6 #include "base/file_path.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "base/string_number_conversions.h"
9 #include "base/test/test_timeouts.h"
10 #include "chrome/app/chrome_command_ids.h"
11 #include "chrome/browser/defaults.h"
12 #include "chrome/common/chrome_paths.h"
13 #include "chrome/common/chrome_switches.h"
14 #include "chrome/test/automation/tab_proxy.h"
15 #include "chrome/test/automation/browser_proxy.h"
16 #include "chrome/test/automation/window_proxy.h"
17 #include "chrome/test/ui/ui_test.h"
18 #include "googleurl/src/gurl.h"
19 #include "net/base/net_util.h"
20 #include "net/test/test_server.h"
21
22 namespace {
23
24 class SessionRestoreUITest : public UITest {
25 protected:
SessionRestoreUITest()26 SessionRestoreUITest() : UITest() {
27 FilePath path_prefix = test_data_directory_.AppendASCII("session_history");
28
29 url1_ = net::FilePathToFileURL(path_prefix.AppendASCII("bot1.html"));
30 url2_ = net::FilePathToFileURL(path_prefix.AppendASCII("bot2.html"));
31 url3_ = net::FilePathToFileURL(path_prefix.AppendASCII("bot3.html"));
32 }
33
QuitBrowserAndRestore(int expected_tab_count)34 virtual void QuitBrowserAndRestore(int expected_tab_count) {
35 #if defined(OS_MACOSX)
36 set_shutdown_type(ProxyLauncher::USER_QUIT);
37 #endif
38 UITest::TearDown();
39
40 clear_profile_ = false;
41
42 launch_arguments_.AppendSwitchASCII(switches::kRestoreLastSession,
43 base::IntToString(expected_tab_count));
44 UITest::SetUp();
45 }
46
CloseWindow(int window_index,int initial_count)47 void CloseWindow(int window_index, int initial_count) {
48 scoped_refptr<BrowserProxy> browser_proxy(
49 automation()->GetBrowserWindow(window_index));
50 ASSERT_TRUE(browser_proxy.get());
51 ASSERT_TRUE(browser_proxy->RunCommand(IDC_CLOSE_WINDOW));
52 int window_count;
53 ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count));
54 ASSERT_EQ(initial_count - 1, window_count);
55 }
56
AssertOneWindowWithOneTab()57 void AssertOneWindowWithOneTab() {
58 int window_count;
59 ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count));
60 ASSERT_EQ(1, window_count);
61 GURL url;
62 AssertWindowHasOneTab(0, &url);
63 }
64
AssertWindowHasOneTab(int window_index,GURL * url)65 void AssertWindowHasOneTab(int window_index, GURL* url) {
66 scoped_refptr<BrowserProxy> browser_proxy(
67 automation()->GetBrowserWindow(window_index));
68 ASSERT_TRUE(browser_proxy.get());
69
70 int tab_count;
71 ASSERT_TRUE(browser_proxy->GetTabCount(&tab_count));
72 ASSERT_EQ(1, tab_count);
73
74 int active_tab_index;
75 ASSERT_TRUE(browser_proxy->GetActiveTabIndex(&active_tab_index));
76 ASSERT_EQ(0, active_tab_index);
77
78 scoped_refptr<TabProxy> tab_proxy(browser_proxy->GetActiveTab());
79 ASSERT_TRUE(tab_proxy.get());
80 ASSERT_TRUE(tab_proxy->WaitForTabToBeRestored(
81 TestTimeouts::action_max_timeout_ms()));
82
83 ASSERT_TRUE(tab_proxy->GetCurrentURL(url));
84 }
85
86 GURL url1_;
87 GURL url2_;
88 GURL url3_;
89
90 private:
91 DISALLOW_COPY_AND_ASSIGN(SessionRestoreUITest);
92 };
93
TEST_F(SessionRestoreUITest,Basic)94 TEST_F(SessionRestoreUITest, Basic) {
95 NavigateToURL(url1_);
96 NavigateToURL(url2_);
97
98 QuitBrowserAndRestore(1);
99
100 // NOTE: Don't use GetActiveWindow here, when run with the screen locked
101 // active windows returns NULL.
102 int window_count;
103 ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count));
104 ASSERT_EQ(1, window_count);
105 scoped_refptr<BrowserProxy> browser_proxy(automation()->GetBrowserWindow(0));
106 ASSERT_TRUE(browser_proxy.get());
107 scoped_refptr<TabProxy> tab_proxy(browser_proxy->GetTab(0));
108 ASSERT_TRUE(tab_proxy->WaitForTabToBeRestored(
109 TestTimeouts::action_max_timeout_ms()));
110
111 ASSERT_EQ(url2_, GetActiveTabURL());
112 ASSERT_EQ(AUTOMATION_MSG_NAVIGATION_SUCCESS, tab_proxy->GoBack());
113 ASSERT_EQ(url1_, GetActiveTabURL());
114 }
115
TEST_F(SessionRestoreUITest,RestoresForwardAndBackwardNavs)116 TEST_F(SessionRestoreUITest, RestoresForwardAndBackwardNavs) {
117 NavigateToURL(url1_);
118 NavigateToURL(url2_);
119 NavigateToURL(url3_);
120
121 scoped_refptr<TabProxy> active_tab(GetActiveTab());
122 ASSERT_TRUE(active_tab.get());
123 ASSERT_TRUE(active_tab->GoBack());
124
125 QuitBrowserAndRestore(1);
126
127 // NOTE: Don't use GetActiveWindow here, when run with the screen locked
128 // active windows returns NULL.
129 int window_count;
130 ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count));
131 ASSERT_EQ(1, window_count);
132 scoped_refptr<BrowserProxy> browser_proxy(automation()->GetBrowserWindow(0));
133 ASSERT_TRUE(browser_proxy.get());
134 scoped_refptr<TabProxy> tab_proxy(browser_proxy->GetTab(0));
135 ASSERT_TRUE(tab_proxy->WaitForTabToBeRestored(
136 TestTimeouts::action_max_timeout_ms()));
137
138 ASSERT_TRUE(GetActiveTabURL() == url2_);
139 ASSERT_TRUE(tab_proxy->GoForward());
140 ASSERT_TRUE(GetActiveTabURL() == url3_);
141 ASSERT_TRUE(tab_proxy->GoBack());
142 ASSERT_TRUE(GetActiveTabURL() == url2_);
143 ASSERT_TRUE(tab_proxy->GoBack());
144 ASSERT_TRUE(GetActiveTabURL() == url1_);
145 }
146
147 // Tests that the SiteInstances used for entries in a restored tab's history
148 // are given appropriate max page IDs, so that going back to a restored
149 // cross-site page and then forward again works. (Bug 1204135)
TEST_F(SessionRestoreUITest,RestoresCrossSiteForwardAndBackwardNavs)150 TEST_F(SessionRestoreUITest, RestoresCrossSiteForwardAndBackwardNavs) {
151 net::TestServer test_server(net::TestServer::TYPE_HTTP,
152 FilePath(FILE_PATH_LITERAL("chrome/test/data")));
153 ASSERT_TRUE(test_server.Start());
154
155 GURL cross_site_url(test_server.GetURL("files/title2.html"));
156
157 // Visit URLs on different sites.
158 NavigateToURL(url1_);
159 NavigateToURL(cross_site_url);
160 NavigateToURL(url2_);
161
162 scoped_refptr<TabProxy> active_tab(GetActiveTab());
163 ASSERT_TRUE(active_tab.get());
164 ASSERT_TRUE(active_tab->GoBack());
165
166 QuitBrowserAndRestore(1);
167
168 // NOTE: Don't use GetActiveWindow here, when run with the screen locked
169 // active windows returns NULL.
170 int window_count;
171 ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count));
172 ASSERT_EQ(1, window_count);
173 scoped_refptr<BrowserProxy> browser_proxy(automation()->GetBrowserWindow(0));
174 ASSERT_TRUE(browser_proxy.get());
175 int tab_count;
176 ASSERT_TRUE(browser_proxy->GetTabCount(&tab_count));
177 ASSERT_EQ(1, tab_count);
178 scoped_refptr<TabProxy> tab_proxy(browser_proxy->GetTab(0));
179 ASSERT_TRUE(tab_proxy.get());
180 ASSERT_TRUE(tab_proxy->WaitForTabToBeRestored(
181 TestTimeouts::action_max_timeout_ms()));
182
183 // Check that back and forward work as expected.
184 GURL url;
185 ASSERT_TRUE(tab_proxy->GetCurrentURL(&url));
186 ASSERT_EQ(cross_site_url, url);
187
188 ASSERT_TRUE(tab_proxy->GoBack());
189 ASSERT_TRUE(tab_proxy->GetCurrentURL(&url));
190 ASSERT_EQ(url1_, url);
191
192 ASSERT_TRUE(tab_proxy->GoForward());
193 ASSERT_TRUE(tab_proxy->GetCurrentURL(&url));
194 ASSERT_EQ(cross_site_url, url);
195
196 ASSERT_TRUE(tab_proxy->GoForward());
197 ASSERT_TRUE(tab_proxy->GetCurrentURL(&url));
198 ASSERT_EQ(url2_, url);
199 }
200
TEST_F(SessionRestoreUITest,TwoTabsSecondSelected)201 TEST_F(SessionRestoreUITest, TwoTabsSecondSelected) {
202 NavigateToURL(url1_);
203
204 // NOTE: Don't use GetActiveWindow here, when run with the screen locked
205 // active windows returns NULL.
206 int window_count;
207 ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count));
208 ASSERT_EQ(1, window_count);
209 scoped_refptr<BrowserProxy> browser_proxy(automation()->GetBrowserWindow(0));
210 ASSERT_TRUE(browser_proxy.get());
211
212 ASSERT_TRUE(browser_proxy->AppendTab(url2_));
213
214 QuitBrowserAndRestore(2);
215 browser_proxy = NULL;
216
217 ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count));
218 ASSERT_EQ(1, window_count);
219 browser_proxy = automation()->GetBrowserWindow(0);
220
221 int tab_count;
222 ASSERT_TRUE(browser_proxy->GetTabCount(&tab_count));
223 ASSERT_EQ(2, tab_count);
224
225 int active_tab_index;
226 ASSERT_TRUE(browser_proxy->GetActiveTabIndex(&active_tab_index));
227 ASSERT_EQ(1, active_tab_index);
228
229 scoped_refptr<TabProxy> tab_proxy(browser_proxy->GetActiveTab());
230 ASSERT_TRUE(tab_proxy.get());
231 ASSERT_TRUE(tab_proxy->WaitForTabToBeRestored(
232 TestTimeouts::action_max_timeout_ms()));
233
234 ASSERT_EQ(url2_, GetActiveTabURL());
235
236 ASSERT_TRUE(browser_proxy->ActivateTab(0));
237 tab_proxy = browser_proxy->GetActiveTab();
238 ASSERT_TRUE(tab_proxy.get());
239 ASSERT_TRUE(tab_proxy->WaitForTabToBeRestored(
240 TestTimeouts::action_max_timeout_ms()));
241
242 ASSERT_EQ(url1_, GetActiveTabURL());
243 }
244
245 // Creates two tabs, closes one, quits and makes sure only one tab is restored.
TEST_F(SessionRestoreUITest,ClosedTabStaysClosed)246 TEST_F(SessionRestoreUITest, ClosedTabStaysClosed) {
247 NavigateToURL(url1_);
248
249 // NOTE: Don't use GetActiveWindow here, when run with the screen locked
250 // active windows returns NULL.
251 int window_count;
252 ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count));
253 ASSERT_EQ(1, window_count);
254 scoped_refptr<BrowserProxy> browser_proxy(automation()->GetBrowserWindow(0));
255 ASSERT_TRUE(browser_proxy.get());
256 scoped_refptr<TabProxy> tab_proxy(browser_proxy->GetTab(0));
257 ASSERT_TRUE(tab_proxy.get());
258
259 ASSERT_TRUE(browser_proxy->AppendTab(url2_));
260
261 scoped_refptr<TabProxy> active_tab(browser_proxy->GetActiveTab());
262 ASSERT_TRUE(active_tab.get());
263 ASSERT_TRUE(active_tab->Close(true));
264
265 QuitBrowserAndRestore(1);
266 browser_proxy = NULL;
267 tab_proxy = NULL;
268
269 AssertOneWindowWithOneTab();
270
271 ASSERT_EQ(url1_, GetActiveTabURL());
272 }
273
274 // Creates a tabbed browser and popup and makes sure we restore both.
TEST_F(SessionRestoreUITest,NormalAndPopup)275 TEST_F(SessionRestoreUITest, NormalAndPopup) {
276 if (!browser_defaults::kRestorePopups)
277 return; // Test only applicable if restoring popups.
278
279 NavigateToURL(url1_);
280
281 // Make sure we have one window.
282 int window_count;
283 ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count));
284 ASSERT_EQ(1, window_count);
285
286 // Open a popup.
287 ASSERT_TRUE(automation()->OpenNewBrowserWindow(Browser::TYPE_POPUP,
288 true));
289 ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count));
290 ASSERT_EQ(2, window_count);
291
292 scoped_refptr<BrowserProxy> popup(automation()->GetBrowserWindow(1));
293 ASSERT_TRUE(popup.get());
294
295 scoped_refptr<TabProxy> tab(popup->GetTab(0));
296 ASSERT_TRUE(tab.get());
297
298 ASSERT_EQ(AUTOMATION_MSG_NAVIGATION_SUCCESS, tab->NavigateToURL(url1_));
299
300 // Simulate an exit by shuting down the session service. If we don't do this
301 // the first window close is treated as though the user closed the window
302 // and won't be restored.
303 ASSERT_TRUE(popup->ShutdownSessionService());
304
305 tab = NULL;
306 popup = NULL;
307
308 // Restart and make sure we have only one window with one tab and the url
309 // is url1_.
310 QuitBrowserAndRestore(1);
311
312 ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count));
313 ASSERT_EQ(2, window_count);
314
315 scoped_refptr<BrowserProxy> browser_proxy1(
316 automation()->GetBrowserWindow(0));
317 ASSERT_TRUE(browser_proxy1.get());
318
319 scoped_refptr<BrowserProxy> browser_proxy2(
320 automation()->GetBrowserWindow(1));
321 ASSERT_TRUE(browser_proxy2.get());
322
323 Browser::Type type1, type2;
324 ASSERT_TRUE(browser_proxy1->GetType(&type1));
325 ASSERT_TRUE(browser_proxy2->GetType(&type2));
326
327 // The order of whether the normal window or popup is first depends upon
328 // activation order, which is not necessarily consistant across runs.
329 if (type1 == Browser::TYPE_NORMAL) {
330 EXPECT_EQ(type2, Browser::TYPE_POPUP);
331 } else {
332 EXPECT_EQ(type1, Browser::TYPE_POPUP);
333 EXPECT_EQ(type2, Browser::TYPE_NORMAL);
334 }
335 }
336
337 #if !defined(OS_MACOSX)
338 // This test doesn't apply to the Mac version; see
339 // LaunchAnotherBrowserBlockUntilClosed for details.
340
341 // Launches an app window, closes tabbed browser, launches and makes sure
342 // we restore the tabbed browser url.
343 // Flaky: http://crbug.com/29110
TEST_F(SessionRestoreUITest,FLAKY_RestoreAfterClosingTabbedBrowserWithAppAndLaunching)344 TEST_F(SessionRestoreUITest,
345 FLAKY_RestoreAfterClosingTabbedBrowserWithAppAndLaunching) {
346 NavigateToURL(url1_);
347
348 // Launch an app.
349
350 bool include_testing_id_orig = include_testing_id_;
351 include_testing_id_ = false;
352 clear_profile_ = false;
353 CommandLine app_launch_arguments = launch_arguments_;
354 app_launch_arguments.AppendSwitchASCII(switches::kApp, url2_.spec());
355 LaunchAnotherBrowserBlockUntilClosed(app_launch_arguments);
356 ASSERT_TRUE(automation()->WaitForWindowCountToBecome(2));
357
358 // Close the first window. The only window left is the App window.
359 CloseWindow(0, 2);
360
361 // Restore the session, which should bring back the first window with url1_.
362 // First restore the settings so we can connect to the browser.
363 include_testing_id_ = include_testing_id_orig;
364 // Restore the session with 1 tab.
365 QuitBrowserAndRestore(1);
366
367 AssertOneWindowWithOneTab();
368
369 ASSERT_EQ(url1_, GetActiveTabURL());
370 }
371
372 #endif // !OS_MACOSX
373
374 // Creates two windows, closes one, restores, make sure only one window open.
TEST_F(SessionRestoreUITest,TwoWindowsCloseOneRestoreOnlyOne)375 TEST_F(SessionRestoreUITest, TwoWindowsCloseOneRestoreOnlyOne) {
376 NavigateToURL(url1_);
377
378 // Make sure we have one window.
379 int window_count;
380 ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count));
381 ASSERT_EQ(1, window_count);
382
383 // Open a second window.
384 ASSERT_TRUE(automation()->OpenNewBrowserWindow(Browser::TYPE_NORMAL,
385 true));
386 ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count));
387 ASSERT_EQ(2, window_count);
388
389 // Close it.
390 CloseWindow(1, 2);
391
392 // Restart and make sure we have only one window with one tab and the url
393 // is url1_.
394 QuitBrowserAndRestore(1);
395
396 AssertOneWindowWithOneTab();
397
398 ASSERT_EQ(url1_, GetActiveTabURL());
399 }
400
401 // Make sure after a restore the number of processes matches that of the number
402 // of processes running before the restore. This creates a new tab so that
403 // we should have two new tabs running. (This test will pass in both
404 // process-per-site and process-per-site-instance, because we treat the new tab
405 // as a special case in process-per-site-instance so that it only ever uses one
406 // process.)
407 //
408 // Flaky: http://code.google.com/p/chromium/issues/detail?id=52022
409 // Unfortunately, the fix at http://codereview.chromium.org/6546078
410 // breaks NTP background image refreshing, so ThemeSource had to revert to
411 // replacing the existing data source.
TEST_F(SessionRestoreUITest,FLAKY_ShareProcessesOnRestore)412 TEST_F(SessionRestoreUITest, FLAKY_ShareProcessesOnRestore) {
413 if (ProxyLauncher::in_process_renderer()) {
414 // No point in running this test in single process mode.
415 return;
416 }
417
418 scoped_refptr<BrowserProxy> browser_proxy(automation()->GetBrowserWindow(0));
419 ASSERT_TRUE(browser_proxy.get() != NULL);
420 int tab_count;
421 ASSERT_TRUE(browser_proxy->GetTabCount(&tab_count));
422
423 // Create two new tabs.
424 ASSERT_TRUE(browser_proxy->RunCommand(IDC_NEW_TAB));
425 ASSERT_TRUE(browser_proxy->RunCommand(IDC_NEW_TAB));
426 int new_tab_count;
427 ASSERT_TRUE(browser_proxy->GetTabCount(&new_tab_count));
428 ASSERT_EQ(tab_count + 2, new_tab_count);
429
430 int expected_process_count = 0;
431 ASSERT_TRUE(GetBrowserProcessCount(&expected_process_count));
432 int expected_tab_count = new_tab_count;
433
434 // Restart.
435 browser_proxy = NULL;
436 QuitBrowserAndRestore(3);
437
438 // Wait for each tab to finish being restored, then make sure the process
439 // count matches.
440 browser_proxy = automation()->GetBrowserWindow(0);
441 ASSERT_TRUE(browser_proxy.get() != NULL);
442 ASSERT_TRUE(browser_proxy->GetTabCount(&tab_count));
443 ASSERT_EQ(expected_tab_count, tab_count);
444
445 for (int i = 0; i < expected_tab_count; ++i) {
446 scoped_refptr<TabProxy> tab_proxy(browser_proxy->GetTab(i));
447 ASSERT_TRUE(tab_proxy.get() != NULL);
448 ASSERT_TRUE(tab_proxy->WaitForTabToBeRestored(
449 TestTimeouts::action_max_timeout_ms()));
450 }
451
452 int process_count = 0;
453 ASSERT_TRUE(GetBrowserProcessCount(&process_count));
454 ASSERT_EQ(expected_process_count, process_count);
455 }
456
457 } // namespace
458