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