#include "base/bind.h"
#include "base/bind_helpers.h"
-#include "base/file_util.h"
+#include "base/files/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/run_loop.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/synchronization/waitable_event.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/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"
SessionServiceTest() : window_bounds(0, 1, 2, 3), sync_save_count_(0) {}
protected:
- virtual void SetUp() {
+ void SetUp() override {
BrowserWithTestWindowTest::SetUp();
- std::string b = base::Int64ToString(base::Time::Now().ToInternalValue());
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- path_ = temp_dir_.path().Append(FILE_PATH_LITERAL("SessionTestDirs"));
- ASSERT_TRUE(base::CreateDirectory(path_));
- path_ = path_.AppendASCII(b);
+ 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();
- SessionService* session_service = new SessionService(path_);
helper_.SetService(session_service);
- service()->SetWindowType(
- window_id, Browser::TYPE_TABBED, SessionService::TYPE_NORMAL);
+ 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 {
+ 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() {
+ void TearDown() override {
helper_.SetService(NULL);
BrowserWithTestWindowTest::TearDown();
}
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()->SetWindowType(window2_id,
+ Browser::TYPE_TABBED,
+ SessionService::TYPE_NORMAL);
service()->SetWindowBounds(window2_id,
window2_bounds,
ui::SHOW_STATE_MAXIMIZED);
SessionService* service() { return helper_.service(); }
- SessionBackend* backend() { return helper_.backend(); }
-
const gfx::Rect window_bounds;
SessionID window_id;
base::FilePath path_;
SessionServiceTestHelper helper_;
+ scoped_ptr<TestingProfileManager> profile_manager_;
};
TEST_F(SessionServiceTest, Basic) {
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);
+ ASSERT_EQ(SessionWindow::TYPE_TABBED, windows[0]->type);
SessionTab* tab = windows[0]->tabs[0];
helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab);
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()->SetWindowType(window2_id,
+ Browser::TYPE_TABBED,
+ SessionService::TYPE_NORMAL);
service()->SetWindowBounds(window2_id,
window2_bounds,
ui::SHOW_STATE_NORMAL);
helper_.AssertNavigationEquals(nav2, tab->navigations[0]);
}
-TEST_F(SessionServiceTest, WindowCloseCommittedAfterNavigate) {
+TEST_F(SessionServiceTest, LockingWindowRemembersAll) {
SessionID window2_id;
- SessionID tab_id;
+ SessionID tab1_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");
+ SerializedNavigationEntry nav1;
+ SerializedNavigationEntry nav2;
- helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
- UpdateNavigation(window_id, tab_id, nav1, true);
+ CreateAndWriteSessionWithTwoWindows(
+ window2_id, tab1_id, tab2_id, &nav1, &nav2);
- helper_.PrepareTabInWindow(window2_id, tab2_id, 0, false);
- UpdateNavigation(window2_id, tab2_id, nav2, true);
+ 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()->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(2U, windows.size());
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]);
+ ASSERT_EQ(1U, windows[1]->tabs.size());
}
-// Makes sure we don't track popups.
-TEST_F(SessionServiceTest, IgnorePopups) {
- if (browser_defaults::kRestorePopups)
- return; // This test is only applicable if popups aren't restored.
-
+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_POPUP, SessionService::TYPE_NORMAL);
+ service()->SetWindowType(window2_id,
+ Browser::TYPE_TABBED,
+ SessionService::TYPE_NORMAL);
service()->SetWindowBounds(window2_id,
window_bounds,
ui::SHOW_STATE_NORMAL);
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);
helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
}
-// Makes sure we track popups.
-TEST_F(SessionServiceTest, RestorePopup) {
- if (!browser_defaults::kRestorePopups)
- return; // This test is only applicable if popups are restored.
-
+// 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()->SetWindowType(window2_id,
+ Browser::TYPE_POPUP,
+ SessionService::TYPE_NORMAL);
service()->SetWindowBounds(window2_id,
window_bounds,
ui::SHOW_STATE_NORMAL);
ScopedVector<SessionWindow> windows;
ReadWindows(&(windows.get()), NULL);
- ASSERT_EQ(2U, windows.size());
- int tabbed_index = windows[0]->type == Browser::TYPE_TABBED ?
- 0 : 1;
- int popup_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());
+ 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[tabbed_index]->tabs[0];
+ SessionTab* tab = windows[0]->tabs[0];
helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab);
helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
-
- ASSERT_EQ(0, windows[popup_index]->selected_tab_index);
- ASSERT_EQ(window2_id.id(), windows[popup_index]->window_id.id());
- ASSERT_EQ(1U, windows[popup_index]->tabs.size());
-
- tab = windows[popup_index]->tabs[0];
- helper_.AssertTabEquals(window2_id, tab2_id, 0, 0, 1, *tab);
- helper_.AssertNavigationEquals(nav2, tab->navigations[0]);
}
#if defined (OS_CHROMEOS)
SessionID tab2_id;
ASSERT_NE(window2_id.id(), window_id.id());
- service()->SetWindowType(
- window2_id, Browser::TYPE_POPUP, SessionService::TYPE_APP);
+ service()->SetWindowType(window2_id,
+ Browser::TYPE_POPUP,
+ SessionService::TYPE_APP);
service()->SetWindowBounds(window2_id,
window_bounds,
ui::SHOW_STATE_NORMAL);
ReadWindows(&(windows.get()), NULL);
ASSERT_EQ(2U, windows.size());
- int tabbed_index = windows[0]->type == Browser::TYPE_TABBED ?
+ int tabbed_index = windows[0]->type == SessionWindow::TYPE_TABBED ?
0 : 1;
int app_index = tabbed_index == 0 ? 1 : 0;
ASSERT_EQ(0, windows[tabbed_index]->selected_tab_index);
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_TRUE(windows[app_index]->type == SessionWindow::TYPE_POPUP);
ASSERT_EQ("TestApp", windows[app_index]->app_name);
tab = windows[app_index]->tabs[0];
content::NotificationRegistrar registrar_;
registrar_.Add(this, chrome::NOTIFICATION_SESSION_SERVICE_SAVED,
content::NotificationService::AllSources());
- service()->Save();
+ service()->GetBaseSessionServiceForTest()->Save();
EXPECT_EQ(sync_save_count_, 1);
}
SerializedNavigationEntry nav1 =
SerializedNavigationEntryTestHelper::CreateNavigation(
"http://google.com", "title");
- SerializedNavigationEntryTestHelper::SetPageState(page_state, &nav1);
+ SerializedNavigationEntryTestHelper::SetEncodedPageState(
+ page_state.ToEncodedData(), &nav1);
SerializedNavigationEntryTestHelper::SetHasPostData(true, &nav1);
// Create a TabNavigation containing page_state and representing a normal
SerializedNavigationEntry nav2 =
SerializedNavigationEntryTestHelper::CreateNavigation(
"http://google.com/nopost", "title");
- SerializedNavigationEntryTestHelper::SetPageState(page_state, &nav2);
+ SerializedNavigationEntryTestHelper::SetEncodedPageState(
+ page_state.ToEncodedData(), &nav2);
nav2.set_index(1);
helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
SerializedNavigationEntry nav1 =
SerializedNavigationEntryTestHelper::CreateNavigation(
"http://google.com", "title");
- SerializedNavigationEntryTestHelper::SetPageState(page_state, &nav1);
+ SerializedNavigationEntryTestHelper::SetEncodedPageState(
+ page_state.ToEncodedData(), &nav1);
SerializedNavigationEntryTestHelper::SetHasPostData(true, &nav1);
helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
UpdateNavigation(window_id, tab_id, nav1, true);
// 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());
+ EXPECT_NE(page_state.ToEncodedData(),
+ windows[0]->tabs[0]->navigations[0].encoded_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;
CreateAndWriteSessionWithTwoWindows(
window2_id, tab1_id, tab2_id, &nav1, &nav2);
- service()->ScheduleCommand(
- service()->CreateSetActiveWindowCommand(window2_id));
- service()->ScheduleCommand(
- service()->CreateSetActiveWindowCommand(window_id));
+ service()->ScheduleCommand(CreateSetActiveWindowCommand(window2_id).Pass());
+ service()->ScheduleCommand(CreateSetActiveWindowCommand(window_id).Pass());
ScopedVector<SessionWindow> windows;
SessionID::id_type active_window_id = 0;
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));
+ service()->ScheduleCommand(CreateSetActiveWindowCommand(window2_id).Pass());
+ service()->ScheduleCommand(CreateSetActiveWindowCommand(window_id).Pass());
+ service()->ScheduleCommand(CreateSetActiveWindowCommand(window2_id).Pass());
ScopedVector<SessionWindow> windows;
SessionID::id_type active_window_id = 0;
helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab);
helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
}
+
+// Functions used by GetSessionsAndDestroy.
+namespace {
+
+void OnGotPreviousSession(ScopedVector<SessionWindow> windows,
+ SessionID::id_type ignored_active_window) {
+ FAIL() << "SessionService was destroyed, this shouldn't be reached.";
+}
+
+void PostBackToThread(base::MessageLoop* message_loop,
+ base::RunLoop* run_loop) {
+ message_loop->PostTask(FROM_HERE,
+ base::Bind(&base::RunLoop::Quit,
+ base::Unretained(run_loop)));
+}
+
+} // namespace
+
+// Verifies that SessionService::GetLastSession() works correctly if the
+// SessionService is deleted during processing. To verify the problematic case
+// does the following:
+// 1. Sends a task to the background thread that blocks.
+// 2. Asks SessionService for the last session commands. This is blocked by 1.
+// 3. Posts another task to the background thread, this too is blocked by 1.
+// 4. Deletes SessionService.
+// 5. Signals the semaphore that 2 and 3 are waiting on, allowing
+// GetLastSession() to continue.
+// 6. runs the message loop, this is quit when the task scheduled in 3 posts
+// back to the ui thread to quit the run loop.
+// The call to get the previous session should never be invoked because the
+// SessionService was destroyed before SessionService could process the results.
+TEST_F(SessionServiceTest, GetSessionsAndDestroy) {
+ base::CancelableTaskTracker cancelable_task_tracker;
+ base::RunLoop run_loop;
+ base::WaitableEvent event(true, false);
+ helper_.RunTaskOnBackendThread(FROM_HERE,
+ base::Bind(&base::WaitableEvent::Wait,
+ base::Unretained(&event)));
+ service()->GetLastSession(base::Bind(&OnGotPreviousSession),
+ &cancelable_task_tracker);
+ helper_.RunTaskOnBackendThread(
+ FROM_HERE,
+ base::Bind(&PostBackToThread,
+ base::Unretained(base::MessageLoop::current()),
+ base::Unretained(&run_loop)));
+ delete helper_.ReleaseService();
+ event.Signal();
+ run_loop.Run();
+}