session_restore_uitest.cc revision dc0f95d653279beabeb9817299e2902918ba123e
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/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
22namespace {
23
24class SessionRestoreUITest : public UITest {
25 protected:
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
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
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
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
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
94TEST_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
116TEST_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)
150TEST_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
201TEST_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.
246TEST_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.
275TEST_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// These tests don't apply to the Mac version; see
339// LaunchAnotherBrowserBlockUntilClosed for details.
340
341// Creates a browser, goes incognito, closes browser, launches and make sure
342// we don't restore.
343//
344TEST_F(SessionRestoreUITest, DontRestoreWhileIncognito) {
345  NavigateToURL(url1_);
346
347  // Make sure we have one window.
348  int initial_window_count;
349  ASSERT_TRUE(automation()->GetBrowserWindowCount(&initial_window_count));
350  ASSERT_EQ(1, initial_window_count);
351
352  scoped_refptr<BrowserProxy> browser_proxy(automation()->GetBrowserWindow(0));
353  ASSERT_TRUE(browser_proxy.get());
354
355  // Create an off the record window.
356  ASSERT_TRUE(browser_proxy->RunCommand(IDC_NEW_INCOGNITO_WINDOW));
357  int window_count;
358  ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count));
359  ASSERT_EQ(2, window_count);
360
361  // Close the first window.
362  CloseWindow(0, 2);
363  browser_proxy = NULL;
364
365  // Launch the browser again. Note, this doesn't spawn a new process, instead
366  // it attaches to the current process.
367  include_testing_id_ = false;
368  clear_profile_ = false;
369  launch_arguments_.AppendSwitch(switches::kRestoreLastSession);
370  LaunchAnotherBrowserBlockUntilClosed(launch_arguments_);
371
372  // A new window should appear;
373  ASSERT_TRUE(automation()->WaitForWindowCountToBecome(2));
374
375  // And it shouldn't have url1_ in it.
376  browser_proxy = automation()->GetBrowserWindow(1);
377  ASSERT_TRUE(browser_proxy.get());
378  scoped_refptr<TabProxy> tab_proxy(browser_proxy->GetTab(0));
379  ASSERT_TRUE(tab_proxy.get());
380  ASSERT_TRUE(tab_proxy->WaitForTabToBeRestored(
381      TestTimeouts::action_max_timeout_ms()));
382  GURL url;
383  ASSERT_TRUE(tab_proxy->GetCurrentURL(&url));
384  ASSERT_TRUE(url != url1_);
385}
386
387// Launches an app window, closes tabbed browser, launches and makes sure
388// we restore the tabbed browser url.
389// Flaky: http://crbug.com/29110
390TEST_F(SessionRestoreUITest,
391       FLAKY_RestoreAfterClosingTabbedBrowserWithAppAndLaunching) {
392  NavigateToURL(url1_);
393
394  // Launch an app.
395
396  bool include_testing_id_orig = include_testing_id_;
397  include_testing_id_ = false;
398  clear_profile_ = false;
399  CommandLine app_launch_arguments = launch_arguments_;
400  app_launch_arguments.AppendSwitchASCII(switches::kApp, url2_.spec());
401  LaunchAnotherBrowserBlockUntilClosed(app_launch_arguments);
402  ASSERT_TRUE(automation()->WaitForWindowCountToBecome(2));
403
404  // Close the first window. The only window left is the App window.
405  CloseWindow(0, 2);
406
407  // Restore the session, which should bring back the first window with url1_.
408  // First restore the settings so we can connect to the browser.
409  include_testing_id_ = include_testing_id_orig;
410  // Restore the session with 1 tab.
411  QuitBrowserAndRestore(1);
412
413  AssertOneWindowWithOneTab();
414
415  ASSERT_EQ(url1_, GetActiveTabURL());
416}
417
418#endif  // !OS_MACOSX
419
420// Creates two windows, closes one, restores, make sure only one window open.
421TEST_F(SessionRestoreUITest, TwoWindowsCloseOneRestoreOnlyOne) {
422  NavigateToURL(url1_);
423
424  // Make sure we have one window.
425  int window_count;
426  ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count));
427  ASSERT_EQ(1, window_count);
428
429  // Open a second window.
430  ASSERT_TRUE(automation()->OpenNewBrowserWindow(Browser::TYPE_NORMAL,
431                                                 true));
432  ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count));
433  ASSERT_EQ(2, window_count);
434
435  // Close it.
436  CloseWindow(1, 2);
437
438  // Restart and make sure we have only one window with one tab and the url
439  // is url1_.
440  QuitBrowserAndRestore(1);
441
442  AssertOneWindowWithOneTab();
443
444  ASSERT_EQ(url1_, GetActiveTabURL());
445}
446
447// Make sure after a restore the number of processes matches that of the number
448// of processes running before the restore. This creates a new tab so that
449// we should have two new tabs running.  (This test will pass in both
450// process-per-site and process-per-site-instance, because we treat the new tab
451// as a special case in process-per-site-instance so that it only ever uses one
452// process.)
453TEST_F(SessionRestoreUITest, ShareProcessesOnRestore) {
454  if (ProxyLauncher::in_process_renderer()) {
455    // No point in running this test in single process mode.
456    return;
457  }
458
459  scoped_refptr<BrowserProxy> browser_proxy(automation()->GetBrowserWindow(0));
460  ASSERT_TRUE(browser_proxy.get() != NULL);
461  int tab_count;
462  ASSERT_TRUE(browser_proxy->GetTabCount(&tab_count));
463
464  // Create two new tabs.
465  ASSERT_TRUE(browser_proxy->RunCommand(IDC_NEW_TAB));
466  ASSERT_TRUE(browser_proxy->RunCommand(IDC_NEW_TAB));
467  int new_tab_count;
468  ASSERT_TRUE(browser_proxy->GetTabCount(&new_tab_count));
469  ASSERT_EQ(tab_count + 2, new_tab_count);
470
471  int expected_process_count = 0;
472  ASSERT_TRUE(GetBrowserProcessCount(&expected_process_count));
473  int expected_tab_count = new_tab_count;
474
475  // Restart.
476  browser_proxy = NULL;
477  QuitBrowserAndRestore(3);
478
479  // Wait for each tab to finish being restored, then make sure the process
480  // count matches.
481  browser_proxy = automation()->GetBrowserWindow(0);
482  ASSERT_TRUE(browser_proxy.get() != NULL);
483  ASSERT_TRUE(browser_proxy->GetTabCount(&tab_count));
484  ASSERT_EQ(expected_tab_count, tab_count);
485
486  for (int i = 0; i < expected_tab_count; ++i) {
487    scoped_refptr<TabProxy> tab_proxy(browser_proxy->GetTab(i));
488    ASSERT_TRUE(tab_proxy.get() != NULL);
489    ASSERT_TRUE(tab_proxy->WaitForTabToBeRestored(
490                    TestTimeouts::action_max_timeout_ms()));
491  }
492
493  int process_count = 0;
494  ASSERT_TRUE(GetBrowserProcessCount(&process_count));
495  ASSERT_EQ(expected_process_count, process_count);
496}
497
498}  // namespace
499