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