| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "base/bind.h" |
| #include "base/bind_helpers.h" |
| #include "base/file_util.h" |
| #include "base/files/scoped_temp_dir.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "base/memory/scoped_vector.h" |
| #include "base/path_service.h" |
| #include "base/stl_util.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/time/time.h" |
| #include "chrome/browser/browser_process.h" |
| #include "chrome/browser/chrome_notification_types.h" |
| #include "chrome/browser/defaults.h" |
| #include "chrome/browser/profiles/profile_manager.h" |
| #include "chrome/browser/sessions/session_backend.h" |
| #include "chrome/browser/sessions/session_service.h" |
| #include "chrome/browser/sessions/session_service_test_helper.h" |
| #include "chrome/browser/sessions/session_types.h" |
| #include "chrome/common/chrome_paths.h" |
| #include "chrome/common/url_constants.h" |
| #include "chrome/test/base/browser_with_test_window_test.h" |
| #include "chrome/test/base/testing_browser_process.h" |
| #include "chrome/test/base/testing_profile.h" |
| #include "chrome/test/base/testing_profile_manager.h" |
| #include "components/sessions/serialized_navigation_entry_test_helper.h" |
| #include "content/public/browser/navigation_entry.h" |
| #include "content/public/browser/notification_observer.h" |
| #include "content/public/browser/notification_registrar.h" |
| #include "content/public/browser/notification_service.h" |
| #include "content/public/common/page_state.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| using content::NavigationEntry; |
| using sessions::SerializedNavigationEntry; |
| using sessions::SerializedNavigationEntryTestHelper; |
| |
| class SessionServiceTest : public BrowserWithTestWindowTest, |
| public content::NotificationObserver { |
| public: |
| SessionServiceTest() : window_bounds(0, 1, 2, 3), sync_save_count_(0) {} |
| |
| protected: |
| virtual void SetUp() { |
| BrowserWithTestWindowTest::SetUp(); |
| |
| profile_manager_.reset( |
| new TestingProfileManager(TestingBrowserProcess::GetGlobal())); |
| ASSERT_TRUE(profile_manager_->SetUp()); |
| |
| std::string b = base::Int64ToString(base::Time::Now().ToInternalValue()); |
| TestingProfile* profile = profile_manager_->CreateTestingProfile(b); |
| SessionService* session_service = new SessionService(profile); |
| path_ = profile->GetPath(); |
| |
| helper_.SetService(session_service); |
| |
| service()->SetWindowType( |
| window_id, Browser::TYPE_TABBED, SessionService::TYPE_NORMAL); |
| service()->SetWindowBounds(window_id, |
| window_bounds, |
| ui::SHOW_STATE_NORMAL); |
| } |
| |
| // Upon notification, increment the sync_save_count variable |
| virtual void Observe(int type, |
| const content::NotificationSource& source, |
| const content::NotificationDetails& details) OVERRIDE { |
| ASSERT_EQ(type, chrome::NOTIFICATION_SESSION_SERVICE_SAVED); |
| sync_save_count_++; |
| } |
| |
| virtual void TearDown() { |
| helper_.SetService(NULL); |
| BrowserWithTestWindowTest::TearDown(); |
| } |
| |
| void UpdateNavigation( |
| const SessionID& window_id, |
| const SessionID& tab_id, |
| const SerializedNavigationEntry& navigation, |
| bool select) { |
| service()->UpdateTabNavigation(window_id, tab_id, navigation); |
| if (select) { |
| service()->SetSelectedNavigationIndex( |
| window_id, tab_id, navigation.index()); |
| } |
| } |
| |
| void ReadWindows(std::vector<SessionWindow*>* windows, |
| SessionID::id_type* active_window_id) { |
| // Forces closing the file. |
| helper_.SetService(NULL); |
| |
| SessionService* session_service = new SessionService(path_); |
| helper_.SetService(session_service); |
| |
| SessionID::id_type* non_null_active_window_id = active_window_id; |
| SessionID::id_type dummy_active_window_id = 0; |
| if (!non_null_active_window_id) |
| non_null_active_window_id = &dummy_active_window_id; |
| helper_.ReadWindows(windows, non_null_active_window_id); |
| } |
| |
| // Configures the session service with one window with one tab and a single |
| // navigation. If |pinned_state| is true or |write_always| is true, the |
| // pinned state of the tab is updated. The session service is then recreated |
| // and the pinned state of the read back tab is returned. |
| bool CreateAndWriteSessionWithOneTab(bool pinned_state, bool write_always) { |
| SessionID tab_id; |
| SerializedNavigationEntry nav1 = |
| SerializedNavigationEntryTestHelper::CreateNavigation( |
| "http://google.com", "abc"); |
| |
| helper_.PrepareTabInWindow(window_id, tab_id, 0, true); |
| UpdateNavigation(window_id, tab_id, nav1, true); |
| |
| if (pinned_state || write_always) |
| helper_.service()->SetPinnedState(window_id, tab_id, pinned_state); |
| |
| ScopedVector<SessionWindow> windows; |
| ReadWindows(&(windows.get()), NULL); |
| |
| EXPECT_EQ(1U, windows.size()); |
| if (HasFatalFailure()) |
| return false; |
| EXPECT_EQ(1U, windows[0]->tabs.size()); |
| if (HasFatalFailure()) |
| return false; |
| |
| SessionTab* tab = windows[0]->tabs[0]; |
| helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab); |
| |
| return tab->pinned; |
| } |
| |
| void CreateAndWriteSessionWithTwoWindows( |
| const SessionID& window2_id, |
| const SessionID& tab1_id, |
| const SessionID& tab2_id, |
| SerializedNavigationEntry* nav1, |
| SerializedNavigationEntry* nav2) { |
| *nav1 = SerializedNavigationEntryTestHelper::CreateNavigation( |
| "http://google.com", "abc"); |
| *nav2 = SerializedNavigationEntryTestHelper::CreateNavigation( |
| "http://google2.com", "abcd"); |
| |
| helper_.PrepareTabInWindow(window_id, tab1_id, 0, true); |
| UpdateNavigation(window_id, tab1_id, *nav1, true); |
| |
| const gfx::Rect window2_bounds(3, 4, 5, 6); |
| service()->SetWindowType( |
| window2_id, Browser::TYPE_TABBED, SessionService::TYPE_NORMAL); |
| service()->SetWindowBounds(window2_id, |
| window2_bounds, |
| ui::SHOW_STATE_MAXIMIZED); |
| helper_.PrepareTabInWindow(window2_id, tab2_id, 0, true); |
| UpdateNavigation(window2_id, tab2_id, *nav2, true); |
| } |
| |
| SessionService* service() { return helper_.service(); } |
| |
| SessionBackend* backend() { return helper_.backend(); } |
| |
| const gfx::Rect window_bounds; |
| |
| SessionID window_id; |
| |
| int sync_save_count_; |
| |
| // Path used in testing. |
| base::ScopedTempDir temp_dir_; |
| base::FilePath path_; |
| |
| SessionServiceTestHelper helper_; |
| scoped_ptr<TestingProfileManager> profile_manager_; |
| }; |
| |
| TEST_F(SessionServiceTest, Basic) { |
| SessionID tab_id; |
| ASSERT_NE(window_id.id(), tab_id.id()); |
| |
| SerializedNavigationEntry nav1 = |
| SerializedNavigationEntryTestHelper::CreateNavigation( |
| "http://google.com", "abc"); |
| SerializedNavigationEntryTestHelper::SetOriginalRequestURL( |
| GURL("http://original.request.com"), &nav1); |
| |
| helper_.PrepareTabInWindow(window_id, tab_id, 0, true); |
| UpdateNavigation(window_id, tab_id, nav1, true); |
| |
| ScopedVector<SessionWindow> windows; |
| ReadWindows(&(windows.get()), NULL); |
| |
| ASSERT_EQ(1U, windows.size()); |
| ASSERT_TRUE(window_bounds == windows[0]->bounds); |
| ASSERT_EQ(0, windows[0]->selected_tab_index); |
| ASSERT_EQ(window_id.id(), windows[0]->window_id.id()); |
| ASSERT_EQ(1U, windows[0]->tabs.size()); |
| ASSERT_EQ(Browser::TYPE_TABBED, windows[0]->type); |
| |
| SessionTab* tab = windows[0]->tabs[0]; |
| helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab); |
| |
| helper_.AssertNavigationEquals(nav1, tab->navigations[0]); |
| } |
| |
| // Make sure we persist post entries. |
| TEST_F(SessionServiceTest, PersistPostData) { |
| SessionID tab_id; |
| ASSERT_NE(window_id.id(), tab_id.id()); |
| |
| SerializedNavigationEntry nav1 = |
| SerializedNavigationEntryTestHelper::CreateNavigation( |
| "http://google.com", "abc"); |
| SerializedNavigationEntryTestHelper::SetHasPostData(true, &nav1); |
| |
| helper_.PrepareTabInWindow(window_id, tab_id, 0, true); |
| UpdateNavigation(window_id, tab_id, nav1, true); |
| |
| ScopedVector<SessionWindow> windows; |
| ReadWindows(&(windows.get()), NULL); |
| |
| helper_.AssertSingleWindowWithSingleTab(windows.get(), 1); |
| } |
| |
| TEST_F(SessionServiceTest, ClosingTabStaysClosed) { |
| SessionID tab_id; |
| SessionID tab2_id; |
| ASSERT_NE(tab_id.id(), tab2_id.id()); |
| |
| SerializedNavigationEntry nav1 = |
| SerializedNavigationEntryTestHelper::CreateNavigation( |
| "http://google.com", "abc"); |
| SerializedNavigationEntry nav2 = |
| SerializedNavigationEntryTestHelper::CreateNavigation( |
| "http://google2.com", "abcd"); |
| |
| helper_.PrepareTabInWindow(window_id, tab_id, 0, true); |
| UpdateNavigation(window_id, tab_id, nav1, true); |
| |
| helper_.PrepareTabInWindow(window_id, tab2_id, 1, false); |
| UpdateNavigation(window_id, tab2_id, nav2, true); |
| service()->TabClosed(window_id, tab2_id, false); |
| |
| ScopedVector<SessionWindow> windows; |
| ReadWindows(&(windows.get()), NULL); |
| |
| ASSERT_EQ(1U, windows.size()); |
| ASSERT_EQ(0, windows[0]->selected_tab_index); |
| ASSERT_EQ(window_id.id(), windows[0]->window_id.id()); |
| ASSERT_EQ(1U, windows[0]->tabs.size()); |
| |
| SessionTab* tab = windows[0]->tabs[0]; |
| helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab); |
| |
| helper_.AssertNavigationEquals(nav1, tab->navigations[0]); |
| } |
| |
| TEST_F(SessionServiceTest, Pruning) { |
| SessionID tab_id; |
| |
| SerializedNavigationEntry nav1 = |
| SerializedNavigationEntryTestHelper::CreateNavigation( |
| "http://google.com", "abc"); |
| SerializedNavigationEntry nav2 = |
| SerializedNavigationEntryTestHelper::CreateNavigation( |
| "http://google2.com", "abcd"); |
| |
| helper_.PrepareTabInWindow(window_id, tab_id, 0, true); |
| for (int i = 0; i < 6; ++i) { |
| SerializedNavigationEntry* nav = (i % 2) == 0 ? &nav1 : &nav2; |
| nav->set_index(i); |
| UpdateNavigation(window_id, tab_id, *nav, true); |
| } |
| service()->TabNavigationPathPrunedFromBack(window_id, tab_id, 3); |
| |
| ScopedVector<SessionWindow> windows; |
| ReadWindows(&(windows.get()), NULL); |
| |
| ASSERT_EQ(1U, windows.size()); |
| ASSERT_EQ(0, windows[0]->selected_tab_index); |
| ASSERT_EQ(1U, windows[0]->tabs.size()); |
| |
| SessionTab* tab = windows[0]->tabs[0]; |
| // We left the selected index at 5, then pruned. When rereading the |
| // index should get reset to last valid navigation, which is 2. |
| helper_.AssertTabEquals(window_id, tab_id, 0, 2, 3, *tab); |
| |
| ASSERT_EQ(3u, tab->navigations.size()); |
| helper_.AssertNavigationEquals(nav1, tab->navigations[0]); |
| helper_.AssertNavigationEquals(nav2, tab->navigations[1]); |
| helper_.AssertNavigationEquals(nav1, tab->navigations[2]); |
| } |
| |
| TEST_F(SessionServiceTest, TwoWindows) { |
| SessionID window2_id; |
| SessionID tab1_id; |
| SessionID tab2_id; |
| SerializedNavigationEntry nav1; |
| SerializedNavigationEntry nav2; |
| |
| CreateAndWriteSessionWithTwoWindows( |
| window2_id, tab1_id, tab2_id, &nav1, &nav2); |
| |
| ScopedVector<SessionWindow> windows; |
| ReadWindows(&(windows.get()), NULL); |
| |
| ASSERT_EQ(2U, windows.size()); |
| ASSERT_EQ(0, windows[0]->selected_tab_index); |
| ASSERT_EQ(0, windows[1]->selected_tab_index); |
| ASSERT_EQ(1U, windows[0]->tabs.size()); |
| ASSERT_EQ(1U, windows[1]->tabs.size()); |
| |
| SessionTab* rt1; |
| SessionTab* rt2; |
| if (windows[0]->window_id.id() == window_id.id()) { |
| ASSERT_EQ(window2_id.id(), windows[1]->window_id.id()); |
| ASSERT_EQ(ui::SHOW_STATE_NORMAL, windows[0]->show_state); |
| ASSERT_EQ(ui::SHOW_STATE_MAXIMIZED, windows[1]->show_state); |
| rt1 = windows[0]->tabs[0]; |
| rt2 = windows[1]->tabs[0]; |
| } else { |
| ASSERT_EQ(window2_id.id(), windows[0]->window_id.id()); |
| ASSERT_EQ(window_id.id(), windows[1]->window_id.id()); |
| ASSERT_EQ(ui::SHOW_STATE_MAXIMIZED, windows[0]->show_state); |
| ASSERT_EQ(ui::SHOW_STATE_NORMAL, windows[1]->show_state); |
| rt1 = windows[1]->tabs[0]; |
| rt2 = windows[0]->tabs[0]; |
| } |
| SessionTab* tab = rt1; |
| helper_.AssertTabEquals(window_id, tab1_id, 0, 0, 1, *tab); |
| helper_.AssertNavigationEquals(nav1, tab->navigations[0]); |
| |
| tab = rt2; |
| helper_.AssertTabEquals(window2_id, tab2_id, 0, 0, 1, *tab); |
| helper_.AssertNavigationEquals(nav2, tab->navigations[0]); |
| } |
| |
| TEST_F(SessionServiceTest, WindowWithNoTabsGetsPruned) { |
| SessionID window2_id; |
| SessionID tab1_id; |
| SessionID tab2_id; |
| |
| SerializedNavigationEntry nav1 = |
| SerializedNavigationEntryTestHelper::CreateNavigation( |
| "http://google.com", "abc"); |
| |
| helper_.PrepareTabInWindow(window_id, tab1_id, 0, true); |
| UpdateNavigation(window_id, tab1_id, nav1, true); |
| |
| const gfx::Rect window2_bounds(3, 4, 5, 6); |
| service()->SetWindowType( |
| window2_id, Browser::TYPE_TABBED, SessionService::TYPE_NORMAL); |
| service()->SetWindowBounds(window2_id, |
| window2_bounds, |
| ui::SHOW_STATE_NORMAL); |
| helper_.PrepareTabInWindow(window2_id, tab2_id, 0, true); |
| |
| ScopedVector<SessionWindow> windows; |
| ReadWindows(&(windows.get()), NULL); |
| |
| ASSERT_EQ(1U, windows.size()); |
| ASSERT_EQ(0, windows[0]->selected_tab_index); |
| ASSERT_EQ(1U, windows[0]->tabs.size()); |
| ASSERT_EQ(window_id.id(), windows[0]->window_id.id()); |
| |
| SessionTab* tab = windows[0]->tabs[0]; |
| helper_.AssertTabEquals(window_id, tab1_id, 0, 0, 1, *tab); |
| helper_.AssertNavigationEquals(nav1, tab->navigations[0]); |
| } |
| |
| TEST_F(SessionServiceTest, ClosingWindowDoesntCloseTabs) { |
| SessionID tab_id; |
| SessionID tab2_id; |
| ASSERT_NE(tab_id.id(), tab2_id.id()); |
| |
| SerializedNavigationEntry nav1 = |
| SerializedNavigationEntryTestHelper::CreateNavigation( |
| "http://google.com", "abc"); |
| SerializedNavigationEntry nav2 = |
| SerializedNavigationEntryTestHelper::CreateNavigation( |
| "http://google2.com", "abcd"); |
| |
| helper_.PrepareTabInWindow(window_id, tab_id, 0, true); |
| UpdateNavigation(window_id, tab_id, nav1, true); |
| |
| helper_.PrepareTabInWindow(window_id, tab2_id, 1, false); |
| UpdateNavigation(window_id, tab2_id, nav2, true); |
| |
| service()->WindowClosing(window_id); |
| |
| ScopedVector<SessionWindow> windows; |
| ReadWindows(&(windows.get()), NULL); |
| |
| ASSERT_EQ(1U, windows.size()); |
| ASSERT_EQ(0, windows[0]->selected_tab_index); |
| ASSERT_EQ(window_id.id(), windows[0]->window_id.id()); |
| ASSERT_EQ(2U, windows[0]->tabs.size()); |
| |
| SessionTab* tab = windows[0]->tabs[0]; |
| helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab); |
| helper_.AssertNavigationEquals(nav1, tab->navigations[0]); |
| |
| tab = windows[0]->tabs[1]; |
| helper_.AssertTabEquals(window_id, tab2_id, 1, 0, 1, *tab); |
| helper_.AssertNavigationEquals(nav2, tab->navigations[0]); |
| } |
| |
| TEST_F(SessionServiceTest, LockingWindowRemembersAll) { |
| SessionID window2_id; |
| SessionID tab1_id; |
| SessionID tab2_id; |
| SerializedNavigationEntry nav1; |
| SerializedNavigationEntry nav2; |
| |
| CreateAndWriteSessionWithTwoWindows( |
| window2_id, tab1_id, tab2_id, &nav1, &nav2); |
| |
| ASSERT_TRUE(service()->profile() != NULL); |
| ASSERT_TRUE(g_browser_process->profile_manager() != NULL); |
| ProfileInfoCache& profile_info = |
| g_browser_process->profile_manager()->GetProfileInfoCache(); |
| size_t profile_index = profile_info.GetIndexOfProfileWithPath( |
| service()->profile()->GetPath()); |
| ASSERT_NE(std::string::npos, profile_index); |
| profile_info.SetProfileSigninRequiredAtIndex(profile_index, true); |
| |
| service()->WindowClosing(window_id); |
| service()->WindowClosed(window_id); |
| service()->WindowClosing(window2_id); |
| service()->WindowClosed(window2_id); |
| |
| ScopedVector<SessionWindow> windows; |
| ReadWindows(&(windows.get()), NULL); |
| |
| ASSERT_EQ(2U, windows.size()); |
| ASSERT_EQ(1U, windows[0]->tabs.size()); |
| ASSERT_EQ(1U, windows[1]->tabs.size()); |
| } |
| |
| TEST_F(SessionServiceTest, WindowCloseCommittedAfterNavigate) { |
| SessionID window2_id; |
| SessionID tab_id; |
| SessionID tab2_id; |
| ASSERT_NE(window2_id.id(), window_id.id()); |
| |
| service()->SetWindowType( |
| window2_id, Browser::TYPE_TABBED, SessionService::TYPE_NORMAL); |
| service()->SetWindowBounds(window2_id, |
| window_bounds, |
| ui::SHOW_STATE_NORMAL); |
| |
| SerializedNavigationEntry nav1 = |
| SerializedNavigationEntryTestHelper::CreateNavigation( |
| "http://google.com", "abc"); |
| SerializedNavigationEntry nav2 = |
| SerializedNavigationEntryTestHelper::CreateNavigation( |
| "http://google2.com", "abcd"); |
| |
| helper_.PrepareTabInWindow(window_id, tab_id, 0, true); |
| UpdateNavigation(window_id, tab_id, nav1, true); |
| |
| helper_.PrepareTabInWindow(window2_id, tab2_id, 0, false); |
| UpdateNavigation(window2_id, tab2_id, nav2, true); |
| |
| service()->WindowClosing(window2_id); |
| service()->TabClosed(window2_id, tab2_id, false); |
| service()->WindowClosed(window2_id); |
| |
| ScopedVector<SessionWindow> windows; |
| ReadWindows(&(windows.get()), NULL); |
| |
| ASSERT_EQ(1U, windows.size()); |
| ASSERT_EQ(0, windows[0]->selected_tab_index); |
| ASSERT_EQ(window_id.id(), windows[0]->window_id.id()); |
| ASSERT_EQ(1U, windows[0]->tabs.size()); |
| |
| SessionTab* tab = windows[0]->tabs[0]; |
| helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab); |
| helper_.AssertNavigationEquals(nav1, tab->navigations[0]); |
| } |
| |
| // Makes sure we don't track popups. |
| TEST_F(SessionServiceTest, IgnorePopups) { |
| SessionID window2_id; |
| SessionID tab_id; |
| SessionID tab2_id; |
| ASSERT_NE(window2_id.id(), window_id.id()); |
| |
| service()->SetWindowType( |
| window2_id, Browser::TYPE_POPUP, SessionService::TYPE_NORMAL); |
| service()->SetWindowBounds(window2_id, |
| window_bounds, |
| ui::SHOW_STATE_NORMAL); |
| |
| SerializedNavigationEntry nav1 = |
| SerializedNavigationEntryTestHelper::CreateNavigation( |
| "http://google.com", "abc"); |
| SerializedNavigationEntry nav2 = |
| SerializedNavigationEntryTestHelper::CreateNavigation( |
| "http://google2.com", "abcd"); |
| |
| helper_.PrepareTabInWindow(window_id, tab_id, 0, true); |
| UpdateNavigation(window_id, tab_id, nav1, true); |
| |
| helper_.PrepareTabInWindow(window2_id, tab2_id, 0, false); |
| UpdateNavigation(window2_id, tab2_id, nav2, true); |
| |
| ScopedVector<SessionWindow> windows; |
| ReadWindows(&(windows.get()), NULL); |
| |
| ASSERT_EQ(1U, windows.size()); |
| ASSERT_EQ(0, windows[0]->selected_tab_index); |
| ASSERT_EQ(window_id.id(), windows[0]->window_id.id()); |
| ASSERT_EQ(1U, windows[0]->tabs.size()); |
| |
| SessionTab* tab = windows[0]->tabs[0]; |
| helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab); |
| helper_.AssertNavigationEquals(nav1, tab->navigations[0]); |
| } |
| |
| #if defined (OS_CHROMEOS) |
| // Makes sure we track apps. Only applicable on chromeos. |
| TEST_F(SessionServiceTest, RestoreApp) { |
| SessionID window2_id; |
| SessionID tab_id; |
| SessionID tab2_id; |
| ASSERT_NE(window2_id.id(), window_id.id()); |
| |
| service()->SetWindowType( |
| window2_id, Browser::TYPE_POPUP, SessionService::TYPE_APP); |
| service()->SetWindowBounds(window2_id, |
| window_bounds, |
| ui::SHOW_STATE_NORMAL); |
| service()->SetWindowAppName(window2_id, "TestApp"); |
| |
| SerializedNavigationEntry nav1 = |
| SerializedNavigationEntryTestHelper::CreateNavigation( |
| "http://google.com", "abc"); |
| SerializedNavigationEntry nav2 = |
| SerializedNavigationEntryTestHelper::CreateNavigation( |
| "http://google2.com", "abcd"); |
| |
| helper_.PrepareTabInWindow(window_id, tab_id, 0, true); |
| UpdateNavigation(window_id, tab_id, nav1, true); |
| |
| helper_.PrepareTabInWindow(window2_id, tab2_id, 0, false); |
| UpdateNavigation(window2_id, tab2_id, nav2, true); |
| |
| ScopedVector<SessionWindow> windows; |
| ReadWindows(&(windows.get()), NULL); |
| |
| ASSERT_EQ(2U, windows.size()); |
| int tabbed_index = windows[0]->type == Browser::TYPE_TABBED ? |
| 0 : 1; |
| int app_index = tabbed_index == 0 ? 1 : 0; |
| ASSERT_EQ(0, windows[tabbed_index]->selected_tab_index); |
| ASSERT_EQ(window_id.id(), windows[tabbed_index]->window_id.id()); |
| ASSERT_EQ(1U, windows[tabbed_index]->tabs.size()); |
| |
| SessionTab* tab = windows[tabbed_index]->tabs[0]; |
| helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab); |
| helper_.AssertNavigationEquals(nav1, tab->navigations[0]); |
| |
| ASSERT_EQ(0, windows[app_index]->selected_tab_index); |
| ASSERT_EQ(window2_id.id(), windows[app_index]->window_id.id()); |
| ASSERT_EQ(1U, windows[app_index]->tabs.size()); |
| ASSERT_TRUE(windows[app_index]->type == Browser::TYPE_POPUP); |
| ASSERT_EQ("TestApp", windows[app_index]->app_name); |
| |
| tab = windows[app_index]->tabs[0]; |
| helper_.AssertTabEquals(window2_id, tab2_id, 0, 0, 1, *tab); |
| helper_.AssertNavigationEquals(nav2, tab->navigations[0]); |
| } |
| #endif // defined (OS_CHROMEOS) |
| |
| // Tests pruning from the front. |
| TEST_F(SessionServiceTest, PruneFromFront) { |
| const std::string base_url("http://google.com/"); |
| SessionID tab_id; |
| |
| helper_.PrepareTabInWindow(window_id, tab_id, 0, true); |
| |
| // Add 5 navigations, with the 4th selected. |
| for (int i = 0; i < 5; ++i) { |
| SerializedNavigationEntry nav = |
| SerializedNavigationEntryTestHelper::CreateNavigation( |
| base_url + base::IntToString(i), "a"); |
| nav.set_index(i); |
| UpdateNavigation(window_id, tab_id, nav, (i == 3)); |
| } |
| |
| // Prune the first two navigations from the front. |
| helper_.service()->TabNavigationPathPrunedFromFront(window_id, tab_id, 2); |
| |
| // Read back in. |
| ScopedVector<SessionWindow> windows; |
| ReadWindows(&(windows.get()), NULL); |
| |
| ASSERT_EQ(1U, windows.size()); |
| ASSERT_EQ(0, windows[0]->selected_tab_index); |
| ASSERT_EQ(window_id.id(), windows[0]->window_id.id()); |
| ASSERT_EQ(1U, windows[0]->tabs.size()); |
| |
| // There shouldn't be an app id. |
| EXPECT_TRUE(windows[0]->tabs[0]->extension_app_id.empty()); |
| |
| // We should be left with three navigations, the 2nd selected. |
| SessionTab* tab = windows[0]->tabs[0]; |
| ASSERT_EQ(1, tab->current_navigation_index); |
| EXPECT_EQ(3U, tab->navigations.size()); |
| EXPECT_TRUE(GURL(base_url + base::IntToString(2)) == |
| tab->navigations[0].virtual_url()); |
| EXPECT_TRUE(GURL(base_url + base::IntToString(3)) == |
| tab->navigations[1].virtual_url()); |
| EXPECT_TRUE(GURL(base_url + base::IntToString(4)) == |
| tab->navigations[2].virtual_url()); |
| } |
| |
| // Prunes from front so that we have no entries. |
| TEST_F(SessionServiceTest, PruneToEmpty) { |
| const std::string base_url("http://google.com/"); |
| SessionID tab_id; |
| |
| helper_.PrepareTabInWindow(window_id, tab_id, 0, true); |
| |
| // Add 5 navigations, with the 4th selected. |
| for (int i = 0; i < 5; ++i) { |
| SerializedNavigationEntry nav = |
| SerializedNavigationEntryTestHelper::CreateNavigation( |
| base_url + base::IntToString(i), "a"); |
| nav.set_index(i); |
| UpdateNavigation(window_id, tab_id, nav, (i == 3)); |
| } |
| |
| // Prune the first two navigations from the front. |
| helper_.service()->TabNavigationPathPrunedFromFront(window_id, tab_id, 5); |
| |
| // Read back in. |
| ScopedVector<SessionWindow> windows; |
| ReadWindows(&(windows.get()), NULL); |
| |
| ASSERT_EQ(0U, windows.size()); |
| } |
| |
| // Don't set the pinned state and make sure the pinned value is false. |
| TEST_F(SessionServiceTest, PinnedDefaultsToFalse) { |
| EXPECT_FALSE(CreateAndWriteSessionWithOneTab(false, false)); |
| } |
| |
| // Explicitly set the pinned state to false and make sure we get back false. |
| TEST_F(SessionServiceTest, PinnedFalseWhenSetToFalse) { |
| EXPECT_FALSE(CreateAndWriteSessionWithOneTab(false, true)); |
| } |
| |
| // Explicitly set the pinned state to true and make sure we get back true. |
| TEST_F(SessionServiceTest, PinnedTrue) { |
| EXPECT_TRUE(CreateAndWriteSessionWithOneTab(true, true)); |
| } |
| |
| // Make sure application extension ids are persisted. |
| TEST_F(SessionServiceTest, PersistApplicationExtensionID) { |
| SessionID tab_id; |
| ASSERT_NE(window_id.id(), tab_id.id()); |
| std::string app_id("foo"); |
| |
| SerializedNavigationEntry nav1 = |
| SerializedNavigationEntryTestHelper::CreateNavigation( |
| "http://google.com", "abc"); |
| |
| helper_.PrepareTabInWindow(window_id, tab_id, 0, true); |
| UpdateNavigation(window_id, tab_id, nav1, true); |
| helper_.SetTabExtensionAppID(window_id, tab_id, app_id); |
| |
| ScopedVector<SessionWindow> windows; |
| ReadWindows(&(windows.get()), NULL); |
| |
| helper_.AssertSingleWindowWithSingleTab(windows.get(), 1); |
| EXPECT_TRUE(app_id == windows[0]->tabs[0]->extension_app_id); |
| } |
| |
| // Check that user agent overrides are persisted. |
| TEST_F(SessionServiceTest, PersistUserAgentOverrides) { |
| SessionID tab_id; |
| ASSERT_NE(window_id.id(), tab_id.id()); |
| std::string user_agent_override = "Mozilla/5.0 (X11; Linux x86_64) " |
| "AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.45 " |
| "Safari/535.19"; |
| |
| SerializedNavigationEntry nav1 = |
| SerializedNavigationEntryTestHelper::CreateNavigation( |
| "http://google.com", "abc"); |
| SerializedNavigationEntryTestHelper::SetIsOverridingUserAgent(true, &nav1); |
| |
| helper_.PrepareTabInWindow(window_id, tab_id, 0, true); |
| UpdateNavigation(window_id, tab_id, nav1, true); |
| helper_.SetTabUserAgentOverride(window_id, tab_id, user_agent_override); |
| |
| ScopedVector<SessionWindow> windows; |
| ReadWindows(&(windows.get()), NULL); |
| helper_.AssertSingleWindowWithSingleTab(windows.get(), 1); |
| |
| SessionTab* tab = windows[0]->tabs[0]; |
| helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab); |
| helper_.AssertNavigationEquals(nav1, tab->navigations[0]); |
| EXPECT_TRUE(user_agent_override == tab->user_agent_override); |
| } |
| |
| // Test that the notification for SESSION_SERVICE_SAVED is working properly. |
| TEST_F(SessionServiceTest, SavedSessionNotification) { |
| content::NotificationRegistrar registrar_; |
| registrar_.Add(this, chrome::NOTIFICATION_SESSION_SERVICE_SAVED, |
| content::NotificationService::AllSources()); |
| service()->Save(); |
| EXPECT_EQ(sync_save_count_, 1); |
| } |
| |
| // Makes sure a tab closed by a user gesture is not restored. |
| TEST_F(SessionServiceTest, CloseTabUserGesture) { |
| SessionID tab_id; |
| ASSERT_NE(window_id.id(), tab_id.id()); |
| |
| SerializedNavigationEntry nav1 = |
| SerializedNavigationEntryTestHelper::CreateNavigation( |
| "http://google.com", "abc"); |
| |
| helper_.PrepareTabInWindow(window_id, tab_id, 0, true); |
| UpdateNavigation(window_id, tab_id, nav1, true); |
| service()->TabClosed(window_id, tab_id, true); |
| |
| ScopedVector<SessionWindow> windows; |
| ReadWindows(&(windows.get()), NULL); |
| |
| ASSERT_TRUE(windows.empty()); |
| } |
| |
| // Verifies SetWindowBounds maps SHOW_STATE_DEFAULT to SHOW_STATE_NORMAL. |
| TEST_F(SessionServiceTest, DontPersistDefault) { |
| SessionID tab_id; |
| ASSERT_NE(window_id.id(), tab_id.id()); |
| SerializedNavigationEntry nav1 = |
| SerializedNavigationEntryTestHelper::CreateNavigation( |
| "http://google.com", "abc"); |
| helper_.PrepareTabInWindow(window_id, tab_id, 0, true); |
| UpdateNavigation(window_id, tab_id, nav1, true); |
| service()->SetWindowBounds(window_id, |
| window_bounds, |
| ui::SHOW_STATE_DEFAULT); |
| |
| ScopedVector<SessionWindow> windows; |
| ReadWindows(&(windows.get()), NULL); |
| ASSERT_EQ(1U, windows.size()); |
| EXPECT_EQ(ui::SHOW_STATE_NORMAL, windows[0]->show_state); |
| } |
| |
| TEST_F(SessionServiceTest, KeepPostDataWithoutPasswords) { |
| SessionID tab_id; |
| ASSERT_NE(window_id.id(), tab_id.id()); |
| |
| // Create a page state representing a HTTP body without posted passwords. |
| content::PageState page_state = |
| content::PageState::CreateForTesting(GURL(), false, "data", NULL); |
| |
| // Create a TabNavigation containing page_state and representing a POST |
| // request. |
| SerializedNavigationEntry nav1 = |
| SerializedNavigationEntryTestHelper::CreateNavigation( |
| "http://google.com", "title"); |
| SerializedNavigationEntryTestHelper::SetPageState(page_state, &nav1); |
| SerializedNavigationEntryTestHelper::SetHasPostData(true, &nav1); |
| |
| // Create a TabNavigation containing page_state and representing a normal |
| // request. |
| SerializedNavigationEntry nav2 = |
| SerializedNavigationEntryTestHelper::CreateNavigation( |
| "http://google.com/nopost", "title"); |
| SerializedNavigationEntryTestHelper::SetPageState(page_state, &nav2); |
| nav2.set_index(1); |
| |
| helper_.PrepareTabInWindow(window_id, tab_id, 0, true); |
| UpdateNavigation(window_id, tab_id, nav1, true); |
| UpdateNavigation(window_id, tab_id, nav2, true); |
| |
| ScopedVector<SessionWindow> windows; |
| ReadWindows(&(windows.get()), NULL); |
| |
| helper_.AssertSingleWindowWithSingleTab(windows.get(), 2); |
| |
| // Expected: the page state of both navigations was saved and restored. |
| ASSERT_EQ(2u, windows[0]->tabs[0]->navigations.size()); |
| helper_.AssertNavigationEquals(nav1, windows[0]->tabs[0]->navigations[0]); |
| helper_.AssertNavigationEquals(nav2, windows[0]->tabs[0]->navigations[1]); |
| } |
| |
| TEST_F(SessionServiceTest, RemovePostDataWithPasswords) { |
| SessionID tab_id; |
| ASSERT_NE(window_id.id(), tab_id.id()); |
| |
| // Create a page state representing a HTTP body with posted passwords. |
| content::PageState page_state = |
| content::PageState::CreateForTesting(GURL(), true, "data", NULL); |
| |
| // Create a TabNavigation containing page_state and representing a POST |
| // request with passwords. |
| SerializedNavigationEntry nav1 = |
| SerializedNavigationEntryTestHelper::CreateNavigation( |
| "http://google.com", "title"); |
| SerializedNavigationEntryTestHelper::SetPageState(page_state, &nav1); |
| SerializedNavigationEntryTestHelper::SetHasPostData(true, &nav1); |
| helper_.PrepareTabInWindow(window_id, tab_id, 0, true); |
| UpdateNavigation(window_id, tab_id, nav1, true); |
| |
| ScopedVector<SessionWindow> windows; |
| ReadWindows(&(windows.get()), NULL); |
| |
| helper_.AssertSingleWindowWithSingleTab(windows.get(), 1); |
| |
| // Expected: the HTTP body was removed from the page state of the POST |
| // navigation with passwords. |
| EXPECT_NE(page_state, windows[0]->tabs[0]->navigations[0].page_state()); |
| } |
| |
| // This test is only applicable to chromeos. |
| #if defined(OS_CHROMEOS) |
| // Verifies migration of tab/window closed works. |
| TEST_F(SessionServiceTest, CanOpenV1TabClosed) { |
| base::FilePath v1_file_path; |
| ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &v1_file_path)); |
| // v1_session_file contains a tab closed command with the original id. The |
| // file was generated from ClosingTabStaysClosed. If we successfully processed |
| // the file we'll have one tab. |
| v1_file_path = |
| v1_file_path.AppendASCII("sessions").AppendASCII("v1_session_file"); |
| base::FilePath dest_file_path(path_); |
| dest_file_path = dest_file_path.AppendASCII("Current Session"); |
| |
| // Forces closing the file. |
| helper_.SetService(NULL); |
| |
| ASSERT_TRUE(base::CopyFile(v1_file_path, dest_file_path)); |
| |
| SessionService* session_service = new SessionService(path_); |
| helper_.SetService(session_service); |
| ScopedVector<SessionWindow> windows; |
| SessionID::id_type active_window_id = 0; |
| helper_.ReadWindows(&(windows.get()), &active_window_id); |
| ASSERT_EQ(1u, windows.size()); |
| EXPECT_EQ(1u, windows[0]->tabs.size()); |
| } |
| #endif // defined(OS_CHROMEOS) |
| |
| TEST_F(SessionServiceTest, ReplacePendingNavigation) { |
| const std::string base_url("http://google.com/"); |
| SessionID tab_id; |
| |
| helper_.PrepareTabInWindow(window_id, tab_id, 0, true); |
| |
| // Add 5 navigations, some with the same index |
| for (int i = 0; i < 5; ++i) { |
| SerializedNavigationEntry nav = |
| SerializedNavigationEntryTestHelper::CreateNavigation( |
| base_url + base::IntToString(i), "a"); |
| nav.set_index(i / 2); |
| UpdateNavigation(window_id, tab_id, nav, true); |
| } |
| |
| // Read back in. |
| ScopedVector<SessionWindow> windows; |
| ReadWindows(&(windows.get()), NULL); |
| |
| // The ones with index 0, and 2 should have been replaced by 1 and 3. |
| ASSERT_EQ(1U, windows.size()); |
| ASSERT_EQ(1U, windows[0]->tabs.size()); |
| EXPECT_EQ(3U, windows[0]->tabs[0]->navigations.size()); |
| EXPECT_EQ(GURL(base_url + base::IntToString(1)), |
| windows[0]->tabs[0]->navigations[0].virtual_url()); |
| EXPECT_EQ(GURL(base_url + base::IntToString(3)), |
| windows[0]->tabs[0]->navigations[1].virtual_url()); |
| EXPECT_EQ(GURL(base_url + base::IntToString(4)), |
| windows[0]->tabs[0]->navigations[2].virtual_url()); |
| } |
| |
| TEST_F(SessionServiceTest, ReplacePendingNavigationAndPrune) { |
| const std::string base_url("http://google.com/"); |
| SessionID tab_id; |
| |
| helper_.PrepareTabInWindow(window_id, tab_id, 0, true); |
| |
| for (int i = 0; i < 5; ++i) { |
| SerializedNavigationEntry nav = |
| SerializedNavigationEntryTestHelper::CreateNavigation( |
| base_url + base::IntToString(i), "a"); |
| nav.set_index(i); |
| UpdateNavigation(window_id, tab_id, nav, true); |
| } |
| |
| // Prune all those navigations. |
| helper_.service()->TabNavigationPathPrunedFromFront(window_id, tab_id, 5); |
| |
| // Add another navigation to replace the last one. |
| SerializedNavigationEntry nav = |
| SerializedNavigationEntryTestHelper::CreateNavigation( |
| base_url + base::IntToString(5), "a"); |
| nav.set_index(4); |
| UpdateNavigation(window_id, tab_id, nav, true); |
| |
| // Read back in. |
| ScopedVector<SessionWindow> windows; |
| ReadWindows(&(windows.get()), NULL); |
| |
| // We should still have that last navigation at the end, |
| // even though it replaced one that was set before the prune. |
| ASSERT_EQ(1U, windows.size()); |
| ASSERT_EQ(1U, windows[0]->tabs.size()); |
| ASSERT_EQ(1U, windows[0]->tabs[0]->navigations.size()); |
| EXPECT_EQ(GURL(base_url + base::IntToString(5)), |
| windows[0]->tabs[0]->navigations[0].virtual_url()); |
| } |
| |
| TEST_F(SessionServiceTest, RestoreActivation1) { |
| SessionID window2_id; |
| SessionID tab1_id; |
| SessionID tab2_id; |
| SerializedNavigationEntry nav1; |
| SerializedNavigationEntry nav2; |
| |
| CreateAndWriteSessionWithTwoWindows( |
| window2_id, tab1_id, tab2_id, &nav1, &nav2); |
| |
| service()->ScheduleCommand( |
| service()->CreateSetActiveWindowCommand(window2_id)); |
| service()->ScheduleCommand( |
| service()->CreateSetActiveWindowCommand(window_id)); |
| |
| ScopedVector<SessionWindow> windows; |
| SessionID::id_type active_window_id = 0; |
| ReadWindows(&(windows.get()), &active_window_id); |
| EXPECT_EQ(window_id.id(), active_window_id); |
| } |
| |
| // It's easier to have two separate tests with setup/teardown than to manualy |
| // reset the state for the different flavors of the test. |
| TEST_F(SessionServiceTest, RestoreActivation2) { |
| SessionID window2_id; |
| SessionID tab1_id; |
| SessionID tab2_id; |
| SerializedNavigationEntry nav1; |
| SerializedNavigationEntry nav2; |
| |
| CreateAndWriteSessionWithTwoWindows( |
| window2_id, tab1_id, tab2_id, &nav1, &nav2); |
| |
| service()->ScheduleCommand( |
| service()->CreateSetActiveWindowCommand(window2_id)); |
| service()->ScheduleCommand( |
| service()->CreateSetActiveWindowCommand(window_id)); |
| service()->ScheduleCommand( |
| service()->CreateSetActiveWindowCommand(window2_id)); |
| |
| ScopedVector<SessionWindow> windows; |
| SessionID::id_type active_window_id = 0; |
| ReadWindows(&(windows.get()), &active_window_id); |
| EXPECT_EQ(window2_id.id(), active_window_id); |
| } |
| |
| // Makes sure we don't track blacklisted URLs. |
| TEST_F(SessionServiceTest, IgnoreBlacklistedUrls) { |
| SessionID tab_id; |
| |
| SerializedNavigationEntry nav1 = |
| SerializedNavigationEntryTestHelper::CreateNavigation( |
| "http://google.com", "abc"); |
| SerializedNavigationEntry nav2 = |
| SerializedNavigationEntryTestHelper::CreateNavigation( |
| chrome::kChromeUIQuitURL, "quit"); |
| SerializedNavigationEntry nav3 = |
| SerializedNavigationEntryTestHelper::CreateNavigation( |
| chrome::kChromeUIRestartURL, "restart"); |
| |
| helper_.PrepareTabInWindow(window_id, tab_id, 0, true); |
| UpdateNavigation(window_id, tab_id, nav1, true); |
| UpdateNavigation(window_id, tab_id, nav2, true); |
| UpdateNavigation(window_id, tab_id, nav3, true); |
| |
| ScopedVector<SessionWindow> windows; |
| ReadWindows(&(windows.get()), NULL); |
| |
| ASSERT_EQ(1U, windows.size()); |
| ASSERT_EQ(0, windows[0]->selected_tab_index); |
| ASSERT_EQ(window_id.id(), windows[0]->window_id.id()); |
| ASSERT_EQ(1U, windows[0]->tabs.size()); |
| |
| SessionTab* tab = windows[0]->tabs[0]; |
| helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab); |
| helper_.AssertNavigationEquals(nav1, tab->navigations[0]); |
| } |