| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef CHROME_BROWSER_SESSIONS_TAB_RESTORE_SERVICE_H_ | 5 #ifndef CHROME_BROWSER_SESSIONS_TAB_RESTORE_SERVICE_H_ |
| 6 #define CHROME_BROWSER_SESSIONS_TAB_RESTORE_SERVICE_H_ | 6 #define CHROME_BROWSER_SESSIONS_TAB_RESTORE_SERVICE_H_ |
| 7 | 7 |
| 8 #include <list> | 8 #include <list> |
| 9 #include <set> | 9 #include <string> |
| 10 #include <vector> | 10 #include <vector> |
| 11 | 11 |
| 12 #include "base/gtest_prod_util.h" | 12 #include "base/memory/ref_counted.h" |
| 13 #include "base/observer_list.h" | |
| 14 #include "base/time.h" | 13 #include "base/time.h" |
| 15 #include "chrome/browser/sessions/base_session_service.h" | 14 #include "chrome/browser/profiles/profile_keyed_service.h" |
| 16 #include "chrome/browser/sessions/session_id.h" | 15 #include "chrome/browser/sessions/session_id.h" |
| 17 #include "chrome/browser/sessions/session_types.h" | 16 #include "chrome/browser/sessions/session_types.h" |
| 18 #include "content/public/browser/session_storage_namespace.h" | 17 #include "content/public/browser/session_storage_namespace.h" |
| 19 #include "webkit/glue/window_open_disposition.h" | 18 #include "webkit/glue/window_open_disposition.h" |
| 20 | 19 |
| 21 class Profile; | |
| 22 class TabRestoreServiceDelegate; | 20 class TabRestoreServiceDelegate; |
| 23 class TabRestoreServiceObserver; | 21 class TabRestoreServiceObserver; |
| 24 struct SessionWindow; | |
| 25 | 22 |
| 26 namespace content { | 23 namespace content { |
| 27 class NavigationController; | |
| 28 class SessionStorageNamespace; | 24 class SessionStorageNamespace; |
| 29 class WebContents; | 25 class WebContents; |
| 30 } | 26 } |
| 31 | 27 |
| 32 // TabRestoreService is responsible for maintaining the most recently closed | 28 // TabRestoreService is responsible for maintaining the most recently closed |
| 33 // tabs and windows. When a tab is closed | 29 // tabs and windows. When a tab is closed |
| 34 // TabRestoreService::CreateHistoricalTab is invoked and a Tab is created to | 30 // TabRestoreService::CreateHistoricalTab is invoked and a Tab is created to |
| 35 // represent the tab. Similarly, when a browser is closed, BrowserClosing is | 31 // represent the tab. Similarly, when a browser is closed, BrowserClosing is |
| 36 // invoked and a Window is created to represent the window. | 32 // invoked and a Window is created to represent the window. |
| 37 // | 33 // |
| 38 // To restore a tab/window from the TabRestoreService invoke RestoreEntryById | 34 // To restore a tab/window from the TabRestoreService invoke RestoreEntryById |
| 39 // or RestoreMostRecentEntry. | 35 // or RestoreMostRecentEntry. |
| 40 // | 36 // |
| 41 // To listen for changes to the set of entries managed by the TabRestoreService | 37 // To listen for changes to the set of entries managed by the TabRestoreService |
| 42 // add an observer. | 38 // add an observer. |
| 43 class TabRestoreService : public BaseSessionService { | 39 class TabRestoreService : public ProfileKeyedService { |
| 44 public: | 40 public: |
| 45 // Interface used to allow the test to provide a custom time. | 41 // Interface used to allow the test to provide a custom time. |
| 46 class TimeFactory { | 42 class TimeFactory { |
| 47 public: | 43 public: |
| 48 virtual ~TimeFactory(); | 44 virtual ~TimeFactory(); |
| 49 virtual base::Time TimeNow() = 0; | 45 virtual base::Time TimeNow() = 0; |
| 50 }; | 46 }; |
| 51 | 47 |
| 52 // The type of entry. | 48 // The type of entry. |
| 53 enum Type { | 49 enum Type { |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 119 | 115 |
| 120 // Index of the selected tab. | 116 // Index of the selected tab. |
| 121 int selected_tab_index; | 117 int selected_tab_index; |
| 122 | 118 |
| 123 // If an application window, the name of the app. | 119 // If an application window, the name of the app. |
| 124 std::string app_name; | 120 std::string app_name; |
| 125 }; | 121 }; |
| 126 | 122 |
| 127 typedef std::list<Entry*> Entries; | 123 typedef std::list<Entry*> Entries; |
| 128 | 124 |
| 129 // Creates a new TabRestoreService and provides an object that provides the | |
| 130 // current time. The TabRestoreService does not take ownership of the | |
| 131 // |time_factory_|. | |
| 132 TabRestoreService(Profile* profile, TimeFactory* time_factory_ = NULL); | |
| 133 | |
| 134 virtual ~TabRestoreService(); | 125 virtual ~TabRestoreService(); |
| 135 | 126 |
| 136 // Adds/removes an observer. TabRestoreService does not take ownership of | 127 // Adds/removes an observer. TabRestoreService does not take ownership of |
| 137 // the observer. | 128 // the observer. |
| 138 void AddObserver(TabRestoreServiceObserver* observer); | 129 virtual void AddObserver(TabRestoreServiceObserver* observer) = 0; |
| 139 void RemoveObserver(TabRestoreServiceObserver* observer); | 130 virtual void RemoveObserver(TabRestoreServiceObserver* observer) = 0; |
| 140 | 131 |
| 141 // Creates a Tab to represent |contents| and notifies observers the list of | 132 // Creates a Tab to represent |contents| and notifies observers the list of |
| 142 // entries has changed. | 133 // entries has changed. |
| 143 void CreateHistoricalTab(content::WebContents* contents, int index); | 134 virtual void CreateHistoricalTab(content::WebContents* contents, |
| 135 int index) = 0; |
| 144 | 136 |
| 145 // Invoked when a browser is closing. If |delegate| is a tabbed browser with | 137 // Invoked when a browser is closing. If |delegate| is a tabbed browser with |
| 146 // at least one tab, a Window is created, added to entries and observers are | 138 // at least one tab, a Window is created, added to entries and observers are |
| 147 // notified. | 139 // notified. |
| 148 void BrowserClosing(TabRestoreServiceDelegate* delegate); | 140 virtual void BrowserClosing(TabRestoreServiceDelegate* delegate) = 0; |
| 149 | 141 |
| 150 // Invoked when the browser is done closing. | 142 // Invoked when the browser is done closing. |
| 151 void BrowserClosed(TabRestoreServiceDelegate* delegate); | 143 virtual void BrowserClosed(TabRestoreServiceDelegate* delegate) = 0; |
| 152 | 144 |
| 153 // Removes all entries from the list and notifies observers the list | 145 // Removes all entries from the list and notifies observers the list |
| 154 // of tabs has changed. | 146 // of tabs has changed. |
| 155 void ClearEntries(); | 147 virtual void ClearEntries() = 0; |
| 156 | 148 |
| 157 // Returns the entries, ordered with most recently closed entries at the | 149 // Returns the entries, ordered with most recently closed entries at the |
| 158 // front. | 150 // front. |
| 159 virtual const Entries& entries() const; | 151 virtual const Entries& entries() const = 0; |
| 160 | 152 |
| 161 // Restores the most recently closed entry. Does nothing if there are no | 153 // Restores the most recently closed entry. Does nothing if there are no |
| 162 // entries to restore. If the most recently restored entry is a tab, it is | 154 // entries to restore. If the most recently restored entry is a tab, it is |
| 163 // added to |delegate|. | 155 // added to |delegate|. |
| 164 void RestoreMostRecentEntry(TabRestoreServiceDelegate* delegate); | 156 virtual void RestoreMostRecentEntry(TabRestoreServiceDelegate* delegate) = 0; |
| 165 | 157 |
| 166 // Removes the Tab with id |id| from the list and returns it; ownership is | 158 // Removes the Tab with id |id| from the list and returns it; ownership is |
| 167 // passed to the caller. | 159 // passed to the caller. |
| 168 Tab* RemoveTabEntryById(SessionID::id_type id); | 160 virtual Tab* RemoveTabEntryById(SessionID::id_type id) = 0; |
| 169 | 161 |
| 170 // Restores an entry by id. If there is no entry with an id matching |id|, | 162 // Restores an entry by id. If there is no entry with an id matching |id|, |
| 171 // this does nothing. If |delegate| is NULL, this creates a new window for the | 163 // this does nothing. If |delegate| is NULL, this creates a new window for the |
| 172 // entry. |disposition| is respected, but the attributes (tabstrip index, | 164 // entry. |disposition| is respected, but the attributes (tabstrip index, |
| 173 // browser window) of the tab when it was closed will be respected if | 165 // browser window) of the tab when it was closed will be respected if |
| 174 // disposition is UNKNOWN. | 166 // disposition is UNKNOWN. |
| 175 void RestoreEntryById(TabRestoreServiceDelegate* delegate, | 167 virtual void RestoreEntryById(TabRestoreServiceDelegate* delegate, |
| 176 SessionID::id_type id, | 168 SessionID::id_type id, |
| 177 WindowOpenDisposition disposition); | 169 WindowOpenDisposition disposition) = 0; |
| 178 | 170 |
| 179 // Loads the tabs and previous session. This does nothing if the tabs | 171 // Loads the tabs and previous session. This does nothing if the tabs |
| 180 // from the previous session have already been loaded. | 172 // from the previous session have already been loaded. |
| 181 void LoadTabsFromLastSession(); | 173 virtual void LoadTabsFromLastSession() = 0; |
| 182 | 174 |
| 183 // Returns true if the tab entries have been loaded. | 175 // Returns true if the tab entries have been loaded. |
| 184 bool IsLoaded() const; | 176 virtual bool IsLoaded() const = 0; |
| 185 | 177 |
| 186 // Max number of entries we'll keep around. | 178 // Deletes the last session. |
| 187 static const size_t kMaxEntries; | 179 virtual void DeleteLastSession() = 0; |
| 188 | |
| 189 // Creates and add entries to |entries| for each of the windows in |windows|. | |
| 190 void CreateEntriesFromWindows(std::vector<SessionWindow*>* windows, | |
| 191 std::vector<Entry*>* entries); | |
| 192 | |
| 193 protected: | |
| 194 // ProfileKeyedService: | |
| 195 virtual void Shutdown() OVERRIDE; | |
| 196 | |
| 197 // BaseSessionService: | |
| 198 virtual void Save() OVERRIDE; | |
| 199 | |
| 200 private: | |
| 201 friend class TabRestoreServiceTest; | |
| 202 FRIEND_TEST_ALL_PREFIXES(TabRestoreServiceTest, PruneEntries); | |
| 203 FRIEND_TEST_ALL_PREFIXES(TabRestoreServiceTest, PruneIsCalled); | |
| 204 | |
| 205 // Used to indicate what has loaded. | |
| 206 enum LoadState { | |
| 207 // Indicates we haven't loaded anything. | |
| 208 NOT_LOADED = 1 << 0, | |
| 209 | |
| 210 // Indicates we've asked for the last sessions and tabs but haven't gotten | |
| 211 // the result back yet. | |
| 212 LOADING = 1 << 2, | |
| 213 | |
| 214 // Indicates we finished loading the last tabs (but not necessarily the | |
| 215 // last session). | |
| 216 LOADED_LAST_TABS = 1 << 3, | |
| 217 | |
| 218 // Indicates we finished loading the last session (but not necessarily the | |
| 219 // last tabs). | |
| 220 LOADED_LAST_SESSION = 1 << 4 | |
| 221 }; | |
| 222 | |
| 223 // Populates the tab's navigations from the NavigationController, and its | |
| 224 // browser_id and pinned state from the browser. | |
| 225 void PopulateTab(Tab* tab, | |
| 226 int index, | |
| 227 TabRestoreServiceDelegate* delegate, | |
| 228 content::NavigationController* controller); | |
| 229 | |
| 230 // Notifies observers the tabs have changed. | |
| 231 void NotifyTabsChanged(); | |
| 232 | |
| 233 // Adds |entry| to the list of entries and takes ownership. If |prune| is true | |
| 234 // |PruneAndNotify| is invoked. If |to_front| is true the entry is added to | |
| 235 // the front, otherwise the back. Normal closes go to the front, but | |
| 236 // tab/window closes from the previous session are added to the back. | |
| 237 void AddEntry(Entry* entry, bool prune, bool to_front); | |
| 238 | |
| 239 // Prunes entries_ to contain only kMaxEntries, and removes uninteresting | |
| 240 // entries. | |
| 241 void PruneEntries(); | |
| 242 | |
| 243 // Returns an iterator into entries_ whose id matches |id|. If |id| identifies | |
| 244 // a Window, then its iterator position will be returned. If it identifies a | |
| 245 // tab, then the iterator position of the Window in which the Tab resides is | |
| 246 // returned. | |
| 247 Entries::iterator GetEntryIteratorById(SessionID::id_type id); | |
| 248 | |
| 249 // Schedules the commands for a window close. | |
| 250 void ScheduleCommandsForWindow(const Window& window); | |
| 251 | |
| 252 // Schedules the commands for a tab close. |selected_index| gives the | |
| 253 // index of the selected navigation. | |
| 254 void ScheduleCommandsForTab(const Tab& tab, int selected_index); | |
| 255 | |
| 256 // Creates a window close command. | |
| 257 SessionCommand* CreateWindowCommand(SessionID::id_type id, | |
| 258 int selected_tab_index, | |
| 259 int num_tabs, | |
| 260 base::Time timestamp); | |
| 261 | |
| 262 // Creates a tab close command. | |
| 263 SessionCommand* CreateSelectedNavigationInTabCommand( | |
| 264 SessionID::id_type tab_id, | |
| 265 int32 index, | |
| 266 base::Time timestamp); | |
| 267 | |
| 268 // Creates a restore command. | |
| 269 SessionCommand* CreateRestoredEntryCommand(SessionID::id_type entry_id); | |
| 270 | |
| 271 // Returns the index to persist as the selected index. This is the same | |
| 272 // as |tab.current_navigation_index| unless the entry at | |
| 273 // |tab.current_navigation_index| shouldn't be persisted. Returns -1 if | |
| 274 // no valid navigation to persist. | |
| 275 int GetSelectedNavigationIndexToPersist(const Tab& tab); | |
| 276 | |
| 277 // Invoked when we've loaded the session commands that identify the | |
| 278 // previously closed tabs. This creates entries, adds them to | |
| 279 // staging_entries_, and invokes LoadState. | |
| 280 void OnGotLastSessionCommands( | |
| 281 Handle handle, | |
| 282 scoped_refptr<InternalGetCommandsRequest> request); | |
| 283 | |
| 284 // Populates |loaded_entries| with Entries from |request|. | |
| 285 void CreateEntriesFromCommands( | |
| 286 scoped_refptr<InternalGetCommandsRequest> request, | |
| 287 std::vector<Entry*>* loaded_entries); | |
| 288 | |
| 289 // This is a helper function for RestoreEntryById() for restoring a single | |
| 290 // tab. If |delegate| is NULL, this creates a new window for the entry. This | |
| 291 // returns the TabRestoreServiceDelegate into which the tab was restored. | |
| 292 // |disposition| will be respected, but if it is UNKNOWN then the tab's | |
| 293 // original attributes will be respected instead. | |
| 294 TabRestoreServiceDelegate* RestoreTab(const Tab& tab, | |
| 295 TabRestoreServiceDelegate* delegate, | |
| 296 WindowOpenDisposition disposition); | |
| 297 | |
| 298 // Returns true if |tab| has more than one navigation. If |tab| has more | |
| 299 // than one navigation |tab->current_navigation_index| is constrained based | |
| 300 // on the number of navigations. | |
| 301 static bool ValidateTab(Tab* tab); | |
| 302 | |
| 303 // Validates all the tabs in a window, plus the window's active tab index. | |
| 304 static bool ValidateWindow(Window* window); | |
| 305 | |
| 306 // Calls either ValidateTab or ValidateWindow as appropriate. | |
| 307 static bool ValidateEntry(Entry* entry); | |
| 308 | |
| 309 // Returns true if |tab| is one we care about restoring. | |
| 310 static bool IsTabInteresting(const Tab* tab); | |
| 311 | |
| 312 // Checks whether |window| is interesting --- if it only contains a single, | |
| 313 // uninteresting tab, it's not interesting. | |
| 314 static bool IsWindowInteresting(const Window* window); | |
| 315 | |
| 316 // Validates and checks |entry| for interesting. | |
| 317 static bool FilterEntry(Entry* entry); | |
| 318 | |
| 319 // Validates all entries in |entries|, deleting any with no navigations. | |
| 320 // This also deletes any entries beyond the max number of entries we can | |
| 321 // hold. | |
| 322 void ValidateAndDeleteEmptyEntries(std::vector<Entry*>* entries); | |
| 323 | |
| 324 // Finds tab entries with the old browser_id and sets it to the new one. | |
| 325 void UpdateTabBrowserIDs(SessionID::id_type old_id, | |
| 326 SessionID::id_type new_id); | |
| 327 | |
| 328 // Callback from SessionService when we've received the windows from the | |
| 329 // previous session. This creates and add entries to |staging_entries_| | |
| 330 // and invokes LoadStateChanged. |ignored_active_window| is ignored because | |
| 331 // we don't need to restore activation. | |
| 332 void OnGotPreviousSession(Handle handle, | |
| 333 std::vector<SessionWindow*>* windows, | |
| 334 SessionID::id_type ignored_active_window); | |
| 335 | |
| 336 // Converts a SessionWindow into a Window, returning true on success. We use 0 | |
| 337 // as the timestamp here since we do not know when the window/tab was closed. | |
| 338 bool ConvertSessionWindowToWindow( | |
| 339 SessionWindow* session_window, | |
| 340 Window* window); | |
| 341 | |
| 342 // Invoked when previous tabs or session is loaded. If both have finished | |
| 343 // loading the entries in staging_entries_ are added to entries_ and | |
| 344 // observers are notified. | |
| 345 void LoadStateChanged(); | |
| 346 | |
| 347 // Gets the current time. This uses the time_factory_ if there is one. | |
| 348 base::Time TimeNow() const; | |
| 349 | |
| 350 // Set of entries. They are ordered from most to least recent. | |
| 351 Entries entries_; | |
| 352 | |
| 353 // Whether we've loaded the last session. | |
| 354 int load_state_; | |
| 355 | |
| 356 // Are we restoring a tab? If this is true we ignore requests to create a | |
| 357 // historical tab. | |
| 358 bool restoring_; | |
| 359 | |
| 360 // The number of entries to write. | |
| 361 int entries_to_write_; | |
| 362 | |
| 363 // Number of entries we've written. | |
| 364 int entries_written_; | |
| 365 | |
| 366 ObserverList<TabRestoreServiceObserver> observer_list_; | |
| 367 | |
| 368 // Set of delegates that we've received a BrowserClosing method for but no | |
| 369 // corresponding BrowserClosed. We cache the set of delegates closing to | |
| 370 // avoid creating historical tabs for them. | |
| 371 std::set<TabRestoreServiceDelegate*> closing_delegates_; | |
| 372 | |
| 373 // Used when loading open tabs/session when recovering from a crash. | |
| 374 CancelableRequestConsumer crash_consumer_; | |
| 375 | |
| 376 // Used when loading previous tabs/session. | |
| 377 CancelableRequestConsumer load_consumer_; | |
| 378 | |
| 379 // Results from previously closed tabs/sessions is first added here. When | |
| 380 // the results from both us and the session restore service have finished | |
| 381 // loading LoadStateChanged is invoked, which adds these entries to | |
| 382 // entries_. | |
| 383 std::vector<Entry*> staging_entries_; | |
| 384 | |
| 385 TimeFactory* time_factory_; | |
| 386 | |
| 387 DISALLOW_COPY_AND_ASSIGN(TabRestoreService); | |
| 388 }; | 180 }; |
| 389 | 181 |
| 390 #endif // CHROME_BROWSER_SESSIONS_TAB_RESTORE_SERVICE_H_ | 182 #endif // CHROME_BROWSER_SESSIONS_TAB_RESTORE_SERVICE_H_ |
| OLD | NEW |