Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3430)

Unified Diff: chrome/browser/sessions/tab_restore_service_helper.cc

Issue 10989027: Split TabRestoreService into InMemoryTRS and PersistentTRS (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: GYP out InMemoryTRS on non-Android and fix incorrect comments Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/sessions/tab_restore_service_helper.cc
diff --git a/chrome/browser/sessions/tab_restore_service.cc b/chrome/browser/sessions/tab_restore_service_helper.cc
similarity index 33%
copy from chrome/browser/sessions/tab_restore_service.cc
copy to chrome/browser/sessions/tab_restore_service_helper.cc
index 4003edb3ad7f707fa978dfab25a33896f38fcf50..27e841a47e266f2d474a5eb2da6a04e4a5d4a25b 100644
--- a/chrome/browser/sessions/tab_restore_service.cc
+++ b/chrome/browser/sessions/tab_restore_service_helper.cc
@@ -2,24 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "chrome/browser/sessions/tab_restore_service.h"
+#include "chrome/browser/sessions/tab_restore_service_helper.h"
#include <algorithm>
#include <iterator>
-#include <map>
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/callback.h"
-#include "base/memory/scoped_vector.h"
+#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/stl_util.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/tab_helper.h"
#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/sessions/session_command.h"
-#include "chrome/browser/sessions/session_service.h"
-#include "chrome/browser/sessions/session_service_factory.h"
#include "chrome/browser/sessions/session_types.h"
#include "chrome/browser/sessions/tab_restore_service_delegate.h"
#include "chrome/browser/sessions/tab_restore_service_observer.h"
@@ -31,139 +24,16 @@
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/browser/session_storage_namespace.h"
-using base::Time;
using content::NavigationController;
using content::NavigationEntry;
using content::WebContents;
-// TimeFactory-----------------------------------------------------------------
-
-TabRestoreService::TimeFactory::~TimeFactory() {}
-
-// Entry ----------------------------------------------------------------------
-
-// ID of the next Entry.
-static SessionID::id_type next_entry_id = 1;
-
-TabRestoreService::Entry::Entry()
- : id(next_entry_id++),
- type(TAB),
- from_last_session(false) {}
-
-TabRestoreService::Entry::Entry(Type type)
- : id(next_entry_id++),
- type(type),
- from_last_session(false) {}
-
-TabRestoreService::Entry::~Entry() {}
-
-// TabRestoreService ----------------------------------------------------------
-
-// static
-const size_t TabRestoreService::kMaxEntries = 25;
-
-// Identifier for commands written to file.
-// The ordering in the file is as follows:
-// . When the user closes a tab a command of type
-// kCommandSelectedNavigationInTab is written identifying the tab and
-// the selected index, then a kCommandPinnedState command if the tab was
-// pinned and kCommandSetExtensionAppID if the tab has an app id and
-// the user agent override if it was using one. This is
-// followed by any number of kCommandUpdateTabNavigation commands (1 per
-// navigation entry).
-// . When the user closes a window a kCommandSelectedNavigationInTab command
-// is written out and followed by n tab closed sequences (as previoulsy
-// described).
-// . When the user restores an entry a command of type kCommandRestoredEntry
-// is written.
-static const SessionCommand::id_type kCommandUpdateTabNavigation = 1;
-static const SessionCommand::id_type kCommandRestoredEntry = 2;
-static const SessionCommand::id_type kCommandWindow = 3;
-static const SessionCommand::id_type kCommandSelectedNavigationInTab = 4;
-static const SessionCommand::id_type kCommandPinnedState = 5;
-static const SessionCommand::id_type kCommandSetExtensionAppID = 6;
-static const SessionCommand::id_type kCommandSetWindowAppName = 7;
-static const SessionCommand::id_type kCommandSetTabUserAgentOverride = 8;
-
-// Number of entries (not commands) before we clobber the file and write
-// everything.
-static const int kEntriesPerReset = 40;
-
namespace {
-// Payload structures.
-
-typedef int32 RestoredEntryPayload;
-
-// Payload used for the start of a window close. This is the old struct that is
-// used for backwards compat when it comes to reading the session files. This
-// struct must be POD, because we memset the contents.
-struct WindowPayload {
- SessionID::id_type window_id;
- int32 selected_tab_index;
- int32 num_tabs;
-};
-
-// Payload used for the start of a tab close. This is the old struct that is
-// used for backwards compat when it comes to reading the session files.
-struct SelectedNavigationInTabPayload {
- SessionID::id_type id;
- int32 index;
-};
-
-// Payload used for the start of a window close. This struct must be POD,
-// because we memset the contents.
-struct WindowPayload2 : WindowPayload {
- int64 timestamp;
-};
-
-// Payload used for the start of a tab close.
-struct SelectedNavigationInTabPayload2 : SelectedNavigationInTabPayload {
- int64 timestamp;
-};
-
-// Only written if the tab is pinned.
-typedef bool PinnedStatePayload;
-
-typedef std::map<SessionID::id_type, TabRestoreService::Entry*> IDToEntry;
-
-// If |id_to_entry| contains an entry for |id| the corresponding entry is
-// deleted and removed from both |id_to_entry| and |entries|. This is used
-// when creating entries from the backend file.
-void RemoveEntryByID(SessionID::id_type id,
- IDToEntry* id_to_entry,
- std::vector<TabRestoreService::Entry*>* entries) {
- // Look for the entry in the map. If it is present, erase it from both
- // collections and return.
- IDToEntry::iterator i = id_to_entry->find(id);
- if (i != id_to_entry->end()) {
- entries->erase(std::find(entries->begin(), entries->end(), i->second));
- delete i->second;
- id_to_entry->erase(i);
- return;
- }
-
- // Otherwise, loop over all items in the map and see if any of the Windows
- // have Tabs with the |id|.
- for (IDToEntry::iterator i = id_to_entry->begin(); i != id_to_entry->end();
- ++i) {
- if (i->second->type == TabRestoreService::WINDOW) {
- TabRestoreService::Window* window =
- static_cast<TabRestoreService::Window*>(i->second);
- std::vector<TabRestoreService::Tab>::iterator j = window->tabs.begin();
- for ( ; j != window->tabs.end(); ++j) {
- // If the ID matches one of this window's tabs, remove it from the list.
- if ((*j).id == id) {
- window->tabs.erase(j);
- return;
- }
- }
- }
- }
-}
-
void RecordAppLaunch(Profile* profile, const TabRestoreService::Tab& tab) {
+#if !defined(OS_ANDROID)
GURL url = tab.navigations.at(tab.current_navigation_index).virtual_url();
DCHECK(profile->GetExtensionService());
if (!profile->GetExtensionService()->IsInstalledApp(url))
@@ -171,56 +41,60 @@ void RecordAppLaunch(Profile* profile, const TabRestoreService::Tab& tab) {
AppLauncherHandler::RecordAppLaunchType(
extension_misc::APP_LAUNCH_NTP_RECENTLY_CLOSED);
+#endif // !defined(OS_ANDROID)
}
} // namespace
-TabRestoreService::Tab::Tab()
- : Entry(TAB),
- current_navigation_index(-1),
- browser_id(0),
- tabstrip_index(-1),
- pinned(false) {
-}
+// TabRestoreServiceHelper::Observer -------------------------------------------
-TabRestoreService::Tab::~Tab() {
-}
+TabRestoreServiceHelper::Observer::~Observer() {}
-TabRestoreService::Window::Window() : Entry(WINDOW), selected_tab_index(-1) {
-}
+void TabRestoreServiceHelper::Observer::OnClearEntries() {}
-TabRestoreService::Window::~Window() {
+void TabRestoreServiceHelper::Observer::OnRestoreEntryById(
+ SessionID::id_type id,
+ Entries::const_iterator entry_iterator) {
}
-TabRestoreService::TabRestoreService(Profile* profile,
+void TabRestoreServiceHelper::Observer::OnAddEntry() {}
+
+// TabRestoreServiceHelper -----------------------------------------------------
+
+const size_t TabRestoreServiceHelper::kMaxEntries = 25;
+
+TabRestoreServiceHelper::TabRestoreServiceHelper(
+ TabRestoreService* tab_restore_service,
+ Observer* observer,
+ Profile* profile,
TabRestoreService::TimeFactory* time_factory)
- : BaseSessionService(BaseSessionService::TAB_RESTORE, profile,
- FilePath()),
- load_state_(NOT_LOADED),
+ : tab_restore_service_(tab_restore_service),
+ observer_(observer),
+ profile_(profile),
restoring_(false),
- entries_to_write_(0),
- entries_written_(0),
time_factory_(time_factory) {
+ DCHECK(tab_restore_service_);
}
-TabRestoreService::~TabRestoreService() {
+TabRestoreServiceHelper::~TabRestoreServiceHelper() {
FOR_EACH_OBSERVER(TabRestoreServiceObserver, observer_list_,
- TabRestoreServiceDestroyed(this));
+ TabRestoreServiceDestroyed(tab_restore_service_));
STLDeleteElements(&entries_);
- STLDeleteElements(&staging_entries_);
- time_factory_ = NULL;
}
-void TabRestoreService::AddObserver(TabRestoreServiceObserver* observer) {
+void TabRestoreServiceHelper::AddObserver(
+ TabRestoreServiceObserver* observer) {
observer_list_.AddObserver(observer);
}
-void TabRestoreService::RemoveObserver(TabRestoreServiceObserver* observer) {
+void TabRestoreServiceHelper::RemoveObserver(
+ TabRestoreServiceObserver* observer) {
observer_list_.RemoveObserver(observer);
}
-void TabRestoreService::CreateHistoricalTab(content::WebContents* contents,
- int index) {
+void TabRestoreServiceHelper::CreateHistoricalTab(
+ content::WebContents* contents,
+ int index) {
if (restoring_)
return;
@@ -237,7 +111,8 @@ void TabRestoreService::CreateHistoricalTab(content::WebContents* contents,
AddEntry(local_tab.release(), true, true);
}
-void TabRestoreService::BrowserClosing(TabRestoreServiceDelegate* delegate) {
+void TabRestoreServiceHelper::BrowserClosing(
+ TabRestoreServiceDelegate* delegate) {
closing_delegates_.insert(delegate);
scoped_ptr<Window> window(new Window());
@@ -276,33 +151,23 @@ void TabRestoreService::BrowserClosing(TabRestoreServiceDelegate* delegate) {
}
}
-void TabRestoreService::BrowserClosed(TabRestoreServiceDelegate* delegate) {
+void TabRestoreServiceHelper::BrowserClosed(
+ TabRestoreServiceDelegate* delegate) {
closing_delegates_.erase(delegate);
}
-void TabRestoreService::ClearEntries() {
- // Mark all the tabs as closed so that we don't attempt to restore them.
- for (Entries::iterator i = entries_.begin(); i != entries_.end(); ++i)
- ScheduleCommand(CreateRestoredEntryCommand((*i)->id));
-
- entries_to_write_ = 0;
-
- // Schedule a pending reset so that we nuke the file on next write.
- set_pending_reset(true);
-
- // Schedule a command, otherwise if there are no pending commands Save does
- // nothing.
- ScheduleCommand(CreateRestoredEntryCommand(1));
-
+void TabRestoreServiceHelper::ClearEntries() {
+ if (observer_)
+ observer_->OnClearEntries();
STLDeleteElements(&entries_);
NotifyTabsChanged();
}
-const TabRestoreService::Entries& TabRestoreService::entries() const {
+const TabRestoreService::Entries& TabRestoreServiceHelper::entries() const {
return entries_;
}
-void TabRestoreService::RestoreMostRecentEntry(
+void TabRestoreServiceHelper::RestoreMostRecentEntry(
TabRestoreServiceDelegate* delegate) {
if (entries_.empty())
return;
@@ -310,14 +175,14 @@ void TabRestoreService::RestoreMostRecentEntry(
RestoreEntryById(delegate, entries_.front()->id, UNKNOWN);
}
-TabRestoreService::Tab* TabRestoreService::RemoveTabEntryById(
+TabRestoreService::Tab* TabRestoreServiceHelper::RemoveTabEntryById(
SessionID::id_type id) {
Entries::iterator i = GetEntryIteratorById(id);
if (i == entries_.end())
return NULL;
Entry* entry = *i;
- if (entry->type != TAB)
+ if (entry->type != TabRestoreService::TAB)
return NULL;
Tab* tab = static_cast<Tab*>(entry);
@@ -325,43 +190,37 @@ TabRestoreService::Tab* TabRestoreService::RemoveTabEntryById(
return tab;
}
-void TabRestoreService::RestoreEntryById(TabRestoreServiceDelegate* delegate,
- SessionID::id_type id,
- WindowOpenDisposition disposition) {
- Entries::iterator i = GetEntryIteratorById(id);
- if (i == entries_.end()) {
+void TabRestoreServiceHelper::RestoreEntryById(
+ TabRestoreServiceDelegate* delegate,
+ SessionID::id_type id,
+ WindowOpenDisposition disposition) {
+ Entries::iterator entry_iterator = GetEntryIteratorById(id);
+ if (entry_iterator == entries_.end())
// Don't hoark here, we allow an invalid id.
return;
- }
-
- size_t index = 0;
- for (Entries::iterator j = entries_.begin(); j != i && j != entries_.end();
- ++j, ++index) {}
- if (static_cast<int>(index) < entries_to_write_)
- entries_to_write_--;
-
- ScheduleCommand(CreateRestoredEntryCommand(id));
+ if (observer_)
+ observer_->OnRestoreEntryById(id, entry_iterator);
restoring_ = true;
- Entry* entry = *i;
+ Entry* entry = *entry_iterator;
// If the entry's ID does not match the ID that is being restored, then the
// entry is a window from which a single tab will be restored.
bool restoring_tab_in_window = entry->id != id;
if (!restoring_tab_in_window) {
- entries_.erase(i);
- i = entries_.end();
+ entries_.erase(entry_iterator);
+ entry_iterator = entries_.end();
}
// |delegate| will be NULL in cases where one isn't already available (eg,
// when invoked on Mac OS X with no windows open). In this case, create a
// new browser into which we restore the tabs.
- if (entry->type == TAB) {
+ if (entry->type == TabRestoreService::TAB) {
Tab* tab = static_cast<Tab*>(entry);
delegate = RestoreTab(*tab, delegate, disposition);
delegate->ShowBrowserWindow();
- } else if (entry->type == WINDOW) {
+ } else if (entry->type == TabRestoreService::WINDOW) {
TabRestoreServiceDelegate* current_delegate = delegate;
Window* window = static_cast<Window*>(entry);
@@ -369,7 +228,7 @@ void TabRestoreService::RestoreEntryById(TabRestoreServiceDelegate* delegate,
// single tab within it. If the entry's ID matches the one to restore, then
// the entire window will be restored.
if (!restoring_tab_in_window) {
- delegate = TabRestoreServiceDelegate::Create(profile(), window->app_name);
+ delegate = TabRestoreServiceDelegate::Create(profile_, window->app_name);
for (size_t tab_i = 0; tab_i < window->tabs.size(); ++tab_i) {
const Tab& tab = window->tabs[tab_i];
WebContents* restored_tab =
@@ -383,7 +242,7 @@ void TabRestoreService::RestoreEntryById(TabRestoreServiceDelegate* delegate,
tab.user_agent_override);
if (restored_tab) {
restored_tab->GetController().LoadIfNecessary();
- RecordAppLaunch(profile(), tab);
+ RecordAppLaunch(profile_, tab);
}
}
// All the window's tabs had the same former browser_id.
@@ -403,7 +262,7 @@ void TabRestoreService::RestoreEntryById(TabRestoreServiceDelegate* delegate,
// If restoring the tab leaves the window with nothing else, delete it
// as well.
if (!window->tabs.size()) {
- entries_.erase(i);
+ entries_.erase(entry_iterator);
delete entry;
} else {
// Update the browser ID of the rest of the tabs in the window so if
@@ -438,140 +297,14 @@ void TabRestoreService::RestoreEntryById(TabRestoreServiceDelegate* delegate,
NotifyTabsChanged();
}
-void TabRestoreService::LoadTabsFromLastSession() {
- if (load_state_ != NOT_LOADED || entries_.size() == kMaxEntries)
- return;
-
-#if !defined(ENABLE_SESSION_SERVICE)
- // If sessions are not stored in the SessionService, default to
- // |LOADED_LAST_SESSION| state.
- load_state_ = LOADING | LOADED_LAST_SESSION;
-#else
- load_state_ = LOADING;
-
- SessionService* session_service =
- SessionServiceFactory::GetForProfile(profile());
- Profile::ExitType exit_type = profile()->GetLastSessionExitType();
- if (!profile()->restored_last_session() && session_service &&
- (exit_type == Profile::EXIT_CRASHED ||
- exit_type == Profile::EXIT_SESSION_ENDED)) {
- // The previous session crashed and wasn't restored, or was a forced
- // shutdown. Both of which won't have notified us of the browser close so
- // that we need to load the windows from session service (which will have
- // saved them).
- session_service->GetLastSession(
- &crash_consumer_,
- base::Bind(&TabRestoreService::OnGotPreviousSession,
- base::Unretained(this)));
- } else {
- load_state_ |= LOADED_LAST_SESSION;
- }
-#endif
-
- // Request the tabs closed in the last session. If the last session crashed,
- // this won't contain the tabs/window that were open at the point of the
- // crash (the call to GetLastSession above requests those).
- ScheduleGetLastSessionCommands(
- new InternalGetCommandsRequest(
- base::Bind(&TabRestoreService::OnGotLastSessionCommands,
- base::Unretained(this))),
- &load_consumer_);
-}
-
-bool TabRestoreService::IsLoaded() const {
- return !(load_state_ & (NOT_LOADED | LOADING));
-}
-
-void TabRestoreService::Shutdown() {
- if (backend())
- Save();
-}
-
-void TabRestoreService::Save() {
- int to_write_count = std::min(entries_to_write_,
- static_cast<int>(entries_.size()));
- entries_to_write_ = 0;
- if (entries_written_ + to_write_count > kEntriesPerReset) {
- to_write_count = entries_.size();
- set_pending_reset(true);
- }
- if (to_write_count) {
- // Write the to_write_count most recently added entries out. The most
- // recently added entry is at the front, so we use a reverse iterator to
- // write in the order the entries were added.
- Entries::reverse_iterator i = entries_.rbegin();
- DCHECK(static_cast<size_t>(to_write_count) <= entries_.size());
- std::advance(i, entries_.size() - static_cast<int>(to_write_count));
- for (; i != entries_.rend(); ++i) {
- Entry* entry = *i;
- if (entry->type == TAB) {
- Tab* tab = static_cast<Tab*>(entry);
- int selected_index = GetSelectedNavigationIndexToPersist(*tab);
- if (selected_index != -1)
- ScheduleCommandsForTab(*tab, selected_index);
- } else {
- ScheduleCommandsForWindow(*static_cast<Window*>(entry));
- }
- entries_written_++;
- }
- }
- if (pending_reset())
- entries_written_ = 0;
- BaseSessionService::Save();
-}
-
-void TabRestoreService::PopulateTab(Tab* tab,
- int index,
- TabRestoreServiceDelegate* delegate,
- NavigationController* controller) {
- const int pending_index = controller->GetPendingEntryIndex();
- int entry_count = controller->GetEntryCount();
- if (entry_count == 0 && pending_index == 0)
- entry_count++;
- tab->navigations.resize(static_cast<int>(entry_count));
- for (int i = 0; i < entry_count; ++i) {
- NavigationEntry* entry = (i == pending_index) ?
- controller->GetPendingEntry() : controller->GetEntryAtIndex(i);
- tab->navigations[i] =
- TabNavigation::FromNavigationEntry(i, *entry);
- }
- tab->timestamp = TimeNow();
- tab->current_navigation_index = controller->GetCurrentEntryIndex();
- if (tab->current_navigation_index == -1 && entry_count > 0)
- tab->current_navigation_index = 0;
- tab->tabstrip_index = index;
-
- TabContents* tab_contents =
- TabContents::FromWebContents(controller->GetWebContents());
- // tab_contents is NULL in some browser tests.
- if (tab_contents) {
- const extensions::Extension* extension =
- extensions::TabHelper::FromWebContents(controller->GetWebContents())->
- extension_app();
- if (extension)
- tab->extension_app_id = extension->id();
- }
-
- tab->user_agent_override =
- controller->GetWebContents()->GetUserAgentOverride();
-
- // TODO(ajwong): This does not correctly handle storage for isolated apps.
- tab->session_storage_namespace =
- controller->GetDefaultSessionStorageNamespace();
-
- // Delegate may be NULL during unit tests.
- if (delegate) {
- tab->browser_id = delegate->GetSessionID().id();
- tab->pinned = delegate->IsTabPinned(tab->tabstrip_index);
- }
-}
-
-void TabRestoreService::NotifyTabsChanged() {
+void TabRestoreServiceHelper::NotifyTabsChanged() {
FOR_EACH_OBSERVER(TabRestoreServiceObserver, observer_list_,
- TabRestoreServiceChanged(this));
+ TabRestoreServiceChanged(tab_restore_service_));
}
-void TabRestoreService::AddEntry(Entry* entry, bool notify, bool to_front) {
+void TabRestoreServiceHelper::AddEntry(Entry* entry,
+ bool notify,
+ bool to_front) {
if (!FilterEntry(entry) || (entries_.size() >= kMaxEntries && !to_front)) {
delete entry;
return;
@@ -587,12 +320,11 @@ void TabRestoreService::AddEntry(Entry* entry, bool notify, bool to_front) {
if (notify)
NotifyTabsChanged();
- // Start the save timer, when it fires we'll generate the commands.
- StartSaveTimer();
- entries_to_write_++;
+ if (observer_)
+ observer_->OnAddEntry();
}
-void TabRestoreService::PruneEntries() {
+void TabRestoreServiceHelper::PruneEntries() {
Entries new_entries;
for (TabRestoreService::Entries::const_iterator iter = entries_.begin();
@@ -610,15 +342,15 @@ void TabRestoreService::PruneEntries() {
entries_ = new_entries;
}
-TabRestoreService::Entries::iterator TabRestoreService::GetEntryIteratorById(
- SessionID::id_type id) {
+TabRestoreService::Entries::iterator
+TabRestoreServiceHelper::GetEntryIteratorById(SessionID::id_type id) {
for (Entries::iterator i = entries_.begin(); i != entries_.end(); ++i) {
if ((*i)->id == id)
return i;
// For Window entries, see if the ID matches a tab. If so, report the window
// as the Entry.
- if ((*i)->type == WINDOW) {
+ if ((*i)->type == TabRestoreService::WINDOW) {
std::vector<Tab>& tabs = static_cast<Window*>(*i)->tabs;
for (std::vector<Tab>::iterator j = tabs.begin();
j != tabs.end(); ++j) {
@@ -631,368 +363,66 @@ TabRestoreService::Entries::iterator TabRestoreService::GetEntryIteratorById(
return entries_.end();
}
-void TabRestoreService::ScheduleCommandsForWindow(const Window& window) {
- DCHECK(!window.tabs.empty());
- int selected_tab = window.selected_tab_index;
- int valid_tab_count = 0;
- int real_selected_tab = selected_tab;
- for (size_t i = 0; i < window.tabs.size(); ++i) {
- if (GetSelectedNavigationIndexToPersist(window.tabs[i]) != -1) {
- valid_tab_count++;
- } else if (static_cast<int>(i) < selected_tab) {
- real_selected_tab--;
- }
- }
- if (valid_tab_count == 0)
- return; // No tabs to persist.
-
- ScheduleCommand(
- CreateWindowCommand(window.id,
- std::min(real_selected_tab, valid_tab_count - 1),
- valid_tab_count,
- window.timestamp));
-
- if (!window.app_name.empty()) {
- ScheduleCommand(
- CreateSetWindowAppNameCommand(kCommandSetWindowAppName,
- window.id,
- window.app_name));
- }
-
- for (size_t i = 0; i < window.tabs.size(); ++i) {
- int selected_index = GetSelectedNavigationIndexToPersist(window.tabs[i]);
- if (selected_index != -1)
- ScheduleCommandsForTab(window.tabs[i], selected_index);
- }
-}
-
-void TabRestoreService::ScheduleCommandsForTab(const Tab& tab,
- int selected_index) {
- const std::vector<TabNavigation>& navigations = tab.navigations;
- int max_index = static_cast<int>(navigations.size());
-
- // Determine the first navigation we'll persist.
- int valid_count_before_selected = 0;
- int first_index_to_persist = selected_index;
- for (int i = selected_index - 1; i >= 0 &&
- valid_count_before_selected < max_persist_navigation_count; --i) {
- if (ShouldTrackEntry(navigations[i].virtual_url())) {
- first_index_to_persist = i;
- valid_count_before_selected++;
- }
- }
-
- // Write the command that identifies the selected tab.
- ScheduleCommand(
- CreateSelectedNavigationInTabCommand(tab.id,
- valid_count_before_selected,
- tab.timestamp));
-
- if (tab.pinned) {
- PinnedStatePayload payload = true;
- SessionCommand* command =
- new SessionCommand(kCommandPinnedState, sizeof(payload));
- memcpy(command->contents(), &payload, sizeof(payload));
- ScheduleCommand(command);
- }
-
- if (!tab.extension_app_id.empty()) {
- ScheduleCommand(
- CreateSetTabExtensionAppIDCommand(kCommandSetExtensionAppID, tab.id,
- tab.extension_app_id));
- }
-
- if (!tab.user_agent_override.empty()) {
- 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]));
- }
- }
-}
-
-SessionCommand* TabRestoreService::CreateWindowCommand(SessionID::id_type id,
- int selected_tab_index,
- int num_tabs,
- Time timestamp) {
- WindowPayload2 payload;
- // |timestamp| is aligned on a 16 byte boundary, leaving 4 bytes of
- // uninitialized memory in the struct.
- memset(&payload, 0, sizeof(payload));
- payload.window_id = id;
- payload.selected_tab_index = selected_tab_index;
- payload.num_tabs = num_tabs;
- payload.timestamp = timestamp.ToInternalValue();
-
- SessionCommand* command =
- new SessionCommand(kCommandWindow, sizeof(payload));
- memcpy(command->contents(), &payload, sizeof(payload));
- return command;
-}
+// static
+bool TabRestoreServiceHelper::ValidateEntry(Entry* entry) {
+ if (entry->type == TabRestoreService::TAB)
+ return ValidateTab(static_cast<Tab*>(entry));
-SessionCommand* TabRestoreService::CreateSelectedNavigationInTabCommand(
- SessionID::id_type tab_id,
- int32 index,
- Time timestamp) {
- SelectedNavigationInTabPayload2 payload;
- payload.id = tab_id;
- payload.index = index;
- payload.timestamp = timestamp.ToInternalValue();
- SessionCommand* command =
- new SessionCommand(kCommandSelectedNavigationInTab, sizeof(payload));
- memcpy(command->contents(), &payload, sizeof(payload));
- return command;
-}
+ if (entry->type == TabRestoreService::WINDOW)
+ return ValidateWindow(static_cast<Window*>(entry));
-SessionCommand* TabRestoreService::CreateRestoredEntryCommand(
- SessionID::id_type entry_id) {
- RestoredEntryPayload payload = entry_id;
- SessionCommand* command =
- new SessionCommand(kCommandRestoredEntry, sizeof(payload));
- memcpy(command->contents(), &payload, sizeof(payload));
- return command;
+ NOTREACHED();
+ return false;
}
-int TabRestoreService::GetSelectedNavigationIndexToPersist(const Tab& tab) {
- const std::vector<TabNavigation>& navigations = tab.navigations;
- int selected_index = tab.current_navigation_index;
- int max_index = static_cast<int>(navigations.size());
-
- // Find the first navigation to persist. We won't persist the selected
- // navigation if ShouldTrackEntry returns false.
- while (selected_index >= 0 &&
- !ShouldTrackEntry(navigations[selected_index].virtual_url())) {
- selected_index--;
+void TabRestoreServiceHelper::PopulateTab(
+ Tab* tab,
+ int index,
+ TabRestoreServiceDelegate* delegate,
+ NavigationController* controller) {
+ const int pending_index = controller->GetPendingEntryIndex();
+ int entry_count = controller->GetEntryCount();
+ if (entry_count == 0 && pending_index == 0)
+ entry_count++;
+ tab->navigations.resize(static_cast<int>(entry_count));
+ for (int i = 0; i < entry_count; ++i) {
+ NavigationEntry* entry = (i == pending_index) ?
+ controller->GetPendingEntry() : controller->GetEntryAtIndex(i);
+ tab->navigations[i] =
+ TabNavigation::FromNavigationEntry(i, *entry);
}
+ tab->timestamp = TimeNow();
+ tab->current_navigation_index = controller->GetCurrentEntryIndex();
+ if (tab->current_navigation_index == -1 && entry_count > 0)
+ tab->current_navigation_index = 0;
+ tab->tabstrip_index = index;
- if (selected_index != -1)
- return selected_index;
-
- // Couldn't find a navigation to persist going back, go forward.
- selected_index = tab.current_navigation_index + 1;
- while (selected_index < max_index &&
- !ShouldTrackEntry(navigations[selected_index].virtual_url())) {
- selected_index++;
+ TabContents* tab_contents =
+ TabContents::FromWebContents(controller->GetWebContents());
+ // tab_contents is NULL in some browser tests.
+ if (tab_contents) {
+ const extensions::Extension* extension =
+ extensions::TabHelper::FromWebContents(controller->GetWebContents())->
+ extension_app();
+ if (extension)
+ tab->extension_app_id = extension->id();
}
- return (selected_index == max_index) ? -1 : selected_index;
-}
-
-void TabRestoreService::OnGotLastSessionCommands(
- Handle handle,
- scoped_refptr<InternalGetCommandsRequest> request) {
- std::vector<Entry*> entries;
- CreateEntriesFromCommands(request, &entries);
- // Closed tabs always go to the end.
- staging_entries_.insert(staging_entries_.end(), entries.begin(),
- entries.end());
- load_state_ |= LOADED_LAST_TABS;
- LoadStateChanged();
-}
-
-void TabRestoreService::CreateEntriesFromCommands(
- scoped_refptr<InternalGetCommandsRequest> request,
- std::vector<Entry*>* loaded_entries) {
- if (request->canceled() || entries_.size() == kMaxEntries)
- return;
-
- std::vector<SessionCommand*>& commands = request->commands;
- // Iterate through the commands populating entries and id_to_entry.
- ScopedVector<Entry> entries;
- IDToEntry id_to_entry;
- // If non-null we're processing the navigations of this tab.
- Tab* current_tab = NULL;
- // If non-null we're processing the tabs of this window.
- Window* current_window = NULL;
- // If > 0, we've gotten a window command but not all the tabs yet.
- int pending_window_tabs = 0;
- for (std::vector<SessionCommand*>::const_iterator i = commands.begin();
- i != commands.end(); ++i) {
- const SessionCommand& command = *(*i);
- switch (command.id()) {
- case kCommandRestoredEntry: {
- if (pending_window_tabs > 0) {
- // Should never receive a restored command while waiting for all the
- // tabs in a window.
- return;
- }
-
- current_tab = NULL;
- current_window = NULL;
-
- RestoredEntryPayload payload;
- if (!command.GetPayload(&payload, sizeof(payload)))
- return;
- RemoveEntryByID(payload, &id_to_entry, &(entries.get()));
- break;
- }
-
- case kCommandWindow: {
- WindowPayload2 payload;
- if (pending_window_tabs > 0) {
- // Should never receive a window command while waiting for all the
- // tabs in a window.
- return;
- }
-
- // Try the new payload first
- if (!command.GetPayload(&payload, sizeof(payload))) {
- // then the old payload
- WindowPayload old_payload;
- if (!command.GetPayload(&old_payload, sizeof(old_payload)))
- return;
-
- // Copy the old payload data to the new payload.
- payload.window_id = old_payload.window_id;
- payload.selected_tab_index = old_payload.selected_tab_index;
- payload.num_tabs = old_payload.num_tabs;
- // Since we don't have a time use time 0 which is used to mark as an
- // unknown timestamp.
- payload.timestamp = 0;
- }
-
- pending_window_tabs = payload.num_tabs;
- if (pending_window_tabs <= 0) {
- // Should always have at least 1 tab. Likely indicates corruption.
- return;
- }
-
- RemoveEntryByID(payload.window_id, &id_to_entry, &(entries.get()));
-
- current_window = new Window();
- current_window->selected_tab_index = payload.selected_tab_index;
- current_window->timestamp = Time::FromInternalValue(payload.timestamp);
- entries.push_back(current_window);
- id_to_entry[payload.window_id] = current_window;
- break;
- }
-
- case kCommandSelectedNavigationInTab: {
- SelectedNavigationInTabPayload2 payload;
- if (!command.GetPayload(&payload, sizeof(payload))) {
- SelectedNavigationInTabPayload old_payload;
- if (!command.GetPayload(&old_payload, sizeof(old_payload)))
- return;
- payload.id = old_payload.id;
- payload.index = old_payload.index;
- // Since we don't have a time use time 0 which is used to mark as an
- // unknown timestamp.
- payload.timestamp = 0;
- }
-
- if (pending_window_tabs > 0) {
- if (!current_window) {
- // We should have created a window already.
- NOTREACHED();
- return;
- }
- current_window->tabs.resize(current_window->tabs.size() + 1);
- current_tab = &(current_window->tabs.back());
- if (--pending_window_tabs == 0)
- current_window = NULL;
- } else {
- RemoveEntryByID(payload.id, &id_to_entry, &(entries.get()));
- current_tab = new Tab();
- id_to_entry[payload.id] = current_tab;
- current_tab->timestamp = Time::FromInternalValue(payload.timestamp);
- entries.push_back(current_tab);
- }
- current_tab->current_navigation_index = payload.index;
- break;
- }
-
- case kCommandUpdateTabNavigation: {
- if (!current_tab) {
- // Should be in a tab when we get this.
- return;
- }
- current_tab->navigations.resize(current_tab->navigations.size() + 1);
- SessionID::id_type tab_id;
- if (!RestoreUpdateTabNavigationCommand(
- command, &current_tab->navigations.back(), &tab_id)) {
- return;
- }
- break;
- }
-
- case kCommandPinnedState: {
- if (!current_tab) {
- // Should be in a tab when we get this.
- return;
- }
- // NOTE: payload doesn't matter. kCommandPinnedState is only written if
- // tab is pinned.
- current_tab->pinned = true;
- break;
- }
-
- case kCommandSetWindowAppName: {
- if (!current_window) {
- // We should have created a window already.
- NOTREACHED();
- return;
- }
-
- SessionID::id_type window_id;
- std::string app_name;
- if (!RestoreSetWindowAppNameCommand(command, &window_id, &app_name))
- return;
-
- current_window->app_name.swap(app_name);
- break;
- }
-
- case kCommandSetExtensionAppID: {
- if (!current_tab) {
- // Should be in a tab when we get this.
- return;
- }
- SessionID::id_type tab_id;
- std::string extension_app_id;
- if (!RestoreSetTabExtensionAppIDCommand(command, &tab_id,
- &extension_app_id)) {
- return;
- }
- current_tab->extension_app_id.swap(extension_app_id);
- break;
- }
+ tab->user_agent_override =
+ controller->GetWebContents()->GetUserAgentOverride();
- case kCommandSetTabUserAgentOverride: {
- if (!current_tab) {
- // Should be in a tab when we get this.
- return;
- }
- SessionID::id_type tab_id;
- std::string user_agent_override;
- if (!RestoreSetTabUserAgentOverrideCommand(command, &tab_id,
- &user_agent_override)) {
- return;
- }
- current_tab->user_agent_override.swap(user_agent_override);
- break;
- }
+ // TODO(ajwong): This does not correctly handle storage for isolated apps.
+ tab->session_storage_namespace =
+ controller->GetDefaultSessionStorageNamespace();
- default:
- // Unknown type, usually indicates corruption of file. Ignore it.
- return;
- }
+ // Delegate may be NULL during unit tests.
+ if (delegate) {
+ tab->browser_id = delegate->GetSessionID().id();
+ tab->pinned = delegate->IsTabPinned(tab->tabstrip_index);
}
-
- // If there was corruption some of the entries won't be valid.
- ValidateAndDeleteEmptyEntries(&(entries.get()));
-
- loaded_entries->swap(entries.get());
}
-TabRestoreServiceDelegate* TabRestoreService::RestoreTab(
+TabRestoreServiceDelegate* TabRestoreServiceHelper::RestoreTab(
const Tab& tab,
TabRestoreServiceDelegate* delegate,
WindowOpenDisposition disposition) {
@@ -1016,7 +446,7 @@ TabRestoreServiceDelegate* TabRestoreService::RestoreTab(
if (delegate && disposition != NEW_WINDOW) {
tab_index = tab.tabstrip_index;
} else {
- delegate = TabRestoreServiceDelegate::Create(profile(), std::string());
+ delegate = TabRestoreServiceDelegate::Create(profile_, std::string());
if (tab.has_browser())
UpdateTabBrowserIDs(tab.browser_id, delegate->GetSessionID().id());
}
@@ -1040,12 +470,12 @@ TabRestoreServiceDelegate* TabRestoreService::RestoreTab(
tab.user_agent_override);
web_contents->GetController().LoadIfNecessary();
}
- RecordAppLaunch(profile(), tab);
+ RecordAppLaunch(profile_, tab);
return delegate;
}
-bool TabRestoreService::ValidateTab(Tab* tab) {
+bool TabRestoreServiceHelper::ValidateTab(Tab* tab) {
if (tab->navigations.empty())
return false;
@@ -1056,7 +486,7 @@ bool TabRestoreService::ValidateTab(Tab* tab) {
return true;
}
-bool TabRestoreService::ValidateWindow(Window* window) {
+bool TabRestoreServiceHelper::ValidateWindow(Window* window) {
window->selected_tab_index =
std::max(0, std::min(window->selected_tab_index,
static_cast<int>(window->tabs.size() - 1)));
@@ -1082,18 +512,7 @@ bool TabRestoreService::ValidateWindow(Window* window) {
return true;
}
-bool TabRestoreService::ValidateEntry(Entry* entry) {
- if (entry->type == TAB)
- return ValidateTab(static_cast<Tab*>(entry));
-
- if (entry->type == WINDOW)
- return ValidateWindow(static_cast<Window*>(entry));
-
- NOTREACHED();
- return false;
-}
-
-bool TabRestoreService::IsTabInteresting(const Tab* tab) {
+bool TabRestoreServiceHelper::IsTabInteresting(const Tab* tab) {
if (tab->navigations.empty())
return false;
@@ -1105,7 +524,7 @@ bool TabRestoreService::IsTabInteresting(const Tab* tab) {
GURL(chrome::kChromeUINewTabURL);
}
-bool TabRestoreService::IsWindowInteresting(const Window* window) {
+bool TabRestoreServiceHelper::IsWindowInteresting(const Window* window) {
if (window->tabs.empty())
return false;
@@ -1115,44 +534,24 @@ bool TabRestoreService::IsWindowInteresting(const Window* window) {
return IsTabInteresting(&window->tabs[0]);
}
-bool TabRestoreService::FilterEntry(Entry* entry) {
+bool TabRestoreServiceHelper::FilterEntry(Entry* entry) {
if (!ValidateEntry(entry))
return false;
- if (entry->type == TAB)
+ if (entry->type == TabRestoreService::TAB)
return IsTabInteresting(static_cast<Tab*>(entry));
- else if (entry->type == WINDOW)
+ else if (entry->type == TabRestoreService::WINDOW)
return IsWindowInteresting(static_cast<Window*>(entry));
NOTREACHED();
return false;
}
-void TabRestoreService::ValidateAndDeleteEmptyEntries(
- std::vector<Entry*>* entries) {
- std::vector<Entry*> valid_entries;
- std::vector<Entry*> invalid_entries;
-
- // Iterate from the back so that we keep the most recently closed entries.
- for (std::vector<Entry*>::reverse_iterator i = entries->rbegin();
- i != entries->rend(); ++i) {
- if (ValidateEntry(*i))
- valid_entries.push_back(*i);
- else
- invalid_entries.push_back(*i);
- }
- // NOTE: at this point the entries are ordered with newest at the front.
- entries->swap(valid_entries);
-
- // Delete the remaining entries.
- STLDeleteElements(&invalid_entries);
-}
-
-void TabRestoreService::UpdateTabBrowserIDs(SessionID::id_type old_id,
- SessionID::id_type new_id) {
+void TabRestoreServiceHelper::UpdateTabBrowserIDs(SessionID::id_type old_id,
+ SessionID::id_type new_id) {
for (Entries::iterator i = entries_.begin(); i != entries_.end(); ++i) {
Entry* entry = *i;
- if (entry->type == TAB) {
+ if (entry->type == TabRestoreService::TAB) {
Tab* tab = static_cast<Tab*>(entry);
if (tab->browser_id == old_id)
tab->browser_id = new_id;
@@ -1160,103 +559,6 @@ void TabRestoreService::UpdateTabBrowserIDs(SessionID::id_type old_id,
}
}
-void TabRestoreService::OnGotPreviousSession(
- Handle handle,
- std::vector<SessionWindow*>* windows,
- SessionID::id_type ignored_active_window) {
- std::vector<Entry*> entries;
- CreateEntriesFromWindows(windows, &entries);
- // Previous session tabs go first.
- staging_entries_.insert(staging_entries_.begin(), entries.begin(),
- entries.end());
- load_state_ |= LOADED_LAST_SESSION;
- LoadStateChanged();
-}
-
-void TabRestoreService::CreateEntriesFromWindows(
- std::vector<SessionWindow*>* windows,
- std::vector<Entry*>* entries) {
- for (size_t i = 0; i < windows->size(); ++i) {
- scoped_ptr<Window> window(new Window());
- if (ConvertSessionWindowToWindow((*windows)[i], window.get()))
- entries->push_back(window.release());
- }
-}
-
-bool TabRestoreService::ConvertSessionWindowToWindow(
- SessionWindow* session_window,
- Window* window) {
- for (size_t i = 0; i < session_window->tabs.size(); ++i) {
- if (!session_window->tabs[i]->navigations.empty()) {
- window->tabs.resize(window->tabs.size() + 1);
- Tab& tab = window->tabs.back();
- tab.pinned = session_window->tabs[i]->pinned;
- tab.navigations.swap(session_window->tabs[i]->navigations);
- tab.current_navigation_index =
- session_window->tabs[i]->current_navigation_index;
- tab.extension_app_id = session_window->tabs[i]->extension_app_id;
- tab.timestamp = Time();
- }
- }
- if (window->tabs.empty())
- return false;
-
- window->selected_tab_index =
- std::min(session_window->selected_tab_index,
- static_cast<int>(window->tabs.size() - 1));
- window->timestamp = Time();
- return true;
-}
-
-void TabRestoreService::LoadStateChanged() {
- if ((load_state_ & (LOADED_LAST_TABS | LOADED_LAST_SESSION)) !=
- (LOADED_LAST_TABS | LOADED_LAST_SESSION)) {
- // Still waiting on previous session or previous tabs.
- return;
- }
-
- // We're done loading.
- load_state_ ^= LOADING;
-
- if (staging_entries_.empty() || entries_.size() >= kMaxEntries) {
- STLDeleteElements(&staging_entries_);
- return;
- }
-
- if (staging_entries_.size() + entries_.size() > kMaxEntries) {
- // If we add all the staged entries we'll end up with more than
- // kMaxEntries. Delete entries such that we only end up with
- // at most kMaxEntries.
- int surplus = kMaxEntries - entries_.size();
- CHECK_LE(0, surplus);
- CHECK_GE(static_cast<int>(staging_entries_.size()), surplus);
- STLDeleteContainerPointers(
- staging_entries_.begin() + (kMaxEntries - entries_.size()),
- staging_entries_.end());
- staging_entries_.erase(
- staging_entries_.begin() + (kMaxEntries - entries_.size()),
- staging_entries_.end());
- }
-
- // And add them.
- for (size_t i = 0; i < staging_entries_.size(); ++i) {
- staging_entries_[i]->from_last_session = true;
- AddEntry(staging_entries_[i], false, false);
- }
-
- // AddEntry takes ownership of the entry, need to clear out entries so that
- // it doesn't delete them.
- staging_entries_.clear();
-
- // Make it so we rewrite all the tabs. We need to do this otherwise we won't
- // correctly write out the entries when Save is invoked (Save starts from
- // the front, not the end and we just added the entries to the end).
- entries_to_write_ = staging_entries_.size();
-
- PruneEntries();
- NotifyTabsChanged();
-}
-
-Time TabRestoreService::TimeNow() const {
- return time_factory_ ? time_factory_->TimeNow() : Time::Now();
+base::Time TabRestoreServiceHelper::TimeNow() const {
+ return time_factory_ ? time_factory_->TimeNow() : base::Time::Now();
}

Powered by Google App Engine
This is Rietveld 408576698