tab_restore_service.h revision c407dc5cd9bdc5668497f21b26b09d988ab439de
1// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#ifndef CHROME_BROWSER_SESSIONS_TAB_RESTORE_SERVICE_H_ 6#define CHROME_BROWSER_SESSIONS_TAB_RESTORE_SERVICE_H_ 7 8#include <list> 9#include <set> 10#include <vector> 11 12#include "base/observer_list.h" 13#include "base/time.h" 14#include "chrome/browser/sessions/base_session_service.h" 15#include "chrome/browser/sessions/session_id.h" 16#include "chrome/browser/sessions/session_types.h" 17 18class Browser; 19class NavigationController; 20class Profile; 21struct SessionWindow; 22 23// TabRestoreService is responsible for maintaining the most recently closed 24// tabs and windows. When a tab is closed 25// TabRestoreService::CreateHistoricalTab is invoked and a Tab is created to 26// represent the tab. Similarly, when a browser is closed, BrowserClosing is 27// invoked and a Window is created to represent the window. 28// 29// To restore a tab/window from the TabRestoreService invoke RestoreEntryById 30// or RestoreMostRecentEntry. 31// 32// To listen for changes to the set of entries managed by the TabRestoreService 33// add an observer. 34class TabRestoreService : public BaseSessionService { 35 public: 36 // Observer is notified when the set of entries managed by TabRestoreService 37 // changes in some way. 38 class Observer { 39 public: 40 // Sent when the set of entries changes in some way. 41 virtual void TabRestoreServiceChanged(TabRestoreService* service) = 0; 42 43 // Sent to all remaining Observers when TabRestoreService's 44 // destructor is run. 45 virtual void TabRestoreServiceDestroyed(TabRestoreService* service) = 0; 46 }; 47 48 // Interface used to allow the test to provide a custom time. 49 class TimeFactory { 50 public: 51 virtual ~TimeFactory(); 52 virtual base::Time TimeNow() = 0; 53 }; 54 55 // The type of entry. 56 enum Type { 57 TAB, 58 WINDOW 59 }; 60 61 struct Entry { 62 Entry(); 63 explicit Entry(Type type); 64 virtual ~Entry(); 65 66 // Unique id for this entry. The id is guaranteed to be unique for a 67 // session. 68 SessionID::id_type id; 69 70 // The type of the entry. 71 Type type; 72 73 // The time when the window or tab was closed. 74 base::Time timestamp; 75 76 // Is this entry from the last session? This is set to true for entries that 77 // were closed during the last session, and false for entries that were 78 // closed during this session. 79 bool from_last_session; 80 }; 81 82 // Represents a previously open tab. 83 struct Tab : public Entry { 84 Tab(); 85 virtual ~Tab(); 86 87 bool has_browser() const { return browser_id > 0; } 88 89 // The navigations. 90 std::vector<TabNavigation> navigations; 91 92 // Index of the selected navigation in navigations. 93 int current_navigation_index; 94 95 // The ID of the browser to which this tab belonged, so it can be restored 96 // there. May be 0 (an invalid SessionID) when restoring an entire session. 97 SessionID::id_type browser_id; 98 99 // Index within the tab strip. May be -1 for an unknown index. 100 int tabstrip_index; 101 102 // True if the tab was pinned. 103 bool pinned; 104 105 // If non-empty gives the id of the extension for the tab. 106 std::string extension_app_id; 107 }; 108 109 // Represents a previously open window. 110 struct Window : public Entry { 111 Window(); 112 virtual ~Window(); 113 114 // The tabs that comprised the window, in order. 115 std::vector<Tab> tabs; 116 117 // Index of the selected tab. 118 int selected_tab_index; 119 }; 120 121 typedef std::list<Entry*> Entries; 122 123 // Creates a new TabRestoreService and provides an object that provides the 124 // current time. The TabRestoreService does not take ownership of the 125 // |time_factory_|. 126 explicit TabRestoreService(Profile* profile, 127 TimeFactory* time_factory_ = NULL); 128 129 // Adds/removes an observer. TabRestoreService does not take ownership of 130 // the observer. 131 void AddObserver(Observer* observer); 132 void RemoveObserver(Observer* observer); 133 134 // Creates a Tab to represent |tab| and notifies observers the list of 135 // entries has changed. 136 void CreateHistoricalTab(NavigationController* tab); 137 138 // Invoked when a browser is closing. If |browser| is a tabbed browser with 139 // at least one tab, a Window is created, added to entries and observers are 140 // notified. 141 void BrowserClosing(Browser* browser); 142 143 // Invoked when the browser is done closing. 144 void BrowserClosed(Browser* browser); 145 146 // Removes all entries from the list and notifies observers the list 147 // of tabs has changed. 148 void ClearEntries(); 149 150 // Returns the entries, ordered with most recently closed entries at the 151 // front. 152 virtual const Entries& entries() const; 153 154 // Restores the most recently closed entry. Does nothing if there are no 155 // entries to restore. If the most recently restored entry is a tab, it is 156 // added to |browser|. 157 void RestoreMostRecentEntry(Browser* browser); 158 159 // Restores an entry by id. If there is no entry with an id matching |id|, 160 // this does nothing. If |replace_existing_tab| is true and id identifies a 161 // tab, the newly created tab replaces the selected tab in |browser|. If 162 // |browser| is NULL, this creates a new window for the entry. 163 void RestoreEntryById(Browser* browser, 164 SessionID::id_type id, 165 bool replace_existing_tab); 166 167 // Loads the tabs and previous session. This does nothing if the tabs 168 // from the previous session have already been loaded. 169 void LoadTabsFromLastSession(); 170 171 // Max number of entries we'll keep around. 172 static const size_t kMaxEntries; 173 174 protected: 175 virtual void Save(); 176 177 virtual ~TabRestoreService(); 178 179 private: 180 // Used to indicate what has loaded. 181 enum LoadState { 182 // Indicates we haven't loaded anything. 183 NOT_LOADED = 1 << 0, 184 185 // Indicates we've asked for the last sessions and tabs but haven't gotten 186 // the result back yet. 187 LOADING = 1 << 2, 188 189 // Indicates we finished loading the last tabs (but not necessarily the 190 // last session). 191 LOADED_LAST_TABS = 1 << 3, 192 193 // Indicates we finished loading the last session (but not necessarily the 194 // last tabs). 195 LOADED_LAST_SESSION = 1 << 4 196 }; 197 198 // Populates the tab's navigations from the NavigationController, and its 199 // browser_id and tabstrip_index from the browser. 200 void PopulateTab(Tab* tab, 201 Browser* browser, 202 NavigationController* controller); 203 204 // Notifies observers the tabs have changed. 205 void NotifyTabsChanged(); 206 207 // Adds |entry| to the list of entries. If |prune| is true |PruneAndNotify| 208 // is invoked. If |to_front| is true the entry is added to the front, 209 // otherwise the back. Normal closes go to the front, but tab/window closes 210 // from the previous session are added to the back. 211 void AddEntry(Entry* entry, bool prune, bool to_front); 212 213 // Prunes entries_ to contain only kMaxEntries and invokes NotifyTabsChanged. 214 void PruneAndNotify(); 215 216 // Returns an iterator into entries_ whose id matches |id|. If |id| identifies 217 // a Window, then its iterator position will be returned. If it identifies a 218 // tab, then the iterator position of the Window in which the Tab resides is 219 // returned. 220 Entries::iterator GetEntryIteratorById(SessionID::id_type id); 221 222 // Schedules the commands for a window close. 223 void ScheduleCommandsForWindow(const Window& window); 224 225 // Schedules the commands for a tab close. |selected_index| gives the 226 // index of the selected navigation. 227 void ScheduleCommandsForTab(const Tab& tab, int selected_index); 228 229 // Creates a window close command. 230 SessionCommand* CreateWindowCommand(SessionID::id_type id, 231 int selected_tab_index, 232 int num_tabs, 233 base::Time timestamp); 234 235 // Creates a tab close command. 236 SessionCommand* CreateSelectedNavigationInTabCommand( 237 SessionID::id_type tab_id, 238 int32 index, 239 base::Time timestamp); 240 241 // Creates a restore command. 242 SessionCommand* CreateRestoredEntryCommand(SessionID::id_type entry_id); 243 244 // Returns the index to persist as the selected index. This is the same 245 // as |tab.current_navigation_index| unless the entry at 246 // |tab.current_navigation_index| shouldn't be persisted. Returns -1 if 247 // no valid navigation to persist. 248 int GetSelectedNavigationIndexToPersist(const Tab& tab); 249 250 // Invoked when we've loaded the session commands that identify the 251 // previously closed tabs. This creates entries, adds them to 252 // staging_entries_, and invokes LoadState. 253 void OnGotLastSessionCommands( 254 Handle handle, 255 scoped_refptr<InternalGetCommandsRequest> request); 256 257 // Populates |loaded_entries| with Entries from |request|. 258 void CreateEntriesFromCommands( 259 scoped_refptr<InternalGetCommandsRequest> request, 260 std::vector<Entry*>* loaded_entries); 261 262 // This is a helper function for RestoreEntryById() for restoring a single 263 // tab. If |replace_existing_tab| is true, the newly created tab replaces the 264 // selected tab in |browser|. If |browser| is NULL, this creates a new window 265 // for the entry. This returns the Browser into which the tab was restored. 266 Browser* RestoreTab(const Tab& tab, 267 Browser* browser, 268 bool replace_existing_tab); 269 270 // Returns true if |tab| has more than one navigation. If |tab| has more 271 // than one navigation |tab->current_navigation_index| is constrained based 272 // on the number of navigations. 273 bool ValidateTab(Tab* tab); 274 275 // Validates all entries in |entries|, deleting any with no navigations. 276 // This also deletes any entries beyond the max number of entries we can 277 // hold. 278 void ValidateAndDeleteEmptyEntries(std::vector<Entry*>* entries); 279 280 // Finds tab entries with the old browser_id and sets it to the new one. 281 void UpdateTabBrowserIDs(SessionID::id_type old_id, 282 SessionID::id_type new_id); 283 284 // Callback from SessionService when we've received the windows from the 285 // previous session. This creates and add entries to |staging_entries_| 286 // and invokes LoadStateChanged. 287 void OnGotPreviousSession(Handle handle, 288 std::vector<SessionWindow*>* windows); 289 290 // Creates and add entries to |entries| for each of the windows in |windows|. 291 void CreateEntriesFromWindows( 292 std::vector<SessionWindow*>* windows, 293 std::vector<Entry*>* entries); 294 295 // Converts a SessionWindow into a Window, returning true on success. We use 0 296 // as the timestamp here since we do not know when the window/tab was closed. 297 bool ConvertSessionWindowToWindow( 298 SessionWindow* session_window, 299 Window* window); 300 301 // Invoked when previous tabs or session is loaded. If both have finished 302 // loading the entries in staging_entries_ are added to entries_ and 303 // observers are notified. 304 void LoadStateChanged(); 305 306 // Gets the current time. This uses the time_factory_ if there is one. 307 base::Time TimeNow() const; 308 309 // Set of entries. 310 Entries entries_; 311 312 // Whether we've loaded the last session. 313 int load_state_; 314 315 // Are we restoring a tab? If this is true we ignore requests to create a 316 // historical tab. 317 bool restoring_; 318 319 // Have the max number of entries ever been created? 320 bool reached_max_; 321 322 // The number of entries to write. 323 int entries_to_write_; 324 325 // Number of entries we've written. 326 int entries_written_; 327 328 ObserverList<Observer> observer_list_; 329 330 // Set of tabs that we've received a BrowserClosing method for but no 331 // corresponding BrowserClosed. We cache the set of browsers closing to 332 // avoid creating historical tabs for them. 333 std::set<Browser*> closing_browsers_; 334 335 // Used when loading previous tabs/session. 336 CancelableRequestConsumer load_consumer_; 337 338 // Results from previously closed tabs/sessions is first added here. When 339 // the results from both us and the session restore service have finished 340 // loading LoadStateChanged is invoked, which adds these entries to 341 // entries_. 342 std::vector<Entry*> staging_entries_; 343 344 TimeFactory* time_factory_; 345 346 DISALLOW_COPY_AND_ASSIGN(TabRestoreService); 347}; 348 349#endif // CHROME_BROWSER_SESSIONS_TAB_RESTORE_SERVICE_H_ 350 351