- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / sessions / session_service.h
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.
4
5 #ifndef CHROME_BROWSER_SESSIONS_SESSION_SERVICE_H_
6 #define CHROME_BROWSER_SESSIONS_SESSION_SERVICE_H_
7
8 #include <map>
9 #include <string>
10
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"
26
27 class Profile;
28 class SessionCommand;
29 struct SessionTab;
30 struct SessionWindow;
31
32 namespace content {
33 class NavigationEntry;
34 class WebContents;
35 }
36
37 // SessionService ------------------------------------------------------------
38
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.
42 //
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.
50 //
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
67   };
68
69   // Creates a SessionService for the specified profile.
70   explicit SessionService(Profile* profile);
71   // For testing.
72   explicit SessionService(const base::FilePath& save_path);
73
74   virtual ~SessionService();
75
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();
81
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);
88
89   // Resets the contents of the file from the current state of all open
90   // browsers whose profile matches our profile.
91   void ResetFromCurrentBrowsers();
92
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();
97
98   // Associates a tab with a window.
99   void SetTabWindow(const SessionID& window_id,
100                     const SessionID& tab_id);
101
102   // Sets the bounds of a window.
103   void SetWindowBounds(const SessionID& window_id,
104                        const gfx::Rect& bounds,
105                        ui::WindowShowState show_state);
106
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);
111
112   // Sets the pinned state of the tab.
113   void SetPinnedState(const SessionID& window_id,
114                       const SessionID& tab_id,
115                       bool is_pinned);
116
117   // Notification that a tab has been closed. |closed_by_user_gesture| comes
118   // from |WebContents::closed_by_user_gesture|; see it for details.
119   //
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);
125
126   // Notification the window is about to close.
127   void WindowClosing(const SessionID& window_id);
128
129   // Notification a window has finished closing.
130   void WindowClosed(const SessionID& window_id);
131
132   // Called when a tab is inserted.
133   void TabInserted(content::WebContents* contents);
134
135   // Called when a tab is closing.
136   void TabClosing(content::WebContents* contents);
137
138   // Sets the type of window. In order for the contents of a window to be
139   // tracked SetWindowType must be invoked with a type we track
140   // (should_track_changes_for_browser_type returns true).
141   void SetWindowType(const SessionID& window_id,
142                      Browser::Type type,
143                      AppType app_type);
144
145   // Sets the application name of the specified window.
146   void SetWindowAppName(const SessionID& window_id,
147                         const std::string& app_name);
148
149   // Invoked when the NavigationController has removed entries from the back of
150   // the list. |count| gives the number of entries in the navigation controller.
151   void TabNavigationPathPrunedFromBack(const SessionID& window_id,
152                                        const SessionID& tab_id,
153                                        int count);
154
155   // Invoked when the NavigationController has removed entries from the front of
156   // the list. |count| gives the number of entries that were removed.
157   void TabNavigationPathPrunedFromFront(const SessionID& window_id,
158                                         const SessionID& tab_id,
159                                         int count);
160
161   // Updates the navigation entry for the specified tab.
162   void UpdateTabNavigation(
163       const SessionID& window_id,
164       const SessionID& tab_id,
165       const sessions::SerializedNavigationEntry& navigation);
166
167   // Notification that a tab has restored its entries or a closed tab is being
168   // reused.
169   void TabRestored(content::WebContents* tab, bool pinned);
170
171   // Sets the index of the selected entry in the navigation controller for the
172   // specified tab.
173   void SetSelectedNavigationIndex(const SessionID& window_id,
174                                   const SessionID& tab_id,
175                                   int index);
176
177   // Sets the index of the selected tab in the specified window.
178   void SetSelectedTabInWindow(const SessionID& window_id, int index);
179
180   // Sets the user agent override of the specified tab.
181   void SetTabUserAgentOverride(const SessionID& window_id,
182                                const SessionID& tab_id,
183                                const std::string& user_agent_override);
184
185   // Callback from GetLastSession.
186   // The second parameter is the id of the window that was last active.
187   typedef base::Callback<void(ScopedVector<SessionWindow>, SessionID::id_type)>
188       SessionCallback;
189
190   // Fetches the contents of the last session, notifying the callback when
191   // done. If the callback is supplied an empty vector of SessionWindows
192   // it means the session could not be restored.
193   CancelableTaskTracker::TaskId GetLastSession(const SessionCallback& callback,
194                                                CancelableTaskTracker* tracker);
195
196   // Overridden from BaseSessionService because we want some UMA reporting on
197   // session update activities.
198   virtual void Save() OVERRIDE;
199
200  private:
201   // Allow tests to access our innards for testing purposes.
202   FRIEND_TEST_ALL_PREFIXES(SessionServiceTest, RestoreActivation1);
203   FRIEND_TEST_ALL_PREFIXES(SessionServiceTest, RestoreActivation2);
204   FRIEND_TEST_ALL_PREFIXES(NoStartupWindowTest, DontInitSessionServiceForApps);
205
206   typedef std::map<SessionID::id_type, std::pair<int, int> > IdToRange;
207   typedef std::map<SessionID::id_type, SessionTab*> IdToSessionTab;
208   typedef std::map<SessionID::id_type, SessionWindow*> IdToSessionWindow;
209
210
211   // These types mirror Browser::Type, but are re-defined here because these
212   // specific enumeration _values_ are written into the session database and
213   // are needed to maintain forward compatibility.
214   // Note that we only store browsers of type TYPE_TABBED and TYPE_POPUP.
215   enum WindowType {
216     TYPE_TABBED = 0,
217     TYPE_POPUP = 1
218   };
219
220   void Init();
221
222   // Returns true if we have scheduled any commands, or any scheduled commands
223   // have been saved.
224   bool processed_any_commands();
225
226   // Implementation of RestoreIfNecessary. If |browser| is non-null and we need
227   // to restore, the tabs are added to it, otherwise a new browser is created.
228   bool RestoreIfNecessary(const std::vector<GURL>& urls_to_open,
229                           Browser* browser);
230
231   virtual void Observe(int type,
232                        const content::NotificationSource& source,
233                        const content::NotificationDetails& details) OVERRIDE;
234
235   // chrome::BrowserListObserver
236   virtual void OnBrowserAdded(Browser* browser) OVERRIDE {}
237   virtual void OnBrowserRemoved(Browser* browser) OVERRIDE {}
238   virtual void OnBrowserSetLastActive(Browser* browser) OVERRIDE;
239
240   // Sets the application extension id of the specified tab.
241   void SetTabExtensionAppID(const SessionID& window_id,
242                             const SessionID& tab_id,
243                             const std::string& extension_app_id);
244
245   // Methods to create the various commands. It is up to the caller to delete
246   // the returned the SessionCommand* object.
247   SessionCommand* CreateSetSelectedTabInWindow(const SessionID& window_id,
248                                                int index);
249
250   SessionCommand* CreateSetTabWindowCommand(const SessionID& window_id,
251                                             const SessionID& tab_id);
252
253   SessionCommand* CreateSetWindowBoundsCommand(const SessionID& window_id,
254                                                const gfx::Rect& bounds,
255                                                ui::WindowShowState show_state);
256
257   SessionCommand* CreateSetTabIndexInWindowCommand(const SessionID& tab_id,
258                                                    int new_index);
259
260   SessionCommand* CreateTabClosedCommand(SessionID::id_type tab_id);
261
262   SessionCommand* CreateWindowClosedCommand(SessionID::id_type tab_id);
263
264   SessionCommand* CreateSetSelectedNavigationIndexCommand(
265       const SessionID& tab_id,
266       int index);
267
268   SessionCommand* CreateSetWindowTypeCommand(const SessionID& window_id,
269                                              WindowType type);
270
271   SessionCommand* CreatePinnedStateCommand(const SessionID& tab_id,
272                                            bool is_pinned);
273
274   SessionCommand* CreateSessionStorageAssociatedCommand(
275       const SessionID& tab_id,
276       const std::string& session_storage_persistent_id);
277
278   SessionCommand* CreateSetActiveWindowCommand(const SessionID& window_id);
279
280   // Converts |commands| to SessionWindows and notifies the callback.
281   void OnGotSessionCommands(const SessionCallback& callback,
282                             ScopedVector<SessionCommand> commands);
283
284   // Converts the commands into SessionWindows. On return any valid
285   // windows are added to valid_windows. It is up to the caller to delete
286   // the windows added to valid_windows. |active_window_id| will be set with the
287   // id of the last active window, but it's only valid when this id corresponds
288   // to the id of one of the windows in valid_windows.
289   void RestoreSessionFromCommands(const std::vector<SessionCommand*>& commands,
290                                   std::vector<SessionWindow*>* valid_windows,
291                                   SessionID::id_type* active_window_id);
292
293   // Iterates through the vector updating the selected_tab_index of each
294   // SessionWindow based on the actual tabs that were restored.
295   void UpdateSelectedTabIndex(std::vector<SessionWindow*>* windows);
296
297   // Returns the window in windows with the specified id. If a window does
298   // not exist, one is created.
299   SessionWindow* GetWindow(SessionID::id_type window_id,
300                            IdToSessionWindow* windows);
301
302   // Returns the tab with the specified id in tabs. If a tab does not exist,
303   // it is created.
304   SessionTab* GetTab(SessionID::id_type tab_id,
305                      IdToSessionTab* tabs);
306
307   // Returns an iterator into navigations pointing to the navigation whose
308   // index matches |index|. If no navigation index matches |index|, the first
309   // navigation with an index > |index| is returned.
310   //
311   // This assumes the navigations are ordered by index in ascending order.
312   std::vector<sessions::SerializedNavigationEntry>::iterator
313   FindClosestNavigationWithIndex(
314       std::vector<sessions::SerializedNavigationEntry>* navigations,
315       int index);
316
317   // Does the following:
318   // . Deletes and removes any windows with no tabs or windows with types other
319   //   than tabbed_browser or browser. NOTE: constrained windows that have
320   //   been dragged out are of type browser. As such, this preserves any dragged
321   //   out constrained windows (aka popups that have been dragged out).
322   // . Sorts the tabs in windows with valid tabs based on the tabs
323   //   visual order, and adds the valid windows to windows.
324   void SortTabsBasedOnVisualOrderAndPrune(
325       std::map<int, SessionWindow*>* windows,
326       std::vector<SessionWindow*>* valid_windows);
327
328   // Adds tabs to their parent window based on the tab's window_id. This
329   // ignores tabs with no navigations.
330   void AddTabsToWindows(std::map<int, SessionTab*>* tabs,
331                         std::map<int, SessionWindow*>* windows);
332
333   // Creates tabs and windows from the commands specified in |data|. The created
334   // tabs and windows are added to |tabs| and |windows| respectively, with the
335   // id of the active window set in |active_window_id|. It is up to the caller
336   // to delete the tabs and windows added to |tabs| and |windows|.
337   //
338   // This does NOT add any created SessionTabs to SessionWindow.tabs, that is
339   // done by AddTabsToWindows.
340   bool CreateTabsAndWindows(const std::vector<SessionCommand*>& data,
341                             std::map<int, SessionTab*>* tabs,
342                             std::map<int, SessionWindow*>* windows,
343                             SessionID::id_type* active_window_id);
344
345   // Adds commands to commands that will recreate the state of the specified
346   // tab. This adds at most kMaxNavigationCountToPersist navigations (in each
347   // direction from the current navigation index).
348   // A pair is added to tab_to_available_range indicating the range of
349   // indices that were written.
350   void BuildCommandsForTab(
351       const SessionID& window_id,
352       content::WebContents* tab,
353       int index_in_window,
354       bool is_pinned,
355       std::vector<SessionCommand*>* commands,
356       IdToRange* tab_to_available_range);
357
358   // Adds commands to create the specified browser, and invokes
359   // BuildCommandsForTab for each of the tabs in the browser. This ignores
360   // any tabs not in the profile we were created with.
361   void BuildCommandsForBrowser(
362       Browser* browser,
363       std::vector<SessionCommand*>* commands,
364       IdToRange* tab_to_available_range,
365       std::set<SessionID::id_type>* windows_to_track);
366
367   // Iterates over all the known browsers invoking BuildCommandsForBrowser.
368   // This only adds browsers that should be tracked
369   // (should_track_changes_for_browser_type returns true). All browsers that
370   // are tracked are added to windows_to_track (as long as it is non-null).
371   void BuildCommandsFromBrowsers(
372       std::vector<SessionCommand*>* commands,
373       IdToRange* tab_to_available_range,
374       std::set<SessionID::id_type>* windows_to_track);
375
376   // Schedules a reset. A reset means the contents of the file are recreated
377   // from the state of the browser.
378   void ScheduleReset();
379
380   // Searches for a pending command that can be replaced with command.
381   // If one is found, pending command is removed, command is added to
382   // the pending commands and true is returned.
383   bool ReplacePendingCommand(SessionCommand* command);
384
385   // Schedules the specified command. This method takes ownership of the
386   // command.
387   virtual void ScheduleCommand(SessionCommand* command) OVERRIDE;
388
389   // Converts all pending tab/window closes to commands and schedules them.
390   void CommitPendingCloses();
391
392   // Returns true if there is only one window open with a single tab that shares
393   // our profile.
394   bool IsOnlyOneTabLeft() const;
395
396   // Returns true if there are open trackable browser windows whose ids do
397   // match |window_id| with our profile. A trackable window is a window from
398   // which |should_track_changes_for_browser_type| returns true. See
399   // |should_track_changes_for_browser_type| for details.
400   bool HasOpenTrackableBrowsers(const SessionID& window_id) const;
401
402   // Returns true if changes to tabs in the specified window should be tracked.
403   bool ShouldTrackChangesToWindow(const SessionID& window_id) const;
404
405   // Returns true if we track changes to the specified browser.
406   bool ShouldTrackBrowser(Browser* browser) const;
407
408   // Returns true if we track changes to the specified browser type.
409   static bool should_track_changes_for_browser_type(
410       Browser::Type type,
411       AppType app_type);
412
413   // Returns true if we should record a window close as pending.
414   // |has_open_trackable_browsers_| must be up-to-date before calling this.
415   bool should_record_close_as_pending() const {
416     // When this is called, the browser window being closed is still open, hence
417     // still in the browser list. If there is a browser window other than the
418     // one being closed but no trackable windows, then the others must be App
419     // windows or similar. In this case, we record the close as pending.
420     return !has_open_trackable_browsers_ &&
421         (!browser_defaults::kBrowserAliveWithNoWindows ||
422          force_browser_not_alive_with_no_windows_ ||
423          chrome::GetTotalBrowserCount() > 1);
424   }
425
426   // Call when certain session relevant notifications
427   // (tab_closed, nav_list_pruned) occur.  In addition, this is
428   // currently called when Save() is called to compare how often the
429   // session data is currently saved verses when we may want to save it.
430   // It records the data in UMA stats.
431   void RecordSessionUpdateHistogramData(int type,
432     base::TimeTicks* last_updated_time);
433
434   // Helper methods to record the histogram data
435   void RecordUpdatedTabClosed(base::TimeDelta delta, bool use_long_period);
436   void RecordUpdatedNavListPruned(base::TimeDelta delta, bool use_long_period);
437   void RecordUpdatedNavEntryCommit(base::TimeDelta delta, bool use_long_period);
438   void RecordUpdatedSaveTime(base::TimeDelta delta, bool use_long_period);
439   void RecordUpdatedSessionNavigationOrTab(base::TimeDelta delta,
440                                            bool use_long_period);
441
442   // Convert back/forward between the Browser and SessionService DB window
443   // types.
444   static WindowType WindowTypeForBrowserType(Browser::Type type);
445   static Browser::Type BrowserTypeForWindowType(WindowType type);
446
447   content::NotificationRegistrar registrar_;
448
449   // Maps from session tab id to the range of navigation entries that has
450   // been written to disk.
451   //
452   // This is only used if not all the navigation entries have been
453   // written.
454   IdToRange tab_to_available_range_;
455
456   // When the user closes the last window, where the last window is the
457   // last tabbed browser and no more tabbed browsers are open with the same
458   // profile, the window ID is added here. These IDs are only committed (which
459   // marks them as closed) if the user creates a new tabbed browser.
460   typedef std::set<SessionID::id_type> PendingWindowCloseIDs;
461   PendingWindowCloseIDs pending_window_close_ids_;
462
463   // Set of tabs that have been closed by way of the last window or last tab
464   // closing, but not yet committed.
465   typedef std::set<SessionID::id_type> PendingTabCloseIDs;
466   PendingTabCloseIDs pending_tab_close_ids_;
467
468   // When a window other than the last window (see description of
469   // pending_window_close_ids) is closed, the id is added to this set.
470   typedef std::set<SessionID::id_type> WindowClosingIDs;
471   WindowClosingIDs window_closing_ids_;
472
473   // Set of windows we're tracking changes to. This is only browsers that
474   // return true from should_track_changes_for_browser_type.
475   typedef std::set<SessionID::id_type> WindowsTracking;
476   WindowsTracking windows_tracking_;
477
478   // Are there any open trackable browsers?
479   bool has_open_trackable_browsers_;
480
481   // If true and a new tabbed browser is created and there are no opened tabbed
482   // browser (has_open_trackable_browsers_ is false), then the current session
483   // is made the last session. See description above class for details on
484   // current/last session.
485   bool move_on_new_browser_;
486
487   // Used for reporting frequency of session altering operations.
488   base::TimeTicks last_updated_tab_closed_time_;
489   base::TimeTicks last_updated_nav_list_pruned_time_;
490   base::TimeTicks last_updated_nav_entry_commit_time_;
491   base::TimeTicks last_updated_save_time_;
492
493   // Constants used in calculating histogram data.
494   const base::TimeDelta save_delay_in_millis_;
495   const base::TimeDelta save_delay_in_mins_;
496   const base::TimeDelta save_delay_in_hrs_;
497
498   // For browser_tests, since we want to simulate the browser shutting down
499   // without quitting.
500   bool force_browser_not_alive_with_no_windows_;
501
502   DISALLOW_COPY_AND_ASSIGN(SessionService);
503 };
504
505 #endif  // CHROME_BROWSER_SESSIONS_SESSION_SERVICE_H_