summaryrefslogtreecommitdiffstats
path: root/chrome/browser/session_service.h
diff options
context:
space:
mode:
authorinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-26 23:55:29 +0000
committerinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-26 23:55:29 +0000
commit09911bf300f1a419907a9412154760efd0b7abc3 (patch)
treef131325fb4e2ad12c6d3504ab75b16dd92facfed /chrome/browser/session_service.h
parent586acc5fe142f498261f52c66862fa417c3d52d2 (diff)
downloadchromium_src-09911bf300f1a419907a9412154760efd0b7abc3.zip
chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.tar.gz
chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.tar.bz2
Add chrome to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@15 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/session_service.h')
-rw-r--r--chrome/browser/session_service.h608
1 files changed, 608 insertions, 0 deletions
diff --git a/chrome/browser/session_service.h b/chrome/browser/session_service.h
new file mode 100644
index 0000000..3877701
--- /dev/null
+++ b/chrome/browser/session_service.h
@@ -0,0 +1,608 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef CHROME_BROWSER_SESSION_SERVICE_H__
+#define CHROME_BROWSER_SESSION_SERVICE_H__
+
+#include <map>
+
+#include "base/basictypes.h"
+#include "base/gfx/rect.h"
+#include "base/task.h"
+#include "base/time.h"
+#include "chrome/browser/browser_type.h"
+#include "chrome/browser/cancelable_request.h"
+#include "chrome/common/page_transition_types.h"
+#include "chrome/common/stl_util-inl.h"
+#include "googleurl/src/gurl.h"
+
+class Browser;
+class NavigationController;
+class NavigationEntry;
+class Profile;
+class TabContents;
+class Thread;
+class Timer;
+class SessionBackend;
+class SessionCommand;
+
+// SessionID ------------------------------------------------------------------
+
+// Uniquely identifies a session, tab or window.
+
+class SessionID {
+ friend class SessionService;
+ public:
+ typedef int32 id_type;
+
+ SessionID();
+ ~SessionID() {}
+
+ // Returns the underlying id.
+ id_type id() const { return id_; }
+
+ // Returns true if the two commands are equal.
+ bool Equals(const SessionID& other) const;
+
+ private:
+ explicit SessionID(id_type id) : id_(id) {}
+
+ // Resets the id. This is used when restoring a session
+ void set_id(id_type id) { id_ = id; }
+
+ id_type id_;
+};
+
+// TabNavigation ------------------------------------------------------------
+
+// TabNavigation corresponds to a NavigationEntry.
+
+struct TabNavigation {
+ enum TypeMask {
+ HAS_POST_DATA = 1
+ };
+
+ TabNavigation() : index(-1), transition(PageTransition::TYPED), type_mask(0) {
+ }
+ TabNavigation(int index,
+ const GURL& url,
+ const std::wstring& title,
+ const std::string& state,
+ PageTransition::Type transition)
+ : index(index),
+ url(url),
+ title(title),
+ state(state),
+ transition(transition),
+ type_mask(0) {}
+
+
+ // The index in the NavigationController. If this is -1, it means this
+ // TabNavigation is bogus.
+ int index;
+ GURL url;
+ // The title of the page.
+ std::wstring title;
+ std::string state;
+ PageTransition::Type transition;
+
+ // A mask used for arbitrary boolean values needed to represent a
+ // NavigationEntry. Currently only contains HAS_POST_DATA or 0.
+ int type_mask;
+};
+
+// SessionTab ----------------------------------------------------------------
+
+// SessionTab corresponds to a NavigationController.
+
+struct SessionTab {
+ SessionTab() : tab_visual_index(-1), current_navigation_index(-1) { }
+
+ // Unique id of the window.
+ SessionID window_id;
+
+ // Unique if of the tab.
+ SessionID tab_id;
+
+ // Visual index of the tab within its window. There may be gaps in these
+ // values.
+ //
+ // NOTE: this is really only useful for the SessionService during
+ // restore, others can likely ignore this and use the order of the
+ // tabs in SessionWindow.tabs.
+ int tab_visual_index;
+
+ // Identifies the index of the current navigation in navigations. For
+ // example, if this is 2 it means the current navigation is navigations[2].
+ //
+ // NOTE: when the service is creating SessionTabs, initially this
+ // corresponds to TabNavigation.index, not the index in navigations. When done
+ // creating though, this is set to the index in navigations.
+ int current_navigation_index;
+
+ std::vector<TabNavigation> navigations;
+
+ private:
+ DISALLOW_EVIL_CONSTRUCTORS(SessionTab);
+};
+
+// SessionWindow -------------------------------------------------------------
+
+// Describes a saved window.
+
+struct SessionWindow {
+ SessionWindow()
+ : selected_tab_index(-1),
+ type(BrowserType::TABBED_BROWSER),
+ is_constrained(true),
+ is_maximized(false) {}
+ ~SessionWindow() { STLDeleteElements(&tabs); }
+
+ // Identifier of the window.
+ SessionID window_id;
+
+ // Bounds of the window.
+ gfx::Rect bounds;
+
+ // Index of the selected tab in tabs; -1 if no tab is selected. After restore
+ // this value is guaranteed to be a valid index into tabs.
+ //
+ // NOTE: when the service is creating SessionWindows, initially this
+ // corresponds to SessionTab.tab_visual_index, not the index in
+ // tabs. When done creating though, this is set to the index in
+ // tabs.
+ int selected_tab_index;
+
+ // Type of the browser. Currently we only store browsers of type
+ // TABBED_BROWSER and BROWSER.
+ BrowserType::Type type;
+
+ // If true, the window is constrained.
+ //
+ // Currently SessionService prunes all constrained windows so that session
+ // restore does not attempt to restore them.
+ bool is_constrained;
+
+ // The tabs, ordered by visual order.
+ std::vector<SessionTab*> tabs;
+
+ // Is the window maximized?
+ bool is_maximized;
+
+ private:
+ DISALLOW_EVIL_CONSTRUCTORS(SessionWindow);
+};
+
+// SessionService ------------------------------------------------------------
+
+// SessionService is responsible for maintaining the state of open windows
+// and tabs so that they can be restored at a later date.
+//
+// SessionService supports restoring from two distinct points:
+// . The last run of the browser.
+// . A user defined point. That is, any time CreateSavedSession is invoked
+// the save session is reset from the current state of the browser.
+//
+// Additionally the current session can be made the 'last' session at any point
+// by way of MoveCurrentSessionToLastSession.
+//
+// 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 CancelableRequestProvider,
+ public base::RefCountedThreadSafe<SessionService> {
+ friend class SessionServiceTestHelper;
+ public:
+ // Creates a SessionService for the specified profile.
+ explicit SessionService(Profile* profile);
+ // For testing.
+ explicit SessionService(const std::wstring& save_path);
+
+ ~SessionService();
+
+ // Returns true if there are any open tabbed browser windows.
+ bool has_open_tabbed_browsers() const { return has_open_tabbed_browsers_; }
+
+ // Returns true if a tabbed browser has ever been created.
+ bool tabbed_browser_created() const { return tabbed_browser_created_; }
+
+ // 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, BrowserType::Type type);
+
+ // Removes the navigation entries for tab_id whose indices are >= index.
+ void TabNavigationPathPruned(const SessionID& window_id,
+ const SessionID& tab_id,
+ int index);
+
+ // 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
+ SavedSessionCallback;
+
+ // Fetches the contents of the save session, notifying the callback when
+ // done. If the callback is supplied an empty vector of SessionWindows
+ // it means the session could not be restored.
+ Handle GetSavedSession(CancelableRequestConsumerBase* consumer,
+ SavedSessionCallback* callback);
+
+ // 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.
+ Handle GetLastSession(CancelableRequestConsumerBase* consumer,
+ SavedSessionCallback* callback);
+
+ // Creates a save session from the current state of the browser.
+ void CreateSavedSession();
+
+ // Deletes the saved session if saved session is true, or the last session
+ // if saved_session is false.
+ void DeleteSession(bool saved_session);
+
+ // Creates a saved session from the contents of the last session.
+ void CopyLastSessionToSavedSession();
+
+ // The callback from Get*Session is internally routed to SessionService
+ // first. This is done so that the SessionWindows can be recreated from
+ // the SessionCommands. The following types are used for this.
+ class InternalSavedSessionRequest;
+
+ typedef Callback2<Handle, scoped_refptr<InternalSavedSessionRequest> >::Type
+ InternalSavedSessionCallback;
+
+ // Request class used from Get*Session.
+ class InternalSavedSessionRequest :
+ public CancelableRequest<InternalSavedSessionCallback> {
+ public:
+ InternalSavedSessionRequest(CallbackType* callback,
+ SavedSessionCallback* real_callback,
+ bool is_saved_session)
+ : CancelableRequest(callback),
+ real_callback(real_callback),
+ is_saved_session(is_saved_session) {
+ }
+ virtual ~InternalSavedSessionRequest();
+
+ // The callback supplied to Get*Session.
+ scoped_ptr<SavedSessionCallback> real_callback;
+
+ // Whether the request is for a saved session, or the last session.
+ bool is_saved_session;
+
+ // The commands. The backend fills this in for us.
+ std::vector<SessionCommand*> commands;
+
+ private:
+ DISALLOW_EVIL_CONSTRUCTORS(InternalSavedSessionRequest);
+ };
+
+ 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;
+
+ // Various initialization; called from the constructor.
+ void Init(const std::wstring& path);
+
+ // Get*Session call into this to schedule the request. The 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 GetSessionImpl(CancelableRequestConsumerBase* consumer,
+ SavedSessionCallback* callback,
+ bool is_saved_session);
+
+ // 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* CreateUpdateTabNavigationCommand(
+ const SessionID& tab_id,
+ int index,
+ const NavigationEntry& entry);
+
+ SessionCommand* CreateSetSelectedNavigationIndexCommand(
+ const SessionID& tab_id,
+ int index);
+
+ SessionCommand* CreateSetWindowTypeCommand(const SessionID& window_id,
+ BrowserType::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 OnGotSessionCommands(
+ Handle handle,
+ scoped_refptr<InternalSavedSessionRequest> 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();
+
+ // Saves pending commands to the backend.
+ void Save();
+
+ // Starts the save timer (if it isn't running already).
+ void StartSaveTimer();
+
+ // 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(BrowserType::Type type) {
+ return type == BrowserType::TABBED_BROWSER;
+ }
+
+ // The profile used to determine where to save, as well as what tabs
+ // to persist.
+ Profile* profile_;
+
+ // The number of commands sent to the backend before doing a reset.
+ int commands_since_reset_;
+
+ // 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_;
+
+ // Commands we need to send over to the backend.
+ std::vector<SessionCommand*> pending_commands_;
+
+ // Whether the backend file should be recreated the next time we send
+ // over the commands.
+ bool pending_reset_;
+
+ // Used to invoke Save.
+ ScopedRunnableMethodFactory<SessionService> save_factory_;
+
+ // When the user closes the last window, where the last window is the 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_;
+
+ // The backend.
+ scoped_refptr<SessionBackend> backend_;
+
+ // Thread backend tasks are run on. This comes from the profile, and is
+ // null during testing.
+ Thread* backend_thread_;
+
+ // Are there any open open tabbed browsers?
+ bool has_open_tabbed_browsers_;
+
+ // Was a tabbed browser ever created?
+ bool tabbed_browser_created_;
+};
+
+#endif // CHROME_BROWSER_SESSION_SERVICE_H__