From c3aa8cf571c5d0ed92725a15d0cd2c54f7da3b05 Mon Sep 17 00:00:00 2001 From: skuhne Date: Wed, 29 Oct 2014 23:02:45 -0700 Subject: [PATCH] Refactoring of SessionService into a component part 3. This CL breaks out the command handling (command creation and session information restore) from |SessionService| into |SessionServiceCommands|, which does have no dependencies on Browser or Content. Furthermore it breaks out the command handling from |BaseSessionService| into |BaseSessionServiceCommands|. This way the |PersistentTabRestoreService| and the |SessionService| can keep using the base command set which is used by both users. BUG=424679 TEST=covered by existing tests Review URL: https://codereview.chromium.org/672083002 Cr-Commit-Position: refs/heads/master@{#302041} --- .../extensions/api/sessions/sessions_api.cc | 4 +- chrome/browser/sessions/base_session_service.cc | 142 ---- chrome/browser/sessions/base_session_service.h | 60 -- .../sessions/base_session_service_commands.cc | 151 ++++ .../sessions/base_session_service_commands.h | 74 ++ .../sessions/persistent_tab_restore_service.cc | 40 +- .../persistent_tab_restore_service_unittest.cc | 6 +- chrome/browser/sessions/session_restore.cc | 13 +- chrome/browser/sessions/session_service.cc | 918 ++------------------- chrome/browser/sessions/session_service.h | 174 +--- .../browser/sessions/session_service_commands.cc | 824 ++++++++++++++++++ chrome/browser/sessions/session_service_commands.h | 84 ++ .../sessions/session_service_test_helper.cc | 4 +- .../browser/sessions/session_service_unittest.cc | 51 +- chrome/browser/sessions/session_service_utils.cc | 27 + chrome/browser/sessions/session_service_utils.h | 15 + chrome/browser/sessions/session_types.cc | 6 +- chrome/browser/sessions/session_types.h | 14 +- .../browser/sync/glue/session_sync_test_helper.cc | 2 +- .../browser/sync/sessions/sessions_sync_manager.cc | 6 +- .../sessions/sessions_sync_manager_unittest.cc | 2 +- .../toolbar/recent_tabs_sub_menu_model_unittest.cc | 5 +- chrome/chrome_browser.gypi | 6 + 23 files changed, 1374 insertions(+), 1254 deletions(-) create mode 100644 chrome/browser/sessions/base_session_service_commands.cc create mode 100644 chrome/browser/sessions/base_session_service_commands.h create mode 100644 chrome/browser/sessions/session_service_commands.cc create mode 100644 chrome/browser/sessions/session_service_commands.h create mode 100644 chrome/browser/sessions/session_service_utils.cc create mode 100644 chrome/browser/sessions/session_service_utils.h diff --git a/chrome/browser/extensions/api/sessions/sessions_api.cc b/chrome/browser/extensions/api/sessions/sessions_api.cc index 0b7a1a71601b..cc4830816433 100644 --- a/chrome/browser/extensions/api/sessions/sessions_api.cc +++ b/chrome/browser/extensions/api/sessions/sessions_api.cc @@ -289,10 +289,10 @@ scoped_ptr SessionsGetDevicesFunction::CreateWindowModel( windows::Window::Type type = windows::Window::TYPE_NONE; switch (window.type) { - case Browser::TYPE_TABBED: + case SessionWindow::TYPE_TABBED: type = windows::Window::TYPE_NORMAL; break; - case Browser::TYPE_POPUP: + case SessionWindow::TYPE_POPUP: type = windows::Window::TYPE_POPUP; break; } diff --git a/chrome/browser/sessions/base_session_service.cc b/chrome/browser/sessions/base_session_service.cc index f85fc8f78faa..05d61bf7213b 100644 --- a/chrome/browser/sessions/base_session_service.cc +++ b/chrome/browser/sessions/base_session_service.cc @@ -5,30 +5,14 @@ #include "chrome/browser/sessions/base_session_service.h" #include "base/bind.h" -#include "base/pickle.h" #include "base/threading/thread.h" #include "chrome/browser/sessions/base_session_service_delegate.h" #include "chrome/browser/sessions/session_backend.h" -#include "chrome/browser/sessions/session_types.h" // BaseSessionService --------------------------------------------------------- namespace { -// Helper used by CreateUpdateTabNavigationCommand(). It writes |str| to -// |pickle|, if and only if |str| fits within (|max_bytes| - |*bytes_written|). -// |bytes_written| is incremented to reflect the data written. -void WriteStringToPickle(Pickle& pickle, int* bytes_written, int max_bytes, - const std::string& str) { - int num_bytes = str.size() * sizeof(char); - if (*bytes_written + num_bytes < max_bytes) { - *bytes_written += num_bytes; - pickle.WriteString(str); - } else { - pickle.WriteString(std::string()); - } -} - // Helper used by ScheduleGetLastSessionCommands. It runs callback on TaskRunner // thread if it's not canceled. void RunIfNotCanceled( @@ -122,132 +106,6 @@ void BaseSessionService::Save() { } } -SessionCommand* BaseSessionService::CreateUpdateTabNavigationCommand( - SessionID::id_type command_id, - SessionID::id_type tab_id, - const sessions::SerializedNavigationEntry& navigation) { - // Use pickle to handle marshalling. - Pickle pickle; - pickle.WriteInt(tab_id); - // We only allow navigations up to 63k (which should be completely - // reasonable). - static const size_t max_state_size = - std::numeric_limits::max() - 1024; - navigation.WriteToPickle(max_state_size, &pickle); - return new SessionCommand(command_id, pickle); -} - -SessionCommand* BaseSessionService::CreateSetTabExtensionAppIDCommand( - SessionID::id_type command_id, - SessionID::id_type tab_id, - const std::string& extension_id) { - // Use pickle to handle marshalling. - Pickle pickle; - pickle.WriteInt(tab_id); - - // Enforce a max for ids. They should never be anywhere near this size. - static const SessionCommand::size_type max_id_size = - std::numeric_limits::max() - 1024; - - int bytes_written = 0; - - WriteStringToPickle(pickle, &bytes_written, max_id_size, extension_id); - - return new SessionCommand(command_id, pickle); -} - -SessionCommand* BaseSessionService::CreateSetTabUserAgentOverrideCommand( - SessionID::id_type command_id, - SessionID::id_type tab_id, - const std::string& user_agent_override) { - // Use pickle to handle marshalling. - Pickle pickle; - pickle.WriteInt(tab_id); - - // Enforce a max for the user agent length. They should never be anywhere - // near this size. - static const SessionCommand::size_type max_user_agent_size = - std::numeric_limits::max() - 1024; - - int bytes_written = 0; - - WriteStringToPickle(pickle, &bytes_written, max_user_agent_size, - user_agent_override); - - return new SessionCommand(command_id, pickle); -} - -SessionCommand* BaseSessionService::CreateSetWindowAppNameCommand( - SessionID::id_type command_id, - SessionID::id_type window_id, - const std::string& app_name) { - // Use pickle to handle marshalling. - Pickle pickle; - pickle.WriteInt(window_id); - - // Enforce a max for ids. They should never be anywhere near this size. - static const SessionCommand::size_type max_id_size = - std::numeric_limits::max() - 1024; - - int bytes_written = 0; - - WriteStringToPickle(pickle, &bytes_written, max_id_size, app_name); - - return new SessionCommand(command_id, pickle); -} - -bool BaseSessionService::RestoreUpdateTabNavigationCommand( - const SessionCommand& command, - sessions::SerializedNavigationEntry* navigation, - SessionID::id_type* tab_id) { - scoped_ptr pickle(command.PayloadAsPickle()); - if (!pickle.get()) - return false; - PickleIterator iterator(*pickle); - return - pickle->ReadInt(&iterator, tab_id) && - navigation->ReadFromPickle(&iterator); -} - -bool BaseSessionService::RestoreSetTabExtensionAppIDCommand( - const SessionCommand& command, - SessionID::id_type* tab_id, - std::string* extension_app_id) { - scoped_ptr pickle(command.PayloadAsPickle()); - if (!pickle.get()) - return false; - - PickleIterator iterator(*pickle); - return pickle->ReadInt(&iterator, tab_id) && - pickle->ReadString(&iterator, extension_app_id); -} - -bool BaseSessionService::RestoreSetTabUserAgentOverrideCommand( - const SessionCommand& command, - SessionID::id_type* tab_id, - std::string* user_agent_override) { - scoped_ptr pickle(command.PayloadAsPickle()); - if (!pickle.get()) - return false; - - PickleIterator iterator(*pickle); - return pickle->ReadInt(&iterator, tab_id) && - pickle->ReadString(&iterator, user_agent_override); -} - -bool BaseSessionService::RestoreSetWindowAppNameCommand( - const SessionCommand& command, - SessionID::id_type* window_id, - std::string* app_name) { - scoped_ptr pickle(command.PayloadAsPickle()); - if (!pickle.get()) - return false; - - PickleIterator iterator(*pickle); - return pickle->ReadInt(&iterator, window_id) && - pickle->ReadString(&iterator, app_name); -} - bool BaseSessionService::ShouldTrackEntry(const GURL& url) { return url.is_valid() && delegate_->ShouldTrackEntry(url); } diff --git a/chrome/browser/sessions/base_session_service.h b/chrome/browser/sessions/base_session_service.h index 3ce684cbf072..704aaea0284f 100644 --- a/chrome/browser/sessions/base_session_service.h +++ b/chrome/browser/sessions/base_session_service.h @@ -9,13 +9,9 @@ #include "base/callback.h" #include "base/files/file_path.h" #include "base/gtest_prod_util.h" -#include "base/location.h" -#include "base/memory/ref_counted.h" #include "base/memory/scoped_vector.h" #include "base/memory/weak_ptr.h" #include "base/task/cancelable_task_tracker.h" -#include "base/threading/sequenced_worker_pool.h" -#include "components/sessions/session_id.h" #include "url/gurl.h" class BaseSessionServiceDelegate; @@ -84,62 +80,6 @@ class BaseSessionService { // scheduled by StartSaveTimer. virtual void Save(); - // Creates a SessionCommand that represents a navigation. - SessionCommand* CreateUpdateTabNavigationCommand( - SessionID::id_type command_id, - SessionID::id_type tab_id, - const sessions::SerializedNavigationEntry& navigation); - - // Creates a SessionCommand that represents marking a tab as an application. - SessionCommand* CreateSetTabExtensionAppIDCommand( - SessionID::id_type command_id, - SessionID::id_type tab_id, - const std::string& extension_id); - - // Creates a SessionCommand that containing user agent override used by a - // tab's navigations. - SessionCommand* CreateSetTabUserAgentOverrideCommand( - SessionID::id_type command_id, - SessionID::id_type tab_id, - const std::string& user_agent_override); - - // Creates a SessionCommand stores a browser window's app name. - SessionCommand* CreateSetWindowAppNameCommand( - SessionID::id_type command_id, - SessionID::id_type window_id, - const std::string& app_name); - - // Converts a SessionCommand previously created by - // CreateUpdateTabNavigationCommand into a - // sessions::SerializedNavigationEntry. Returns true on success. If - // successful |tab_id| is set to the id of the restored tab. - bool RestoreUpdateTabNavigationCommand( - const SessionCommand& command, - sessions::SerializedNavigationEntry* navigation, - SessionID::id_type* tab_id); - - // Extracts a SessionCommand as previously created by - // CreateSetTabExtensionAppIDCommand into the tab id and application - // extension id. - bool RestoreSetTabExtensionAppIDCommand( - const SessionCommand& command, - SessionID::id_type* tab_id, - std::string* extension_app_id); - - // Extracts a SessionCommand as previously created by - // CreateSetTabUserAgentOverrideCommand into the tab id and user agent. - bool RestoreSetTabUserAgentOverrideCommand( - const SessionCommand& command, - SessionID::id_type* tab_id, - std::string* user_agent_override); - - // Extracts a SessionCommand as previously created by - // CreateSetWindowAppNameCommand into the window id and application name. - bool RestoreSetWindowAppNameCommand( - const SessionCommand& command, - SessionID::id_type* window_id, - std::string* app_name); - // Returns true if the entry at specified |url| should be written to disk. bool ShouldTrackEntry(const GURL& url); diff --git a/chrome/browser/sessions/base_session_service_commands.cc b/chrome/browser/sessions/base_session_service_commands.cc new file mode 100644 index 000000000000..7e3fd5f89e1f --- /dev/null +++ b/chrome/browser/sessions/base_session_service_commands.cc @@ -0,0 +1,151 @@ +// Copyright 2014 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 "chrome/browser/sessions/base_session_service_commands.h" + +#include "base/pickle.h" +#include "chrome/browser/sessions/session_backend.h" +#include "chrome/browser/sessions/session_types.h" + +// BaseSessionService --------------------------------------------------------- + +namespace { + +// Helper used by CreateUpdateTabNavigationCommand(). It writes |str| to +// |pickle|, if and only if |str| fits within (|max_bytes| - |*bytes_written|). +// |bytes_written| is incremented to reflect the data written. +void WriteStringToPickle(Pickle& pickle, int* bytes_written, int max_bytes, + const std::string& str) { + int num_bytes = str.size() * sizeof(char); + if (*bytes_written + num_bytes < max_bytes) { + *bytes_written += num_bytes; + pickle.WriteString(str); + } else { + pickle.WriteString(std::string()); + } +} + +} // namespace + +SessionCommand* CreateUpdateTabNavigationCommand( + SessionID::id_type command_id, + SessionID::id_type tab_id, + const sessions::SerializedNavigationEntry& navigation) { + // Use pickle to handle marshalling. + Pickle pickle; + pickle.WriteInt(tab_id); + // We only allow navigations up to 63k (which should be completely + // reasonable). + static const size_t max_state_size = + std::numeric_limits::max() - 1024; + navigation.WriteToPickle(max_state_size, &pickle); + return new SessionCommand(command_id, pickle); +} + +SessionCommand* CreateSetTabExtensionAppIDCommand( + SessionID::id_type command_id, + SessionID::id_type tab_id, + const std::string& extension_id) { + // Use pickle to handle marshalling. + Pickle pickle; + pickle.WriteInt(tab_id); + + // Enforce a max for ids. They should never be anywhere near this size. + static const SessionCommand::size_type max_id_size = + std::numeric_limits::max() - 1024; + + int bytes_written = 0; + + WriteStringToPickle(pickle, &bytes_written, max_id_size, extension_id); + + return new SessionCommand(command_id, pickle); +} + +SessionCommand* CreateSetTabUserAgentOverrideCommand( + SessionID::id_type command_id, + SessionID::id_type tab_id, + const std::string& user_agent_override) { + // Use pickle to handle marshalling. + Pickle pickle; + pickle.WriteInt(tab_id); + + // Enforce a max for the user agent length. They should never be anywhere + // near this size. + static const SessionCommand::size_type max_user_agent_size = + std::numeric_limits::max() - 1024; + + int bytes_written = 0; + + WriteStringToPickle(pickle, &bytes_written, max_user_agent_size, + user_agent_override); + + return new SessionCommand(command_id, pickle); +} + +SessionCommand* CreateSetWindowAppNameCommand(SessionID::id_type command_id, + SessionID::id_type window_id, + const std::string& app_name) { + // Use pickle to handle marshalling. + Pickle pickle; + pickle.WriteInt(window_id); + + // Enforce a max for ids. They should never be anywhere near this size. + static const SessionCommand::size_type max_id_size = + std::numeric_limits::max() - 1024; + + int bytes_written = 0; + + WriteStringToPickle(pickle, &bytes_written, max_id_size, app_name); + + return new SessionCommand(command_id, pickle); +} + +bool RestoreUpdateTabNavigationCommand( + const SessionCommand& command, + sessions::SerializedNavigationEntry* navigation, + SessionID::id_type* tab_id) { + scoped_ptr pickle(command.PayloadAsPickle()); + if (!pickle.get()) + return false; + PickleIterator iterator(*pickle); + return + pickle->ReadInt(&iterator, tab_id) && + navigation->ReadFromPickle(&iterator); +} + +bool RestoreSetTabExtensionAppIDCommand(const SessionCommand& command, + SessionID::id_type* tab_id, + std::string* extension_app_id) { + scoped_ptr pickle(command.PayloadAsPickle()); + if (!pickle.get()) + return false; + + PickleIterator iterator(*pickle); + return pickle->ReadInt(&iterator, tab_id) && + pickle->ReadString(&iterator, extension_app_id); +} + +bool RestoreSetTabUserAgentOverrideCommand(const SessionCommand& command, + SessionID::id_type* tab_id, + std::string* user_agent_override) { + scoped_ptr pickle(command.PayloadAsPickle()); + if (!pickle.get()) + return false; + + PickleIterator iterator(*pickle); + return pickle->ReadInt(&iterator, tab_id) && + pickle->ReadString(&iterator, user_agent_override); +} + +bool RestoreSetWindowAppNameCommand(const SessionCommand& command, + SessionID::id_type* window_id, + std::string* app_name) { + scoped_ptr pickle(command.PayloadAsPickle()); + if (!pickle.get()) + return false; + + PickleIterator iterator(*pickle); + return pickle->ReadInt(&iterator, window_id) && + pickle->ReadString(&iterator, app_name); +} diff --git a/chrome/browser/sessions/base_session_service_commands.h b/chrome/browser/sessions/base_session_service_commands.h new file mode 100644 index 000000000000..8e0d27e2cc4b --- /dev/null +++ b/chrome/browser/sessions/base_session_service_commands.h @@ -0,0 +1,74 @@ +// Copyright 2014 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. + +#ifndef CHROME_BROWSER_SESSIONS_BASE_SESSION_SERVICE_COMMANDS_H_ +#define CHROME_BROWSER_SESSIONS_BASE_SESSION_SERVICE_COMMANDS_H_ + +#include + +#include "components/sessions/session_id.h" + +class SessionCommand; + +namespace sessions { +class SerializedNavigationEntry; +} + +// These commands create and read common base commands for SessionService and +// PersistentTabRestoreService. +// TODO(skuhne): Make ownership cleaner by using scoped_ptr's for return values. + +// Creates a SessionCommand that represents a navigation. +SessionCommand* CreateUpdateTabNavigationCommand( + SessionID::id_type command_id, + SessionID::id_type tab_id, + const sessions::SerializedNavigationEntry& navigation); + +// Creates a SessionCommand that represents marking a tab as an application. +SessionCommand* CreateSetTabExtensionAppIDCommand( + SessionID::id_type command_id, + SessionID::id_type tab_id, + const std::string& extension_id); + +// Creates a SessionCommand that containing user agent override used by a +// tab's navigations. +SessionCommand* CreateSetTabUserAgentOverrideCommand( + SessionID::id_type command_id, + SessionID::id_type tab_id, + const std::string& user_agent_override); + +// Creates a SessionCommand stores a browser window's app name. +SessionCommand* CreateSetWindowAppNameCommand(SessionID::id_type command_id, + SessionID::id_type window_id, + const std::string& app_name); + +// Converts a SessionCommand previously created by +// CreateUpdateTabNavigationCommand into a +// sessions::SerializedNavigationEntry. Returns true on success. If +// successful |tab_id| is set to the id of the restored tab. +bool RestoreUpdateTabNavigationCommand( + const SessionCommand& command, + sessions::SerializedNavigationEntry* navigation, + SessionID::id_type* tab_id); + +// Extracts a SessionCommand as previously created by +// CreateSetTabExtensionAppIDCommand into the tab id and application +// extension id. +bool RestoreSetTabExtensionAppIDCommand(const SessionCommand& command, + SessionID::id_type* tab_id, + std::string* extension_app_id); + +// Extracts a SessionCommand as previously created by +// CreateSetTabUserAgentOverrideCommand into the tab id and user agent. +bool RestoreSetTabUserAgentOverrideCommand(const SessionCommand& command, + SessionID::id_type* tab_id, + std::string* user_agent_override); + +// Extracts a SessionCommand as previously created by +// CreateSetWindowAppNameCommand into the window id and application name. +bool RestoreSetWindowAppNameCommand(const SessionCommand& command, + SessionID::id_type* window_id, + std::string* app_name); + +#endif // CHROME_BROWSER_SESSIONS_BASE_SESSION_SERVICE_COMMANDS_H_ diff --git a/chrome/browser/sessions/persistent_tab_restore_service.cc b/chrome/browser/sessions/persistent_tab_restore_service.cc index f0be5620b3c1..da03acffdca2 100644 --- a/chrome/browser/sessions/persistent_tab_restore_service.cc +++ b/chrome/browser/sessions/persistent_tab_restore_service.cc @@ -19,6 +19,7 @@ #include "base/time/time.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sessions/base_session_service.h" +#include "chrome/browser/sessions/base_session_service_commands.h" #include "chrome/browser/sessions/base_session_service_delegate_impl.h" #include "chrome/browser/sessions/session_command.h" #include "chrome/browser/sessions/session_service.h" @@ -413,10 +414,9 @@ void PersistentTabRestoreService::Delegate::ScheduleCommandsForWindow( window.timestamp)); if (!window.app_name.empty()) { - ScheduleCommand( - CreateSetWindowAppNameCommand(kCommandSetWindowAppName, - window.id, - window.app_name)); + ScheduleCommand(CreateSetWindowAppNameCommand(kCommandSetWindowAppName, + window.id, + window.app_name)); } for (size_t i = 0; i < window.tabs.size(); ++i) { @@ -459,24 +459,27 @@ void PersistentTabRestoreService::Delegate::ScheduleCommandsForTab( } if (!tab.extension_app_id.empty()) { - ScheduleCommand( - CreateSetTabExtensionAppIDCommand(kCommandSetExtensionAppID, tab.id, - tab.extension_app_id)); + ScheduleCommand(CreateSetTabExtensionAppIDCommand( + kCommandSetExtensionAppID, + tab.id, + tab.extension_app_id)); } if (!tab.user_agent_override.empty()) { - ScheduleCommand( - CreateSetTabUserAgentOverrideCommand(kCommandSetTabUserAgentOverride, - tab.id, tab.user_agent_override)); + ScheduleCommand(CreateSetTabUserAgentOverrideCommand( + kCommandSetTabUserAgentOverride, + tab.id, + tab.user_agent_override)); } // Then write the navigations. for (int i = first_index_to_persist, wrote_count = 0; i < max_index && wrote_count < 2 * max_persist_navigation_count; ++i) { if (ShouldTrackEntry(navigations[i].virtual_url())) { - ScheduleCommand( - CreateUpdateTabNavigationCommand(kCommandUpdateTabNavigation, tab.id, - navigations[i])); + ScheduleCommand(CreateUpdateTabNavigationCommand( + kCommandUpdateTabNavigation, + tab.id, + navigations[i])); } } } @@ -686,8 +689,9 @@ void PersistentTabRestoreService::Delegate::CreateEntriesFromCommands( } current_tab->navigations.resize(current_tab->navigations.size() + 1); SessionID::id_type tab_id; - if (!RestoreUpdateTabNavigationCommand( - command, ¤t_tab->navigations.back(), &tab_id)) { + if (!RestoreUpdateTabNavigationCommand(command, + ¤t_tab->navigations.back(), + &tab_id)) { return; } break; @@ -727,7 +731,8 @@ void PersistentTabRestoreService::Delegate::CreateEntriesFromCommands( } SessionID::id_type tab_id; std::string extension_app_id; - if (!RestoreSetTabExtensionAppIDCommand(command, &tab_id, + if (!RestoreSetTabExtensionAppIDCommand(command, + &tab_id, &extension_app_id)) { return; } @@ -742,7 +747,8 @@ void PersistentTabRestoreService::Delegate::CreateEntriesFromCommands( } SessionID::id_type tab_id; std::string user_agent_override; - if (!RestoreSetTabUserAgentOverrideCommand(command, &tab_id, + if (!RestoreSetTabUserAgentOverrideCommand(command, + &tab_id, &user_agent_override)) { return; } diff --git a/chrome/browser/sessions/persistent_tab_restore_service_unittest.cc b/chrome/browser/sessions/persistent_tab_restore_service_unittest.cc index 4a30d1b94912..76c37a09a216 100644 --- a/chrome/browser/sessions/persistent_tab_restore_service_unittest.cc +++ b/chrome/browser/sessions/persistent_tab_restore_service_unittest.cc @@ -13,6 +13,7 @@ #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/sessions/session_service.h" #include "chrome/browser/sessions/session_service_factory.h" +#include "chrome/browser/sessions/session_service_utils.h" #include "chrome/browser/sessions/session_types.h" #include "chrome/browser/sessions/tab_restore_service_factory.h" #include "chrome/browser/sessions/tab_restore_service_observer.h" @@ -126,8 +127,9 @@ class PersistentTabRestoreServiceTest : public ChromeRenderViewHostTestHarness { SessionServiceFactory::GetForProfile(profile()); SessionID tab_id; SessionID window_id; - session_service->SetWindowType( - window_id, Browser::TYPE_TABBED, SessionService::TYPE_NORMAL); + session_service->SetWindowType(window_id, + Browser::TYPE_TABBED, + SessionService::TYPE_NORMAL); session_service->SetTabWindow(window_id, tab_id); session_service->SetTabIndexInWindow(window_id, tab_id, 0); session_service->SetSelectedTabInWindow(window_id, 0); diff --git a/chrome/browser/sessions/session_restore.cc b/chrome/browser/sessions/session_restore.cc index b824aef74e8d..6246bc0adcf2 100644 --- a/chrome/browser/sessions/session_restore.cc +++ b/chrome/browser/sessions/session_restore.cc @@ -27,6 +27,7 @@ #include "chrome/browser/search/search.h" #include "chrome/browser/sessions/session_service.h" #include "chrome/browser/sessions/session_service_factory.h" +#include "chrome/browser/sessions/session_service_utils.h" #include "chrome/browser/sessions/session_types.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_finder.h" @@ -629,7 +630,7 @@ class SessionRestoreImpl : public content::NotificationObserver { for (std::vector::const_iterator i = begin; i != end; ++i) { Browser* browser = CreateRestoredBrowser( - static_cast((*i)->type), + BrowserTypeForWindowType((*i)->type), (*i)->bounds, (*i)->show_state, (*i)->app_name); @@ -873,9 +874,9 @@ class SessionRestoreImpl : public content::NotificationObserver { for (std::vector::iterator i = windows->begin(); i != windows->end(); ++i) { Browser* browser = NULL; - if (!has_tabbed_browser && (*i)->type == Browser::TYPE_TABBED) + if (!has_tabbed_browser && (*i)->type == SessionWindow::TYPE_TABBED) has_tabbed_browser = true; - if (i == windows->begin() && (*i)->type == Browser::TYPE_TABBED && + if (i == windows->begin() && (*i)->type == SessionWindow::TYPE_TABBED && browser_ && browser_->is_type_tabbed() && !browser_->profile()->IsOffTheRecord()) { // The first set of tabs is added to the existing browser. @@ -892,7 +893,7 @@ class SessionRestoreImpl : public content::NotificationObserver { has_visible_browser = true; } browser = CreateRestoredBrowser( - static_cast((*i)->type), + BrowserTypeForWindowType((*i)->type), (*i)->bounds, show_state, (*i)->app_name); @@ -901,14 +902,14 @@ class SessionRestoreImpl : public content::NotificationObserver { "SessionRestore-CreateRestoredBrowser-End", false); #endif } - if ((*i)->type == Browser::TYPE_TABBED) + if ((*i)->type == SessionWindow::TYPE_TABBED) last_browser = browser; WebContents* active_tab = browser->tab_strip_model()->GetActiveWebContents(); int initial_tab_count = browser->tab_strip_model()->count(); bool close_active_tab = clobber_existing_tab_ && i == windows->begin() && - (*i)->type == Browser::TYPE_TABBED && + (*i)->type == SessionWindow::TYPE_TABBED && active_tab && browser == browser_ && (*i)->tabs.size() > 0; if (close_active_tab) diff --git a/chrome/browser/sessions/session_service.cc b/chrome/browser/sessions/session_service.cc index 8094054f7e50..573d226c066d 100644 --- a/chrome/browser/sessions/session_service.cc +++ b/chrome/browser/sessions/session_service.cc @@ -29,6 +29,7 @@ #include "chrome/browser/sessions/session_command.h" #include "chrome/browser/sessions/session_data_deleter.h" #include "chrome/browser/sessions/session_restore.h" +#include "chrome/browser/sessions/session_service_utils.h" #include "chrome/browser/sessions/session_tab_helper.h" #include "chrome/browser/sessions/session_types.h" #include "chrome/browser/ui/browser_iterator.h" @@ -58,150 +59,9 @@ using content::WebContents; using sessions::ContentSerializedNavigationBuilder; using sessions::SerializedNavigationEntry; -// Identifier for commands written to file. -static const SessionCommand::id_type kCommandSetTabWindow = 0; -// OBSOLETE Superseded by kCommandSetWindowBounds3. -// static const SessionCommand::id_type kCommandSetWindowBounds = 1; -static const SessionCommand::id_type kCommandSetTabIndexInWindow = 2; -// OBSOLETE Superseded kCommandTabClosed/kCommandWindowClosed commands. -// static const SessionCommand::id_type kCommandTabClosedObsolete = 3; -// static const SessionCommand::id_type kCommandWindowClosedObsolete = 4; -static const SessionCommand::id_type - kCommandTabNavigationPathPrunedFromBack = 5; -static const SessionCommand::id_type kCommandUpdateTabNavigation = 6; -static const SessionCommand::id_type kCommandSetSelectedNavigationIndex = 7; -static const SessionCommand::id_type kCommandSetSelectedTabInIndex = 8; -static const SessionCommand::id_type kCommandSetWindowType = 9; -// OBSOLETE Superseded by kCommandSetWindowBounds3. Except for data migration. -// static const SessionCommand::id_type kCommandSetWindowBounds2 = 10; -static const SessionCommand::id_type - kCommandTabNavigationPathPrunedFromFront = 11; -static const SessionCommand::id_type kCommandSetPinnedState = 12; -static const SessionCommand::id_type kCommandSetExtensionAppID = 13; -static const SessionCommand::id_type kCommandSetWindowBounds3 = 14; -static const SessionCommand::id_type kCommandSetWindowAppName = 15; -static const SessionCommand::id_type kCommandTabClosed = 16; -static const SessionCommand::id_type kCommandWindowClosed = 17; -static const SessionCommand::id_type kCommandSetTabUserAgentOverride = 18; -static const SessionCommand::id_type kCommandSessionStorageAssociated = 19; -static const SessionCommand::id_type kCommandSetActiveWindow = 20; - // Every kWritesPerReset commands triggers recreating the file. static const int kWritesPerReset = 250; -namespace { - -// Various payload structures. -struct ClosedPayload { - SessionID::id_type id; - int64 close_time; -}; - -struct WindowBoundsPayload2 { - SessionID::id_type window_id; - int32 x; - int32 y; - int32 w; - int32 h; - bool is_maximized; -}; - -struct WindowBoundsPayload3 { - SessionID::id_type window_id; - int32 x; - int32 y; - int32 w; - int32 h; - int32 show_state; -}; - -typedef SessionID::id_type ActiveWindowPayload; - -struct IDAndIndexPayload { - SessionID::id_type id; - int32 index; -}; - -typedef IDAndIndexPayload TabIndexInWindowPayload; - -typedef IDAndIndexPayload TabNavigationPathPrunedFromBackPayload; - -typedef IDAndIndexPayload SelectedNavigationIndexPayload; - -typedef IDAndIndexPayload SelectedTabInIndexPayload; - -typedef IDAndIndexPayload WindowTypePayload; - -typedef IDAndIndexPayload TabNavigationPathPrunedFromFrontPayload; - -struct PinnedStatePayload { - SessionID::id_type tab_id; - bool pinned_state; -}; - -// Persisted versions of ui::WindowShowState that are written to disk and can -// never change. -enum PersistedWindowShowState { - // SHOW_STATE_DEFAULT (0) never persisted. - PERSISTED_SHOW_STATE_NORMAL = 1, - PERSISTED_SHOW_STATE_MINIMIZED = 2, - PERSISTED_SHOW_STATE_MAXIMIZED = 3, - // SHOW_STATE_INACTIVE (4) never persisted. - PERSISTED_SHOW_STATE_FULLSCREEN = 5, - PERSISTED_SHOW_STATE_DETACHED_DEPRECATED = 6, - PERSISTED_SHOW_STATE_END = 6 -}; - -// Assert to ensure PersistedWindowShowState is updated if ui::WindowShowState -// is changed. -COMPILE_ASSERT(ui::SHOW_STATE_END == - static_cast(PERSISTED_SHOW_STATE_END), - persisted_show_state_mismatch); - -// Returns the show state to store to disk based |state|. -PersistedWindowShowState ShowStateToPersistedShowState( - ui::WindowShowState state) { - switch (state) { - case ui::SHOW_STATE_NORMAL: - return PERSISTED_SHOW_STATE_NORMAL; - case ui::SHOW_STATE_MINIMIZED: - return PERSISTED_SHOW_STATE_MINIMIZED; - case ui::SHOW_STATE_MAXIMIZED: - return PERSISTED_SHOW_STATE_MAXIMIZED; - case ui::SHOW_STATE_FULLSCREEN: - return PERSISTED_SHOW_STATE_FULLSCREEN; - - case ui::SHOW_STATE_DEFAULT: - case ui::SHOW_STATE_INACTIVE: - return PERSISTED_SHOW_STATE_NORMAL; - - case ui::SHOW_STATE_END: - break; - } - NOTREACHED(); - return PERSISTED_SHOW_STATE_NORMAL; -} - -// Lints show state values when read back from persited disk. -ui::WindowShowState PersistedShowStateToShowState(int state) { - switch (state) { - case PERSISTED_SHOW_STATE_NORMAL: - return ui::SHOW_STATE_NORMAL; - case PERSISTED_SHOW_STATE_MINIMIZED: - return ui::SHOW_STATE_MINIMIZED; - case PERSISTED_SHOW_STATE_MAXIMIZED: - return ui::SHOW_STATE_MAXIMIZED; - case PERSISTED_SHOW_STATE_FULLSCREEN: - return ui::SHOW_STATE_FULLSCREEN; - case PERSISTED_SHOW_STATE_DETACHED_DEPRECATED: - return ui::SHOW_STATE_NORMAL; - } - NOTREACHED(); - return ui::SHOW_STATE_NORMAL; -} - -} // namespace - // SessionService ------------------------------------------------------------- SessionService::SessionService(Profile* profile) @@ -252,7 +112,7 @@ bool SessionService::RestoreIfNecessary(const std::vector& urls_to_open) { } void SessionService::ResetFromCurrentBrowsers() { - ScheduleReset(); + ScheduleResetCommands(); } void SessionService::MoveCurrentSessionToLastSession() { @@ -343,9 +203,10 @@ void SessionService::WindowOpened(Browser* browser) { if (!ShouldTrackBrowser(browser)) return; - AppType app_type = browser->is_app() ? TYPE_APP : TYPE_NORMAL; RestoreIfNecessary(std::vector(), browser); - SetWindowType(browser->session_id(), browser->type(), app_type); + SetWindowType(browser->session_id(), + browser->type(), + browser->is_app() ? TYPE_APP : TYPE_NORMAL); SetWindowAppName(browser->session_id(), browser->app_name()); } @@ -419,7 +280,8 @@ void SessionService::WindowClosed(const SessionID& window_id) { void SessionService::SetWindowType(const SessionID& window_id, Browser::Type type, AppType app_type) { - if (!should_track_changes_for_browser_type(type, app_type)) + SessionWindow::WindowType window_type = WindowTypeForBrowserType(type); + if (!ShouldRestoreWindowOfType(window_type, app_type)) return; windows_tracking_.insert(window_id.id()); @@ -431,8 +293,7 @@ void SessionService::SetWindowType(const SessionID& window_id, has_open_trackable_browsers_ = true; move_on_new_browser_ = true; - ScheduleCommand( - CreateSetWindowTypeCommand(window_id, WindowTypeForBrowserType(type))); + ScheduleCommand(CreateSetWindowTypeCommand(window_id, window_type)); } void SessionService::SetWindowAppName( @@ -441,10 +302,7 @@ void SessionService::SetWindowAppName( if (!ShouldTrackChangesToWindow(window_id)) return; - ScheduleCommand(CreateSetTabExtensionAppIDCommand( - kCommandSetWindowAppName, - window_id.id(), - app_name)); + ScheduleCommand(CreateSetWindowAppNameCommand(window_id, app_name)); } void SessionService::TabNavigationPathPrunedFromBack(const SessionID& window_id, @@ -453,14 +311,7 @@ void SessionService::TabNavigationPathPrunedFromBack(const SessionID& window_id, if (!ShouldTrackChangesToWindow(window_id)) return; - TabNavigationPathPrunedFromBackPayload payload = { 0 }; - payload.id = tab_id.id(); - payload.index = count; - SessionCommand* command = - new SessionCommand(kCommandTabNavigationPathPrunedFromBack, - sizeof(payload)); - memcpy(command->contents(), &payload, sizeof(payload)); - ScheduleCommand(command); + ScheduleCommand(CreateTabNavigationPathPrunedFromBackCommand(tab_id, count)); } void SessionService::TabNavigationPathPrunedFromFront( @@ -478,14 +329,7 @@ void SessionService::TabNavigationPathPrunedFromFront( range.second = std::max(0, range.second - count); } - TabNavigationPathPrunedFromFrontPayload payload = { 0 }; - payload.id = tab_id.id(); - payload.index = count; - SessionCommand* command = - new SessionCommand(kCommandTabNavigationPathPrunedFromFront, - sizeof(payload)); - memcpy(command->contents(), &payload, sizeof(payload)); - ScheduleCommand(command); + ScheduleCommand(CreateTabNavigationPathPrunedFromFrontCommand(tab_id, count)); } void SessionService::UpdateTabNavigation( @@ -503,8 +347,7 @@ void SessionService::UpdateTabNavigation( range.first = std::min(navigation.index(), range.first); range.second = std::max(navigation.index(), range.second); } - ScheduleCommand(CreateUpdateTabNavigationCommand(kCommandUpdateTabNavigation, - tab_id.id(), navigation)); + ScheduleCommand(CreateUpdateTabNavigationCommand(tab_id, navigation)); } void SessionService::TabRestored(WebContents* tab, bool pinned) { @@ -541,7 +384,7 @@ void SessionService::SetSelectedTabInWindow(const SessionID& window_id, if (!ShouldTrackChangesToWindow(window_id)) return; - ScheduleCommand(CreateSetSelectedTabInWindow(window_id, index)); + ScheduleCommand(CreateSetSelectedTabInWindowCommand(window_id, index)); } void SessionService::SetTabUserAgentOverride( @@ -551,8 +394,18 @@ void SessionService::SetTabUserAgentOverride( if (!ShouldTrackChangesToWindow(window_id)) return; - ScheduleCommand(CreateSetTabUserAgentOverrideCommand( - kCommandSetTabUserAgentOverride, tab_id.id(), user_agent_override)); + ScheduleCommand(CreateSetTabUserAgentOverrideCommand(tab_id, + user_agent_override)); +} + +void SessionService::SetTabExtensionAppID( + const SessionID& window_id, + const SessionID& tab_id, + const std::string& extension_app_id) { + if (!ShouldTrackChangesToWindow(window_id)) + return; + + ScheduleCommand(CreateSetTabExtensionAppIDCommand(tab_id, extension_app_id)); } base::CancelableTaskTracker::TaskId SessionService::GetLastSession( @@ -594,6 +447,34 @@ void SessionService::Init() { BrowserList::AddObserver(this); } +bool SessionService::ShouldRestoreWindowOfType( + SessionWindow::WindowType window_type, + AppType app_type) const { +#if defined(OS_CHROMEOS) + // Restore app popups for ChromeOS alone. + if (window_type == SessionWindow::TYPE_POPUP && app_type == TYPE_APP) + return true; +#endif + + return window_type == SessionWindow::TYPE_TABBED; +} + +void SessionService::RemoveUnusedRestoreWindows( + std::vector* window_list) { + std::vector::iterator i = window_list->begin(); + while (i != window_list->end()) { + SessionWindow* window = *i; + if (!ShouldRestoreWindowOfType(window->type, + window->app_name.empty() ? TYPE_NORMAL : + TYPE_APP)) { + delete window; + window_list->erase(i++); + } else { + ++i; + } + } +} + bool SessionService::processed_any_commands() { return backend()->inited() || !pending_commands().empty(); } @@ -752,569 +633,20 @@ void SessionService::OnBrowserSetLastActive(Browser* browser) { ScheduleCommand(CreateSetActiveWindowCommand(browser->session_id())); } -void SessionService::SetTabExtensionAppID( - const SessionID& window_id, - const SessionID& tab_id, - const std::string& extension_app_id) { - if (!ShouldTrackChangesToWindow(window_id)) - return; - - ScheduleCommand(CreateSetTabExtensionAppIDCommand(kCommandSetExtensionAppID, - tab_id.id(), extension_app_id)); -} - -SessionCommand* SessionService::CreateSetSelectedTabInWindow( - const SessionID& window_id, - int index) { - SelectedTabInIndexPayload payload = { 0 }; - payload.id = window_id.id(); - payload.index = index; - SessionCommand* command = new SessionCommand(kCommandSetSelectedTabInIndex, - sizeof(payload)); - memcpy(command->contents(), &payload, sizeof(payload)); - return command; -} - -SessionCommand* SessionService::CreateSetTabWindowCommand( - const SessionID& window_id, - const SessionID& tab_id) { - SessionID::id_type payload[] = { window_id.id(), tab_id.id() }; - SessionCommand* command = - new SessionCommand(kCommandSetTabWindow, sizeof(payload)); - memcpy(command->contents(), payload, sizeof(payload)); - return command; -} - -SessionCommand* SessionService::CreateSetWindowBoundsCommand( - const SessionID& window_id, - const gfx::Rect& bounds, - ui::WindowShowState show_state) { - WindowBoundsPayload3 payload = { 0 }; - payload.window_id = window_id.id(); - payload.x = bounds.x(); - payload.y = bounds.y(); - payload.w = bounds.width(); - payload.h = bounds.height(); - payload.show_state = ShowStateToPersistedShowState(show_state); - SessionCommand* command = new SessionCommand(kCommandSetWindowBounds3, - sizeof(payload)); - memcpy(command->contents(), &payload, sizeof(payload)); - return command; -} - -SessionCommand* SessionService::CreateSetTabIndexInWindowCommand( - const SessionID& tab_id, - int new_index) { - TabIndexInWindowPayload payload = { 0 }; - payload.id = tab_id.id(); - payload.index = new_index; - SessionCommand* command = - new SessionCommand(kCommandSetTabIndexInWindow, sizeof(payload)); - memcpy(command->contents(), &payload, sizeof(payload)); - return command; -} - -SessionCommand* SessionService::CreateTabClosedCommand( - const SessionID::id_type tab_id) { - ClosedPayload payload; - // Because of what appears to be a compiler bug setting payload to {0} doesn't - // set the padding to 0, resulting in Purify reporting an UMR when we write - // the structure to disk. To avoid this we explicitly memset the struct. - memset(&payload, 0, sizeof(payload)); - payload.id = tab_id; - payload.close_time = Time::Now().ToInternalValue(); - SessionCommand* command = - new SessionCommand(kCommandTabClosed, sizeof(payload)); - memcpy(command->contents(), &payload, sizeof(payload)); - return command; -} - -SessionCommand* SessionService::CreateWindowClosedCommand( - const SessionID::id_type window_id) { - ClosedPayload payload; - // See comment in CreateTabClosedCommand as to why we do this. - memset(&payload, 0, sizeof(payload)); - payload.id = window_id; - payload.close_time = Time::Now().ToInternalValue(); - SessionCommand* command = - new SessionCommand(kCommandWindowClosed, sizeof(payload)); - memcpy(command->contents(), &payload, sizeof(payload)); - return command; -} - -SessionCommand* SessionService::CreateSetSelectedNavigationIndexCommand( - const SessionID& tab_id, - int index) { - SelectedNavigationIndexPayload payload = { 0 }; - payload.id = tab_id.id(); - payload.index = index; - SessionCommand* command = new SessionCommand( - kCommandSetSelectedNavigationIndex, sizeof(payload)); - memcpy(command->contents(), &payload, sizeof(payload)); - return command; -} - -SessionCommand* SessionService::CreateSetWindowTypeCommand( - const SessionID& window_id, - WindowType type) { - WindowTypePayload payload = { 0 }; - payload.id = window_id.id(); - payload.index = static_cast(type); - SessionCommand* command = new SessionCommand( - kCommandSetWindowType, sizeof(payload)); - memcpy(command->contents(), &payload, sizeof(payload)); - return command; -} - -SessionCommand* SessionService::CreatePinnedStateCommand( - const SessionID& tab_id, - bool is_pinned) { - PinnedStatePayload payload = { 0 }; - payload.tab_id = tab_id.id(); - payload.pinned_state = is_pinned; - SessionCommand* command = - new SessionCommand(kCommandSetPinnedState, sizeof(payload)); - memcpy(command->contents(), &payload, sizeof(payload)); - return command; -} - -SessionCommand* SessionService::CreateSessionStorageAssociatedCommand( - const SessionID& tab_id, - const std::string& session_storage_persistent_id) { - Pickle pickle; - pickle.WriteInt(tab_id.id()); - pickle.WriteString(session_storage_persistent_id); - return new SessionCommand(kCommandSessionStorageAssociated, pickle); -} - -SessionCommand* SessionService::CreateSetActiveWindowCommand( - const SessionID& window_id) { - ActiveWindowPayload payload = 0; - payload = window_id.id(); - SessionCommand* command = - new SessionCommand(kCommandSetActiveWindow, sizeof(payload)); - memcpy(command->contents(), &payload, sizeof(payload)); - return command; -} - void SessionService::OnGotSessionCommands( const SessionCallback& callback, ScopedVector commands) { ScopedVector valid_windows; SessionID::id_type active_window_id = 0; - RestoreSessionFromCommands( - commands.get(), &valid_windows.get(), &active_window_id); - callback.Run(valid_windows.Pass(), active_window_id); -} - -void SessionService::RestoreSessionFromCommands( - const std::vector& commands, - std::vector* valid_windows, - SessionID::id_type* active_window_id) { - std::map tabs; - std::map windows; - - VLOG(1) << "RestoreSessionFromCommands " << commands.size(); - if (CreateTabsAndWindows(commands, &tabs, &windows, active_window_id)) { - AddTabsToWindows(&tabs, &windows); - SortTabsBasedOnVisualOrderAndPrune(&windows, valid_windows); - UpdateSelectedTabIndex(valid_windows); - } - STLDeleteValues(&tabs); - // Don't delete conents of windows, that is done by the caller as all - // valid windows are added to valid_windows. -} - -void SessionService::UpdateSelectedTabIndex( - std::vector* windows) { - for (std::vector::const_iterator i = windows->begin(); - i != windows->end(); ++i) { - // See note in SessionWindow as to why we do this. - int new_index = 0; - for (std::vector::const_iterator j = (*i)->tabs.begin(); - j != (*i)->tabs.end(); ++j) { - if ((*j)->tab_visual_index == (*i)->selected_tab_index) { - new_index = static_cast(j - (*i)->tabs.begin()); - break; - } - } - (*i)->selected_tab_index = new_index; - } -} - -SessionWindow* SessionService::GetWindow( - SessionID::id_type window_id, - IdToSessionWindow* windows) { - std::map::iterator i = windows->find(window_id); - if (i == windows->end()) { - SessionWindow* window = new SessionWindow(); - window->window_id.set_id(window_id); - (*windows)[window_id] = window; - return window; - } - return i->second; -} - -SessionTab* SessionService::GetTab( - SessionID::id_type tab_id, - IdToSessionTab* tabs) { - DCHECK(tabs); - std::map::iterator i = tabs->find(tab_id); - if (i == tabs->end()) { - SessionTab* tab = new SessionTab(); - tab->tab_id.set_id(tab_id); - (*tabs)[tab_id] = tab; - return tab; - } - return i->second; -} - -std::vector::iterator - SessionService::FindClosestNavigationWithIndex( - std::vector* navigations, - int index) { - DCHECK(navigations); - for (std::vector::iterator - i = navigations->begin(); i != navigations->end(); ++i) { - if (i->index() >= index) - return i; - } - return navigations->end(); -} - -// Function used in sorting windows. Sorting is done based on window id. As -// window ids increment for each new window, this effectively sorts by creation -// time. -static bool WindowOrderSortFunction(const SessionWindow* w1, - const SessionWindow* w2) { - return w1->window_id.id() < w2->window_id.id(); -} - -// Compares the two tabs based on visual index. -static bool TabVisualIndexSortFunction(const SessionTab* t1, - const SessionTab* t2) { - const int delta = t1->tab_visual_index - t2->tab_visual_index; - return delta == 0 ? (t1->tab_id.id() < t2->tab_id.id()) : (delta < 0); -} - -void SessionService::SortTabsBasedOnVisualOrderAndPrune( - std::map* windows, - std::vector* valid_windows) { - std::map::iterator i = windows->begin(); - while (i != windows->end()) { - SessionWindow* window = i->second; - AppType app_type = window->app_name.empty() ? TYPE_NORMAL : TYPE_APP; - if (window->tabs.empty() || window->is_constrained || - !should_track_changes_for_browser_type( - static_cast(window->type), - app_type)) { - delete window; - windows->erase(i++); - } else { - // Valid window; sort the tabs and add it to the list of valid windows. - std::sort(window->tabs.begin(), window->tabs.end(), - &TabVisualIndexSortFunction); - // Otherwise, add the window such that older windows appear first. - if (valid_windows->empty()) { - valid_windows->push_back(window); - } else { - valid_windows->insert( - std::upper_bound(valid_windows->begin(), valid_windows->end(), - window, &WindowOrderSortFunction), - window); - } - ++i; - } - } -} - -void SessionService::AddTabsToWindows(std::map* tabs, - std::map* windows) { - VLOG(1) << "AddTabsToWindws"; - VLOG(1) << "Tabs " << tabs->size() << ", windows " << windows->size(); - std::map::iterator i = tabs->begin(); - while (i != tabs->end()) { - SessionTab* tab = i->second; - if (tab->window_id.id() && !tab->navigations.empty()) { - SessionWindow* window = GetWindow(tab->window_id.id(), windows); - window->tabs.push_back(tab); - tabs->erase(i++); - - // See note in SessionTab as to why we do this. - std::vector::iterator j = - FindClosestNavigationWithIndex(&(tab->navigations), - tab->current_navigation_index); - if (j == tab->navigations.end()) { - tab->current_navigation_index = - static_cast(tab->navigations.size() - 1); - } else { - tab->current_navigation_index = - static_cast(j - tab->navigations.begin()); - } - } else { - // Never got a set tab index in window, or tabs are empty, nothing - // to do. - ++i; - } - } -} - -bool SessionService::CreateTabsAndWindows( - const std::vector& data, - std::map* tabs, - std::map* windows, - SessionID::id_type* active_window_id) { - // If the file is corrupt (command with wrong size, or unknown command), we - // still return true and attempt to restore what we we can. - VLOG(1) << "CreateTabsAndWindows"; - startup_metric_utils::ScopedSlowStartupUMA scoped_timer("Startup.SlowStartupSessionServiceCreateTabsAndWindows"); - for (std::vector::const_iterator i = data.begin(); - i != data.end(); ++i) { - const SessionCommand::id_type kCommandSetWindowBounds2 = 10; - const SessionCommand* command = *i; - - VLOG(1) << "Read command " << (int) command->id(); - switch (command->id()) { - case kCommandSetTabWindow: { - SessionID::id_type payload[2]; - if (!command->GetPayload(payload, sizeof(payload))) { - VLOG(1) << "Failed reading command " << command->id(); - return true; - } - GetTab(payload[1], tabs)->window_id.set_id(payload[0]); - break; - } - - // This is here for forward migration only. New data is saved with - // |kCommandSetWindowBounds3|. - case kCommandSetWindowBounds2: { - WindowBoundsPayload2 payload; - if (!command->GetPayload(&payload, sizeof(payload))) { - VLOG(1) << "Failed reading command " << command->id(); - return true; - } - GetWindow(payload.window_id, windows)->bounds.SetRect(payload.x, - payload.y, - payload.w, - payload.h); - GetWindow(payload.window_id, windows)->show_state = - payload.is_maximized ? - ui::SHOW_STATE_MAXIMIZED : ui::SHOW_STATE_NORMAL; - break; - } - - case kCommandSetWindowBounds3: { - WindowBoundsPayload3 payload; - if (!command->GetPayload(&payload, sizeof(payload))) { - VLOG(1) << "Failed reading command " << command->id(); - return true; - } - GetWindow(payload.window_id, windows)->bounds.SetRect(payload.x, - payload.y, - payload.w, - payload.h); - GetWindow(payload.window_id, windows)->show_state = - PersistedShowStateToShowState(payload.show_state); - break; - } - - case kCommandSetTabIndexInWindow: { - TabIndexInWindowPayload payload; - if (!command->GetPayload(&payload, sizeof(payload))) { - VLOG(1) << "Failed reading command " << command->id(); - return true; - } - GetTab(payload.id, tabs)->tab_visual_index = payload.index; - break; - } - - case kCommandTabClosed: - case kCommandWindowClosed: { - ClosedPayload payload; - if (!command->GetPayload(&payload, sizeof(payload))) { - VLOG(1) << "Failed reading command " << command->id(); - return true; - } - if (command->id() == kCommandTabClosed) { - delete GetTab(payload.id, tabs); - tabs->erase(payload.id); - } else { - delete GetWindow(payload.id, windows); - windows->erase(payload.id); - } - break; - } - - case kCommandTabNavigationPathPrunedFromBack: { - TabNavigationPathPrunedFromBackPayload payload; - if (!command->GetPayload(&payload, sizeof(payload))) { - VLOG(1) << "Failed reading command " << command->id(); - return true; - } - SessionTab* tab = GetTab(payload.id, tabs); - tab->navigations.erase( - FindClosestNavigationWithIndex(&(tab->navigations), payload.index), - tab->navigations.end()); - break; - } - - case kCommandTabNavigationPathPrunedFromFront: { - TabNavigationPathPrunedFromFrontPayload payload; - if (!command->GetPayload(&payload, sizeof(payload)) || - payload.index <= 0) { - VLOG(1) << "Failed reading command " << command->id(); - return true; - } - SessionTab* tab = GetTab(payload.id, tabs); - - // Update the selected navigation index. - tab->current_navigation_index = - std::max(-1, tab->current_navigation_index - payload.index); - - // And update the index of existing navigations. - for (std::vector::iterator - i = tab->navigations.begin(); - i != tab->navigations.end();) { - i->set_index(i->index() - payload.index); - if (i->index() < 0) - i = tab->navigations.erase(i); - else - ++i; - } - break; - } - - case kCommandUpdateTabNavigation: { - SerializedNavigationEntry navigation; - SessionID::id_type tab_id; - if (!RestoreUpdateTabNavigationCommand( - *command, &navigation, &tab_id)) { - VLOG(1) << "Failed reading command " << command->id(); - return true; - } - SessionTab* tab = GetTab(tab_id, tabs); - std::vector::iterator i = - FindClosestNavigationWithIndex(&(tab->navigations), - navigation.index()); - if (i != tab->navigations.end() && i->index() == navigation.index()) - *i = navigation; - else - tab->navigations.insert(i, navigation); - break; - } - - case kCommandSetSelectedNavigationIndex: { - SelectedNavigationIndexPayload payload; - if (!command->GetPayload(&payload, sizeof(payload))) { - VLOG(1) << "Failed reading command " << command->id(); - return true; - } - GetTab(payload.id, tabs)->current_navigation_index = payload.index; - break; - } - - case kCommandSetSelectedTabInIndex: { - SelectedTabInIndexPayload payload; - if (!command->GetPayload(&payload, sizeof(payload))) { - VLOG(1) << "Failed reading command " << command->id(); - return true; - } - GetWindow(payload.id, windows)->selected_tab_index = payload.index; - break; - } - - case kCommandSetWindowType: { - WindowTypePayload payload; - if (!command->GetPayload(&payload, sizeof(payload))) { - VLOG(1) << "Failed reading command " << command->id(); - return true; - } - GetWindow(payload.id, windows)->is_constrained = false; - GetWindow(payload.id, windows)->type = - BrowserTypeForWindowType( - static_cast(payload.index)); - break; - } - - case kCommandSetPinnedState: { - PinnedStatePayload payload; - if (!command->GetPayload(&payload, sizeof(payload))) { - VLOG(1) << "Failed reading command " << command->id(); - return true; - } - GetTab(payload.tab_id, tabs)->pinned = payload.pinned_state; - break; - } - - case kCommandSetWindowAppName: { - SessionID::id_type window_id; - std::string app_name; - if (!RestoreSetWindowAppNameCommand(*command, &window_id, &app_name)) - return true; - - GetWindow(window_id, windows)->app_name.swap(app_name); - break; - } - - case kCommandSetExtensionAppID: { - SessionID::id_type tab_id; - std::string extension_app_id; - if (!RestoreSetTabExtensionAppIDCommand( - *command, &tab_id, &extension_app_id)) { - VLOG(1) << "Failed reading command " << command->id(); - return true; - } - - GetTab(tab_id, tabs)->extension_app_id.swap(extension_app_id); - break; - } - - case kCommandSetTabUserAgentOverride: { - SessionID::id_type tab_id; - std::string user_agent_override; - if (!RestoreSetTabUserAgentOverrideCommand( - *command, &tab_id, &user_agent_override)) { - return true; - } - - GetTab(tab_id, tabs)->user_agent_override.swap(user_agent_override); - break; - } - - case kCommandSessionStorageAssociated: { - scoped_ptr command_pickle(command->PayloadAsPickle()); - SessionID::id_type command_tab_id; - std::string session_storage_persistent_id; - PickleIterator iter(*command_pickle.get()); - if (!command_pickle->ReadInt(&iter, &command_tab_id) || - !command_pickle->ReadString(&iter, &session_storage_persistent_id)) - return true; - // Associate the session storage back. - GetTab(command_tab_id, tabs)->session_storage_persistent_id = - session_storage_persistent_id; - break; - } - - case kCommandSetActiveWindow: { - ActiveWindowPayload payload; - if (!command->GetPayload(&payload, sizeof(payload))) { - VLOG(1) << "Failed reading command " << command->id(); - return true; - } - *active_window_id = payload; - break; - } + RestoreSessionFromCommands( + commands.get(), &valid_windows.get(), &active_window_id); + RemoveUnusedRestoreWindows(&valid_windows.get()); - default: - VLOG(1) << "Failed reading an unknown command " << command->id(); - return true; - } - } - return true; + callback.Run(valid_windows.Pass(), active_window_id); } void SessionService::BuildCommandsForTab(const SessionID& window_id, @@ -1340,24 +672,21 @@ void SessionService::BuildCommandsForTab(const SessionID& window_id, std::pair(min_index, max_index); } - if (is_pinned) { + if (is_pinned) commands->push_back(CreatePinnedStateCommand(session_id, true)); - } extensions::TabHelper* extensions_tab_helper = extensions::TabHelper::FromWebContents(tab); if (extensions_tab_helper->extension_app()) { - commands->push_back( - CreateSetTabExtensionAppIDCommand( - kCommandSetExtensionAppID, session_id.id(), - extensions_tab_helper->extension_app()->id())); + commands->push_back(CreateSetTabExtensionAppIDCommand( + session_id, + extensions_tab_helper->extension_app()->id())); } const std::string& ua_override = tab->GetUserAgentOverride(); if (!ua_override.empty()) { - commands->push_back( - CreateSetTabUserAgentOverrideCommand( - kCommandSetTabUserAgentOverride, session_id.id(), ua_override)); + commands->push_back(CreateSetTabUserAgentOverrideCommand(session_id, + ua_override)); } for (int i = min_index; i < max_index; ++i) { @@ -1369,8 +698,7 @@ void SessionService::BuildCommandsForTab(const SessionID& window_id, const SerializedNavigationEntry navigation = ContentSerializedNavigationBuilder::FromNavigationEntry(i, *entry); commands->push_back( - CreateUpdateTabNavigationCommand( - kCommandUpdateTabNavigation, session_id.id(), navigation)); + CreateUpdateTabNavigationCommand(session_id, navigation)); } } commands->push_back( @@ -1403,13 +731,12 @@ void SessionService::BuildCommandsForBrowser( browser->window()->GetRestoredState())); commands->push_back(CreateSetWindowTypeCommand( - browser->session_id(), WindowTypeForBrowserType(browser->type()))); + browser->session_id(), + WindowTypeForBrowserType(browser->type()))); if (!browser->app_name().empty()) { - commands->push_back(CreateSetWindowAppNameCommand( - kCommandSetWindowAppName, - browser->session_id().id(), - browser->app_name())); + commands->push_back(CreateSetWindowAppNameCommand(browser->session_id(), + browser->app_name())); } windows_to_track->insert(browser->session_id().id()); @@ -1422,9 +749,9 @@ void SessionService::BuildCommandsForBrowser( commands, tab_to_available_range); } - commands->push_back( - CreateSetSelectedTabInWindow(browser->session_id(), - browser->tab_strip_model()->active_index())); + commands->push_back(CreateSetSelectedTabInWindowCommand( + browser->session_id(), + browser->tab_strip_model()->active_index())); } void SessionService::BuildCommandsFromBrowsers( @@ -1448,7 +775,7 @@ void SessionService::BuildCommandsFromBrowsers( } } -void SessionService::ScheduleReset() { +void SessionService::ScheduleResetCommands() { set_pending_reset(true); STLDeleteElements(&pending_commands()); tab_to_available_range_.clear(); @@ -1464,73 +791,16 @@ void SessionService::ScheduleReset() { StartSaveTimer(); } -bool SessionService::ReplacePendingCommand(SessionCommand* command) { - // We optimize page navigations, which can happen quite frequently and - // are expensive. And activation is like Highlander, there can only be one! - if (command->id() != kCommandUpdateTabNavigation && - command->id() != kCommandSetActiveWindow) { - return false; - } - for (std::vector::reverse_iterator i = - pending_commands().rbegin(); i != pending_commands().rend(); ++i) { - SessionCommand* existing_command = *i; - if (command->id() == kCommandUpdateTabNavigation && - existing_command->id() == kCommandUpdateTabNavigation) { - scoped_ptr command_pickle(command->PayloadAsPickle()); - PickleIterator iterator(*command_pickle); - SessionID::id_type command_tab_id; - int command_nav_index; - if (!command_pickle->ReadInt(&iterator, &command_tab_id) || - !command_pickle->ReadInt(&iterator, &command_nav_index)) { - return false; - } - SessionID::id_type existing_tab_id; - int existing_nav_index; - { - // Creating a pickle like this means the Pickle references the data from - // the command. Make sure we delete the pickle before the command, else - // the pickle references deleted memory. - scoped_ptr existing_pickle(existing_command->PayloadAsPickle()); - iterator = PickleIterator(*existing_pickle); - if (!existing_pickle->ReadInt(&iterator, &existing_tab_id) || - !existing_pickle->ReadInt(&iterator, &existing_nav_index)) { - return false; - } - } - if (existing_tab_id == command_tab_id && - existing_nav_index == command_nav_index) { - // existing_command is an update for the same tab/index pair. Replace - // it with the new one. We need to add to the end of the list just in - // case there is a prune command after the update command. - delete existing_command; - pending_commands().erase(i.base() - 1); - pending_commands().push_back(command); - return true; - } - return false; - } - if (command->id() == kCommandSetActiveWindow && - existing_command->id() == kCommandSetActiveWindow) { - *i = command; - delete existing_command; - return true; - } - } - return false; -} - void SessionService::ScheduleCommand(SessionCommand* command) { DCHECK(command); - if (ReplacePendingCommand(command)) + if (ReplacePendingCommand(command, pending_commands())) return; BaseSessionService::ScheduleCommand(command); // Don't schedule a reset on tab closed/window closed. Otherwise we may // lose tabs/windows we want to restore from if we exit right after this. if (!pending_reset() && pending_window_close_ids_.empty() && - commands_since_reset() >= kWritesPerReset && - (command->id() != kCommandTabClosed && - command->id() != kCommandWindowClosed)) { - ScheduleReset(); + commands_since_reset() >= kWritesPerReset && !IsClosingCommand(command)) { + ScheduleResetCommands(); } } @@ -1605,42 +875,8 @@ bool SessionService::ShouldTrackBrowser(Browser* browser) const { !browser->is_trusted_source()) { return false; } - AppType app_type = browser->is_app() ? TYPE_APP : TYPE_NORMAL; - return should_track_changes_for_browser_type(browser->type(), app_type); -} - -bool SessionService::should_track_changes_for_browser_type(Browser::Type type, - AppType app_type) { -#if defined(OS_CHROMEOS) - // Restore app popups for chromeos alone. - if (type == Browser::TYPE_POPUP && app_type == TYPE_APP) - return true; -#endif - - return type == Browser::TYPE_TABBED; -} - -SessionService::WindowType SessionService::WindowTypeForBrowserType( - Browser::Type type) { - switch (type) { - case Browser::TYPE_POPUP: - return TYPE_POPUP; - case Browser::TYPE_TABBED: - return TYPE_TABBED; - default: - DCHECK(false); - return TYPE_TABBED; - } -} - -Browser::Type SessionService::BrowserTypeForWindowType(WindowType type) { - switch (type) { - case TYPE_POPUP: - return Browser::TYPE_POPUP; - case TYPE_TABBED: - default: - return Browser::TYPE_TABBED; - } + return ShouldRestoreWindowOfType(WindowTypeForBrowserType(browser->type()), + browser->is_app() ? TYPE_APP : TYPE_NORMAL); } void SessionService::RecordSessionUpdateHistogramData(int type, diff --git a/chrome/browser/sessions/session_service.h b/chrome/browser/sessions/session_service.h index d602669ea8ae..1398b4bc1b09 100644 --- a/chrome/browser/sessions/session_service.h +++ b/chrome/browser/sessions/session_service.h @@ -16,11 +16,12 @@ #include "base/time/time.h" #include "chrome/browser/defaults.h" #include "chrome/browser/sessions/base_session_service.h" +#include "chrome/browser/sessions/session_service_commands.h" +#include "chrome/browser/sessions/session_service_utils.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_list_observer.h" #include "components/keyed_service/core/keyed_service.h" -#include "components/sessions/session_id.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" #include "ui/base/ui_base_types.h" @@ -49,11 +50,11 @@ class WebContents; // illusion that app windows run in separate processes. Similar behavior occurs // with incognito windows. // -// SessionService itself maintains a set of SessionCommands that allow -// SessionService to rebuild the open state of the browser (as SessionWindow, -// SessionTab and SerializedNavigationEntry). The commands are periodically -// flushed to SessionBackend and written to a file. Every so often -// SessionService rebuilds the contents of the file from the open state of the +// SessionService itself uses functions from session_service_commands to store +// commands which can rebuild the open state of the browser (as |SessionWindow|, +// |SessionTab| and |SerializedNavigationEntry|). The commands are periodically +// flushed to |SessionBackend| and written to a file. Every so often +// |SessionService| rebuilds the contents of the file from the open state of the // browser. class SessionService : public BaseSessionService, public KeyedService, @@ -61,7 +62,7 @@ class SessionService : public BaseSessionService, public chrome::BrowserListObserver { friend class SessionServiceTestHelper; public: - // Used to distinguish an application window from a normal one. + // Used to distinguish an application from a ordinary content window. enum AppType { TYPE_APP, TYPE_NORMAL @@ -144,7 +145,7 @@ class SessionService : public BaseSessionService, // Sets the type of window. In order for the contents of a window to be // tracked SetWindowType must be invoked with a type we track - // (should_track_changes_for_browser_type returns true). + // (ShouldRestoreOfWindowType returns true). void SetWindowType(const SessionID& window_id, Browser::Type type, AppType app_type); @@ -189,6 +190,11 @@ class SessionService : public BaseSessionService, const SessionID& tab_id, const std::string& user_agent_override); + // Sets the application extension id of the specified tab. + void SetTabExtensionAppID(const SessionID& window_id, + const SessionID& tab_id, + const std::string& extension_app_id); + // Callback from GetLastSession. // The second parameter is the id of the window that was last active. typedef base::Callback, SessionID::id_type)> @@ -212,20 +218,16 @@ class SessionService : public BaseSessionService, FRIEND_TEST_ALL_PREFIXES(NoStartupWindowTest, DontInitSessionServiceForApps); typedef std::map > IdToRange; - typedef std::map IdToSessionTab; - typedef std::map IdToSessionWindow; + void Init(); - // These types mirror Browser::Type, but are re-defined here because these - // specific enumeration _values_ are written into the session database and - // are needed to maintain forward compatibility. - // Note that we only store browsers of type TYPE_TABBED and TYPE_POPUP. - enum WindowType { - TYPE_TABBED = 0, - TYPE_POPUP = 1 - }; + // Returns true if a window of given |window_type| and |app_type| should get + // restored upon session restore. + bool ShouldRestoreWindowOfType(SessionWindow::WindowType type, + AppType app_type) const; - void Init(); + // Removes unrestorable windows from the previous windows list. + void RemoveUnusedRestoreWindows(std::vector* window_list); // Returns true if we have scheduled any commands, or any scheduled commands // have been saved. @@ -245,111 +247,10 @@ class SessionService : public BaseSessionService, void OnBrowserRemoved(Browser* browser) override {} void OnBrowserSetLastActive(Browser* browser) override; - // Sets the application extension id of the specified tab. - void SetTabExtensionAppID(const SessionID& window_id, - const SessionID& tab_id, - const std::string& extension_app_id); - - // Methods to create the various commands. It is up to the caller to delete - // the returned the SessionCommand* object. - SessionCommand* CreateSetSelectedTabInWindow(const SessionID& window_id, - int index); - - SessionCommand* CreateSetTabWindowCommand(const SessionID& window_id, - const SessionID& tab_id); - - SessionCommand* CreateSetWindowBoundsCommand(const SessionID& window_id, - const gfx::Rect& bounds, - ui::WindowShowState show_state); - - SessionCommand* CreateSetTabIndexInWindowCommand(const SessionID& tab_id, - int new_index); - - SessionCommand* CreateTabClosedCommand(SessionID::id_type tab_id); - - SessionCommand* CreateWindowClosedCommand(SessionID::id_type tab_id); - - SessionCommand* CreateSetSelectedNavigationIndexCommand( - const SessionID& tab_id, - int index); - - SessionCommand* CreateSetWindowTypeCommand(const SessionID& window_id, - WindowType type); - - SessionCommand* CreatePinnedStateCommand(const SessionID& tab_id, - bool is_pinned); - - SessionCommand* CreateSessionStorageAssociatedCommand( - const SessionID& tab_id, - const std::string& session_storage_persistent_id); - - SessionCommand* CreateSetActiveWindowCommand(const SessionID& window_id); - // Converts |commands| to SessionWindows and notifies the callback. void OnGotSessionCommands(const SessionCallback& callback, ScopedVector commands); - // Converts the commands into SessionWindows. On return any valid - // windows are added to valid_windows. It is up to the caller to delete - // the windows added to valid_windows. |active_window_id| will be set with the - // id of the last active window, but it's only valid when this id corresponds - // to the id of one of the windows in valid_windows. - void RestoreSessionFromCommands(const std::vector& commands, - std::vector* valid_windows, - SessionID::id_type* active_window_id); - - // Iterates through the vector updating the selected_tab_index of each - // SessionWindow based on the actual tabs that were restored. - void UpdateSelectedTabIndex(std::vector* windows); - - // Returns the window in windows with the specified id. If a window does - // not exist, one is created. - SessionWindow* GetWindow(SessionID::id_type window_id, - IdToSessionWindow* windows); - - // Returns the tab with the specified id in tabs. If a tab does not exist, - // it is created. - SessionTab* GetTab(SessionID::id_type tab_id, - IdToSessionTab* tabs); - - // Returns an iterator into navigations pointing to the navigation whose - // index matches |index|. If no navigation index matches |index|, the first - // navigation with an index > |index| is returned. - // - // This assumes the navigations are ordered by index in ascending order. - std::vector::iterator - FindClosestNavigationWithIndex( - std::vector* navigations, - int index); - - // Does the following: - // . Deletes and removes any windows with no tabs or windows with types other - // than tabbed_browser or browser. NOTE: constrained windows that have - // been dragged out are of type browser. As such, this preserves any dragged - // out constrained windows (aka popups that have been dragged out). - // . Sorts the tabs in windows with valid tabs based on the tabs - // visual order, and adds the valid windows to windows. - void SortTabsBasedOnVisualOrderAndPrune( - std::map* windows, - std::vector* valid_windows); - - // Adds tabs to their parent window based on the tab's window_id. This - // ignores tabs with no navigations. - void AddTabsToWindows(std::map* tabs, - std::map* windows); - - // Creates tabs and windows from the commands specified in |data|. The created - // tabs and windows are added to |tabs| and |windows| respectively, with the - // id of the active window set in |active_window_id|. It is up to the caller - // to delete the tabs and windows added to |tabs| and |windows|. - // - // This does NOT add any created SessionTabs to SessionWindow.tabs, that is - // done by AddTabsToWindows. - bool CreateTabsAndWindows(const std::vector& data, - std::map* tabs, - std::map* windows, - SessionID::id_type* active_window_id); - // Adds commands to commands that will recreate the state of the specified // tab. This adds at most kMaxNavigationCountToPersist navigations (in each // direction from the current navigation index). @@ -373,22 +274,17 @@ class SessionService : public BaseSessionService, std::set* windows_to_track); // Iterates over all the known browsers invoking BuildCommandsForBrowser. - // This only adds browsers that should be tracked - // (should_track_changes_for_browser_type returns true). All browsers that - // are tracked are added to windows_to_track (as long as it is non-null). + // This only adds browsers that should be tracked (|ShouldRestoreWindowOfType| + // returns true). All browsers that are tracked are added to windows_to_track + // (as long as it is non-null). void BuildCommandsFromBrowsers( std::vector* commands, IdToRange* tab_to_available_range, std::set* windows_to_track); - // Schedules a reset. A reset means the contents of the file are recreated - // from the state of the browser. - void ScheduleReset(); - - // Searches for a pending command that can be replaced with command. - // If one is found, pending command is removed, command is added to - // the pending commands and true is returned. - bool ReplacePendingCommand(SessionCommand* command); + // Schedules a reset of the existing commands. A reset means the contents + // of the file are recreated from the state of the browser. + void ScheduleResetCommands(); // Schedules the specified command. This method takes ownership of the // command. @@ -403,8 +299,8 @@ class SessionService : public BaseSessionService, // Returns true if there are open trackable browser windows whose ids do // match |window_id| with our profile. A trackable window is a window from - // which |should_track_changes_for_browser_type| returns true. See - // |should_track_changes_for_browser_type| for details. + // which |ShouldRestoreWindowOfType| returns true. See + // |ShouldRestoreWindowOfType| for details. bool HasOpenTrackableBrowsers(const SessionID& window_id) const; // Returns true if changes to tabs in the specified window should be tracked. @@ -413,11 +309,6 @@ class SessionService : public BaseSessionService, // Returns true if we track changes to the specified browser. bool ShouldTrackBrowser(Browser* browser) const; - // Returns true if we track changes to the specified browser type. - static bool should_track_changes_for_browser_type( - Browser::Type type, - AppType app_type); - // Call when certain session relevant notifications // (tab_closed, nav_list_pruned) occur. In addition, this is // currently called when Save() is called to compare how often the @@ -437,11 +328,6 @@ class SessionService : public BaseSessionService, // Deletes session data if no windows are open for the current profile. void MaybeDeleteSessionOnlyData(); - // Convert back/forward between the Browser and SessionService DB window - // types. - static WindowType WindowTypeForBrowserType(Browser::Type type); - static Browser::Type BrowserTypeForWindowType(WindowType type); - // The profile. This may be null during testing. Profile* profile_; @@ -472,7 +358,7 @@ class SessionService : public BaseSessionService, WindowClosingIDs window_closing_ids_; // Set of windows we're tracking changes to. This is only browsers that - // return true from should_track_changes_for_browser_type. + // return true from |ShouldRestoreWindowOfType|. typedef std::set WindowsTracking; WindowsTracking windows_tracking_; diff --git a/chrome/browser/sessions/session_service_commands.cc b/chrome/browser/sessions/session_service_commands.cc new file mode 100644 index 000000000000..a313e753344e --- /dev/null +++ b/chrome/browser/sessions/session_service_commands.cc @@ -0,0 +1,824 @@ +// Copyright 2014 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 "chrome/browser/sessions/session_service_commands.h" + +#include + +#include "base/pickle.h" +#include "chrome/browser/sessions/base_session_service_commands.h" +#include "chrome/browser/sessions/base_session_service_delegate.h" +#include "chrome/browser/sessions/session_command.h" +#include "chrome/browser/sessions/session_types.h" + +// Identifier for commands written to file. +static const SessionCommand::id_type kCommandSetTabWindow = 0; +// OBSOLETE Superseded by kCommandSetWindowBounds3. +// static const SessionCommand::id_type kCommandSetWindowBounds = 1; +static const SessionCommand::id_type kCommandSetTabIndexInWindow = 2; +static const SessionCommand::id_type + kCommandTabNavigationPathPrunedFromBack = 5; +static const SessionCommand::id_type kCommandUpdateTabNavigation = 6; +static const SessionCommand::id_type kCommandSetSelectedNavigationIndex = 7; +static const SessionCommand::id_type kCommandSetSelectedTabInIndex = 8; +static const SessionCommand::id_type kCommandSetWindowType = 9; +// OBSOLETE Superseded by kCommandSetWindowBounds3. Except for data migration. +// static const SessionCommand::id_type kCommandSetWindowBounds2 = 10; +static const SessionCommand::id_type + kCommandTabNavigationPathPrunedFromFront = 11; +static const SessionCommand::id_type kCommandSetPinnedState = 12; +static const SessionCommand::id_type kCommandSetExtensionAppID = 13; +static const SessionCommand::id_type kCommandSetWindowBounds3 = 14; +static const SessionCommand::id_type kCommandSetWindowAppName = 15; +static const SessionCommand::id_type kCommandTabClosed = 16; +static const SessionCommand::id_type kCommandWindowClosed = 17; +static const SessionCommand::id_type kCommandSetTabUserAgentOverride = 18; +static const SessionCommand::id_type kCommandSessionStorageAssociated = 19; +static const SessionCommand::id_type kCommandSetActiveWindow = 20; + +namespace { + +// Various payload structures. +struct ClosedPayload { + SessionID::id_type id; + int64 close_time; +}; + +struct WindowBoundsPayload2 { + SessionID::id_type window_id; + int32 x; + int32 y; + int32 w; + int32 h; + bool is_maximized; +}; + +struct WindowBoundsPayload3 { + SessionID::id_type window_id; + int32 x; + int32 y; + int32 w; + int32 h; + int32 show_state; +}; + +typedef SessionID::id_type ActiveWindowPayload; + +struct IDAndIndexPayload { + SessionID::id_type id; + int32 index; +}; + +typedef IDAndIndexPayload TabIndexInWindowPayload; + +typedef IDAndIndexPayload TabNavigationPathPrunedFromBackPayload; + +typedef IDAndIndexPayload SelectedNavigationIndexPayload; + +typedef IDAndIndexPayload SelectedTabInIndexPayload; + +typedef IDAndIndexPayload WindowTypePayload; + +typedef IDAndIndexPayload TabNavigationPathPrunedFromFrontPayload; + +struct PinnedStatePayload { + SessionID::id_type tab_id; + bool pinned_state; +}; + +// Persisted versions of ui::WindowShowState that are written to disk and can +// never change. +enum PersistedWindowShowState { + // SHOW_STATE_DEFAULT (0) never persisted. + PERSISTED_SHOW_STATE_NORMAL = 1, + PERSISTED_SHOW_STATE_MINIMIZED = 2, + PERSISTED_SHOW_STATE_MAXIMIZED = 3, + // SHOW_STATE_INACTIVE (4) never persisted. + PERSISTED_SHOW_STATE_FULLSCREEN = 5, + PERSISTED_SHOW_STATE_DETACHED_DEPRECATED = 6, + PERSISTED_SHOW_STATE_END = 6 +}; + +typedef std::map IdToSessionTab; +typedef std::map IdToSessionWindow; + +// Assert to ensure PersistedWindowShowState is updated if ui::WindowShowState +// is changed. +COMPILE_ASSERT(ui::SHOW_STATE_END == + static_cast(PERSISTED_SHOW_STATE_END), + persisted_show_state_mismatch); + +// Returns the show state to store to disk based |state|. +PersistedWindowShowState ShowStateToPersistedShowState( + ui::WindowShowState state) { + switch (state) { + case ui::SHOW_STATE_NORMAL: + return PERSISTED_SHOW_STATE_NORMAL; + case ui::SHOW_STATE_MINIMIZED: + return PERSISTED_SHOW_STATE_MINIMIZED; + case ui::SHOW_STATE_MAXIMIZED: + return PERSISTED_SHOW_STATE_MAXIMIZED; + case ui::SHOW_STATE_FULLSCREEN: + return PERSISTED_SHOW_STATE_FULLSCREEN; + + case ui::SHOW_STATE_DEFAULT: + case ui::SHOW_STATE_INACTIVE: + return PERSISTED_SHOW_STATE_NORMAL; + + case ui::SHOW_STATE_END: + break; + } + NOTREACHED(); + return PERSISTED_SHOW_STATE_NORMAL; +} + +// Lints show state values when read back from persited disk. +ui::WindowShowState PersistedShowStateToShowState(int state) { + switch (state) { + case PERSISTED_SHOW_STATE_NORMAL: + return ui::SHOW_STATE_NORMAL; + case PERSISTED_SHOW_STATE_MINIMIZED: + return ui::SHOW_STATE_MINIMIZED; + case PERSISTED_SHOW_STATE_MAXIMIZED: + return ui::SHOW_STATE_MAXIMIZED; + case PERSISTED_SHOW_STATE_FULLSCREEN: + return ui::SHOW_STATE_FULLSCREEN; + case PERSISTED_SHOW_STATE_DETACHED_DEPRECATED: + return ui::SHOW_STATE_NORMAL; + } + NOTREACHED(); + return ui::SHOW_STATE_NORMAL; +} + +// Iterates through the vector updating the selected_tab_index of each +// SessionWindow based on the actual tabs that were restored. +void UpdateSelectedTabIndex(std::vector* windows) { + for (std::vector::const_iterator i = windows->begin(); + i != windows->end(); ++i) { + // See note in SessionWindow as to why we do this. + int new_index = 0; + for (std::vector::const_iterator j = (*i)->tabs.begin(); + j != (*i)->tabs.end(); ++j) { + if ((*j)->tab_visual_index == (*i)->selected_tab_index) { + new_index = static_cast(j - (*i)->tabs.begin()); + break; + } + } + (*i)->selected_tab_index = new_index; + } +} + +// Returns the window in windows with the specified id. If a window does +// not exist, one is created. +SessionWindow* GetWindow(SessionID::id_type window_id, + IdToSessionWindow* windows) { + std::map::iterator i = windows->find(window_id); + if (i == windows->end()) { + SessionWindow* window = new SessionWindow(); + window->window_id.set_id(window_id); + (*windows)[window_id] = window; + return window; + } + return i->second; +} + +// Returns the tab with the specified id in tabs. If a tab does not exist, +// it is created. +SessionTab* GetTab(SessionID::id_type tab_id, IdToSessionTab* tabs) { + DCHECK(tabs); + std::map::iterator i = tabs->find(tab_id); + if (i == tabs->end()) { + SessionTab* tab = new SessionTab(); + tab->tab_id.set_id(tab_id); + (*tabs)[tab_id] = tab; + return tab; + } + return i->second; +} + +// Returns an iterator into navigations pointing to the navigation whose +// index matches |index|. If no navigation index matches |index|, the first +// navigation with an index > |index| is returned. +// +// This assumes the navigations are ordered by index in ascending order. +std::vector::iterator + FindClosestNavigationWithIndex( + std::vector* navigations, + int index) { + DCHECK(navigations); + for (std::vector::iterator + i = navigations->begin(); i != navigations->end(); ++i) { + if (i->index() >= index) + return i; + } + return navigations->end(); +} + +// Function used in sorting windows. Sorting is done based on window id. As +// window ids increment for each new window, this effectively sorts by creation +// time. +static bool WindowOrderSortFunction(const SessionWindow* w1, + const SessionWindow* w2) { + return w1->window_id.id() < w2->window_id.id(); +} + +// Compares the two tabs based on visual index. +static bool TabVisualIndexSortFunction(const SessionTab* t1, + const SessionTab* t2) { + const int delta = t1->tab_visual_index - t2->tab_visual_index; + return delta == 0 ? (t1->tab_id.id() < t2->tab_id.id()) : (delta < 0); +} + +// Does the following: +// . Deletes and removes any windows with no tabs. NOTE: constrained windows +// that have been dragged out are of type browser. As such, this preserves any +// dragged out constrained windows (aka popups that have been dragged out). +// . Sorts the tabs in windows with valid tabs based on the tabs +// visual order, and adds the valid windows to windows. +void SortTabsBasedOnVisualOrderAndPrune( + std::map* windows, + std::vector* valid_windows) { + std::map::iterator i = windows->begin(); + while (i != windows->end()) { + SessionWindow* window = i->second; + if (window->tabs.empty() || window->is_constrained) { + delete window; + windows->erase(i++); + } else { + // Valid window; sort the tabs and add it to the list of valid windows. + std::sort(window->tabs.begin(), window->tabs.end(), + &TabVisualIndexSortFunction); + // Otherwise, add the window such that older windows appear first. + if (valid_windows->empty()) { + valid_windows->push_back(window); + } else { + valid_windows->insert( + std::upper_bound(valid_windows->begin(), valid_windows->end(), + window, &WindowOrderSortFunction), + window); + } + ++i; + } + } +} + +// Adds tabs to their parent window based on the tab's window_id. This +// ignores tabs with no navigations. +void AddTabsToWindows(std::map* tabs, + std::map* windows) { + VLOG(1) << "AddTabsToWindws"; + VLOG(1) << "Tabs " << tabs->size() << ", windows " << windows->size(); + std::map::iterator i = tabs->begin(); + while (i != tabs->end()) { + SessionTab* tab = i->second; + if (tab->window_id.id() && !tab->navigations.empty()) { + SessionWindow* window = GetWindow(tab->window_id.id(), windows); + window->tabs.push_back(tab); + tabs->erase(i++); + + // See note in SessionTab as to why we do this. + std::vector::iterator j = + FindClosestNavigationWithIndex(&(tab->navigations), + tab->current_navigation_index); + if (j == tab->navigations.end()) { + tab->current_navigation_index = + static_cast(tab->navigations.size() - 1); + } else { + tab->current_navigation_index = + static_cast(j - tab->navigations.begin()); + } + } else { + // Never got a set tab index in window, or tabs are empty, nothing + // to do. + ++i; + } + } +} + +// Creates tabs and windows from the commands specified in |data|. The created +// tabs and windows are added to |tabs| and |windows| respectively, with the +// id of the active window set in |active_window_id|. It is up to the caller +// to delete the tabs and windows added to |tabs| and |windows|. +// +// This does NOT add any created SessionTabs to SessionWindow.tabs, that is +// done by AddTabsToWindows. +bool CreateTabsAndWindows(const std::vector& data, + std::map* tabs, + std::map* windows, + SessionID::id_type* active_window_id) { + // If the file is corrupt (command with wrong size, or unknown command), we + // still return true and attempt to restore what we we can. + VLOG(1) << "CreateTabsAndWindows"; + + for (std::vector::const_iterator i = data.begin(); + i != data.end(); ++i) { + const SessionCommand::id_type kCommandSetWindowBounds2 = 10; + const SessionCommand* command = *i; + + VLOG(1) << "Read command " << (int) command->id(); + switch (command->id()) { + case kCommandSetTabWindow: { + SessionID::id_type payload[2]; + if (!command->GetPayload(payload, sizeof(payload))) { + VLOG(1) << "Failed reading command " << command->id(); + return true; + } + GetTab(payload[1], tabs)->window_id.set_id(payload[0]); + break; + } + + // This is here for forward migration only. New data is saved with + // |kCommandSetWindowBounds3|. + case kCommandSetWindowBounds2: { + WindowBoundsPayload2 payload; + if (!command->GetPayload(&payload, sizeof(payload))) { + VLOG(1) << "Failed reading command " << command->id(); + return true; + } + GetWindow(payload.window_id, windows)->bounds.SetRect(payload.x, + payload.y, + payload.w, + payload.h); + GetWindow(payload.window_id, windows)->show_state = + payload.is_maximized ? + ui::SHOW_STATE_MAXIMIZED : ui::SHOW_STATE_NORMAL; + break; + } + + case kCommandSetWindowBounds3: { + WindowBoundsPayload3 payload; + if (!command->GetPayload(&payload, sizeof(payload))) { + VLOG(1) << "Failed reading command " << command->id(); + return true; + } + GetWindow(payload.window_id, windows)->bounds.SetRect(payload.x, + payload.y, + payload.w, + payload.h); + GetWindow(payload.window_id, windows)->show_state = + PersistedShowStateToShowState(payload.show_state); + break; + } + + case kCommandSetTabIndexInWindow: { + TabIndexInWindowPayload payload; + if (!command->GetPayload(&payload, sizeof(payload))) { + VLOG(1) << "Failed reading command " << command->id(); + return true; + } + GetTab(payload.id, tabs)->tab_visual_index = payload.index; + break; + } + + case kCommandTabClosed: + case kCommandWindowClosed: { + ClosedPayload payload; + if (!command->GetPayload(&payload, sizeof(payload))) { + VLOG(1) << "Failed reading command " << command->id(); + return true; + } + if (command->id() == kCommandTabClosed) { + delete GetTab(payload.id, tabs); + tabs->erase(payload.id); + } else { + delete GetWindow(payload.id, windows); + windows->erase(payload.id); + } + break; + } + + case kCommandTabNavigationPathPrunedFromBack: { + TabNavigationPathPrunedFromBackPayload payload; + if (!command->GetPayload(&payload, sizeof(payload))) { + VLOG(1) << "Failed reading command " << command->id(); + return true; + } + SessionTab* tab = GetTab(payload.id, tabs); + tab->navigations.erase( + FindClosestNavigationWithIndex(&(tab->navigations), payload.index), + tab->navigations.end()); + break; + } + + case kCommandTabNavigationPathPrunedFromFront: { + TabNavigationPathPrunedFromFrontPayload payload; + if (!command->GetPayload(&payload, sizeof(payload)) || + payload.index <= 0) { + VLOG(1) << "Failed reading command " << command->id(); + return true; + } + SessionTab* tab = GetTab(payload.id, tabs); + + // Update the selected navigation index. + tab->current_navigation_index = + std::max(-1, tab->current_navigation_index - payload.index); + + // And update the index of existing navigations. + for (std::vector::iterator + i = tab->navigations.begin(); + i != tab->navigations.end();) { + i->set_index(i->index() - payload.index); + if (i->index() < 0) + i = tab->navigations.erase(i); + else + ++i; + } + break; + } + + case kCommandUpdateTabNavigation: { + sessions::SerializedNavigationEntry navigation; + SessionID::id_type tab_id; + if (!RestoreUpdateTabNavigationCommand(*command, + &navigation, + &tab_id)) { + VLOG(1) << "Failed reading command " << command->id(); + return true; + } + SessionTab* tab = GetTab(tab_id, tabs); + std::vector::iterator i = + FindClosestNavigationWithIndex(&(tab->navigations), + navigation.index()); + if (i != tab->navigations.end() && i->index() == navigation.index()) + *i = navigation; + else + tab->navigations.insert(i, navigation); + break; + } + + case kCommandSetSelectedNavigationIndex: { + SelectedNavigationIndexPayload payload; + if (!command->GetPayload(&payload, sizeof(payload))) { + VLOG(1) << "Failed reading command " << command->id(); + return true; + } + GetTab(payload.id, tabs)->current_navigation_index = payload.index; + break; + } + + case kCommandSetSelectedTabInIndex: { + SelectedTabInIndexPayload payload; + if (!command->GetPayload(&payload, sizeof(payload))) { + VLOG(1) << "Failed reading command " << command->id(); + return true; + } + GetWindow(payload.id, windows)->selected_tab_index = payload.index; + break; + } + + case kCommandSetWindowType: { + WindowTypePayload payload; + if (!command->GetPayload(&payload, sizeof(payload))) { + VLOG(1) << "Failed reading command " << command->id(); + return true; + } + GetWindow(payload.id, windows)->is_constrained = false; + GetWindow(payload.id, windows)->type = + static_cast(payload.index); + break; + } + + case kCommandSetPinnedState: { + PinnedStatePayload payload; + if (!command->GetPayload(&payload, sizeof(payload))) { + VLOG(1) << "Failed reading command " << command->id(); + return true; + } + GetTab(payload.tab_id, tabs)->pinned = payload.pinned_state; + break; + } + + case kCommandSetWindowAppName: { + SessionID::id_type window_id; + std::string app_name; + if (!RestoreSetWindowAppNameCommand(*command, &window_id, &app_name)) + return true; + + GetWindow(window_id, windows)->app_name.swap(app_name); + break; + } + + case kCommandSetExtensionAppID: { + SessionID::id_type tab_id; + std::string extension_app_id; + if (!RestoreSetTabExtensionAppIDCommand(*command, + &tab_id, + &extension_app_id)) { + VLOG(1) << "Failed reading command " << command->id(); + return true; + } + + GetTab(tab_id, tabs)->extension_app_id.swap(extension_app_id); + break; + } + + case kCommandSetTabUserAgentOverride: { + SessionID::id_type tab_id; + std::string user_agent_override; + if (!RestoreSetTabUserAgentOverrideCommand( + *command, + &tab_id, + &user_agent_override)) { + return true; + } + + GetTab(tab_id, tabs)->user_agent_override.swap(user_agent_override); + break; + } + + case kCommandSessionStorageAssociated: { + scoped_ptr command_pickle(command->PayloadAsPickle()); + SessionID::id_type command_tab_id; + std::string session_storage_persistent_id; + PickleIterator iter(*command_pickle.get()); + if (!command_pickle->ReadInt(&iter, &command_tab_id) || + !command_pickle->ReadString(&iter, &session_storage_persistent_id)) + return true; + // Associate the session storage back. + GetTab(command_tab_id, tabs)->session_storage_persistent_id = + session_storage_persistent_id; + break; + } + + case kCommandSetActiveWindow: { + ActiveWindowPayload payload; + if (!command->GetPayload(&payload, sizeof(payload))) { + VLOG(1) << "Failed reading command " << command->id(); + return true; + } + *active_window_id = payload; + break; + } + + default: + // TODO(skuhne): This might call back into a callback handler to extend + // the command set for specific implementations. + VLOG(1) << "Failed reading an unknown command " << command->id(); + return true; + } + } + return true; +} + +} // namespace + +SessionCommand* CreateSetSelectedTabInWindowCommand(const SessionID& window_id, + int index) { + SelectedTabInIndexPayload payload = { 0 }; + payload.id = window_id.id(); + payload.index = index; + SessionCommand* command = new SessionCommand(kCommandSetSelectedTabInIndex, + sizeof(payload)); + memcpy(command->contents(), &payload, sizeof(payload)); + return command; +} + +SessionCommand* CreateSetTabWindowCommand(const SessionID& window_id, + const SessionID& tab_id) { + SessionID::id_type payload[] = { window_id.id(), tab_id.id() }; + SessionCommand* command = + new SessionCommand(kCommandSetTabWindow, sizeof(payload)); + memcpy(command->contents(), payload, sizeof(payload)); + return command; +} + +SessionCommand* CreateSetWindowBoundsCommand(const SessionID& window_id, + const gfx::Rect& bounds, + ui::WindowShowState show_state) { + WindowBoundsPayload3 payload = { 0 }; + payload.window_id = window_id.id(); + payload.x = bounds.x(); + payload.y = bounds.y(); + payload.w = bounds.width(); + payload.h = bounds.height(); + payload.show_state = ShowStateToPersistedShowState(show_state); + SessionCommand* command = new SessionCommand(kCommandSetWindowBounds3, + sizeof(payload)); + memcpy(command->contents(), &payload, sizeof(payload)); + return command; +} + +SessionCommand* CreateSetTabIndexInWindowCommand(const SessionID& tab_id, + int new_index) { + TabIndexInWindowPayload payload = { 0 }; + payload.id = tab_id.id(); + payload.index = new_index; + SessionCommand* command = + new SessionCommand(kCommandSetTabIndexInWindow, sizeof(payload)); + memcpy(command->contents(), &payload, sizeof(payload)); + return command; +} + +SessionCommand* CreateTabClosedCommand(const SessionID::id_type tab_id) { + ClosedPayload payload; + // Because of what appears to be a compiler bug setting payload to {0} doesn't + // set the padding to 0, resulting in Purify reporting an UMR when we write + // the structure to disk. To avoid this we explicitly memset the struct. + memset(&payload, 0, sizeof(payload)); + payload.id = tab_id; + payload.close_time = base::Time::Now().ToInternalValue(); + SessionCommand* command = + new SessionCommand(kCommandTabClosed, sizeof(payload)); + memcpy(command->contents(), &payload, sizeof(payload)); + return command; +} + +SessionCommand* CreateWindowClosedCommand(const SessionID::id_type window_id) { + ClosedPayload payload; + // See comment in CreateTabClosedCommand as to why we do this. + memset(&payload, 0, sizeof(payload)); + payload.id = window_id; + payload.close_time = base::Time::Now().ToInternalValue(); + SessionCommand* command = + new SessionCommand(kCommandWindowClosed, sizeof(payload)); + memcpy(command->contents(), &payload, sizeof(payload)); + return command; +} + +SessionCommand* CreateSetSelectedNavigationIndexCommand(const SessionID& tab_id, + int index) { + SelectedNavigationIndexPayload payload = { 0 }; + payload.id = tab_id.id(); + payload.index = index; + SessionCommand* command = new SessionCommand( + kCommandSetSelectedNavigationIndex, sizeof(payload)); + memcpy(command->contents(), &payload, sizeof(payload)); + return command; +} + +SessionCommand* CreateSetWindowTypeCommand(const SessionID& window_id, + SessionWindow::WindowType type) { + WindowTypePayload payload = { 0 }; + payload.id = window_id.id(); + payload.index = static_cast(type); + SessionCommand* command = new SessionCommand( + kCommandSetWindowType, sizeof(payload)); + memcpy(command->contents(), &payload, sizeof(payload)); + return command; +} + +SessionCommand* CreatePinnedStateCommand(const SessionID& tab_id, + bool is_pinned) { + PinnedStatePayload payload = { 0 }; + payload.tab_id = tab_id.id(); + payload.pinned_state = is_pinned; + SessionCommand* command = + new SessionCommand(kCommandSetPinnedState, sizeof(payload)); + memcpy(command->contents(), &payload, sizeof(payload)); + return command; +} + +SessionCommand* CreateSessionStorageAssociatedCommand( + const SessionID& tab_id, + const std::string& session_storage_persistent_id) { + Pickle pickle; + pickle.WriteInt(tab_id.id()); + pickle.WriteString(session_storage_persistent_id); + return new SessionCommand(kCommandSessionStorageAssociated, pickle); +} + +SessionCommand* CreateSetActiveWindowCommand(const SessionID& window_id) { + ActiveWindowPayload payload = 0; + payload = window_id.id(); + SessionCommand* command = + new SessionCommand(kCommandSetActiveWindow, sizeof(payload)); + memcpy(command->contents(), &payload, sizeof(payload)); + return command; +} + +SessionCommand* CreateTabNavigationPathPrunedFromBackCommand( + const SessionID& tab_id, + int count) { + TabNavigationPathPrunedFromBackPayload payload = { 0 }; + payload.id = tab_id.id(); + payload.index = count; + SessionCommand* command = + new SessionCommand(kCommandTabNavigationPathPrunedFromBack, + sizeof(payload)); + memcpy(command->contents(), &payload, sizeof(payload)); + return command; +} + +SessionCommand* CreateTabNavigationPathPrunedFromFrontCommand( + const SessionID& tab_id, + int count) { + TabNavigationPathPrunedFromFrontPayload payload = { 0 }; + payload.id = tab_id.id(); + payload.index = count; + SessionCommand* command = + new SessionCommand(kCommandTabNavigationPathPrunedFromFront, + sizeof(payload)); + memcpy(command->contents(), &payload, sizeof(payload)); + return command; +} + +SessionCommand* CreateUpdateTabNavigationCommand( + const SessionID& tab_id, + const sessions::SerializedNavigationEntry& navigation) { + return ::CreateUpdateTabNavigationCommand(kCommandUpdateTabNavigation, + tab_id.id(), + navigation); +} + +SessionCommand* CreateSetTabExtensionAppIDCommand( + const SessionID& tab_id, + const std::string& extension_id) { + return ::CreateSetTabExtensionAppIDCommand(kCommandSetExtensionAppID, + tab_id.id(), + extension_id); +} + +SessionCommand* CreateSetTabUserAgentOverrideCommand( + const SessionID& tab_id, + const std::string& user_agent_override) { + return ::CreateSetTabUserAgentOverrideCommand(kCommandSetTabUserAgentOverride, + tab_id.id(), + user_agent_override); +} + +SessionCommand* CreateSetWindowAppNameCommand( + const SessionID& window_id, + const std::string& app_name) { + return ::CreateSetWindowAppNameCommand(kCommandSetWindowAppName, + window_id.id(), + app_name); +} + +bool ReplacePendingCommand(SessionCommand* command, + std::vector& pending_commands) { + // We optimize page navigations, which can happen quite frequently and + // is expensive. And activation is like Highlander, there can only be one! + if (command->id() != kCommandUpdateTabNavigation && + command->id() != kCommandSetActiveWindow) { + return false; + } + for (std::vector::reverse_iterator i = + pending_commands.rbegin(); i != pending_commands.rend(); ++i) { + SessionCommand* existing_command = *i; + if (command->id() == kCommandUpdateTabNavigation && + existing_command->id() == kCommandUpdateTabNavigation) { + scoped_ptr command_pickle(command->PayloadAsPickle()); + PickleIterator iterator(*command_pickle); + SessionID::id_type command_tab_id; + int command_nav_index; + if (!command_pickle->ReadInt(&iterator, &command_tab_id) || + !command_pickle->ReadInt(&iterator, &command_nav_index)) { + return false; + } + SessionID::id_type existing_tab_id; + int existing_nav_index; + { + // Creating a pickle like this means the Pickle references the data from + // the command. Make sure we delete the pickle before the command, else + // the pickle references deleted memory. + scoped_ptr existing_pickle(existing_command->PayloadAsPickle()); + iterator = PickleIterator(*existing_pickle); + if (!existing_pickle->ReadInt(&iterator, &existing_tab_id) || + !existing_pickle->ReadInt(&iterator, &existing_nav_index)) { + return false; + } + } + if (existing_tab_id == command_tab_id && + existing_nav_index == command_nav_index) { + // existing_command is an update for the same tab/index pair. Replace + // it with the new one. We need to add to the end of the list just in + // case there is a prune command after the update command. + delete existing_command; + pending_commands.erase(i.base() - 1); + pending_commands.push_back(command); + return true; + } + return false; + } + if (command->id() == kCommandSetActiveWindow && + existing_command->id() == kCommandSetActiveWindow) { + *i = command; + delete existing_command; + return true; + } + } + return false; +} + +bool IsClosingCommand(SessionCommand* command) { + return command->id() == kCommandTabClosed || + command->id() == kCommandWindowClosed; +} + +void RestoreSessionFromCommands(const std::vector& commands, + std::vector* valid_windows, + SessionID::id_type* active_window_id) { + std::map tabs; + std::map windows; + + VLOG(1) << "RestoreSessionFromCommands " << commands.size(); + if (CreateTabsAndWindows(commands, &tabs, &windows, active_window_id)) { + AddTabsToWindows(&tabs, &windows); + SortTabsBasedOnVisualOrderAndPrune(&windows, valid_windows); + UpdateSelectedTabIndex(valid_windows); + } + STLDeleteValues(&tabs); + // Don't delete contents of windows, that is done by the caller as all + // valid windows are added to valid_windows. +} diff --git a/chrome/browser/sessions/session_service_commands.h b/chrome/browser/sessions/session_service_commands.h new file mode 100644 index 000000000000..b91b95727303 --- /dev/null +++ b/chrome/browser/sessions/session_service_commands.h @@ -0,0 +1,84 @@ +// Copyright 2014 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. + +#ifndef CHROME_BROWSER_SESSIONS_SESSION_SERVICE_COMMANDS_H_ +#define CHROME_BROWSER_SESSIONS_SESSION_SERVICE_COMMANDS_H_ + +#include +#include + +#include "base/basictypes.h" +#include "base/callback.h" +#include "base/memory/scoped_vector.h" +#include "base/memory/weak_ptr.h" +#include "base/task/cancelable_task_tracker.h" +#include "chrome/browser/sessions/base_session_service.h" +#include "chrome/browser/sessions/session_types.h" +#include "ui/base/ui_base_types.h" + +class SessionCommand; + +// The following functions create sequentialized change commands which are +// used to reconstruct the current/previous session state. +// It is up to the caller to delete the returned SessionCommand* object. +SessionCommand* CreateSetSelectedTabInWindowCommand( + const SessionID& window_id, + int index); +SessionCommand* CreateSetTabWindowCommand(const SessionID& window_id, + const SessionID& tab_id); +SessionCommand* CreateSetWindowBoundsCommand(const SessionID& window_id, + const gfx::Rect& bounds, + ui::WindowShowState show_state); +SessionCommand* CreateSetTabIndexInWindowCommand(const SessionID& tab_id, + int new_index); +SessionCommand* CreateTabClosedCommand(SessionID::id_type tab_id); +SessionCommand* CreateWindowClosedCommand(SessionID::id_type tab_id); +SessionCommand* CreateSetSelectedNavigationIndexCommand( + const SessionID& tab_id, + int index); +SessionCommand* CreateSetWindowTypeCommand(const SessionID& window_id, + SessionWindow::WindowType type); +SessionCommand* CreatePinnedStateCommand(const SessionID& tab_id, + bool is_pinned); +SessionCommand* CreateSessionStorageAssociatedCommand( + const SessionID& tab_id, + const std::string& session_storage_persistent_id); +SessionCommand* CreateSetActiveWindowCommand(const SessionID& window_id); +SessionCommand* CreateTabNavigationPathPrunedFromBackCommand( + const SessionID& tab_id, + int count); +SessionCommand* CreateTabNavigationPathPrunedFromFrontCommand( + const SessionID& tab_id, + int count); +SessionCommand* CreateUpdateTabNavigationCommand( + const SessionID& tab_id, + const sessions::SerializedNavigationEntry& navigation); +SessionCommand* CreateSetTabExtensionAppIDCommand( + const SessionID& tab_id, + const std::string& extension_id); +SessionCommand* CreateSetTabUserAgentOverrideCommand( + const SessionID& tab_id, + const std::string& user_agent_override); +SessionCommand* CreateSetWindowAppNameCommand(const SessionID& window_id, + const std::string& app_name); + +// Searches for a pending command in |pending_commands| that can be replaced +// with |command|. If one is found, pending command is removed, command is +// added to the pending commands and true is returned. +bool ReplacePendingCommand(SessionCommand* command, + std::vector& pending_commands); + +// Returns true if provided |command| either closes a window or a tab. +bool IsClosingCommand(SessionCommand* command); + +// Converts a list of commands into SessionWindows. On return any valid +// windows are added to valid_windows. It is up to the caller to delete +// the windows added to valid_windows. |active_window_id| will be set with the +// id of the last active window, but it's only valid when this id corresponds +// to the id of one of the windows in valid_windows. +void RestoreSessionFromCommands(const std::vector& commands, + std::vector* valid_windows, + SessionID::id_type* active_window_id); + +#endif // CHROME_BROWSER_SESSIONS_SESSION_SERVICE_COMMANDS_H_ diff --git a/chrome/browser/sessions/session_service_test_helper.cc b/chrome/browser/sessions/session_service_test_helper.cc index 2c2fc404ba7f..93c5e3518afd 100644 --- a/chrome/browser/sessions/session_service_test_helper.cc +++ b/chrome/browser/sessions/session_service_test_helper.cc @@ -61,8 +61,8 @@ void SessionServiceTestHelper::ReadWindows( Time last_time; ScopedVector read_commands; backend()->ReadLastSessionCommandsImpl(&(read_commands.get())); - service()->RestoreSessionFromCommands( - read_commands.get(), windows, active_window_id); + RestoreSessionFromCommands(read_commands.get(), windows, active_window_id); + service()->RemoveUnusedRestoreWindows(windows); } void SessionServiceTestHelper::AssertTabEquals(const SessionID& window_id, diff --git a/chrome/browser/sessions/session_service_unittest.cc b/chrome/browser/sessions/session_service_unittest.cc index db6da824f122..e77a970164fa 100644 --- a/chrome/browser/sessions/session_service_unittest.cc +++ b/chrome/browser/sessions/session_service_unittest.cc @@ -61,8 +61,9 @@ class SessionServiceTest : public BrowserWithTestWindowTest, 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); @@ -155,8 +156,9 @@ class SessionServiceTest : public BrowserWithTestWindowTest, 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); @@ -201,7 +203,7 @@ 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); @@ -354,8 +356,9 @@ TEST_F(SessionServiceTest, WindowWithNoTabsGetsPruned) { 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); @@ -449,8 +452,9 @@ TEST_F(SessionServiceTest, WindowCloseCommittedAfterNavigate) { SessionID tab2_id; ASSERT_NE(window2_id.id(), window_id.id()); - service()->SetWindowType( - window2_id, Browser::TYPE_TABBED, SessionService::TYPE_NORMAL); + service()->SetWindowType(window2_id, + Browser::TYPE_TABBED, + SessionService::TYPE_NORMAL); service()->SetWindowBounds(window2_id, window_bounds, ui::SHOW_STATE_NORMAL); @@ -492,8 +496,9 @@ TEST_F(SessionServiceTest, IgnorePopups) { 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); @@ -532,8 +537,9 @@ TEST_F(SessionServiceTest, RestoreApp) { 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); @@ -556,7 +562,7 @@ TEST_F(SessionServiceTest, RestoreApp) { 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); @@ -570,7 +576,7 @@ TEST_F(SessionServiceTest, RestoreApp) { 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]; @@ -907,10 +913,8 @@ TEST_F(SessionServiceTest, RestoreActivation1) { 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)); + service()->ScheduleCommand(CreateSetActiveWindowCommand(window_id)); ScopedVector windows; SessionID::id_type active_window_id = 0; @@ -930,12 +934,9 @@ TEST_F(SessionServiceTest, RestoreActivation2) { 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)); + service()->ScheduleCommand(CreateSetActiveWindowCommand(window_id)); + service()->ScheduleCommand(CreateSetActiveWindowCommand(window2_id)); ScopedVector windows; SessionID::id_type active_window_id = 0; diff --git a/chrome/browser/sessions/session_service_utils.cc b/chrome/browser/sessions/session_service_utils.cc new file mode 100644 index 000000000000..4be56e4fa75c --- /dev/null +++ b/chrome/browser/sessions/session_service_utils.cc @@ -0,0 +1,27 @@ +// Copyright 2014 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 "chrome/browser/sessions/session_service_utils.h" + +SessionWindow::WindowType WindowTypeForBrowserType(Browser::Type type) { + switch (type) { + case Browser::TYPE_POPUP: + return SessionWindow::TYPE_POPUP; + case Browser::TYPE_TABBED: + return SessionWindow::TYPE_TABBED; + } + NOTREACHED(); + return SessionWindow::TYPE_TABBED; +} + +Browser::Type BrowserTypeForWindowType(SessionWindow::WindowType type) { + switch (type) { + case SessionWindow::TYPE_POPUP: + return Browser::TYPE_POPUP; + case SessionWindow::TYPE_TABBED: + return Browser::TYPE_TABBED; + } + NOTREACHED(); + return Browser::TYPE_TABBED; +} diff --git a/chrome/browser/sessions/session_service_utils.h b/chrome/browser/sessions/session_service_utils.h new file mode 100644 index 000000000000..2fdcba05a9ba --- /dev/null +++ b/chrome/browser/sessions/session_service_utils.h @@ -0,0 +1,15 @@ +// Copyright 2014 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. + +#ifndef CHROME_BROWSER_SESSIONS_SESSION_SERVICE_UTILS_H_ +#define CHROME_BROWSER_SESSIONS_SESSION_SERVICE_UTILS_H_ + +#include "chrome/browser/sessions/session_types.h" +#include "chrome/browser/ui/browser.h" + +// Convert back/forward between the Browser and SessionService window types. +SessionWindow::WindowType WindowTypeForBrowserType(Browser::Type type); +Browser::Type BrowserTypeForWindowType(SessionWindow::WindowType type); + +#endif // CHROME_BROWSER_SESSIONS_SESSION_SERVICE_UTILS_H_ diff --git a/chrome/browser/sessions/session_types.cc b/chrome/browser/sessions/session_types.cc index a7ec0221734f..5664743fa96a 100644 --- a/chrome/browser/sessions/session_types.cc +++ b/chrome/browser/sessions/session_types.cc @@ -59,7 +59,7 @@ sync_pb::SessionTab SessionTab::ToSyncData() const { SessionWindow::SessionWindow() : selected_tab_index(-1), - type(Browser::TYPE_TABBED), + type(TYPE_TABBED), is_constrained(true), show_state(ui::SHOW_STATE_DEFAULT) { } @@ -73,11 +73,11 @@ sync_pb::SessionWindow SessionWindow::ToSyncData() const { sync_data.set_window_id(window_id.id()); sync_data.set_selected_tab_index(selected_tab_index); switch (type) { - case Browser::TYPE_TABBED: + case SessionWindow::TYPE_TABBED: sync_data.set_browser_type( sync_pb::SessionWindow_BrowserType_TYPE_TABBED); break; - case Browser::TYPE_POPUP: + case SessionWindow::TYPE_POPUP: sync_data.set_browser_type( sync_pb::SessionWindow_BrowserType_TYPE_POPUP); break; diff --git a/chrome/browser/sessions/session_types.h b/chrome/browser/sessions/session_types.h index 35b4d29bae78..3ab53ff70fbb 100644 --- a/chrome/browser/sessions/session_types.h +++ b/chrome/browser/sessions/session_types.h @@ -109,6 +109,13 @@ struct SessionWindow { SessionWindow(); ~SessionWindow(); + // Possible window types which can be stored here. Note that these values will + // be written out to disc via session commands. + enum WindowType { + TYPE_TABBED = 0, + TYPE_POPUP = 1 + }; + // Convert this object into its sync protocol buffer equivalent. Note that // not all fields are synced here, because they don't all make sense or // translate when restoring a SessionWindow on another device. @@ -129,10 +136,9 @@ struct SessionWindow { // tabs. int selected_tab_index; - // Type of the browser. Currently we only store browsers of type - // TYPE_TABBED and TYPE_POPUP. - // This would be Browser::Type, but that would cause a circular dependency. - int type; + // Type of the window. Note: This type is used to determine if the window gets + // saved or not. + WindowType type; // If true, the window is constrained. // diff --git a/chrome/browser/sync/glue/session_sync_test_helper.cc b/chrome/browser/sync/glue/session_sync_test_helper.cc index 29fe6ab1e98d..8be02d5ede80 100644 --- a/chrome/browser/sync/glue/session_sync_test_helper.cc +++ b/chrome/browser/sync/glue/session_sync_test_helper.cc @@ -69,7 +69,7 @@ void SessionSyncTestHelper::VerifySyncedSession( FAIL(); ASSERT_EQ(win_iter->size(), win_ptr->tabs.size()); ASSERT_EQ(0, win_ptr->selected_tab_index); - ASSERT_EQ(1, win_ptr->type); + ASSERT_EQ(SessionWindow::TYPE_TABBED, win_ptr->type); int j = 0; for (std::vector::const_iterator tab_iter = (*win_iter).begin(); tab_iter != (*win_iter).end(); ++tab_iter, ++j) { diff --git a/chrome/browser/sync/sessions/sessions_sync_manager.cc b/chrome/browser/sync/sessions/sessions_sync_manager.cc index 0a92ddd34176..05bc92690331 100644 --- a/chrome/browser/sync/sessions/sessions_sync_manager.cc +++ b/chrome/browser/sync/sessions/sessions_sync_manager.cc @@ -740,11 +740,13 @@ void SessionsSyncManager::BuildSyncedSessionFromSpecifics( if (specifics.has_selected_tab_index()) session_window->selected_tab_index = specifics.selected_tab_index(); if (specifics.has_browser_type()) { + // TODO(skuhne): Sync data writes |BrowserType| not + // |SessionWindow::WindowType|. This should get changed. if (specifics.browser_type() == sync_pb::SessionWindow_BrowserType_TYPE_TABBED) { - session_window->type = 1; + session_window->type = SessionWindow::TYPE_TABBED; } else { - session_window->type = 2; + session_window->type = SessionWindow::TYPE_POPUP; } } session_window->timestamp = mtime; diff --git a/chrome/browser/sync/sessions/sessions_sync_manager_unittest.cc b/chrome/browser/sync/sessions/sessions_sync_manager_unittest.cc index 08d1526efabf..59dafe7ce67a 100644 --- a/chrome/browser/sync/sessions/sessions_sync_manager_unittest.cc +++ b/chrome/browser/sync/sessions/sessions_sync_manager_unittest.cc @@ -335,7 +335,7 @@ TEST_F(SessionsSyncManagerTest, PopulateSessionWindow) { tag, window_s, base::Time(), session->windows[0]); ASSERT_EQ(1U, session->windows[0]->tabs.size()); ASSERT_EQ(1, session->windows[0]->selected_tab_index); - ASSERT_EQ(1, session->windows[0]->type); + ASSERT_EQ(SessionWindow::TYPE_TABBED, session->windows[0]->type); ASSERT_EQ(1U, manager()->session_tracker_.num_synced_sessions()); ASSERT_EQ(1U, manager()->session_tracker_.num_synced_tabs(std::string("tag"))); diff --git a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model_unittest.cc b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model_unittest.cc index 3236754ac400..f6b97ae6d40b 100644 --- a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model_unittest.cc +++ b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model_unittest.cc @@ -261,8 +261,9 @@ TEST_F(RecentTabsSubMenuModelTest, SessionServiceFactory::SetForTestProfile(profile(), session_service); SessionID tab_id; SessionID window_id; - session_service->SetWindowType( - window_id, Browser::TYPE_TABBED, SessionService::TYPE_NORMAL); + session_service->SetWindowType(window_id, + Browser::TYPE_TABBED, + SessionService::TYPE_NORMAL); session_service->SetTabWindow(window_id, tab_id); session_service->SetTabIndexInWindow(window_id, tab_id, 0); session_service->SetSelectedTabInWindow(window_id, 0); diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 85367b34b922..fc5f1ba9a015 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -1106,9 +1106,13 @@ 'browser/services/gcm/push_messaging_service_impl.h', 'browser/sessions/base_session_service.cc', 'browser/sessions/base_session_service.h', + 'browser/sessions/base_session_service_commands.cc', + 'browser/sessions/base_session_service_commands.h', 'browser/sessions/base_session_service_delegate_impl.cc', 'browser/sessions/base_session_service_delegate_impl.h', 'browser/sessions/base_session_service_delegate.h', + 'browser/sessions/session_service_commands.cc', + 'browser/sessions/session_service_commands.h', 'browser/sessions/session_data_deleter.cc', 'browser/sessions/session_data_deleter.h', 'browser/sessions/session_restore_android.cc', @@ -1884,6 +1888,8 @@ 'browser/sessions/session_service.h', 'browser/sessions/session_service_factory.cc', 'browser/sessions/session_service_factory.h', + 'browser/sessions/session_service_utils.cc', + 'browser/sessions/session_service_utils.h', ], 'chrome_browser_android_sources': [ 'browser/metrics/android_metrics_provider.cc', -- 2.11.4.GIT