Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / sessions / session_service.h
blob5bcac95e87389df82b700b40b5db4888e5f54ba3
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
3 // found in the LICENSE file.
5 #ifndef CHROME_BROWSER_SESSIONS_SESSION_SERVICE_H_
6 #define CHROME_BROWSER_SESSIONS_SESSION_SERVICE_H_
8 #include <map>
9 #include <string>
11 #include "base/basictypes.h"
12 #include "base/callback.h"
13 #include "base/memory/scoped_vector.h"
14 #include "base/time/time.h"
15 #include "chrome/browser/defaults.h"
16 #include "chrome/browser/sessions/base_session_service.h"
17 #include "chrome/browser/sessions/session_id.h"
18 #include "chrome/browser/ui/browser.h"
19 #include "chrome/browser/ui/browser_finder.h"
20 #include "chrome/browser/ui/browser_list_observer.h"
21 #include "chrome/common/cancelable_task_tracker.h"
22 #include "components/browser_context_keyed_service/browser_context_keyed_service.h"
23 #include "content/public/browser/notification_observer.h"
24 #include "content/public/browser/notification_registrar.h"
25 #include "ui/base/ui_base_types.h"
27 class Profile;
28 class SessionCommand;
29 struct SessionTab;
30 struct SessionWindow;
32 namespace content {
33 class NavigationEntry;
34 class WebContents;
37 // SessionService ------------------------------------------------------------
39 // SessionService is responsible for maintaining the state of open windows
40 // and tabs so that they can be restored at a later date. The state of the
41 // currently open browsers is referred to as the current session.
43 // SessionService supports restoring from the last session. The last session
44 // typically corresponds to the last run of the browser, but not always. For
45 // example, if the user has a tabbed browser and app window running, closes the
46 // tabbed browser, then creates a new tabbed browser the current session is made
47 // the last session and the current session reset. This is done to provide the
48 // illusion that app windows run in separate processes. Similar behavior occurs
49 // with incognito windows.
51 // SessionService itself maintains a set of SessionCommands that allow
52 // SessionService to rebuild the open state of the browser (as SessionWindow,
53 // SessionTab and SerializedNavigationEntry). The commands are periodically
54 // flushed to SessionBackend and written to a file. Every so often
55 // SessionService rebuilds the contents of the file from the open state of the
56 // browser.
57 class SessionService : public BaseSessionService,
58 public BrowserContextKeyedService,
59 public content::NotificationObserver,
60 public chrome::BrowserListObserver {
61 friend class SessionServiceTestHelper;
62 public:
63 // Used to distinguish an application window from a normal one.
64 enum AppType {
65 TYPE_APP,
66 TYPE_NORMAL
69 // Creates a SessionService for the specified profile.
70 explicit SessionService(Profile* profile);
71 // For testing.
72 explicit SessionService(const base::FilePath& save_path);
74 virtual ~SessionService();
76 // Returns true if a new window opening should really be treated like the
77 // start of a session (with potential session restore, startup URLs, etc.).
78 // In particular, this is true if there are no tabbed browsers running
79 // currently (eg. because only background or other app pages are running).
80 bool ShouldNewWindowStartSession();
82 // Invoke at a point when you think session restore might occur. For example,
83 // during startup and window creation this is invoked to see if a session
84 // needs to be restored. If a session needs to be restored it is done so
85 // asynchronously and true is returned. If false is returned the session was
86 // not restored and the caller needs to create a new window.
87 bool RestoreIfNecessary(const std::vector<GURL>& urls_to_open);
89 // Resets the contents of the file from the current state of all open
90 // browsers whose profile matches our profile.
91 void ResetFromCurrentBrowsers();
93 // Moves the current session to the last session. This is useful when a
94 // checkpoint occurs, such as when the user launches the app and no tabbed
95 // browsers are running.
96 void MoveCurrentSessionToLastSession();
98 // Associates a tab with a window.
99 void SetTabWindow(const SessionID& window_id,
100 const SessionID& tab_id);
102 // Sets the bounds of a window.
103 void SetWindowBounds(const SessionID& window_id,
104 const gfx::Rect& bounds,
105 ui::WindowShowState show_state);
107 // Sets the visual index of the tab in its parent window.
108 void SetTabIndexInWindow(const SessionID& window_id,
109 const SessionID& tab_id,
110 int new_index);
112 // Sets the pinned state of the tab.
113 void SetPinnedState(const SessionID& window_id,
114 const SessionID& tab_id,
115 bool is_pinned);
117 // Notification that a tab has been closed. |closed_by_user_gesture| comes
118 // from |WebContents::closed_by_user_gesture|; see it for details.
120 // Note: this is invoked from the NavigationController's destructor, which is
121 // after the actual tab has been removed.
122 void TabClosed(const SessionID& window_id,
123 const SessionID& tab_id,
124 bool closed_by_user_gesture);
126 // Notification a window has opened.
127 void WindowOpened(Browser* browser);
129 // Notification the window is about to close.
130 void WindowClosing(const SessionID& window_id);
132 // Notification a window has finished closing.
133 void WindowClosed(const SessionID& window_id);
135 // Called when a tab is inserted.
136 void TabInserted(content::WebContents* contents);
138 // Called when a tab is closing.
139 void TabClosing(content::WebContents* contents);
141 // Sets the type of window. In order for the contents of a window to be
142 // tracked SetWindowType must be invoked with a type we track
143 // (should_track_changes_for_browser_type returns true).
144 void SetWindowType(const SessionID& window_id,
145 Browser::Type type,
146 AppType app_type);
148 // Sets the application name of the specified window.
149 void SetWindowAppName(const SessionID& window_id,
150 const std::string& app_name);
152 // Invoked when the NavigationController has removed entries from the back of
153 // the list. |count| gives the number of entries in the navigation controller.
154 void TabNavigationPathPrunedFromBack(const SessionID& window_id,
155 const SessionID& tab_id,
156 int count);
158 // Invoked when the NavigationController has removed entries from the front of
159 // the list. |count| gives the number of entries that were removed.
160 void TabNavigationPathPrunedFromFront(const SessionID& window_id,
161 const SessionID& tab_id,
162 int count);
164 // Updates the navigation entry for the specified tab.
165 void UpdateTabNavigation(
166 const SessionID& window_id,
167 const SessionID& tab_id,
168 const sessions::SerializedNavigationEntry& navigation);
170 // Notification that a tab has restored its entries or a closed tab is being
171 // reused.
172 void TabRestored(content::WebContents* tab, bool pinned);
174 // Sets the index of the selected entry in the navigation controller for the
175 // specified tab.
176 void SetSelectedNavigationIndex(const SessionID& window_id,
177 const SessionID& tab_id,
178 int index);
180 // Sets the index of the selected tab in the specified window.
181 void SetSelectedTabInWindow(const SessionID& window_id, int index);
183 // Sets the user agent override of the specified tab.
184 void SetTabUserAgentOverride(const SessionID& window_id,
185 const SessionID& tab_id,
186 const std::string& user_agent_override);
188 // Callback from GetLastSession.
189 // The second parameter is the id of the window that was last active.
190 typedef base::Callback<void(ScopedVector<SessionWindow>, SessionID::id_type)>
191 SessionCallback;
193 // Fetches the contents of the last session, notifying the callback when
194 // done. If the callback is supplied an empty vector of SessionWindows
195 // it means the session could not be restored.
196 CancelableTaskTracker::TaskId GetLastSession(const SessionCallback& callback,
197 CancelableTaskTracker* tracker);
199 // Overridden from BaseSessionService because we want some UMA reporting on
200 // session update activities.
201 virtual void Save() OVERRIDE;
203 private:
204 // Allow tests to access our innards for testing purposes.
205 FRIEND_TEST_ALL_PREFIXES(SessionServiceTest, RestoreActivation1);
206 FRIEND_TEST_ALL_PREFIXES(SessionServiceTest, RestoreActivation2);
207 FRIEND_TEST_ALL_PREFIXES(NoStartupWindowTest, DontInitSessionServiceForApps);
209 typedef std::map<SessionID::id_type, std::pair<int, int> > IdToRange;
210 typedef std::map<SessionID::id_type, SessionTab*> IdToSessionTab;
211 typedef std::map<SessionID::id_type, SessionWindow*> IdToSessionWindow;
214 // These types mirror Browser::Type, but are re-defined here because these
215 // specific enumeration _values_ are written into the session database and
216 // are needed to maintain forward compatibility.
217 // Note that we only store browsers of type TYPE_TABBED and TYPE_POPUP.
218 enum WindowType {
219 TYPE_TABBED = 0,
220 TYPE_POPUP = 1
223 void Init();
225 // Returns true if we have scheduled any commands, or any scheduled commands
226 // have been saved.
227 bool processed_any_commands();
229 // Implementation of RestoreIfNecessary. If |browser| is non-null and we need
230 // to restore, the tabs are added to it, otherwise a new browser is created.
231 bool RestoreIfNecessary(const std::vector<GURL>& urls_to_open,
232 Browser* browser);
234 virtual void Observe(int type,
235 const content::NotificationSource& source,
236 const content::NotificationDetails& details) OVERRIDE;
238 // chrome::BrowserListObserver
239 virtual void OnBrowserAdded(Browser* browser) OVERRIDE {}
240 virtual void OnBrowserRemoved(Browser* browser) OVERRIDE {}
241 virtual void OnBrowserSetLastActive(Browser* browser) OVERRIDE;
243 // Sets the application extension id of the specified tab.
244 void SetTabExtensionAppID(const SessionID& window_id,
245 const SessionID& tab_id,
246 const std::string& extension_app_id);
248 // Methods to create the various commands. It is up to the caller to delete
249 // the returned the SessionCommand* object.
250 SessionCommand* CreateSetSelectedTabInWindow(const SessionID& window_id,
251 int index);
253 SessionCommand* CreateSetTabWindowCommand(const SessionID& window_id,
254 const SessionID& tab_id);
256 SessionCommand* CreateSetWindowBoundsCommand(const SessionID& window_id,
257 const gfx::Rect& bounds,
258 ui::WindowShowState show_state);
260 SessionCommand* CreateSetTabIndexInWindowCommand(const SessionID& tab_id,
261 int new_index);
263 SessionCommand* CreateTabClosedCommand(SessionID::id_type tab_id);
265 SessionCommand* CreateWindowClosedCommand(SessionID::id_type tab_id);
267 SessionCommand* CreateSetSelectedNavigationIndexCommand(
268 const SessionID& tab_id,
269 int index);
271 SessionCommand* CreateSetWindowTypeCommand(const SessionID& window_id,
272 WindowType type);
274 SessionCommand* CreatePinnedStateCommand(const SessionID& tab_id,
275 bool is_pinned);
277 SessionCommand* CreateSessionStorageAssociatedCommand(
278 const SessionID& tab_id,
279 const std::string& session_storage_persistent_id);
281 SessionCommand* CreateSetActiveWindowCommand(const SessionID& window_id);
283 // Converts |commands| to SessionWindows and notifies the callback.
284 void OnGotSessionCommands(const SessionCallback& callback,
285 ScopedVector<SessionCommand> commands);
287 // Converts the commands into SessionWindows. On return any valid
288 // windows are added to valid_windows. It is up to the caller to delete
289 // the windows added to valid_windows. |active_window_id| will be set with the
290 // id of the last active window, but it's only valid when this id corresponds
291 // to the id of one of the windows in valid_windows.
292 void RestoreSessionFromCommands(const std::vector<SessionCommand*>& commands,
293 std::vector<SessionWindow*>* valid_windows,
294 SessionID::id_type* active_window_id);
296 // Iterates through the vector updating the selected_tab_index of each
297 // SessionWindow based on the actual tabs that were restored.
298 void UpdateSelectedTabIndex(std::vector<SessionWindow*>* windows);
300 // Returns the window in windows with the specified id. If a window does
301 // not exist, one is created.
302 SessionWindow* GetWindow(SessionID::id_type window_id,
303 IdToSessionWindow* windows);
305 // Returns the tab with the specified id in tabs. If a tab does not exist,
306 // it is created.
307 SessionTab* GetTab(SessionID::id_type tab_id,
308 IdToSessionTab* tabs);
310 // Returns an iterator into navigations pointing to the navigation whose
311 // index matches |index|. If no navigation index matches |index|, the first
312 // navigation with an index > |index| is returned.
314 // This assumes the navigations are ordered by index in ascending order.
315 std::vector<sessions::SerializedNavigationEntry>::iterator
316 FindClosestNavigationWithIndex(
317 std::vector<sessions::SerializedNavigationEntry>* navigations,
318 int index);
320 // Does the following:
321 // . Deletes and removes any windows with no tabs or windows with types other
322 // than tabbed_browser or browser. NOTE: constrained windows that have
323 // been dragged out are of type browser. As such, this preserves any dragged
324 // out constrained windows (aka popups that have been dragged out).
325 // . Sorts the tabs in windows with valid tabs based on the tabs
326 // visual order, and adds the valid windows to windows.
327 void SortTabsBasedOnVisualOrderAndPrune(
328 std::map<int, SessionWindow*>* windows,
329 std::vector<SessionWindow*>* valid_windows);
331 // Adds tabs to their parent window based on the tab's window_id. This
332 // ignores tabs with no navigations.
333 void AddTabsToWindows(std::map<int, SessionTab*>* tabs,
334 std::map<int, SessionWindow*>* windows);
336 // Creates tabs and windows from the commands specified in |data|. The created
337 // tabs and windows are added to |tabs| and |windows| respectively, with the
338 // id of the active window set in |active_window_id|. It is up to the caller
339 // to delete the tabs and windows added to |tabs| and |windows|.
341 // This does NOT add any created SessionTabs to SessionWindow.tabs, that is
342 // done by AddTabsToWindows.
343 bool CreateTabsAndWindows(const std::vector<SessionCommand*>& data,
344 std::map<int, SessionTab*>* tabs,
345 std::map<int, SessionWindow*>* windows,
346 SessionID::id_type* active_window_id);
348 // Adds commands to commands that will recreate the state of the specified
349 // tab. This adds at most kMaxNavigationCountToPersist navigations (in each
350 // direction from the current navigation index).
351 // A pair is added to tab_to_available_range indicating the range of
352 // indices that were written.
353 void BuildCommandsForTab(
354 const SessionID& window_id,
355 content::WebContents* tab,
356 int index_in_window,
357 bool is_pinned,
358 std::vector<SessionCommand*>* commands,
359 IdToRange* tab_to_available_range);
361 // Adds commands to create the specified browser, and invokes
362 // BuildCommandsForTab for each of the tabs in the browser. This ignores
363 // any tabs not in the profile we were created with.
364 void BuildCommandsForBrowser(
365 Browser* browser,
366 std::vector<SessionCommand*>* commands,
367 IdToRange* tab_to_available_range,
368 std::set<SessionID::id_type>* windows_to_track);
370 // Iterates over all the known browsers invoking BuildCommandsForBrowser.
371 // This only adds browsers that should be tracked
372 // (should_track_changes_for_browser_type returns true). All browsers that
373 // are tracked are added to windows_to_track (as long as it is non-null).
374 void BuildCommandsFromBrowsers(
375 std::vector<SessionCommand*>* commands,
376 IdToRange* tab_to_available_range,
377 std::set<SessionID::id_type>* windows_to_track);
379 // Schedules a reset. A reset means the contents of the file are recreated
380 // from the state of the browser.
381 void ScheduleReset();
383 // Searches for a pending command that can be replaced with command.
384 // If one is found, pending command is removed, command is added to
385 // the pending commands and true is returned.
386 bool ReplacePendingCommand(SessionCommand* command);
388 // Schedules the specified command. This method takes ownership of the
389 // command.
390 virtual void ScheduleCommand(SessionCommand* command) OVERRIDE;
392 // Converts all pending tab/window closes to commands and schedules them.
393 void CommitPendingCloses();
395 // Returns true if there is only one window open with a single tab that shares
396 // our profile.
397 bool IsOnlyOneTabLeft() const;
399 // Returns true if there are open trackable browser windows whose ids do
400 // match |window_id| with our profile. A trackable window is a window from
401 // which |should_track_changes_for_browser_type| returns true. See
402 // |should_track_changes_for_browser_type| for details.
403 bool HasOpenTrackableBrowsers(const SessionID& window_id) const;
405 // Returns true if changes to tabs in the specified window should be tracked.
406 bool ShouldTrackChangesToWindow(const SessionID& window_id) const;
408 // Returns true if we track changes to the specified browser.
409 bool ShouldTrackBrowser(Browser* browser) const;
411 // Returns true if we track changes to the specified browser type.
412 static bool should_track_changes_for_browser_type(
413 Browser::Type type,
414 AppType app_type);
416 // Returns true if we should record a window close as pending.
417 // |has_open_trackable_browsers_| must be up-to-date before calling this.
418 bool should_record_close_as_pending() const {
419 // When this is called, the browser window being closed is still open, hence
420 // still in the browser list. If there is a browser window other than the
421 // one being closed but no trackable windows, then the others must be App
422 // windows or similar. In this case, we record the close as pending.
423 return !has_open_trackable_browsers_ &&
424 (!browser_defaults::kBrowserAliveWithNoWindows ||
425 force_browser_not_alive_with_no_windows_ ||
426 chrome::GetTotalBrowserCount() > 1);
429 // Call when certain session relevant notifications
430 // (tab_closed, nav_list_pruned) occur. In addition, this is
431 // currently called when Save() is called to compare how often the
432 // session data is currently saved verses when we may want to save it.
433 // It records the data in UMA stats.
434 void RecordSessionUpdateHistogramData(int type,
435 base::TimeTicks* last_updated_time);
437 // Helper methods to record the histogram data
438 void RecordUpdatedTabClosed(base::TimeDelta delta, bool use_long_period);
439 void RecordUpdatedNavListPruned(base::TimeDelta delta, bool use_long_period);
440 void RecordUpdatedNavEntryCommit(base::TimeDelta delta, bool use_long_period);
441 void RecordUpdatedSaveTime(base::TimeDelta delta, bool use_long_period);
442 void RecordUpdatedSessionNavigationOrTab(base::TimeDelta delta,
443 bool use_long_period);
445 // Convert back/forward between the Browser and SessionService DB window
446 // types.
447 static WindowType WindowTypeForBrowserType(Browser::Type type);
448 static Browser::Type BrowserTypeForWindowType(WindowType type);
450 content::NotificationRegistrar registrar_;
452 // Maps from session tab id to the range of navigation entries that has
453 // been written to disk.
455 // This is only used if not all the navigation entries have been
456 // written.
457 IdToRange tab_to_available_range_;
459 // When the user closes the last window, where the last window is the
460 // last tabbed browser and no more tabbed browsers are open with the same
461 // profile, the window ID is added here. These IDs are only committed (which
462 // marks them as closed) if the user creates a new tabbed browser.
463 typedef std::set<SessionID::id_type> PendingWindowCloseIDs;
464 PendingWindowCloseIDs pending_window_close_ids_;
466 // Set of tabs that have been closed by way of the last window or last tab
467 // closing, but not yet committed.
468 typedef std::set<SessionID::id_type> PendingTabCloseIDs;
469 PendingTabCloseIDs pending_tab_close_ids_;
471 // When a window other than the last window (see description of
472 // pending_window_close_ids) is closed, the id is added to this set.
473 typedef std::set<SessionID::id_type> WindowClosingIDs;
474 WindowClosingIDs window_closing_ids_;
476 // Set of windows we're tracking changes to. This is only browsers that
477 // return true from should_track_changes_for_browser_type.
478 typedef std::set<SessionID::id_type> WindowsTracking;
479 WindowsTracking windows_tracking_;
481 // Are there any open trackable browsers?
482 bool has_open_trackable_browsers_;
484 // If true and a new tabbed browser is created and there are no opened tabbed
485 // browser (has_open_trackable_browsers_ is false), then the current session
486 // is made the last session. See description above class for details on
487 // current/last session.
488 bool move_on_new_browser_;
490 // Used for reporting frequency of session altering operations.
491 base::TimeTicks last_updated_tab_closed_time_;
492 base::TimeTicks last_updated_nav_list_pruned_time_;
493 base::TimeTicks last_updated_nav_entry_commit_time_;
494 base::TimeTicks last_updated_save_time_;
496 // Constants used in calculating histogram data.
497 const base::TimeDelta save_delay_in_millis_;
498 const base::TimeDelta save_delay_in_mins_;
499 const base::TimeDelta save_delay_in_hrs_;
501 // For browser_tests, since we want to simulate the browser shutting down
502 // without quitting.
503 bool force_browser_not_alive_with_no_windows_;
505 DISALLOW_COPY_AND_ASSIGN(SessionService);
508 #endif // CHROME_BROWSER_SESSIONS_SESSION_SERVICE_H_