blob: 1398b4bc1b097787c4e6e50c2a2aec62041b17a7 [file] [log] [blame]
[email protected]a636d8e52012-02-28 15:40:411// Copyright (c) 2012 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
[email protected]169627b2008-12-06 19:30:195#ifndef CHROME_BROWSER_SESSIONS_SESSION_SERVICE_H_
6#define CHROME_BROWSER_SESSIONS_SESSION_SERVICE_H_
initial.commit09911bf2008-07-26 23:55:297
8#include <map>
[email protected]23da84e152010-07-14 01:29:059#include <string>
initial.commit09911bf2008-07-26 23:55:2910
11#include "base/basictypes.h"
[email protected]f9ffb892011-11-28 18:57:3112#include "base/callback.h"
[email protected]4c7f9c52012-12-11 21:51:3013#include "base/memory/scoped_vector.h"
sky1a14f492014-08-26 21:44:2614#include "base/memory/weak_ptr.h"
[email protected]e95b717f2014-02-06 13:47:1315#include "base/task/cancelable_task_tracker.h"
[email protected]cc86ccfe2013-06-28 00:10:5016#include "base/time/time.h"
[email protected]982921f12009-10-27 21:43:5317#include "chrome/browser/defaults.h"
[email protected]926bfeb2009-02-14 23:19:4718#include "chrome/browser/sessions/base_session_service.h"
skuhnec3aa8cf2014-10-30 06:02:4519#include "chrome/browser/sessions/session_service_commands.h"
20#include "chrome/browser/sessions/session_service_utils.h"
[email protected]2ad4a902010-11-17 06:05:1321#include "chrome/browser/ui/browser.h"
[email protected]0665ebe2013-02-13 09:53:1922#include "chrome/browser/ui/browser_finder.h"
[email protected]bf219e9eb2012-10-10 15:20:3823#include "chrome/browser/ui/browser_list_observer.h"
[email protected]540380fc2014-03-14 10:10:3424#include "components/keyed_service/core/keyed_service.h"
[email protected]6c2381d2011-10-19 02:52:5325#include "content/public/browser/notification_observer.h"
26#include "content/public/browser/notification_registrar.h"
[email protected]400eaf82011-08-22 15:47:3927#include "ui/base/ui_base_types.h"
initial.commit09911bf2008-07-26 23:55:2928
initial.commit09911bf2008-07-26 23:55:2929class Profile;
initial.commit09911bf2008-07-26 23:55:2930class SessionCommand;
[email protected]169627b2008-12-06 19:30:1931struct SessionTab;
32struct SessionWindow;
[email protected]ad23a092011-12-28 07:02:0433
34namespace content {
35class NavigationEntry;
[email protected]40600152012-09-26 10:04:3136class WebContents;
[email protected]ad23a092011-12-28 07:02:0437}
initial.commit09911bf2008-07-26 23:55:2938
39// SessionService ------------------------------------------------------------
40
41// SessionService is responsible for maintaining the state of open windows
[email protected]6ea265a2008-10-30 02:58:3642// and tabs so that they can be restored at a later date. The state of the
43// currently open browsers is referred to as the current session.
initial.commit09911bf2008-07-26 23:55:2944//
[email protected]668cd422011-04-06 21:00:0145// SessionService supports restoring from the last session. The last session
46// typically corresponds to the last run of the browser, but not always. For
47// example, if the user has a tabbed browser and app window running, closes the
48// tabbed browser, then creates a new tabbed browser the current session is made
49// the last session and the current session reset. This is done to provide the
50// illusion that app windows run in separate processes. Similar behavior occurs
51// with incognito windows.
initial.commit09911bf2008-07-26 23:55:2952//
skuhnec3aa8cf2014-10-30 06:02:4553// SessionService itself uses functions from session_service_commands to store
54// commands which can rebuild the open state of the browser (as |SessionWindow|,
55// |SessionTab| and |SerializedNavigationEntry|). The commands are periodically
56// flushed to |SessionBackend| and written to a file. Every so often
57// |SessionService| rebuilds the contents of the file from the open state of the
[email protected]40a7e412013-04-29 18:13:0158// browser.
[email protected]169627b2008-12-06 19:30:1959class SessionService : public BaseSessionService,
[email protected]540380fc2014-03-14 10:10:3460 public KeyedService,
[email protected]bf219e9eb2012-10-10 15:20:3861 public content::NotificationObserver,
62 public chrome::BrowserListObserver {
[email protected]86ef6a392012-05-11 22:03:1163 friend class SessionServiceTestHelper;
initial.commit09911bf2008-07-26 23:55:2964 public:
skuhnec3aa8cf2014-10-30 06:02:4565 // Used to distinguish an application from a ordinary content window.
[email protected]a636d8e52012-02-28 15:40:4166 enum AppType {
67 TYPE_APP,
68 TYPE_NORMAL
69 };
70
initial.commit09911bf2008-07-26 23:55:2971 // Creates a SessionService for the specified profile.
72 explicit SessionService(Profile* profile);
73 // For testing.
[email protected]650b2d52013-02-10 03:41:4574 explicit SessionService(const base::FilePath& save_path);
initial.commit09911bf2008-07-26 23:55:2975
Daniel Chenga542fca2014-10-21 09:51:2976 ~SessionService() override;
[email protected]f0a58a382011-04-26 16:09:2977
skuhned58ab122014-10-22 20:23:0278 // This may be NULL during testing.
79 Profile* profile() const { return profile_; }
80
[email protected]8ddbb642011-09-01 02:52:2081 // Returns true if a new window opening should really be treated like the
82 // start of a session (with potential session restore, startup URLs, etc.).
83 // In particular, this is true if there are no tabbed browsers running
84 // currently (eg. because only background or other app pages are running).
85 bool ShouldNewWindowStartSession();
86
[email protected]c9b19942010-03-26 15:58:0887 // Invoke at a point when you think session restore might occur. For example,
88 // during startup and window creation this is invoked to see if a session
89 // needs to be restored. If a session needs to be restored it is done so
90 // asynchronously and true is returned. If false is returned the session was
91 // not restored and the caller needs to create a new window.
92 bool RestoreIfNecessary(const std::vector<GURL>& urls_to_open);
93
initial.commit09911bf2008-07-26 23:55:2994 // Resets the contents of the file from the current state of all open
95 // browsers whose profile matches our profile.
96 void ResetFromCurrentBrowsers();
97
98 // Moves the current session to the last session. This is useful when a
99 // checkpoint occurs, such as when the user launches the app and no tabbed
100 // browsers are running.
101 void MoveCurrentSessionToLastSession();
102
103 // Associates a tab with a window.
104 void SetTabWindow(const SessionID& window_id,
105 const SessionID& tab_id);
106
107 // Sets the bounds of a window.
108 void SetWindowBounds(const SessionID& window_id,
109 const gfx::Rect& bounds,
[email protected]400eaf82011-08-22 15:47:39110 ui::WindowShowState show_state);
initial.commit09911bf2008-07-26 23:55:29111
112 // Sets the visual index of the tab in its parent window.
113 void SetTabIndexInWindow(const SessionID& window_id,
114 const SessionID& tab_id,
115 int new_index);
116
[email protected]5c0e6482009-07-14 20:20:09117 // Sets the pinned state of the tab.
118 void SetPinnedState(const SessionID& window_id,
119 const SessionID& tab_id,
120 bool is_pinned);
121
[email protected]c0e3ee42010-05-26 22:11:07122 // Notification that a tab has been closed. |closed_by_user_gesture| comes
[email protected]e6ff1d52012-04-17 20:00:40123 // from |WebContents::closed_by_user_gesture|; see it for details.
initial.commit09911bf2008-07-26 23:55:29124 //
125 // Note: this is invoked from the NavigationController's destructor, which is
126 // after the actual tab has been removed.
[email protected]c0e3ee42010-05-26 22:11:07127 void TabClosed(const SessionID& window_id,
128 const SessionID& tab_id,
129 bool closed_by_user_gesture);
initial.commit09911bf2008-07-26 23:55:29130
[email protected]7d52ea4c62013-11-13 03:52:14131 // Notification a window has opened.
132 void WindowOpened(Browser* browser);
133
initial.commit09911bf2008-07-26 23:55:29134 // Notification the window is about to close.
135 void WindowClosing(const SessionID& window_id);
136
137 // Notification a window has finished closing.
138 void WindowClosed(const SessionID& window_id);
139
[email protected]40600152012-09-26 10:04:31140 // Called when a tab is inserted.
141 void TabInserted(content::WebContents* contents);
142
143 // Called when a tab is closing.
144 void TabClosing(content::WebContents* contents);
145
initial.commit09911bf2008-07-26 23:55:29146 // Sets the type of window. In order for the contents of a window to be
147 // tracked SetWindowType must be invoked with a type we track
skuhnec3aa8cf2014-10-30 06:02:45148 // (ShouldRestoreOfWindowType returns true).
[email protected]a636d8e52012-02-28 15:40:41149 void SetWindowType(const SessionID& window_id,
150 Browser::Type type,
151 AppType app_type);
152
[email protected]18ab5152013-03-28 23:14:05153 // Sets the application name of the specified window.
154 void SetWindowAppName(const SessionID& window_id,
155 const std::string& app_name);
initial.commit09911bf2008-07-26 23:55:29156
[email protected]c12bf1a12008-09-17 16:28:49157 // Invoked when the NavigationController has removed entries from the back of
158 // the list. |count| gives the number of entries in the navigation controller.
159 void TabNavigationPathPrunedFromBack(const SessionID& window_id,
160 const SessionID& tab_id,
161 int count);
162
163 // Invoked when the NavigationController has removed entries from the front of
164 // the list. |count| gives the number of entries that were removed.
165 void TabNavigationPathPrunedFromFront(const SessionID& window_id,
166 const SessionID& tab_id,
167 int count);
initial.commit09911bf2008-07-26 23:55:29168
169 // Updates the navigation entry for the specified tab.
[email protected]40a7e412013-04-29 18:13:01170 void UpdateTabNavigation(
171 const SessionID& window_id,
172 const SessionID& tab_id,
173 const sessions::SerializedNavigationEntry& navigation);
initial.commit09911bf2008-07-26 23:55:29174
175 // Notification that a tab has restored its entries or a closed tab is being
176 // reused.
[email protected]b624ddc2012-11-15 18:04:13177 void TabRestored(content::WebContents* tab, bool pinned);
initial.commit09911bf2008-07-26 23:55:29178
179 // Sets the index of the selected entry in the navigation controller for the
180 // specified tab.
181 void SetSelectedNavigationIndex(const SessionID& window_id,
182 const SessionID& tab_id,
183 int index);
184
185 // Sets the index of the selected tab in the specified window.
186 void SetSelectedTabInWindow(const SessionID& window_id, int index);
187
[email protected]8d0f3312012-08-18 01:47:53188 // Sets the user agent override of the specified tab.
189 void SetTabUserAgentOverride(const SessionID& window_id,
190 const SessionID& tab_id,
191 const std::string& user_agent_override);
192
skuhnec3aa8cf2014-10-30 06:02:45193 // Sets the application extension id of the specified tab.
194 void SetTabExtensionAppID(const SessionID& window_id,
195 const SessionID& tab_id,
196 const std::string& extension_app_id);
197
[email protected]4c7f9c52012-12-11 21:51:30198 // Callback from GetLastSession.
199 // The second parameter is the id of the window that was last active.
200 typedef base::Callback<void(ScopedVector<SessionWindow>, SessionID::id_type)>
201 SessionCallback;
initial.commit09911bf2008-07-26 23:55:29202
203 // Fetches the contents of the last session, notifying the callback when
204 // done. If the callback is supplied an empty vector of SessionWindows
205 // it means the session could not be restored.
[email protected]e95b717f2014-02-06 13:47:13206 base::CancelableTaskTracker::TaskId GetLastSession(
207 const SessionCallback& callback,
208 base::CancelableTaskTracker* tracker);
[email protected]3acb70ef2010-03-01 18:44:38209
[email protected]70eb8ed92010-06-10 18:13:12210 // Overridden from BaseSessionService because we want some UMA reporting on
211 // session update activities.
Daniel Chenga542fca2014-10-21 09:51:29212 void Save() override;
[email protected]70eb8ed92010-06-10 18:13:12213
initial.commit09911bf2008-07-26 23:55:29214 private:
[email protected]bf219e9eb2012-10-10 15:20:38215 // Allow tests to access our innards for testing purposes.
216 FRIEND_TEST_ALL_PREFIXES(SessionServiceTest, RestoreActivation1);
217 FRIEND_TEST_ALL_PREFIXES(SessionServiceTest, RestoreActivation2);
[email protected]51e5bdc2012-12-06 06:12:56218 FRIEND_TEST_ALL_PREFIXES(NoStartupWindowTest, DontInitSessionServiceForApps);
[email protected]bf219e9eb2012-10-10 15:20:38219
[email protected]23da84e152010-07-14 01:29:05220 typedef std::map<SessionID::id_type, std::pair<int, int> > IdToRange;
[email protected]97d2c1e2009-11-05 03:55:05221
[email protected]169627b2008-12-06 19:30:19222 void Init();
initial.commit09911bf2008-07-26 23:55:29223
skuhnec3aa8cf2014-10-30 06:02:45224 // Returns true if a window of given |window_type| and |app_type| should get
225 // restored upon session restore.
226 bool ShouldRestoreWindowOfType(SessionWindow::WindowType type,
227 AppType app_type) const;
228
229 // Removes unrestorable windows from the previous windows list.
230 void RemoveUnusedRestoreWindows(std::vector<SessionWindow*>* window_list);
231
[email protected]51e5bdc2012-12-06 06:12:56232 // Returns true if we have scheduled any commands, or any scheduled commands
233 // have been saved.
234 bool processed_any_commands();
235
[email protected]c9b19942010-03-26 15:58:08236 // Implementation of RestoreIfNecessary. If |browser| is non-null and we need
237 // to restore, the tabs are added to it, otherwise a new browser is created.
238 bool RestoreIfNecessary(const std::vector<GURL>& urls_to_open,
239 Browser* browser);
240
Daniel Chenga542fca2014-10-21 09:51:29241 void Observe(int type,
242 const content::NotificationSource& source,
243 const content::NotificationDetails& details) override;
[email protected]534e54b2008-08-13 15:40:09244
[email protected]bf219e9eb2012-10-10 15:20:38245 // chrome::BrowserListObserver
Daniel Chenga542fca2014-10-21 09:51:29246 void OnBrowserAdded(Browser* browser) override {}
247 void OnBrowserRemoved(Browser* browser) override {}
248 void OnBrowserSetLastActive(Browser* browser) override;
[email protected]bf219e9eb2012-10-10 15:20:38249
[email protected]4c7f9c52012-12-11 21:51:30250 // Converts |commands| to SessionWindows and notifies the callback.
251 void OnGotSessionCommands(const SessionCallback& callback,
252 ScopedVector<SessionCommand> commands);
initial.commit09911bf2008-07-26 23:55:29253
initial.commit09911bf2008-07-26 23:55:29254 // Adds commands to commands that will recreate the state of the specified
[email protected]81898992011-06-14 22:15:00255 // tab. This adds at most kMaxNavigationCountToPersist navigations (in each
256 // direction from the current navigation index).
initial.commit09911bf2008-07-26 23:55:29257 // A pair is added to tab_to_available_range indicating the range of
258 // indices that were written.
259 void BuildCommandsForTab(
260 const SessionID& window_id,
[email protected]b624ddc2012-11-15 18:04:13261 content::WebContents* tab,
initial.commit09911bf2008-07-26 23:55:29262 int index_in_window,
[email protected]5c0e6482009-07-14 20:20:09263 bool is_pinned,
initial.commit09911bf2008-07-26 23:55:29264 std::vector<SessionCommand*>* commands,
265 IdToRange* tab_to_available_range);
266
267 // Adds commands to create the specified browser, and invokes
268 // BuildCommandsForTab for each of the tabs in the browser. This ignores
269 // any tabs not in the profile we were created with.
270 void BuildCommandsForBrowser(
271 Browser* browser,
272 std::vector<SessionCommand*>* commands,
273 IdToRange* tab_to_available_range,
274 std::set<SessionID::id_type>* windows_to_track);
275
276 // Iterates over all the known browsers invoking BuildCommandsForBrowser.
skuhnec3aa8cf2014-10-30 06:02:45277 // This only adds browsers that should be tracked (|ShouldRestoreWindowOfType|
278 // returns true). All browsers that are tracked are added to windows_to_track
279 // (as long as it is non-null).
initial.commit09911bf2008-07-26 23:55:29280 void BuildCommandsFromBrowsers(
281 std::vector<SessionCommand*>* commands,
282 IdToRange* tab_to_available_range,
283 std::set<SessionID::id_type>* windows_to_track);
284
skuhnec3aa8cf2014-10-30 06:02:45285 // Schedules a reset of the existing commands. A reset means the contents
286 // of the file are recreated from the state of the browser.
287 void ScheduleResetCommands();
initial.commit09911bf2008-07-26 23:55:29288
289 // Schedules the specified command. This method takes ownership of the
290 // command.
Daniel Chenga542fca2014-10-21 09:51:29291 void ScheduleCommand(SessionCommand* command) override;
initial.commit09911bf2008-07-26 23:55:29292
293 // Converts all pending tab/window closes to commands and schedules them.
294 void CommitPendingCloses();
295
initial.commit09911bf2008-07-26 23:55:29296 // Returns true if there is only one window open with a single tab that shares
297 // our profile.
[email protected]bf219e9eb2012-10-10 15:20:38298 bool IsOnlyOneTabLeft() const;
initial.commit09911bf2008-07-26 23:55:29299
[email protected]982921f12009-10-27 21:43:53300 // Returns true if there are open trackable browser windows whose ids do
301 // match |window_id| with our profile. A trackable window is a window from
skuhnec3aa8cf2014-10-30 06:02:45302 // which |ShouldRestoreWindowOfType| returns true. See
303 // |ShouldRestoreWindowOfType| for details.
[email protected]bf219e9eb2012-10-10 15:20:38304 bool HasOpenTrackableBrowsers(const SessionID& window_id) const;
initial.commit09911bf2008-07-26 23:55:29305
306 // Returns true if changes to tabs in the specified window should be tracked.
[email protected]bf219e9eb2012-10-10 15:20:38307 bool ShouldTrackChangesToWindow(const SessionID& window_id) const;
308
309 // Returns true if we track changes to the specified browser.
310 bool ShouldTrackBrowser(Browser* browser) const;
initial.commit09911bf2008-07-26 23:55:29311
[email protected]23da84e152010-07-14 01:29:05312 // Call when certain session relevant notifications
313 // (tab_closed, nav_list_pruned) occur. In addition, this is
314 // currently called when Save() is called to compare how often the
315 // session data is currently saved verses when we may want to save it.
316 // It records the data in UMA stats.
[email protected]432115822011-07-10 15:52:27317 void RecordSessionUpdateHistogramData(int type,
[email protected]23da84e152010-07-14 01:29:05318 base::TimeTicks* last_updated_time);
319
320 // Helper methods to record the histogram data
321 void RecordUpdatedTabClosed(base::TimeDelta delta, bool use_long_period);
322 void RecordUpdatedNavListPruned(base::TimeDelta delta, bool use_long_period);
323 void RecordUpdatedNavEntryCommit(base::TimeDelta delta, bool use_long_period);
324 void RecordUpdatedSaveTime(base::TimeDelta delta, bool use_long_period);
325 void RecordUpdatedSessionNavigationOrTab(base::TimeDelta delta,
326 bool use_long_period);
[email protected]4070a6b2009-11-05 23:33:55327
[email protected]3efee4172014-01-23 13:53:36328 // Deletes session data if no windows are open for the current profile.
329 void MaybeDeleteSessionOnlyData();
330
skuhned58ab122014-10-22 20:23:02331 // The profile. This may be null during testing.
332 Profile* profile_;
333
[email protected]6c2381d2011-10-19 02:52:53334 content::NotificationRegistrar registrar_;
[email protected]6a02963e2009-01-06 16:58:03335
initial.commit09911bf2008-07-26 23:55:29336 // Maps from session tab id to the range of navigation entries that has
337 // been written to disk.
338 //
339 // This is only used if not all the navigation entries have been
340 // written.
341 IdToRange tab_to_available_range_;
342
[email protected]6ea265a2008-10-30 02:58:36343 // When the user closes the last window, where the last window is the
initial.commit09911bf2008-07-26 23:55:29344 // last tabbed browser and no more tabbed browsers are open with the same
345 // profile, the window ID is added here. These IDs are only committed (which
346 // marks them as closed) if the user creates a new tabbed browser.
347 typedef std::set<SessionID::id_type> PendingWindowCloseIDs;
348 PendingWindowCloseIDs pending_window_close_ids_;
349
350 // Set of tabs that have been closed by way of the last window or last tab
351 // closing, but not yet committed.
352 typedef std::set<SessionID::id_type> PendingTabCloseIDs;
353 PendingTabCloseIDs pending_tab_close_ids_;
354
355 // When a window other than the last window (see description of
356 // pending_window_close_ids) is closed, the id is added to this set.
357 typedef std::set<SessionID::id_type> WindowClosingIDs;
358 WindowClosingIDs window_closing_ids_;
359
360 // Set of windows we're tracking changes to. This is only browsers that
skuhnec3aa8cf2014-10-30 06:02:45361 // return true from |ShouldRestoreWindowOfType|.
initial.commit09911bf2008-07-26 23:55:29362 typedef std::set<SessionID::id_type> WindowsTracking;
363 WindowsTracking windows_tracking_;
364
[email protected]982921f12009-10-27 21:43:53365 // Are there any open trackable browsers?
366 bool has_open_trackable_browsers_;
initial.commit09911bf2008-07-26 23:55:29367
[email protected]6ea265a2008-10-30 02:58:36368 // If true and a new tabbed browser is created and there are no opened tabbed
[email protected]982921f12009-10-27 21:43:53369 // browser (has_open_trackable_browsers_ is false), then the current session
[email protected]668cd422011-04-06 21:00:01370 // is made the last session. See description above class for details on
371 // current/last session.
[email protected]6ea265a2008-10-30 02:58:36372 bool move_on_new_browser_;
[email protected]169627b2008-12-06 19:30:19373
[email protected]47db9a92011-01-24 20:10:13374 // Used for reporting frequency of session altering operations.
[email protected]23da84e152010-07-14 01:29:05375 base::TimeTicks last_updated_tab_closed_time_;
376 base::TimeTicks last_updated_nav_list_pruned_time_;
377 base::TimeTicks last_updated_nav_entry_commit_time_;
378 base::TimeTicks last_updated_save_time_;
379
380 // Constants used in calculating histogram data.
381 const base::TimeDelta save_delay_in_millis_;
382 const base::TimeDelta save_delay_in_mins_;
383 const base::TimeDelta save_delay_in_hrs_;
[email protected]70eb8ed92010-06-10 18:13:12384
[email protected]c4340bc02012-04-25 02:49:38385 // For browser_tests, since we want to simulate the browser shutting down
386 // without quitting.
387 bool force_browser_not_alive_with_no_windows_;
388
sky1a14f492014-08-26 21:44:26389 base::WeakPtrFactory<SessionService> weak_factory_;
390
[email protected]169627b2008-12-06 19:30:19391 DISALLOW_COPY_AND_ASSIGN(SessionService);
initial.commit09911bf2008-07-26 23:55:29392};
393
[email protected]169627b2008-12-06 19:30:19394#endif // CHROME_BROWSER_SESSIONS_SESSION_SERVICE_H_