1 // Copyright (c) 2012 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/bind.h" 6 #include "base/bind_helpers.h" 7 #include "base/file_util.h" 8 #include "base/files/scoped_temp_dir.h" 9 #include "base/memory/scoped_ptr.h" 10 #include "base/memory/scoped_vector.h" 11 #include "base/path_service.h" 12 #include "base/stl_util.h" 13 #include "base/strings/string_number_conversions.h" 14 #include "base/strings/utf_string_conversions.h" 15 #include "base/time/time.h" 16 #include "chrome/browser/browser_process.h" 17 #include "chrome/browser/chrome_notification_types.h" 18 #include "chrome/browser/defaults.h" 19 #include "chrome/browser/profiles/profile_manager.h" 20 #include "chrome/browser/sessions/session_backend.h" 21 #include "chrome/browser/sessions/session_service.h" 22 #include "chrome/browser/sessions/session_service_test_helper.h" 23 #include "chrome/browser/sessions/session_types.h" 24 #include "chrome/common/chrome_paths.h" 25 #include "chrome/common/url_constants.h" 26 #include "chrome/test/base/browser_with_test_window_test.h" 27 #include "chrome/test/base/testing_browser_process.h" 28 #include "chrome/test/base/testing_profile.h" 29 #include "chrome/test/base/testing_profile_manager.h" 30 #include "components/sessions/serialized_navigation_entry_test_helper.h" 31 #include "content/public/browser/navigation_entry.h" 32 #include "content/public/browser/notification_observer.h" 33 #include "content/public/browser/notification_registrar.h" 34 #include "content/public/browser/notification_service.h" 35 #include "content/public/common/page_state.h" 36 #include "testing/gtest/include/gtest/gtest.h" 37 38 using content::NavigationEntry; 39 using sessions::SerializedNavigationEntry; 40 using sessions::SerializedNavigationEntryTestHelper; 41 42 class SessionServiceTest : public BrowserWithTestWindowTest, 43 public content::NotificationObserver { 44 public: 45 SessionServiceTest() : window_bounds(0, 1, 2, 3), sync_save_count_(0) {} 46 47 protected: 48 virtual void SetUp() { 49 BrowserWithTestWindowTest::SetUp(); 50 51 profile_manager_.reset( 52 new TestingProfileManager(TestingBrowserProcess::GetGlobal())); 53 ASSERT_TRUE(profile_manager_->SetUp()); 54 55 std::string b = base::Int64ToString(base::Time::Now().ToInternalValue()); 56 TestingProfile* profile = profile_manager_->CreateTestingProfile(b); 57 SessionService* session_service = new SessionService(profile); 58 path_ = profile->GetPath(); 59 60 helper_.SetService(session_service); 61 62 service()->SetWindowType( 63 window_id, Browser::TYPE_TABBED, SessionService::TYPE_NORMAL); 64 service()->SetWindowBounds(window_id, 65 window_bounds, 66 ui::SHOW_STATE_NORMAL); 67 } 68 69 // Upon notification, increment the sync_save_count variable 70 virtual void Observe(int type, 71 const content::NotificationSource& source, 72 const content::NotificationDetails& details) OVERRIDE { 73 ASSERT_EQ(type, chrome::NOTIFICATION_SESSION_SERVICE_SAVED); 74 sync_save_count_++; 75 } 76 77 virtual void TearDown() { 78 helper_.SetService(NULL); 79 BrowserWithTestWindowTest::TearDown(); 80 } 81 82 void UpdateNavigation( 83 const SessionID& window_id, 84 const SessionID& tab_id, 85 const SerializedNavigationEntry& navigation, 86 bool select) { 87 service()->UpdateTabNavigation(window_id, tab_id, navigation); 88 if (select) { 89 service()->SetSelectedNavigationIndex( 90 window_id, tab_id, navigation.index()); 91 } 92 } 93 94 void ReadWindows(std::vector<SessionWindow*>* windows, 95 SessionID::id_type* active_window_id) { 96 // Forces closing the file. 97 helper_.SetService(NULL); 98 99 SessionService* session_service = new SessionService(path_); 100 helper_.SetService(session_service); 101 102 SessionID::id_type* non_null_active_window_id = active_window_id; 103 SessionID::id_type dummy_active_window_id = 0; 104 if (!non_null_active_window_id) 105 non_null_active_window_id = &dummy_active_window_id; 106 helper_.ReadWindows(windows, non_null_active_window_id); 107 } 108 109 // Configures the session service with one window with one tab and a single 110 // navigation. If |pinned_state| is true or |write_always| is true, the 111 // pinned state of the tab is updated. The session service is then recreated 112 // and the pinned state of the read back tab is returned. 113 bool CreateAndWriteSessionWithOneTab(bool pinned_state, bool write_always) { 114 SessionID tab_id; 115 SerializedNavigationEntry nav1 = 116 SerializedNavigationEntryTestHelper::CreateNavigation( 117 "http://google.com", "abc"); 118 119 helper_.PrepareTabInWindow(window_id, tab_id, 0, true); 120 UpdateNavigation(window_id, tab_id, nav1, true); 121 122 if (pinned_state || write_always) 123 helper_.service()->SetPinnedState(window_id, tab_id, pinned_state); 124 125 ScopedVector<SessionWindow> windows; 126 ReadWindows(&(windows.get()), NULL); 127 128 EXPECT_EQ(1U, windows.size()); 129 if (HasFatalFailure()) 130 return false; 131 EXPECT_EQ(1U, windows[0]->tabs.size()); 132 if (HasFatalFailure()) 133 return false; 134 135 SessionTab* tab = windows[0]->tabs[0]; 136 helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab); 137 138 return tab->pinned; 139 } 140 141 void CreateAndWriteSessionWithTwoWindows( 142 const SessionID& window2_id, 143 const SessionID& tab1_id, 144 const SessionID& tab2_id, 145 SerializedNavigationEntry* nav1, 146 SerializedNavigationEntry* nav2) { 147 *nav1 = SerializedNavigationEntryTestHelper::CreateNavigation( 148 "http://google.com", "abc"); 149 *nav2 = SerializedNavigationEntryTestHelper::CreateNavigation( 150 "http://google2.com", "abcd"); 151 152 helper_.PrepareTabInWindow(window_id, tab1_id, 0, true); 153 UpdateNavigation(window_id, tab1_id, *nav1, true); 154 155 const gfx::Rect window2_bounds(3, 4, 5, 6); 156 service()->SetWindowType( 157 window2_id, Browser::TYPE_TABBED, SessionService::TYPE_NORMAL); 158 service()->SetWindowBounds(window2_id, 159 window2_bounds, 160 ui::SHOW_STATE_MAXIMIZED); 161 helper_.PrepareTabInWindow(window2_id, tab2_id, 0, true); 162 UpdateNavigation(window2_id, tab2_id, *nav2, true); 163 } 164 165 SessionService* service() { return helper_.service(); } 166 167 SessionBackend* backend() { return helper_.backend(); } 168 169 const gfx::Rect window_bounds; 170 171 SessionID window_id; 172 173 int sync_save_count_; 174 175 // Path used in testing. 176 base::ScopedTempDir temp_dir_; 177 base::FilePath path_; 178 179 SessionServiceTestHelper helper_; 180 scoped_ptr<TestingProfileManager> profile_manager_; 181 }; 182 183 TEST_F(SessionServiceTest, Basic) { 184 SessionID tab_id; 185 ASSERT_NE(window_id.id(), tab_id.id()); 186 187 SerializedNavigationEntry nav1 = 188 SerializedNavigationEntryTestHelper::CreateNavigation( 189 "http://google.com", "abc"); 190 SerializedNavigationEntryTestHelper::SetOriginalRequestURL( 191 GURL("http://original.request.com"), &nav1); 192 193 helper_.PrepareTabInWindow(window_id, tab_id, 0, true); 194 UpdateNavigation(window_id, tab_id, nav1, true); 195 196 ScopedVector<SessionWindow> windows; 197 ReadWindows(&(windows.get()), NULL); 198 199 ASSERT_EQ(1U, windows.size()); 200 ASSERT_TRUE(window_bounds == windows[0]->bounds); 201 ASSERT_EQ(0, windows[0]->selected_tab_index); 202 ASSERT_EQ(window_id.id(), windows[0]->window_id.id()); 203 ASSERT_EQ(1U, windows[0]->tabs.size()); 204 ASSERT_EQ(Browser::TYPE_TABBED, windows[0]->type); 205 206 SessionTab* tab = windows[0]->tabs[0]; 207 helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab); 208 209 helper_.AssertNavigationEquals(nav1, tab->navigations[0]); 210 } 211 212 // Make sure we persist post entries. 213 TEST_F(SessionServiceTest, PersistPostData) { 214 SessionID tab_id; 215 ASSERT_NE(window_id.id(), tab_id.id()); 216 217 SerializedNavigationEntry nav1 = 218 SerializedNavigationEntryTestHelper::CreateNavigation( 219 "http://google.com", "abc"); 220 SerializedNavigationEntryTestHelper::SetHasPostData(true, &nav1); 221 222 helper_.PrepareTabInWindow(window_id, tab_id, 0, true); 223 UpdateNavigation(window_id, tab_id, nav1, true); 224 225 ScopedVector<SessionWindow> windows; 226 ReadWindows(&(windows.get()), NULL); 227 228 helper_.AssertSingleWindowWithSingleTab(windows.get(), 1); 229 } 230 231 TEST_F(SessionServiceTest, ClosingTabStaysClosed) { 232 SessionID tab_id; 233 SessionID tab2_id; 234 ASSERT_NE(tab_id.id(), tab2_id.id()); 235 236 SerializedNavigationEntry nav1 = 237 SerializedNavigationEntryTestHelper::CreateNavigation( 238 "http://google.com", "abc"); 239 SerializedNavigationEntry nav2 = 240 SerializedNavigationEntryTestHelper::CreateNavigation( 241 "http://google2.com", "abcd"); 242 243 helper_.PrepareTabInWindow(window_id, tab_id, 0, true); 244 UpdateNavigation(window_id, tab_id, nav1, true); 245 246 helper_.PrepareTabInWindow(window_id, tab2_id, 1, false); 247 UpdateNavigation(window_id, tab2_id, nav2, true); 248 service()->TabClosed(window_id, tab2_id, false); 249 250 ScopedVector<SessionWindow> windows; 251 ReadWindows(&(windows.get()), NULL); 252 253 ASSERT_EQ(1U, windows.size()); 254 ASSERT_EQ(0, windows[0]->selected_tab_index); 255 ASSERT_EQ(window_id.id(), windows[0]->window_id.id()); 256 ASSERT_EQ(1U, windows[0]->tabs.size()); 257 258 SessionTab* tab = windows[0]->tabs[0]; 259 helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab); 260 261 helper_.AssertNavigationEquals(nav1, tab->navigations[0]); 262 } 263 264 TEST_F(SessionServiceTest, Pruning) { 265 SessionID tab_id; 266 267 SerializedNavigationEntry nav1 = 268 SerializedNavigationEntryTestHelper::CreateNavigation( 269 "http://google.com", "abc"); 270 SerializedNavigationEntry nav2 = 271 SerializedNavigationEntryTestHelper::CreateNavigation( 272 "http://google2.com", "abcd"); 273 274 helper_.PrepareTabInWindow(window_id, tab_id, 0, true); 275 for (int i = 0; i < 6; ++i) { 276 SerializedNavigationEntry* nav = (i % 2) == 0 ? &nav1 : &nav2; 277 nav->set_index(i); 278 UpdateNavigation(window_id, tab_id, *nav, true); 279 } 280 service()->TabNavigationPathPrunedFromBack(window_id, tab_id, 3); 281 282 ScopedVector<SessionWindow> windows; 283 ReadWindows(&(windows.get()), NULL); 284 285 ASSERT_EQ(1U, windows.size()); 286 ASSERT_EQ(0, windows[0]->selected_tab_index); 287 ASSERT_EQ(1U, windows[0]->tabs.size()); 288 289 SessionTab* tab = windows[0]->tabs[0]; 290 // We left the selected index at 5, then pruned. When rereading the 291 // index should get reset to last valid navigation, which is 2. 292 helper_.AssertTabEquals(window_id, tab_id, 0, 2, 3, *tab); 293 294 ASSERT_EQ(3u, tab->navigations.size()); 295 helper_.AssertNavigationEquals(nav1, tab->navigations[0]); 296 helper_.AssertNavigationEquals(nav2, tab->navigations[1]); 297 helper_.AssertNavigationEquals(nav1, tab->navigations[2]); 298 } 299 300 TEST_F(SessionServiceTest, TwoWindows) { 301 SessionID window2_id; 302 SessionID tab1_id; 303 SessionID tab2_id; 304 SerializedNavigationEntry nav1; 305 SerializedNavigationEntry nav2; 306 307 CreateAndWriteSessionWithTwoWindows( 308 window2_id, tab1_id, tab2_id, &nav1, &nav2); 309 310 ScopedVector<SessionWindow> windows; 311 ReadWindows(&(windows.get()), NULL); 312 313 ASSERT_EQ(2U, windows.size()); 314 ASSERT_EQ(0, windows[0]->selected_tab_index); 315 ASSERT_EQ(0, windows[1]->selected_tab_index); 316 ASSERT_EQ(1U, windows[0]->tabs.size()); 317 ASSERT_EQ(1U, windows[1]->tabs.size()); 318 319 SessionTab* rt1; 320 SessionTab* rt2; 321 if (windows[0]->window_id.id() == window_id.id()) { 322 ASSERT_EQ(window2_id.id(), windows[1]->window_id.id()); 323 ASSERT_EQ(ui::SHOW_STATE_NORMAL, windows[0]->show_state); 324 ASSERT_EQ(ui::SHOW_STATE_MAXIMIZED, windows[1]->show_state); 325 rt1 = windows[0]->tabs[0]; 326 rt2 = windows[1]->tabs[0]; 327 } else { 328 ASSERT_EQ(window2_id.id(), windows[0]->window_id.id()); 329 ASSERT_EQ(window_id.id(), windows[1]->window_id.id()); 330 ASSERT_EQ(ui::SHOW_STATE_MAXIMIZED, windows[0]->show_state); 331 ASSERT_EQ(ui::SHOW_STATE_NORMAL, windows[1]->show_state); 332 rt1 = windows[1]->tabs[0]; 333 rt2 = windows[0]->tabs[0]; 334 } 335 SessionTab* tab = rt1; 336 helper_.AssertTabEquals(window_id, tab1_id, 0, 0, 1, *tab); 337 helper_.AssertNavigationEquals(nav1, tab->navigations[0]); 338 339 tab = rt2; 340 helper_.AssertTabEquals(window2_id, tab2_id, 0, 0, 1, *tab); 341 helper_.AssertNavigationEquals(nav2, tab->navigations[0]); 342 } 343 344 TEST_F(SessionServiceTest, WindowWithNoTabsGetsPruned) { 345 SessionID window2_id; 346 SessionID tab1_id; 347 SessionID tab2_id; 348 349 SerializedNavigationEntry nav1 = 350 SerializedNavigationEntryTestHelper::CreateNavigation( 351 "http://google.com", "abc"); 352 353 helper_.PrepareTabInWindow(window_id, tab1_id, 0, true); 354 UpdateNavigation(window_id, tab1_id, nav1, true); 355 356 const gfx::Rect window2_bounds(3, 4, 5, 6); 357 service()->SetWindowType( 358 window2_id, Browser::TYPE_TABBED, SessionService::TYPE_NORMAL); 359 service()->SetWindowBounds(window2_id, 360 window2_bounds, 361 ui::SHOW_STATE_NORMAL); 362 helper_.PrepareTabInWindow(window2_id, tab2_id, 0, true); 363 364 ScopedVector<SessionWindow> windows; 365 ReadWindows(&(windows.get()), NULL); 366 367 ASSERT_EQ(1U, windows.size()); 368 ASSERT_EQ(0, windows[0]->selected_tab_index); 369 ASSERT_EQ(1U, windows[0]->tabs.size()); 370 ASSERT_EQ(window_id.id(), windows[0]->window_id.id()); 371 372 SessionTab* tab = windows[0]->tabs[0]; 373 helper_.AssertTabEquals(window_id, tab1_id, 0, 0, 1, *tab); 374 helper_.AssertNavigationEquals(nav1, tab->navigations[0]); 375 } 376 377 TEST_F(SessionServiceTest, ClosingWindowDoesntCloseTabs) { 378 SessionID tab_id; 379 SessionID tab2_id; 380 ASSERT_NE(tab_id.id(), tab2_id.id()); 381 382 SerializedNavigationEntry nav1 = 383 SerializedNavigationEntryTestHelper::CreateNavigation( 384 "http://google.com", "abc"); 385 SerializedNavigationEntry nav2 = 386 SerializedNavigationEntryTestHelper::CreateNavigation( 387 "http://google2.com", "abcd"); 388 389 helper_.PrepareTabInWindow(window_id, tab_id, 0, true); 390 UpdateNavigation(window_id, tab_id, nav1, true); 391 392 helper_.PrepareTabInWindow(window_id, tab2_id, 1, false); 393 UpdateNavigation(window_id, tab2_id, nav2, true); 394 395 service()->WindowClosing(window_id); 396 397 ScopedVector<SessionWindow> windows; 398 ReadWindows(&(windows.get()), NULL); 399 400 ASSERT_EQ(1U, windows.size()); 401 ASSERT_EQ(0, windows[0]->selected_tab_index); 402 ASSERT_EQ(window_id.id(), windows[0]->window_id.id()); 403 ASSERT_EQ(2U, windows[0]->tabs.size()); 404 405 SessionTab* tab = windows[0]->tabs[0]; 406 helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab); 407 helper_.AssertNavigationEquals(nav1, tab->navigations[0]); 408 409 tab = windows[0]->tabs[1]; 410 helper_.AssertTabEquals(window_id, tab2_id, 1, 0, 1, *tab); 411 helper_.AssertNavigationEquals(nav2, tab->navigations[0]); 412 } 413 414 TEST_F(SessionServiceTest, LockingWindowRemembersAll) { 415 SessionID window2_id; 416 SessionID tab1_id; 417 SessionID tab2_id; 418 SerializedNavigationEntry nav1; 419 SerializedNavigationEntry nav2; 420 421 CreateAndWriteSessionWithTwoWindows( 422 window2_id, tab1_id, tab2_id, &nav1, &nav2); 423 424 ASSERT_TRUE(service()->profile() != NULL); 425 ASSERT_TRUE(g_browser_process->profile_manager() != NULL); 426 ProfileInfoCache& profile_info = 427 g_browser_process->profile_manager()->GetProfileInfoCache(); 428 size_t profile_index = profile_info.GetIndexOfProfileWithPath( 429 service()->profile()->GetPath()); 430 ASSERT_NE(std::string::npos, profile_index); 431 profile_info.SetProfileSigninRequiredAtIndex(profile_index, true); 432 433 service()->WindowClosing(window_id); 434 service()->WindowClosed(window_id); 435 service()->WindowClosing(window2_id); 436 service()->WindowClosed(window2_id); 437 438 ScopedVector<SessionWindow> windows; 439 ReadWindows(&(windows.get()), NULL); 440 441 ASSERT_EQ(2U, windows.size()); 442 ASSERT_EQ(1U, windows[0]->tabs.size()); 443 ASSERT_EQ(1U, windows[1]->tabs.size()); 444 } 445 446 TEST_F(SessionServiceTest, WindowCloseCommittedAfterNavigate) { 447 SessionID window2_id; 448 SessionID tab_id; 449 SessionID tab2_id; 450 ASSERT_NE(window2_id.id(), window_id.id()); 451 452 service()->SetWindowType( 453 window2_id, Browser::TYPE_TABBED, SessionService::TYPE_NORMAL); 454 service()->SetWindowBounds(window2_id, 455 window_bounds, 456 ui::SHOW_STATE_NORMAL); 457 458 SerializedNavigationEntry nav1 = 459 SerializedNavigationEntryTestHelper::CreateNavigation( 460 "http://google.com", "abc"); 461 SerializedNavigationEntry nav2 = 462 SerializedNavigationEntryTestHelper::CreateNavigation( 463 "http://google2.com", "abcd"); 464 465 helper_.PrepareTabInWindow(window_id, tab_id, 0, true); 466 UpdateNavigation(window_id, tab_id, nav1, true); 467 468 helper_.PrepareTabInWindow(window2_id, tab2_id, 0, false); 469 UpdateNavigation(window2_id, tab2_id, nav2, true); 470 471 service()->WindowClosing(window2_id); 472 service()->TabClosed(window2_id, tab2_id, false); 473 service()->WindowClosed(window2_id); 474 475 ScopedVector<SessionWindow> windows; 476 ReadWindows(&(windows.get()), NULL); 477 478 ASSERT_EQ(1U, windows.size()); 479 ASSERT_EQ(0, windows[0]->selected_tab_index); 480 ASSERT_EQ(window_id.id(), windows[0]->window_id.id()); 481 ASSERT_EQ(1U, windows[0]->tabs.size()); 482 483 SessionTab* tab = windows[0]->tabs[0]; 484 helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab); 485 helper_.AssertNavigationEquals(nav1, tab->navigations[0]); 486 } 487 488 // Makes sure we don't track popups. 489 TEST_F(SessionServiceTest, IgnorePopups) { 490 SessionID window2_id; 491 SessionID tab_id; 492 SessionID tab2_id; 493 ASSERT_NE(window2_id.id(), window_id.id()); 494 495 service()->SetWindowType( 496 window2_id, Browser::TYPE_POPUP, SessionService::TYPE_NORMAL); 497 service()->SetWindowBounds(window2_id, 498 window_bounds, 499 ui::SHOW_STATE_NORMAL); 500 501 SerializedNavigationEntry nav1 = 502 SerializedNavigationEntryTestHelper::CreateNavigation( 503 "http://google.com", "abc"); 504 SerializedNavigationEntry nav2 = 505 SerializedNavigationEntryTestHelper::CreateNavigation( 506 "http://google2.com", "abcd"); 507 508 helper_.PrepareTabInWindow(window_id, tab_id, 0, true); 509 UpdateNavigation(window_id, tab_id, nav1, true); 510 511 helper_.PrepareTabInWindow(window2_id, tab2_id, 0, false); 512 UpdateNavigation(window2_id, tab2_id, nav2, true); 513 514 ScopedVector<SessionWindow> windows; 515 ReadWindows(&(windows.get()), NULL); 516 517 ASSERT_EQ(1U, windows.size()); 518 ASSERT_EQ(0, windows[0]->selected_tab_index); 519 ASSERT_EQ(window_id.id(), windows[0]->window_id.id()); 520 ASSERT_EQ(1U, windows[0]->tabs.size()); 521 522 SessionTab* tab = windows[0]->tabs[0]; 523 helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab); 524 helper_.AssertNavigationEquals(nav1, tab->navigations[0]); 525 } 526 527 #if defined (OS_CHROMEOS) 528 // Makes sure we track apps. Only applicable on chromeos. 529 TEST_F(SessionServiceTest, RestoreApp) { 530 SessionID window2_id; 531 SessionID tab_id; 532 SessionID tab2_id; 533 ASSERT_NE(window2_id.id(), window_id.id()); 534 535 service()->SetWindowType( 536 window2_id, Browser::TYPE_POPUP, SessionService::TYPE_APP); 537 service()->SetWindowBounds(window2_id, 538 window_bounds, 539 ui::SHOW_STATE_NORMAL); 540 service()->SetWindowAppName(window2_id, "TestApp"); 541 542 SerializedNavigationEntry nav1 = 543 SerializedNavigationEntryTestHelper::CreateNavigation( 544 "http://google.com", "abc"); 545 SerializedNavigationEntry nav2 = 546 SerializedNavigationEntryTestHelper::CreateNavigation( 547 "http://google2.com", "abcd"); 548 549 helper_.PrepareTabInWindow(window_id, tab_id, 0, true); 550 UpdateNavigation(window_id, tab_id, nav1, true); 551 552 helper_.PrepareTabInWindow(window2_id, tab2_id, 0, false); 553 UpdateNavigation(window2_id, tab2_id, nav2, true); 554 555 ScopedVector<SessionWindow> windows; 556 ReadWindows(&(windows.get()), NULL); 557 558 ASSERT_EQ(2U, windows.size()); 559 int tabbed_index = windows[0]->type == Browser::TYPE_TABBED ? 560 0 : 1; 561 int app_index = tabbed_index == 0 ? 1 : 0; 562 ASSERT_EQ(0, windows[tabbed_index]->selected_tab_index); 563 ASSERT_EQ(window_id.id(), windows[tabbed_index]->window_id.id()); 564 ASSERT_EQ(1U, windows[tabbed_index]->tabs.size()); 565 566 SessionTab* tab = windows[tabbed_index]->tabs[0]; 567 helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab); 568 helper_.AssertNavigationEquals(nav1, tab->navigations[0]); 569 570 ASSERT_EQ(0, windows[app_index]->selected_tab_index); 571 ASSERT_EQ(window2_id.id(), windows[app_index]->window_id.id()); 572 ASSERT_EQ(1U, windows[app_index]->tabs.size()); 573 ASSERT_TRUE(windows[app_index]->type == Browser::TYPE_POPUP); 574 ASSERT_EQ("TestApp", windows[app_index]->app_name); 575 576 tab = windows[app_index]->tabs[0]; 577 helper_.AssertTabEquals(window2_id, tab2_id, 0, 0, 1, *tab); 578 helper_.AssertNavigationEquals(nav2, tab->navigations[0]); 579 } 580 #endif // defined (OS_CHROMEOS) 581 582 // Tests pruning from the front. 583 TEST_F(SessionServiceTest, PruneFromFront) { 584 const std::string base_url("http://google.com/"); 585 SessionID tab_id; 586 587 helper_.PrepareTabInWindow(window_id, tab_id, 0, true); 588 589 // Add 5 navigations, with the 4th selected. 590 for (int i = 0; i < 5; ++i) { 591 SerializedNavigationEntry nav = 592 SerializedNavigationEntryTestHelper::CreateNavigation( 593 base_url + base::IntToString(i), "a"); 594 nav.set_index(i); 595 UpdateNavigation(window_id, tab_id, nav, (i == 3)); 596 } 597 598 // Prune the first two navigations from the front. 599 helper_.service()->TabNavigationPathPrunedFromFront(window_id, tab_id, 2); 600 601 // Read back in. 602 ScopedVector<SessionWindow> windows; 603 ReadWindows(&(windows.get()), NULL); 604 605 ASSERT_EQ(1U, windows.size()); 606 ASSERT_EQ(0, windows[0]->selected_tab_index); 607 ASSERT_EQ(window_id.id(), windows[0]->window_id.id()); 608 ASSERT_EQ(1U, windows[0]->tabs.size()); 609 610 // There shouldn't be an app id. 611 EXPECT_TRUE(windows[0]->tabs[0]->extension_app_id.empty()); 612 613 // We should be left with three navigations, the 2nd selected. 614 SessionTab* tab = windows[0]->tabs[0]; 615 ASSERT_EQ(1, tab->current_navigation_index); 616 EXPECT_EQ(3U, tab->navigations.size()); 617 EXPECT_TRUE(GURL(base_url + base::IntToString(2)) == 618 tab->navigations[0].virtual_url()); 619 EXPECT_TRUE(GURL(base_url + base::IntToString(3)) == 620 tab->navigations[1].virtual_url()); 621 EXPECT_TRUE(GURL(base_url + base::IntToString(4)) == 622 tab->navigations[2].virtual_url()); 623 } 624 625 // Prunes from front so that we have no entries. 626 TEST_F(SessionServiceTest, PruneToEmpty) { 627 const std::string base_url("http://google.com/"); 628 SessionID tab_id; 629 630 helper_.PrepareTabInWindow(window_id, tab_id, 0, true); 631 632 // Add 5 navigations, with the 4th selected. 633 for (int i = 0; i < 5; ++i) { 634 SerializedNavigationEntry nav = 635 SerializedNavigationEntryTestHelper::CreateNavigation( 636 base_url + base::IntToString(i), "a"); 637 nav.set_index(i); 638 UpdateNavigation(window_id, tab_id, nav, (i == 3)); 639 } 640 641 // Prune the first two navigations from the front. 642 helper_.service()->TabNavigationPathPrunedFromFront(window_id, tab_id, 5); 643 644 // Read back in. 645 ScopedVector<SessionWindow> windows; 646 ReadWindows(&(windows.get()), NULL); 647 648 ASSERT_EQ(0U, windows.size()); 649 } 650 651 // Don't set the pinned state and make sure the pinned value is false. 652 TEST_F(SessionServiceTest, PinnedDefaultsToFalse) { 653 EXPECT_FALSE(CreateAndWriteSessionWithOneTab(false, false)); 654 } 655 656 // Explicitly set the pinned state to false and make sure we get back false. 657 TEST_F(SessionServiceTest, PinnedFalseWhenSetToFalse) { 658 EXPECT_FALSE(CreateAndWriteSessionWithOneTab(false, true)); 659 } 660 661 // Explicitly set the pinned state to true and make sure we get back true. 662 TEST_F(SessionServiceTest, PinnedTrue) { 663 EXPECT_TRUE(CreateAndWriteSessionWithOneTab(true, true)); 664 } 665 666 // Make sure application extension ids are persisted. 667 TEST_F(SessionServiceTest, PersistApplicationExtensionID) { 668 SessionID tab_id; 669 ASSERT_NE(window_id.id(), tab_id.id()); 670 std::string app_id("foo"); 671 672 SerializedNavigationEntry nav1 = 673 SerializedNavigationEntryTestHelper::CreateNavigation( 674 "http://google.com", "abc"); 675 676 helper_.PrepareTabInWindow(window_id, tab_id, 0, true); 677 UpdateNavigation(window_id, tab_id, nav1, true); 678 helper_.SetTabExtensionAppID(window_id, tab_id, app_id); 679 680 ScopedVector<SessionWindow> windows; 681 ReadWindows(&(windows.get()), NULL); 682 683 helper_.AssertSingleWindowWithSingleTab(windows.get(), 1); 684 EXPECT_TRUE(app_id == windows[0]->tabs[0]->extension_app_id); 685 } 686 687 // Check that user agent overrides are persisted. 688 TEST_F(SessionServiceTest, PersistUserAgentOverrides) { 689 SessionID tab_id; 690 ASSERT_NE(window_id.id(), tab_id.id()); 691 std::string user_agent_override = "Mozilla/5.0 (X11; Linux x86_64) " 692 "AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.45 " 693 "Safari/535.19"; 694 695 SerializedNavigationEntry nav1 = 696 SerializedNavigationEntryTestHelper::CreateNavigation( 697 "http://google.com", "abc"); 698 SerializedNavigationEntryTestHelper::SetIsOverridingUserAgent(true, &nav1); 699 700 helper_.PrepareTabInWindow(window_id, tab_id, 0, true); 701 UpdateNavigation(window_id, tab_id, nav1, true); 702 helper_.SetTabUserAgentOverride(window_id, tab_id, user_agent_override); 703 704 ScopedVector<SessionWindow> windows; 705 ReadWindows(&(windows.get()), NULL); 706 helper_.AssertSingleWindowWithSingleTab(windows.get(), 1); 707 708 SessionTab* tab = windows[0]->tabs[0]; 709 helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab); 710 helper_.AssertNavigationEquals(nav1, tab->navigations[0]); 711 EXPECT_TRUE(user_agent_override == tab->user_agent_override); 712 } 713 714 // Test that the notification for SESSION_SERVICE_SAVED is working properly. 715 TEST_F(SessionServiceTest, SavedSessionNotification) { 716 content::NotificationRegistrar registrar_; 717 registrar_.Add(this, chrome::NOTIFICATION_SESSION_SERVICE_SAVED, 718 content::NotificationService::AllSources()); 719 service()->Save(); 720 EXPECT_EQ(sync_save_count_, 1); 721 } 722 723 // Makes sure a tab closed by a user gesture is not restored. 724 TEST_F(SessionServiceTest, CloseTabUserGesture) { 725 SessionID tab_id; 726 ASSERT_NE(window_id.id(), tab_id.id()); 727 728 SerializedNavigationEntry nav1 = 729 SerializedNavigationEntryTestHelper::CreateNavigation( 730 "http://google.com", "abc"); 731 732 helper_.PrepareTabInWindow(window_id, tab_id, 0, true); 733 UpdateNavigation(window_id, tab_id, nav1, true); 734 service()->TabClosed(window_id, tab_id, true); 735 736 ScopedVector<SessionWindow> windows; 737 ReadWindows(&(windows.get()), NULL); 738 739 ASSERT_TRUE(windows.empty()); 740 } 741 742 // Verifies SetWindowBounds maps SHOW_STATE_DEFAULT to SHOW_STATE_NORMAL. 743 TEST_F(SessionServiceTest, DontPersistDefault) { 744 SessionID tab_id; 745 ASSERT_NE(window_id.id(), tab_id.id()); 746 SerializedNavigationEntry nav1 = 747 SerializedNavigationEntryTestHelper::CreateNavigation( 748 "http://google.com", "abc"); 749 helper_.PrepareTabInWindow(window_id, tab_id, 0, true); 750 UpdateNavigation(window_id, tab_id, nav1, true); 751 service()->SetWindowBounds(window_id, 752 window_bounds, 753 ui::SHOW_STATE_DEFAULT); 754 755 ScopedVector<SessionWindow> windows; 756 ReadWindows(&(windows.get()), NULL); 757 ASSERT_EQ(1U, windows.size()); 758 EXPECT_EQ(ui::SHOW_STATE_NORMAL, windows[0]->show_state); 759 } 760 761 TEST_F(SessionServiceTest, KeepPostDataWithoutPasswords) { 762 SessionID tab_id; 763 ASSERT_NE(window_id.id(), tab_id.id()); 764 765 // Create a page state representing a HTTP body without posted passwords. 766 content::PageState page_state = 767 content::PageState::CreateForTesting(GURL(), false, "data", NULL); 768 769 // Create a TabNavigation containing page_state and representing a POST 770 // request. 771 SerializedNavigationEntry nav1 = 772 SerializedNavigationEntryTestHelper::CreateNavigation( 773 "http://google.com", "title"); 774 SerializedNavigationEntryTestHelper::SetPageState(page_state, &nav1); 775 SerializedNavigationEntryTestHelper::SetHasPostData(true, &nav1); 776 777 // Create a TabNavigation containing page_state and representing a normal 778 // request. 779 SerializedNavigationEntry nav2 = 780 SerializedNavigationEntryTestHelper::CreateNavigation( 781 "http://google.com/nopost", "title"); 782 SerializedNavigationEntryTestHelper::SetPageState(page_state, &nav2); 783 nav2.set_index(1); 784 785 helper_.PrepareTabInWindow(window_id, tab_id, 0, true); 786 UpdateNavigation(window_id, tab_id, nav1, true); 787 UpdateNavigation(window_id, tab_id, nav2, true); 788 789 ScopedVector<SessionWindow> windows; 790 ReadWindows(&(windows.get()), NULL); 791 792 helper_.AssertSingleWindowWithSingleTab(windows.get(), 2); 793 794 // Expected: the page state of both navigations was saved and restored. 795 ASSERT_EQ(2u, windows[0]->tabs[0]->navigations.size()); 796 helper_.AssertNavigationEquals(nav1, windows[0]->tabs[0]->navigations[0]); 797 helper_.AssertNavigationEquals(nav2, windows[0]->tabs[0]->navigations[1]); 798 } 799 800 TEST_F(SessionServiceTest, RemovePostDataWithPasswords) { 801 SessionID tab_id; 802 ASSERT_NE(window_id.id(), tab_id.id()); 803 804 // Create a page state representing a HTTP body with posted passwords. 805 content::PageState page_state = 806 content::PageState::CreateForTesting(GURL(), true, "data", NULL); 807 808 // Create a TabNavigation containing page_state and representing a POST 809 // request with passwords. 810 SerializedNavigationEntry nav1 = 811 SerializedNavigationEntryTestHelper::CreateNavigation( 812 "http://google.com", "title"); 813 SerializedNavigationEntryTestHelper::SetPageState(page_state, &nav1); 814 SerializedNavigationEntryTestHelper::SetHasPostData(true, &nav1); 815 helper_.PrepareTabInWindow(window_id, tab_id, 0, true); 816 UpdateNavigation(window_id, tab_id, nav1, true); 817 818 ScopedVector<SessionWindow> windows; 819 ReadWindows(&(windows.get()), NULL); 820 821 helper_.AssertSingleWindowWithSingleTab(windows.get(), 1); 822 823 // Expected: the HTTP body was removed from the page state of the POST 824 // navigation with passwords. 825 EXPECT_NE(page_state, windows[0]->tabs[0]->navigations[0].page_state()); 826 } 827 828 // This test is only applicable to chromeos. 829 #if defined(OS_CHROMEOS) 830 // Verifies migration of tab/window closed works. 831 TEST_F(SessionServiceTest, CanOpenV1TabClosed) { 832 base::FilePath v1_file_path; 833 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &v1_file_path)); 834 // v1_session_file contains a tab closed command with the original id. The 835 // file was generated from ClosingTabStaysClosed. If we successfully processed 836 // the file we'll have one tab. 837 v1_file_path = 838 v1_file_path.AppendASCII("sessions").AppendASCII("v1_session_file"); 839 base::FilePath dest_file_path(path_); 840 dest_file_path = dest_file_path.AppendASCII("Current Session"); 841 842 // Forces closing the file. 843 helper_.SetService(NULL); 844 845 ASSERT_TRUE(base::CopyFile(v1_file_path, dest_file_path)); 846 847 SessionService* session_service = new SessionService(path_); 848 helper_.SetService(session_service); 849 ScopedVector<SessionWindow> windows; 850 SessionID::id_type active_window_id = 0; 851 helper_.ReadWindows(&(windows.get()), &active_window_id); 852 ASSERT_EQ(1u, windows.size()); 853 EXPECT_EQ(1u, windows[0]->tabs.size()); 854 } 855 #endif // defined(OS_CHROMEOS) 856 857 TEST_F(SessionServiceTest, ReplacePendingNavigation) { 858 const std::string base_url("http://google.com/"); 859 SessionID tab_id; 860 861 helper_.PrepareTabInWindow(window_id, tab_id, 0, true); 862 863 // Add 5 navigations, some with the same index 864 for (int i = 0; i < 5; ++i) { 865 SerializedNavigationEntry nav = 866 SerializedNavigationEntryTestHelper::CreateNavigation( 867 base_url + base::IntToString(i), "a"); 868 nav.set_index(i / 2); 869 UpdateNavigation(window_id, tab_id, nav, true); 870 } 871 872 // Read back in. 873 ScopedVector<SessionWindow> windows; 874 ReadWindows(&(windows.get()), NULL); 875 876 // The ones with index 0, and 2 should have been replaced by 1 and 3. 877 ASSERT_EQ(1U, windows.size()); 878 ASSERT_EQ(1U, windows[0]->tabs.size()); 879 EXPECT_EQ(3U, windows[0]->tabs[0]->navigations.size()); 880 EXPECT_EQ(GURL(base_url + base::IntToString(1)), 881 windows[0]->tabs[0]->navigations[0].virtual_url()); 882 EXPECT_EQ(GURL(base_url + base::IntToString(3)), 883 windows[0]->tabs[0]->navigations[1].virtual_url()); 884 EXPECT_EQ(GURL(base_url + base::IntToString(4)), 885 windows[0]->tabs[0]->navigations[2].virtual_url()); 886 } 887 888 TEST_F(SessionServiceTest, ReplacePendingNavigationAndPrune) { 889 const std::string base_url("http://google.com/"); 890 SessionID tab_id; 891 892 helper_.PrepareTabInWindow(window_id, tab_id, 0, true); 893 894 for (int i = 0; i < 5; ++i) { 895 SerializedNavigationEntry nav = 896 SerializedNavigationEntryTestHelper::CreateNavigation( 897 base_url + base::IntToString(i), "a"); 898 nav.set_index(i); 899 UpdateNavigation(window_id, tab_id, nav, true); 900 } 901 902 // Prune all those navigations. 903 helper_.service()->TabNavigationPathPrunedFromFront(window_id, tab_id, 5); 904 905 // Add another navigation to replace the last one. 906 SerializedNavigationEntry nav = 907 SerializedNavigationEntryTestHelper::CreateNavigation( 908 base_url + base::IntToString(5), "a"); 909 nav.set_index(4); 910 UpdateNavigation(window_id, tab_id, nav, true); 911 912 // Read back in. 913 ScopedVector<SessionWindow> windows; 914 ReadWindows(&(windows.get()), NULL); 915 916 // We should still have that last navigation at the end, 917 // even though it replaced one that was set before the prune. 918 ASSERT_EQ(1U, windows.size()); 919 ASSERT_EQ(1U, windows[0]->tabs.size()); 920 ASSERT_EQ(1U, windows[0]->tabs[0]->navigations.size()); 921 EXPECT_EQ(GURL(base_url + base::IntToString(5)), 922 windows[0]->tabs[0]->navigations[0].virtual_url()); 923 } 924 925 TEST_F(SessionServiceTest, RestoreActivation1) { 926 SessionID window2_id; 927 SessionID tab1_id; 928 SessionID tab2_id; 929 SerializedNavigationEntry nav1; 930 SerializedNavigationEntry nav2; 931 932 CreateAndWriteSessionWithTwoWindows( 933 window2_id, tab1_id, tab2_id, &nav1, &nav2); 934 935 service()->ScheduleCommand( 936 service()->CreateSetActiveWindowCommand(window2_id)); 937 service()->ScheduleCommand( 938 service()->CreateSetActiveWindowCommand(window_id)); 939 940 ScopedVector<SessionWindow> windows; 941 SessionID::id_type active_window_id = 0; 942 ReadWindows(&(windows.get()), &active_window_id); 943 EXPECT_EQ(window_id.id(), active_window_id); 944 } 945 946 // It's easier to have two separate tests with setup/teardown than to manualy 947 // reset the state for the different flavors of the test. 948 TEST_F(SessionServiceTest, RestoreActivation2) { 949 SessionID window2_id; 950 SessionID tab1_id; 951 SessionID tab2_id; 952 SerializedNavigationEntry nav1; 953 SerializedNavigationEntry nav2; 954 955 CreateAndWriteSessionWithTwoWindows( 956 window2_id, tab1_id, tab2_id, &nav1, &nav2); 957 958 service()->ScheduleCommand( 959 service()->CreateSetActiveWindowCommand(window2_id)); 960 service()->ScheduleCommand( 961 service()->CreateSetActiveWindowCommand(window_id)); 962 service()->ScheduleCommand( 963 service()->CreateSetActiveWindowCommand(window2_id)); 964 965 ScopedVector<SessionWindow> windows; 966 SessionID::id_type active_window_id = 0; 967 ReadWindows(&(windows.get()), &active_window_id); 968 EXPECT_EQ(window2_id.id(), active_window_id); 969 } 970 971 // Makes sure we don't track blacklisted URLs. 972 TEST_F(SessionServiceTest, IgnoreBlacklistedUrls) { 973 SessionID tab_id; 974 975 SerializedNavigationEntry nav1 = 976 SerializedNavigationEntryTestHelper::CreateNavigation( 977 "http://google.com", "abc"); 978 SerializedNavigationEntry nav2 = 979 SerializedNavigationEntryTestHelper::CreateNavigation( 980 chrome::kChromeUIQuitURL, "quit"); 981 SerializedNavigationEntry nav3 = 982 SerializedNavigationEntryTestHelper::CreateNavigation( 983 chrome::kChromeUIRestartURL, "restart"); 984 985 helper_.PrepareTabInWindow(window_id, tab_id, 0, true); 986 UpdateNavigation(window_id, tab_id, nav1, true); 987 UpdateNavigation(window_id, tab_id, nav2, true); 988 UpdateNavigation(window_id, tab_id, nav3, true); 989 990 ScopedVector<SessionWindow> windows; 991 ReadWindows(&(windows.get()), NULL); 992 993 ASSERT_EQ(1U, windows.size()); 994 ASSERT_EQ(0, windows[0]->selected_tab_index); 995 ASSERT_EQ(window_id.id(), windows[0]->window_id.id()); 996 ASSERT_EQ(1U, windows[0]->tabs.size()); 997 998 SessionTab* tab = windows[0]->tabs[0]; 999 helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab); 1000 helper_.AssertNavigationEquals(nav1, tab->navigations[0]); 1001 } 1002