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: 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 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 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) 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 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. 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. 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 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. 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. 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