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