diff options
author | sky@google.com <sky@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-12-06 19:30:19 +0000 |
---|---|---|
committer | sky@google.com <sky@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-12-06 19:30:19 +0000 |
commit | 169627b81ce036a7014476c366b060e050b5ff70 (patch) | |
tree | 6231d8cfaa065513b4742d99204b25da4178037a /chrome/browser/sessions/session_service.h | |
parent | ee824a436efbdeed4ca78efc4dd2aa4976ba43a9 (diff) | |
download | chromium_src-169627b81ce036a7014476c366b060e050b5ff70.zip chromium_src-169627b81ce036a7014476c366b060e050b5ff70.tar.gz chromium_src-169627b81ce036a7014476c366b060e050b5ff70.tar.bz2 |
Makes the tab restore service persist closed tabs/windows to disk and
reload them when asked.
Sorry for largish looking change. It's made big by refactoring common
code between TabRestoreService and SessionService into a common
superclass. At the same time I removed some dead code and shuffled the
session related classes into a single directory for easier perusal.
BUG=384
TEST=close the browser, start the browser and make sure the new tab
page shows closed windows/tabs from the previous session.
Review URL: http://codereview.chromium.org/13152
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@6490 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/sessions/session_service.h')
-rw-r--r-- | chrome/browser/sessions/session_service.h | 349 |
1 files changed, 349 insertions, 0 deletions
diff --git a/chrome/browser/sessions/session_service.h b/chrome/browser/sessions/session_service.h new file mode 100644 index 0000000..1c3402d3 --- /dev/null +++ b/chrome/browser/sessions/session_service.h @@ -0,0 +1,349 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_SESSIONS_SESSION_SERVICE_H_ +#define CHROME_BROWSER_SESSIONS_SESSION_SERVICE_H_ + +#include <map> + +#include "base/basictypes.h" +#include "chrome/browser/browser.h" +#include "chrome/browser/sessions/base_session_service.h" +#include "chrome/browser/sessions/session_id.h" +#include "chrome/common/notification_service.h" + +class Browser; +class NavigationController; +class NavigationEntry; +class Profile; +class SessionCommand; +struct SessionTab; +struct SessionWindow; + +// SessionService ------------------------------------------------------------ + +// SessionService is responsible for maintaining the state of open windows +// and tabs so that they can be restored at a later date. The state of the +// currently open browsers is referred to as the current session. +// +// SessionService supports restoring from the previous or last session. The +// previous session typically corresponds to the last run of the browser, but +// not always. For example, if the user has a tabbed browser and app window +// running, closes the tabbed browser, then creates a new tabbed browser the +// current session is made the last session and the current session reset. This +// is done to provide the illusion that app windows run in separate processes. +// +// SessionService itself maintains a set of SessionCommands that allow +// SessionService to rebuild the open state of the browser (as +// SessionWindow, SessionTab and TabNavigation). The commands are periodically +// flushed to SessionBackend and written to a file. Every so often +// SessionService rebuilds the contents of the file from the open state +// of the browser. +class SessionService : public BaseSessionService, + public NotificationObserver { + friend class SessionServiceTestHelper; + public: + // Creates a SessionService for the specified profile. + explicit SessionService(Profile* profile); + // For testing. + explicit SessionService(const std::wstring& save_path); + + virtual ~SessionService(); + + // Resets the contents of the file from the current state of all open + // browsers whose profile matches our profile. + void ResetFromCurrentBrowsers(); + + // Moves the current session to the last session. This is useful when a + // checkpoint occurs, such as when the user launches the app and no tabbed + // browsers are running. + void MoveCurrentSessionToLastSession(); + + // Associates a tab with a window. + void SetTabWindow(const SessionID& window_id, + const SessionID& tab_id); + + // Sets the bounds of a window. + void SetWindowBounds(const SessionID& window_id, + const gfx::Rect& bounds, + bool is_maximized); + + // Sets the visual index of the tab in its parent window. + void SetTabIndexInWindow(const SessionID& window_id, + const SessionID& tab_id, + int new_index); + + // Notification that a tab has been closed. + // + // Note: this is invoked from the NavigationController's destructor, which is + // after the actual tab has been removed. + void TabClosed(const SessionID& window_id, const SessionID& tab_id); + + // Notification the window is about to close. + void WindowClosing(const SessionID& window_id); + + // Notification a window has finished closing. + void WindowClosed(const SessionID& window_id); + + // Sets the type of window. In order for the contents of a window to be + // tracked SetWindowType must be invoked with a type we track + // (should_track_changes_for_browser_type returns true). + void SetWindowType(const SessionID& window_id, Browser::Type type); + + // Invoked when the NavigationController has removed entries from the back of + // the list. |count| gives the number of entries in the navigation controller. + void TabNavigationPathPrunedFromBack(const SessionID& window_id, + const SessionID& tab_id, + int count); + + // Invoked when the NavigationController has removed entries from the front of + // the list. |count| gives the number of entries that were removed. + void TabNavigationPathPrunedFromFront(const SessionID& window_id, + const SessionID& tab_id, + int count); + + // Updates the navigation entry for the specified tab. + void UpdateTabNavigation(const SessionID& window_id, + const SessionID& tab_id, + int index, + const NavigationEntry& entry); + + // Notification that a tab has restored its entries or a closed tab is being + // reused. + void TabRestored(NavigationController* controller); + + // Sets the index of the selected entry in the navigation controller for the + // specified tab. + void SetSelectedNavigationIndex(const SessionID& window_id, + const SessionID& tab_id, + int index); + + // Sets the index of the selected tab in the specified window. + void SetSelectedTabInWindow(const SessionID& window_id, int index); + + // Callback from GetSavedSession of GetLastSession. + // + // The contents of the supplied vector are deleted after the callback is + // notified. To take ownership of the vector clear it before returning. + // + // The time gives the time the session was closed. + typedef Callback2<Handle, std::vector<SessionWindow*>*>::Type + LastSessionCallback; + + // Fetches the contents of the last session, notifying the callback when + // done. If the callback is supplied an empty vector of SessionWindows + // it means the session could not be restored. + // + // The created request does NOT directly invoke the callback, rather the + // callback invokes OnGotSessionCommands from which we map the + // SessionCommands to browser state, then notify the callback. + Handle GetLastSession(CancelableRequestConsumerBase* consumer, + LastSessionCallback* callback); + + private: + typedef std::map<SessionID::id_type,std::pair<int,int> > IdToRange; + typedef std::map<SessionID::id_type,SessionTab*> IdToSessionTab; + typedef std::map<SessionID::id_type,SessionWindow*> IdToSessionWindow; + + void Init(); + + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + // Methods to create the various commands. It is up to the caller to delete + // the returned the SessionCommand* object. + SessionCommand* CreateSetSelectedTabInWindow(const SessionID& window_id, + int index); + + SessionCommand* CreateSetTabWindowCommand(const SessionID& window_id, + const SessionID& tab_id); + + SessionCommand* CreateSetWindowBoundsCommand(const SessionID& window_id, + const gfx::Rect& bounds, + bool is_maximized); + + SessionCommand* CreateSetTabIndexInWindowCommand(const SessionID& tab_id, + int new_index); + + SessionCommand* CreateTabClosedCommand(SessionID::id_type tab_id); + + SessionCommand* CreateWindowClosedCommand(SessionID::id_type tab_id); + + SessionCommand* CreateSetSelectedNavigationIndexCommand( + const SessionID& tab_id, + int index); + + SessionCommand* CreateSetWindowTypeCommand(const SessionID& window_id, + Browser::Type type); + + // Callback form the backend for getting the commands from the previous + // or save file. Converts the commands in SessionWindows and notifies + // the real callback. + void OnGotLastSessionCommands( + Handle handle, + scoped_refptr<InternalGetCommandsRequest> request); + + // Converts the commands into SessionWindows. On return any valid + // windows are added to valid_windows. It is up to the caller to delete + // the windows added to valid_windows. + // + // If ignore_recent_closes is true, any window/tab closes within in a certain + // time frame are ignored. + void RestoreSessionFromCommands(const std::vector<SessionCommand*>& commands, + std::vector<SessionWindow*>* valid_windows); + + // Iterates through the vector updating the selected_tab_index of each + // SessionWindow based on the actual tabs that were restored. + void UpdateSelectedTabIndex(std::vector<SessionWindow*>* windows); + + // Returns the window in windows with the specified id. If a window does + // not exist, one is created. + SessionWindow* GetWindow(SessionID::id_type window_id, + IdToSessionWindow* windows); + + // Returns the tab with the specified id in tabs. If a tab does not exist, + // it is created. + SessionTab* GetTab(SessionID::id_type tab_id, + IdToSessionTab* tabs); + + // Returns an iterator into navigations pointing to the navigation whose + // index matches |index|. If no navigation index matches |index|, the first + // navigation with an index > |index| is returned. + // + // This assumes the navigations are ordered by index in ascending order. + std::vector<TabNavigation>::iterator FindClosestNavigationWithIndex( + std::vector<TabNavigation>* navigations, + int index); + + // Does the following: + // . Deletes and removes any windows with no tabs or windows with types other + // than tabbed_browser or browser. NOTE: constrained windows that have + // been dragged out are of type browser. As such, this preserves any dragged + // out constrained windows (aka popups that have been dragged out). + // . Sorts the tabs in windows with valid tabs based on the tabs + // visual order, and adds the valid windows to windows. + void SortTabsBasedOnVisualOrderAndPrune( + std::map<int,SessionWindow*>* windows, + std::vector<SessionWindow*>* valid_windows); + + // Adds tabs to their parent window based on the tab's window_id. This + // ignores tabs with no navigations. + void AddTabsToWindows(std::map<int,SessionTab*>* tabs, + std::map<int,SessionWindow*>* windows); + + // Creates tabs and windows from the specified commands. The created tabs + // and windows are added to |tabs| and |windows| respectively. It is up to + // the caller to delete the tabs and windows added to |tabs| and |windows|. + // + // This does NOT add any created SessionTabs to SessionWindow.tabs, that is + // done by AddTabsToWindows. + bool CreateTabsAndWindows(const std::vector<SessionCommand*>& data, + std::map<int,SessionTab*>* tabs, + std::map<int,SessionWindow*>* windows); + + // Adds commands to commands that will recreate the state of the specified + // NavigationController. This adds at most kMaxNavigationCountToPersist + // navigations (in each direction from the current navigation index). + // A pair is added to tab_to_available_range indicating the range of + // indices that were written. + void BuildCommandsForTab( + const SessionID& window_id, + NavigationController* controller, + int index_in_window, + std::vector<SessionCommand*>* commands, + IdToRange* tab_to_available_range); + + // Adds commands to create the specified browser, and invokes + // BuildCommandsForTab for each of the tabs in the browser. This ignores + // any tabs not in the profile we were created with. + void BuildCommandsForBrowser( + Browser* browser, + std::vector<SessionCommand*>* commands, + IdToRange* tab_to_available_range, + std::set<SessionID::id_type>* windows_to_track); + + // Iterates over all the known browsers invoking BuildCommandsForBrowser. + // This only adds browsers that should be tracked + // (should_track_changes_for_browser_type returns true). All browsers that + // are tracked are added to windows_to_track (as long as it is non-null). + void BuildCommandsFromBrowsers( + std::vector<SessionCommand*>* commands, + IdToRange* tab_to_available_range, + std::set<SessionID::id_type>* windows_to_track); + + // Schedules a reset. A reset means the contents of the file are recreated + // from the state of the browser. + void ScheduleReset(); + + // Searches for a pending command that can be replaced with command. + // If one is found, pending command is removed, command is added to + // the pending commands and true is returned. + bool ReplacePendingCommand(SessionCommand* command); + + // Schedules the specified command. This method takes ownership of the + // command. + void ScheduleCommand(SessionCommand* command); + + // Converts all pending tab/window closes to commands and schedules them. + void CommitPendingCloses(); + + // Returns true if there is only one window open with a single tab that shares + // our profile. + bool IsOnlyOneTabLeft(); + + // Returns true if there are no open tabbed browser windows with our profile, + // or the only tabbed browser open has a session id of window_id. + bool HasOpenTabbedBrowsers(const SessionID& window_id); + + // Returns true if changes to tabs in the specified window should be tracked. + bool ShouldTrackChangesToWindow(const SessionID& window_id); + + // Returns true if we track changes to the specified browser type. + static bool should_track_changes_for_browser_type(Browser::Type type) { + return type == Browser::TYPE_NORMAL; + } + + // Maps from session tab id to the range of navigation entries that has + // been written to disk. + // + // This is only used if not all the navigation entries have been + // written. + IdToRange tab_to_available_range_; + + // When the user closes the last window, where the last window is the + // last tabbed browser and no more tabbed browsers are open with the same + // profile, the window ID is added here. These IDs are only committed (which + // marks them as closed) if the user creates a new tabbed browser. + typedef std::set<SessionID::id_type> PendingWindowCloseIDs; + PendingWindowCloseIDs pending_window_close_ids_; + + // Set of tabs that have been closed by way of the last window or last tab + // closing, but not yet committed. + typedef std::set<SessionID::id_type> PendingTabCloseIDs; + PendingTabCloseIDs pending_tab_close_ids_; + + // When a window other than the last window (see description of + // pending_window_close_ids) is closed, the id is added to this set. + typedef std::set<SessionID::id_type> WindowClosingIDs; + WindowClosingIDs window_closing_ids_; + + // Set of windows we're tracking changes to. This is only browsers that + // return true from should_track_changes_for_browser_type. + typedef std::set<SessionID::id_type> WindowsTracking; + WindowsTracking windows_tracking_; + + // Are there any open open tabbed browsers? + bool has_open_tabbed_browsers_; + + // If true and a new tabbed browser is created and there are no opened tabbed + // browser (has_open_tabbed_browsers_ is false), then the current session + // is made the previous session. See description above class for details on + // current/previou session. + bool move_on_new_browser_; + + DISALLOW_COPY_AND_ASSIGN(SessionService); +}; + +#endif // CHROME_BROWSER_SESSIONS_SESSION_SERVICE_H_ |