15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/persistent_tab_restore_service.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cstring> // memcpy 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_vector.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h" 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/task/cancelable_task_tracker.h" 19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/base_session_service.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/session_command.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/session_service.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/session_service_factory.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/tab_restore_service_factory.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/session_storage_namespace.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Only written if the tab is pinned. 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef bool PinnedStatePayload; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef int32 RestoredEntryPayload; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef std::map<SessionID::id_type, TabRestoreService::Entry*> IDToEntry; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Payload used for the start of a tab close. This is the old struct that is 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// used for backwards compat when it comes to reading the session files. 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct SelectedNavigationInTabPayload { 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SessionID::id_type id; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 index; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Payload used for the start of a window close. This is the old struct that is 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// used for backwards compat when it comes to reading the session files. This 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// struct must be POD, because we memset the contents. 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct WindowPayload { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SessionID::id_type window_id; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 selected_tab_index; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 num_tabs; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Payload used for the start of a window close. This struct must be POD, 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// because we memset the contents. 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct WindowPayload2 : WindowPayload { 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 timestamp; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Payload used for the start of a tab close. 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct SelectedNavigationInTabPayload2 : SelectedNavigationInTabPayload { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 timestamp; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Used to indicate what has loaded. 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum LoadState { 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Indicates we haven't loaded anything. 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOT_LOADED = 1 << 0, 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Indicates we've asked for the last sessions and tabs but haven't gotten the 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // result back yet. 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOADING = 1 << 2, 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Indicates we finished loading the last tabs (but not necessarily the last 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // session). 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOADED_LAST_TABS = 1 << 3, 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Indicates we finished loading the last session (but not necessarily the 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // last tabs). 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOADED_LAST_SESSION = 1 << 4 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Identifier for commands written to file. The ordering in the file is as 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// follows: 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// . When the user closes a tab a command of type 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// kCommandSelectedNavigationInTab is written identifying the tab and 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the selected index, then a kCommandPinnedState command if the tab was 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// pinned and kCommandSetExtensionAppID if the tab has an app id and 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the user agent override if it was using one. This is 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// followed by any number of kCommandUpdateTabNavigation commands (1 per 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// navigation entry). 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// . When the user closes a window a kCommandSelectedNavigationInTab command 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is written out and followed by n tab closed sequences (as previoulsy 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// described). 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// . When the user restores an entry a command of type kCommandRestoredEntry 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is written. 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const SessionCommand::id_type kCommandUpdateTabNavigation = 1; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const SessionCommand::id_type kCommandRestoredEntry = 2; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const SessionCommand::id_type kCommandWindow = 3; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const SessionCommand::id_type kCommandSelectedNavigationInTab = 4; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const SessionCommand::id_type kCommandPinnedState = 5; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const SessionCommand::id_type kCommandSetExtensionAppID = 6; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const SessionCommand::id_type kCommandSetWindowAppName = 7; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const SessionCommand::id_type kCommandSetTabUserAgentOverride = 8; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Number of entries (not commands) before we clobber the file and write 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// everything. 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kEntriesPerReset = 40; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const size_t kMaxEntries = TabRestoreServiceHelper::kMaxEntries; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// PersistentTabRestoreService::Delegate --------------------------------------- 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Implements the link between the tab restore service and the session backend. 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PersistentTabRestoreService::Delegate 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : public BaseSessionService, 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public TabRestoreServiceHelper::Observer { 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit Delegate(Profile* profile); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~Delegate(); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // BaseSessionService: 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Save() OVERRIDE; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TabRestoreServiceHelper::Observer: 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnClearEntries() OVERRIDE; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnRestoreEntryById( 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SessionID::id_type id, 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Entries::const_iterator entry_iterator) OVERRIDE; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnAddEntry() OVERRIDE; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void set_tab_restore_service_helper( 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabRestoreServiceHelper* tab_restore_service_helper) { 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_restore_service_helper_ = tab_restore_service_helper; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void LoadTabsFromLastSession(); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool IsLoaded() const; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Creates and add entries to |entries| for each of the windows in |windows|. 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void CreateEntriesFromWindows(std::vector<SessionWindow*>* windows, 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<Entry*>* entries); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Shutdown(); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Schedules the commands for a window close. 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ScheduleCommandsForWindow(const Window& window); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Schedules the commands for a tab close. |selected_index| gives the index of 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the selected navigation. 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ScheduleCommandsForTab(const Tab& tab, int selected_index); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Creates a window close command. 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static SessionCommand* CreateWindowCommand(SessionID::id_type id, 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int selected_tab_index, 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_tabs, 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time timestamp); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Creates a tab close command. 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static SessionCommand* CreateSelectedNavigationInTabCommand( 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SessionID::id_type tab_id, 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 index, 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time timestamp); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Creates a restore command. 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static SessionCommand* CreateRestoredEntryCommand( 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SessionID::id_type entry_id); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns the index to persist as the selected index. This is the same as 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |tab.current_navigation_index| unless the entry at 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |tab.current_navigation_index| shouldn't be persisted. Returns -1 if no 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // valid navigation to persist. 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int GetSelectedNavigationIndexToPersist(const Tab& tab); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Invoked when we've loaded the session commands that identify the previously 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // closed tabs. This creates entries, adds them to staging_entries_, and 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // invokes LoadState. 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void OnGotLastSessionCommands(ScopedVector<SessionCommand> commands); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Populates |loaded_entries| with Entries from |commands|. 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void CreateEntriesFromCommands(const std::vector<SessionCommand*>& commands, 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<Entry*>* loaded_entries); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Validates all entries in |entries|, deleting any with no navigations. This 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // also deletes any entries beyond the max number of entries we can hold. 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void ValidateAndDeleteEmptyEntries(std::vector<Entry*>* entries); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Callback from SessionService when we've received the windows from the 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // previous session. This creates and add entries to |staging_entries_| and 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // invokes LoadStateChanged. |ignored_active_window| is ignored because we 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // don't need to restore activation. 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void OnGotPreviousSession(ScopedVector<SessionWindow> windows, 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SessionID::id_type ignored_active_window); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Converts a SessionWindow into a Window, returning true on success. We use 0 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // as the timestamp here since we do not know when the window/tab was closed. 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool ConvertSessionWindowToWindow(SessionWindow* session_window, 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Window* window); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Invoked when previous tabs or session is loaded. If both have finished 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // loading the entries in |staging_entries_| are added to entries and 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // observers are notified. 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void LoadStateChanged(); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If |id_to_entry| contains an entry for |id| the corresponding entry is 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // deleted and removed from both |id_to_entry| and |entries|. This is used 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // when creating entries from the backend file. 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void RemoveEntryByID(SessionID::id_type id, 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDToEntry* id_to_entry, 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<TabRestoreService::Entry*>* entries); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabRestoreServiceHelper* tab_restore_service_helper_; 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The number of entries to write. 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int entries_to_write_; 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Number of entries we've written. 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int entries_written_; 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Whether we've loaded the last session. 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int load_state_; 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Results from previously closed tabs/sessions is first added here. When the 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // results from both us and the session restore service have finished loading 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // LoadStateChanged is invoked, which adds these entries to entries_. 230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ScopedVector<Entry> staging_entries_; 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Used when loading previous tabs/session and open tabs/session. 2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::CancelableTaskTracker cancelable_task_tracker_; 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(Delegate); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PersistentTabRestoreService::Delegate::Delegate(Profile* profile) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : BaseSessionService(BaseSessionService::TAB_RESTORE, profile, 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath()), 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_restore_service_helper_(NULL), 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entries_to_write_(0), 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entries_written_(0), 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) load_state_(NOT_LOADED) { 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)PersistentTabRestoreService::Delegate::~Delegate() {} 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PersistentTabRestoreService::Delegate::Save() { 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Entries& entries = tab_restore_service_helper_->entries(); 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int to_write_count = std::min(entries_to_write_, 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>(entries.size())); 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entries_to_write_ = 0; 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (entries_written_ + to_write_count > kEntriesPerReset) { 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) to_write_count = entries.size(); 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_pending_reset(true); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (to_write_count) { 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Write the to_write_count most recently added entries out. The most 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // recently added entry is at the front, so we use a reverse iterator to 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // write in the order the entries were added. 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Entries::const_reverse_iterator i = entries.rbegin(); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(static_cast<size_t>(to_write_count) <= entries.size()); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::advance(i, entries.size() - static_cast<int>(to_write_count)); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (; i != entries.rend(); ++i) { 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Entry* entry = *i; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (entry->type == TAB) { 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Tab* tab = static_cast<Tab*>(entry); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int selected_index = GetSelectedNavigationIndexToPersist(*tab); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (selected_index != -1) 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommandsForTab(*tab, selected_index); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommandsForWindow(*static_cast<Window*>(entry)); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entries_written_++; 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pending_reset()) 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entries_written_ = 0; 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BaseSessionService::Save(); 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PersistentTabRestoreService::Delegate::OnClearEntries() { 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Mark all the tabs as closed so that we don't attempt to restore them. 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Entries& entries = tab_restore_service_helper_->entries(); 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (Entries::const_iterator i = entries.begin(); i != entries.end(); ++i) 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommand(CreateRestoredEntryCommand((*i)->id)); 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entries_to_write_ = 0; 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Schedule a pending reset so that we nuke the file on next write. 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_pending_reset(true); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Schedule a command, otherwise if there are no pending commands Save does 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // nothing. 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommand(CreateRestoredEntryCommand(1)); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PersistentTabRestoreService::Delegate::OnRestoreEntryById( 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SessionID::id_type id, 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Entries::const_iterator entry_iterator) { 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t index = 0; 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Entries& entries = tab_restore_service_helper_->entries(); 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (Entries::const_iterator j = entries.begin(); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) j != entry_iterator && j != entries.end(); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++j, ++index) {} 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (static_cast<int>(index) < entries_to_write_) 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entries_to_write_--; 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommand(CreateRestoredEntryCommand(id)); 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PersistentTabRestoreService::Delegate::OnAddEntry() { 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start the save timer, when it fires we'll generate the commands. 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartSaveTimer(); 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entries_to_write_++; 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PersistentTabRestoreService::Delegate::LoadTabsFromLastSession() { 320a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (load_state_ != NOT_LOADED) 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 323a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (tab_restore_service_helper_->entries().size() == kMaxEntries) { 324a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // We already have the max number of entries we can take. There is no point 325a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // in attempting to load since we'll just drop the results. Skip to loaded. 326a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) load_state_ = (LOADING | LOADED_LAST_SESSION | LOADED_LAST_TABS); 327a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) LoadStateChanged(); 328a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return; 329a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 330a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(ENABLE_SESSION_SERVICE) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If sessions are not stored in the SessionService, default to 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |LOADED_LAST_SESSION| state. 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) load_state_ = LOADING | LOADED_LAST_SESSION; 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) load_state_ = LOADING; 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SessionService* session_service = 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SessionServiceFactory::GetForProfile(profile()); 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile::ExitType exit_type = profile()->GetLastSessionExitType(); 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!profile()->restored_last_session() && session_service && 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (exit_type == Profile::EXIT_CRASHED || 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) exit_type == Profile::EXIT_SESSION_ENDED)) { 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The previous session crashed and wasn't restored, or was a forced 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // shutdown. Both of which won't have notified us of the browser close so 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that we need to load the windows from session service (which will have 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // saved them). 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) session_service->GetLastSession( 3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&Delegate::OnGotPreviousSession, base::Unretained(this)), 3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &cancelable_task_tracker_); 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) load_state_ |= LOADED_LAST_SESSION; 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Request the tabs closed in the last session. If the last session crashed, 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this won't contain the tabs/window that were open at the point of the 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // crash (the call to GetLastSession above requests those). 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleGetLastSessionCommands( 3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&Delegate::OnGotLastSessionCommands, base::Unretained(this)), 3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &cancelable_task_tracker_); 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PersistentTabRestoreService::Delegate::IsLoaded() const { 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !(load_state_ & (NOT_LOADED | LOADING)); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PersistentTabRestoreService::Delegate::CreateEntriesFromWindows( 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<SessionWindow*>* windows, 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<Entry*>* entries) { 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < windows->size(); ++i) { 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<Window> window(new Window()); 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ConvertSessionWindowToWindow((*windows)[i], window.get())) 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entries->push_back(window.release()); 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PersistentTabRestoreService::Delegate::Shutdown() { 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (backend()) 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Save(); 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PersistentTabRestoreService::Delegate::ScheduleCommandsForWindow( 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Window& window) { 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!window.tabs.empty()); 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int selected_tab = window.selected_tab_index; 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int valid_tab_count = 0; 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int real_selected_tab = selected_tab; 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < window.tabs.size(); ++i) { 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (GetSelectedNavigationIndexToPersist(window.tabs[i]) != -1) { 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) valid_tab_count++; 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (static_cast<int>(i) < selected_tab) { 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) real_selected_tab--; 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (valid_tab_count == 0) 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; // No tabs to persist. 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommand( 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateWindowCommand(window.id, 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::min(real_selected_tab, valid_tab_count - 1), 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) valid_tab_count, 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window.timestamp)); 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!window.app_name.empty()) { 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommand( 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateSetWindowAppNameCommand(kCommandSetWindowAppName, 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window.id, 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window.app_name)); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < window.tabs.size(); ++i) { 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int selected_index = GetSelectedNavigationIndexToPersist(window.tabs[i]); 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (selected_index != -1) 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommandsForTab(window.tabs[i], selected_index); 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PersistentTabRestoreService::Delegate::ScheduleCommandsForTab( 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Tab& tab, 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int selected_index) { 423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::vector<sessions::SerializedNavigationEntry>& navigations = 424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) tab.navigations; 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_index = static_cast<int>(navigations.size()); 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Determine the first navigation we'll persist. 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int valid_count_before_selected = 0; 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int first_index_to_persist = selected_index; 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = selected_index - 1; i >= 0 && 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) valid_count_before_selected < max_persist_navigation_count; --i) { 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ShouldTrackEntry(navigations[i].virtual_url())) { 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first_index_to_persist = i; 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) valid_count_before_selected++; 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Write the command that identifies the selected tab. 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommand( 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateSelectedNavigationInTabCommand(tab.id, 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) valid_count_before_selected, 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab.timestamp)); 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tab.pinned) { 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PinnedStatePayload payload = true; 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SessionCommand* command = 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new SessionCommand(kCommandPinnedState, sizeof(payload)); 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(command->contents(), &payload, sizeof(payload)); 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommand(command); 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!tab.extension_app_id.empty()) { 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommand( 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateSetTabExtensionAppIDCommand(kCommandSetExtensionAppID, tab.id, 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab.extension_app_id)); 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!tab.user_agent_override.empty()) { 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommand( 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateSetTabUserAgentOverrideCommand(kCommandSetTabUserAgentOverride, 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab.id, tab.user_agent_override)); 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Then write the navigations. 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = first_index_to_persist, wrote_count = 0; 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i < max_index && wrote_count < 2 * max_persist_navigation_count; ++i) { 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ShouldTrackEntry(navigations[i].virtual_url())) { 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommand( 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateUpdateTabNavigationCommand(kCommandUpdateTabNavigation, tab.id, 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) navigations[i])); 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SessionCommand* PersistentTabRestoreService::Delegate::CreateWindowCommand( 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SessionID::id_type id, 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int selected_tab_index, 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_tabs, 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time timestamp) { 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WindowPayload2 payload; 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |timestamp| is aligned on a 16 byte boundary, leaving 4 bytes of 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // uninitialized memory in the struct. 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&payload, 0, sizeof(payload)); 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) payload.window_id = id; 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) payload.selected_tab_index = selected_tab_index; 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) payload.num_tabs = num_tabs; 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) payload.timestamp = timestamp.ToInternalValue(); 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SessionCommand* command = 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new SessionCommand(kCommandWindow, sizeof(payload)); 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(command->contents(), &payload, sizeof(payload)); 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return command; 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SessionCommand* 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PersistentTabRestoreService::Delegate::CreateSelectedNavigationInTabCommand( 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SessionID::id_type tab_id, 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 index, 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time timestamp) { 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SelectedNavigationInTabPayload2 payload; 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) payload.id = tab_id; 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) payload.index = index; 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) payload.timestamp = timestamp.ToInternalValue(); 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SessionCommand* command = 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new SessionCommand(kCommandSelectedNavigationInTab, sizeof(payload)); 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(command->contents(), &payload, sizeof(payload)); 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return command; 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SessionCommand* 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PersistentTabRestoreService::Delegate::CreateRestoredEntryCommand( 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SessionID::id_type entry_id) { 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RestoredEntryPayload payload = entry_id; 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SessionCommand* command = 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new SessionCommand(kCommandRestoredEntry, sizeof(payload)); 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(command->contents(), &payload, sizeof(payload)); 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return command; 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int PersistentTabRestoreService::Delegate::GetSelectedNavigationIndexToPersist( 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Tab& tab) { 525c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::vector<sessions::SerializedNavigationEntry>& navigations = 526c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) tab.navigations; 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int selected_index = tab.current_navigation_index; 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_index = static_cast<int>(navigations.size()); 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Find the first navigation to persist. We won't persist the selected 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // navigation if ShouldTrackEntry returns false. 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (selected_index >= 0 && 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !ShouldTrackEntry(navigations[selected_index].virtual_url())) { 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selected_index--; 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (selected_index != -1) 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return selected_index; 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Couldn't find a navigation to persist going back, go forward. 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selected_index = tab.current_navigation_index + 1; 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (selected_index < max_index && 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !ShouldTrackEntry(navigations[selected_index].virtual_url())) { 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selected_index++; 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (selected_index == max_index) ? -1 : selected_index; 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PersistentTabRestoreService::Delegate::OnGotLastSessionCommands( 5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ScopedVector<SessionCommand> commands) { 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<Entry*> entries; 5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateEntriesFromCommands(commands.get(), &entries); 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Closed tabs always go to the end. 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) staging_entries_.insert(staging_entries_.end(), entries.begin(), 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entries.end()); 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) load_state_ |= LOADED_LAST_TABS; 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadStateChanged(); 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PersistentTabRestoreService::Delegate::CreateEntriesFromCommands( 5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<SessionCommand*>& commands, 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<Entry*>* loaded_entries) { 5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (tab_restore_service_helper_->entries().size() == kMaxEntries) 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Iterate through the commands populating entries and id_to_entry. 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedVector<Entry> entries; 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDToEntry id_to_entry; 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If non-null we're processing the navigations of this tab. 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Tab* current_tab = NULL; 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If non-null we're processing the tabs of this window. 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Window* current_window = NULL; 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If > 0, we've gotten a window command but not all the tabs yet. 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int pending_window_tabs = 0; 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<SessionCommand*>::const_iterator i = commands.begin(); 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != commands.end(); ++i) { 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SessionCommand& command = *(*i); 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (command.id()) { 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kCommandRestoredEntry: { 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pending_window_tabs > 0) { 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Should never receive a restored command while waiting for all the 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // tabs in a window. 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_tab = NULL; 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_window = NULL; 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RestoredEntryPayload payload; 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!command.GetPayload(&payload, sizeof(payload))) 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RemoveEntryByID(payload, &id_to_entry, &(entries.get())); 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kCommandWindow: { 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WindowPayload2 payload; 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pending_window_tabs > 0) { 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Should never receive a window command while waiting for all the 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // tabs in a window. 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Try the new payload first 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!command.GetPayload(&payload, sizeof(payload))) { 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // then the old payload 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WindowPayload old_payload; 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!command.GetPayload(&old_payload, sizeof(old_payload))) 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Copy the old payload data to the new payload. 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) payload.window_id = old_payload.window_id; 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) payload.selected_tab_index = old_payload.selected_tab_index; 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) payload.num_tabs = old_payload.num_tabs; 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Since we don't have a time use time 0 which is used to mark as an 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // unknown timestamp. 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) payload.timestamp = 0; 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_window_tabs = payload.num_tabs; 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pending_window_tabs <= 0) { 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Should always have at least 1 tab. Likely indicates corruption. 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RemoveEntryByID(payload.window_id, &id_to_entry, &(entries.get())); 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_window = new Window(); 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_window->selected_tab_index = payload.selected_tab_index; 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_window->timestamp = 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time::FromInternalValue(payload.timestamp); 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entries.push_back(current_window); 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) id_to_entry[payload.window_id] = current_window; 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kCommandSelectedNavigationInTab: { 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SelectedNavigationInTabPayload2 payload; 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!command.GetPayload(&payload, sizeof(payload))) { 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SelectedNavigationInTabPayload old_payload; 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!command.GetPayload(&old_payload, sizeof(old_payload))) 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) payload.id = old_payload.id; 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) payload.index = old_payload.index; 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Since we don't have a time use time 0 which is used to mark as an 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // unknown timestamp. 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) payload.timestamp = 0; 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pending_window_tabs > 0) { 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!current_window) { 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We should have created a window already. 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_window->tabs.resize(current_window->tabs.size() + 1); 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_tab = &(current_window->tabs.back()); 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (--pending_window_tabs == 0) 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_window = NULL; 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RemoveEntryByID(payload.id, &id_to_entry, &(entries.get())); 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_tab = new Tab(); 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) id_to_entry[payload.id] = current_tab; 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_tab->timestamp = 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time::FromInternalValue(payload.timestamp); 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entries.push_back(current_tab); 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_tab->current_navigation_index = payload.index; 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kCommandUpdateTabNavigation: { 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!current_tab) { 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Should be in a tab when we get this. 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_tab->navigations.resize(current_tab->navigations.size() + 1); 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SessionID::id_type tab_id; 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!RestoreUpdateTabNavigationCommand( 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) command, ¤t_tab->navigations.back(), &tab_id)) { 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kCommandPinnedState: { 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!current_tab) { 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Should be in a tab when we get this. 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: payload doesn't matter. kCommandPinnedState is only written if 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // tab is pinned. 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_tab->pinned = true; 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kCommandSetWindowAppName: { 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!current_window) { 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We should have created a window already. 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SessionID::id_type window_id; 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string app_name; 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!RestoreSetWindowAppNameCommand(command, &window_id, &app_name)) 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_window->app_name.swap(app_name); 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kCommandSetExtensionAppID: { 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!current_tab) { 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Should be in a tab when we get this. 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SessionID::id_type tab_id; 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string extension_app_id; 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!RestoreSetTabExtensionAppIDCommand(command, &tab_id, 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &extension_app_id)) { 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_tab->extension_app_id.swap(extension_app_id); 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kCommandSetTabUserAgentOverride: { 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!current_tab) { 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Should be in a tab when we get this. 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SessionID::id_type tab_id; 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string user_agent_override; 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!RestoreSetTabUserAgentOverrideCommand(command, &tab_id, 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &user_agent_override)) { 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_tab->user_agent_override.swap(user_agent_override); 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Unknown type, usually indicates corruption of file. Ignore it. 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If there was corruption some of the entries won't be valid. 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ValidateAndDeleteEmptyEntries(&(entries.get())); 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) loaded_entries->swap(entries.get()); 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PersistentTabRestoreService::Delegate::ValidateAndDeleteEmptyEntries( 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<Entry*>* entries) { 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<Entry*> valid_entries; 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<Entry*> invalid_entries; 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Iterate from the back so that we keep the most recently closed entries. 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<Entry*>::reverse_iterator i = entries->rbegin(); 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != entries->rend(); ++i) { 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (TabRestoreServiceHelper::ValidateEntry(*i)) 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) valid_entries.push_back(*i); 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) invalid_entries.push_back(*i); 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: at this point the entries are ordered with newest at the front. 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entries->swap(valid_entries); 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Delete the remaining entries. 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STLDeleteElements(&invalid_entries); 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PersistentTabRestoreService::Delegate::OnGotPreviousSession( 7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ScopedVector<SessionWindow> windows, 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SessionID::id_type ignored_active_window) { 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<Entry*> entries; 7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateEntriesFromWindows(&windows.get(), &entries); 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Previous session tabs go first. 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) staging_entries_.insert(staging_entries_.begin(), entries.begin(), 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entries.end()); 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) load_state_ |= LOADED_LAST_SESSION; 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadStateChanged(); 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PersistentTabRestoreService::Delegate::ConvertSessionWindowToWindow( 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SessionWindow* session_window, 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Window* window) { 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < session_window->tabs.size(); ++i) { 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!session_window->tabs[i]->navigations.empty()) { 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window->tabs.resize(window->tabs.size() + 1); 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Tab& tab = window->tabs.back(); 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab.pinned = session_window->tabs[i]->pinned; 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab.navigations.swap(session_window->tabs[i]->navigations); 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab.current_navigation_index = 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) session_window->tabs[i]->current_navigation_index; 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab.extension_app_id = session_window->tabs[i]->extension_app_id; 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab.timestamp = base::Time(); 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (window->tabs.empty()) 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window->selected_tab_index = 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::min(session_window->selected_tab_index, 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>(window->tabs.size() - 1)); 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window->timestamp = base::Time(); 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PersistentTabRestoreService::Delegate::LoadStateChanged() { 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((load_state_ & (LOADED_LAST_TABS | LOADED_LAST_SESSION)) != 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (LOADED_LAST_TABS | LOADED_LAST_SESSION)) { 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Still waiting on previous session or previous tabs. 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We're done loading. 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) load_state_ ^= LOADING; 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Entries& entries = tab_restore_service_helper_->entries(); 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (staging_entries_.empty() || entries.size() >= kMaxEntries) { 826c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) staging_entries_.clear(); 827a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) tab_restore_service_helper_->NotifyLoaded(); 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (staging_entries_.size() + entries.size() > kMaxEntries) { 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we add all the staged entries we'll end up with more than 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // kMaxEntries. Delete entries such that we only end up with at most 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // kMaxEntries. 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int surplus = kMaxEntries - entries.size(); 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_LE(0, surplus); 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_GE(static_cast<int>(staging_entries_.size()), surplus); 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) staging_entries_.erase( 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) staging_entries_.begin() + (kMaxEntries - entries.size()), 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) staging_entries_.end()); 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // And add them. 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < staging_entries_.size(); ++i) { 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) staging_entries_[i]->from_last_session = true; 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_restore_service_helper_->AddEntry(staging_entries_[i], false, false); 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // AddEntry takes ownership of the entry, need to clear out entries so that 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // it doesn't delete them. 851c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) staging_entries_.weak_clear(); 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make it so we rewrite all the tabs. We need to do this otherwise we won't 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // correctly write out the entries when Save is invoked (Save starts from 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the front, not the end and we just added the entries to the end). 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entries_to_write_ = staging_entries_.size(); 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_restore_service_helper_->PruneEntries(); 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_restore_service_helper_->NotifyTabsChanged(); 860a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 861a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) tab_restore_service_helper_->NotifyLoaded(); 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PersistentTabRestoreService::Delegate::RemoveEntryByID( 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SessionID::id_type id, 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDToEntry* id_to_entry, 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<TabRestoreService::Entry*>* entries) { 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Look for the entry in the map. If it is present, erase it from both 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // collections and return. 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDToEntry::iterator i = id_to_entry->find(id); 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i != id_to_entry->end()) { 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entries->erase(std::find(entries->begin(), entries->end(), i->second)); 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete i->second; 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) id_to_entry->erase(i); 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Otherwise, loop over all items in the map and see if any of the Windows 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // have Tabs with the |id|. 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (IDToEntry::iterator i = id_to_entry->begin(); i != id_to_entry->end(); 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++i) { 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i->second->type == TabRestoreService::WINDOW) { 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabRestoreService::Window* window = 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<TabRestoreService::Window*>(i->second); 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<TabRestoreService::Tab>::iterator j = window->tabs.begin(); 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for ( ; j != window->tabs.end(); ++j) { 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the ID matches one of this window's tabs, remove it from the 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // list. 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((*j).id == id) { 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window->tabs.erase(j); 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// PersistentTabRestoreService ------------------------------------------------- 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PersistentTabRestoreService::PersistentTabRestoreService( 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* profile, 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeFactory* time_factory) 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : delegate_(new Delegate(profile)), 904c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) helper_(this, delegate_.get(), profile, time_factory) { 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->set_tab_restore_service_helper(&helper_); 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PersistentTabRestoreService::~PersistentTabRestoreService() {} 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PersistentTabRestoreService::AddObserver( 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabRestoreServiceObserver* observer) { 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) helper_.AddObserver(observer); 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PersistentTabRestoreService::RemoveObserver( 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabRestoreServiceObserver* observer) { 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) helper_.RemoveObserver(observer); 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PersistentTabRestoreService::CreateHistoricalTab( 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::WebContents* contents, 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index) { 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) helper_.CreateHistoricalTab(contents, index); 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PersistentTabRestoreService::BrowserClosing( 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabRestoreServiceDelegate* delegate) { 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) helper_.BrowserClosing(delegate); 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PersistentTabRestoreService::BrowserClosed( 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabRestoreServiceDelegate* delegate) { 9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) helper_.BrowserClosed(delegate); 9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PersistentTabRestoreService::ClearEntries() { 9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) helper_.ClearEntries(); 9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const TabRestoreService::Entries& PersistentTabRestoreService::entries() const { 9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return helper_.entries(); 9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9443240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochstd::vector<content::WebContents*> 9453240926e260ce088908e02ac07a6cf7b0c0cbf44Ben MurdochPersistentTabRestoreService::RestoreMostRecentEntry( 9462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TabRestoreServiceDelegate* delegate, 9472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) chrome::HostDesktopType host_desktop_type) { 9483240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch return helper_.RestoreMostRecentEntry(delegate, host_desktop_type); 9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TabRestoreService::Tab* PersistentTabRestoreService::RemoveTabEntryById( 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SessionID::id_type id) { 9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return helper_.RemoveTabEntryById(id); 9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9563240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochstd::vector<content::WebContents*> 9573240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch PersistentTabRestoreService::RestoreEntryById( 9583240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch TabRestoreServiceDelegate* delegate, 9593240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch SessionID::id_type id, 9603240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch chrome::HostDesktopType host_desktop_type, 9613240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch WindowOpenDisposition disposition) { 9623240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch return helper_.RestoreEntryById(delegate, id, host_desktop_type, disposition); 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PersistentTabRestoreService::IsLoaded() const { 9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return delegate_->IsLoaded(); 9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PersistentTabRestoreService::DeleteLastSession() { 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return delegate_->DeleteLastSession(); 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PersistentTabRestoreService::Shutdown() { 9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return delegate_->Shutdown(); 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PersistentTabRestoreService::LoadTabsFromLastSession() { 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->LoadTabsFromLastSession(); 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TabRestoreService::Entries* PersistentTabRestoreService::mutable_entries() { 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return &helper_.entries_; 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PersistentTabRestoreService::PruneEntries() { 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) helper_.PruneEntries(); 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 989a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)KeyedService* TabRestoreServiceFactory::BuildServiceInstanceFor( 990c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) content::BrowserContext* profile) const { 991c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return new PersistentTabRestoreService(static_cast<Profile*>(profile), NULL); 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 993