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_TAB_RESTORE_SERVICE_HELPER_H_ 6 #define CHROME_BROWSER_SESSIONS_TAB_RESTORE_SERVICE_HELPER_H_ 7 8 #include <set> 9 #include <vector> 10 11 #include "base/basictypes.h" 12 #include "base/observer_list.h" 13 #include "base/time/time.h" 14 #include "chrome/browser/sessions/session_types.h" 15 #include "chrome/browser/sessions/tab_restore_service.h" 16 #include "chrome/browser/ui/host_desktop.h" 17 #include "components/sessions/session_id.h" 18 19 class Profile; 20 class TabRestoreService; 21 class TabRestoreServiceDelegate; 22 class TabRestoreServiceObserver; 23 class TimeFactory; 24 25 namespace content { 26 class NavigationController; 27 class WebContents; 28 } 29 30 // Helper class used to implement InMemoryTabRestoreService and 31 // PersistentTabRestoreService. See tab_restore_service.h for method-level 32 // comments. 33 class TabRestoreServiceHelper { 34 public: 35 typedef TabRestoreService::Entries Entries; 36 typedef TabRestoreService::Entry Entry; 37 typedef TabRestoreService::Tab Tab; 38 typedef TabRestoreService::TimeFactory TimeFactory; 39 typedef TabRestoreService::Window Window; 40 41 // Provides a way for the client to add behavior to the tab restore service 42 // helper (e.g. implementing tabs persistence). 43 class Observer { 44 public: 45 // Invoked before the entries are cleared. 46 virtual void OnClearEntries(); 47 48 // Invoked before the entry is restored. |entry_iterator| points to the 49 // entry corresponding to the session identified by |id|. 50 virtual void OnRestoreEntryById(SessionID::id_type id, 51 Entries::const_iterator entry_iterator); 52 53 // Invoked after an entry was added. 54 virtual void OnAddEntry(); 55 56 protected: 57 virtual ~Observer(); 58 }; 59 60 enum { 61 // Max number of entries we'll keep around. 62 kMaxEntries = 25, 63 }; 64 65 // Creates a new TabRestoreServiceHelper and provides an object that provides 66 // the current time. The TabRestoreServiceHelper does not take ownership of 67 // |time_factory| and |observer|. Note that |observer| can also be NULL. 68 TabRestoreServiceHelper(TabRestoreService* tab_restore_service, 69 Observer* observer, 70 Profile* profile, 71 TimeFactory* time_factory); 72 73 ~TabRestoreServiceHelper(); 74 75 // Helper methods used to implement TabRestoreService. 76 void AddObserver(TabRestoreServiceObserver* observer); 77 void RemoveObserver(TabRestoreServiceObserver* observer); 78 void CreateHistoricalTab(content::WebContents* contents, int index); 79 void BrowserClosing(TabRestoreServiceDelegate* delegate); 80 void BrowserClosed(TabRestoreServiceDelegate* delegate); 81 void ClearEntries(); 82 const Entries& entries() const; 83 std::vector<content::WebContents*> RestoreMostRecentEntry( 84 TabRestoreServiceDelegate* delegate, 85 chrome::HostDesktopType host_desktop_type); 86 Tab* RemoveTabEntryById(SessionID::id_type id); 87 std::vector<content::WebContents*> RestoreEntryById( 88 TabRestoreServiceDelegate* delegate, 89 SessionID::id_type id, 90 chrome::HostDesktopType host_desktop_type, 91 WindowOpenDisposition disposition); 92 93 // Notifies observers the tabs have changed. 94 void NotifyTabsChanged(); 95 96 // Notifies observers the service has loaded. 97 void NotifyLoaded(); 98 99 // Adds |entry| to the list of entries and takes ownership. If |prune| is true 100 // |PruneAndNotify| is invoked. If |to_front| is true the entry is added to 101 // the front, otherwise the back. Normal closes go to the front, but 102 // tab/window closes from the previous session are added to the back. 103 void AddEntry(Entry* entry, bool prune, bool to_front); 104 105 // Prunes |entries_| to contain only kMaxEntries, and removes uninteresting 106 // entries. 107 void PruneEntries(); 108 109 // Returns an iterator into |entries_| whose id matches |id|. If |id| 110 // identifies a Window, then its iterator position will be returned. If it 111 // identifies a tab, then the iterator position of the Window in which the Tab 112 // resides is returned. 113 Entries::iterator GetEntryIteratorById(SessionID::id_type id); 114 115 // Calls either ValidateTab or ValidateWindow as appropriate. 116 static bool ValidateEntry(Entry* entry); 117 118 private: 119 friend class PersistentTabRestoreService; 120 121 // Populates the tab's navigations from the NavigationController, and its 122 // browser_id and pinned state from the browser. 123 void PopulateTab(Tab* tab, 124 int index, 125 TabRestoreServiceDelegate* delegate, 126 content::NavigationController* controller); 127 128 // This is a helper function for RestoreEntryById() for restoring a single 129 // tab. If |delegate| is NULL, this creates a new window for the entry. This 130 // returns the TabRestoreServiceDelegate into which the tab was restored. 131 // |disposition| will be respected, but if it is UNKNOWN then the tab's 132 // original attributes will be respected instead. If a new browser needs to be 133 // created for this tab, it will be created on the desktop specified by 134 // |host_desktop_type|. If present, |contents| will be populated with the 135 // WebContents of the restored tab. 136 TabRestoreServiceDelegate* RestoreTab( 137 const Tab& tab, 138 TabRestoreServiceDelegate* delegate, 139 chrome::HostDesktopType host_desktop_type, 140 WindowOpenDisposition disposition, 141 content::WebContents** contents); 142 143 // Returns true if |tab| has more than one navigation. If |tab| has more 144 // than one navigation |tab->current_navigation_index| is constrained based 145 // on the number of navigations. 146 static bool ValidateTab(Tab* tab); 147 148 // Validates all the tabs in a window, plus the window's active tab index. 149 static bool ValidateWindow(Window* window); 150 151 // Returns true if |tab| is one we care about restoring. 152 static bool IsTabInteresting(const Tab* tab); 153 154 // Checks whether |window| is interesting --- if it only contains a single, 155 // uninteresting tab, it's not interesting. 156 static bool IsWindowInteresting(const Window* window); 157 158 // Validates and checks |entry| for interesting. 159 static bool FilterEntry(Entry* entry); 160 161 // Finds tab entries with the old browser_id and sets it to the new one. 162 void UpdateTabBrowserIDs(SessionID::id_type old_id, 163 SessionID::id_type new_id); 164 165 // Gets the current time. This uses the time_factory_ if there is one. 166 base::Time TimeNow() const; 167 168 TabRestoreService* const tab_restore_service_; 169 170 Observer* const observer_; 171 172 Profile* const profile_; 173 174 // Set of entries. They are ordered from most to least recent. 175 Entries entries_; 176 177 // Are we restoring a tab? If this is true we ignore requests to create a 178 // historical tab. 179 bool restoring_; 180 181 ObserverList<TabRestoreServiceObserver> observer_list_; 182 183 // Set of delegates that we've received a BrowserClosing method for but no 184 // corresponding BrowserClosed. We cache the set of delegates closing to 185 // avoid creating historical tabs for them. 186 std::set<TabRestoreServiceDelegate*> closing_delegates_; 187 188 TimeFactory* const time_factory_; 189 190 DISALLOW_COPY_AND_ASSIGN(TabRestoreServiceHelper); 191 }; 192 193 #endif // CHROME_BROWSER_SESSIONS_TAB_RESTORE_SERVICE_HELPER_H_ 194