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_SYNC_GLUE_SYNCED_SESSION_TRACKER_H_ 6 #define CHROME_BROWSER_SYNC_GLUE_SYNCED_SESSION_TRACKER_H_ 7 8 #include <map> 9 #include <set> 10 #include <string> 11 #include <vector> 12 13 #include "base/basictypes.h" 14 #include "base/memory/scoped_vector.h" 15 #include "chrome/browser/sessions/session_types.h" 16 #include "chrome/browser/sync/glue/synced_session.h" 17 #include "chrome/browser/sync/sessions/tab_node_pool.h" 18 #include "components/sessions/session_id.h" 19 20 namespace browser_sync { 21 22 // Class to manage synced sessions. The tracker will own all SyncedSession 23 // and SyncedSessionTab objects it creates, and deletes them appropriately on 24 // destruction. 25 // Note: SyncedSession objects are created for all synced sessions, including 26 // the local session (whose tag we maintain separately). 27 class SyncedSessionTracker { 28 public: 29 SyncedSessionTracker(); 30 ~SyncedSessionTracker(); 31 32 // We track and distinguish the local session from foreign sessions. 33 void SetLocalSessionTag(const std::string& local_session_tag); 34 35 // Fill a preallocated vector with all foreign sessions we're tracking (skips 36 // the local session object). SyncedSession ownership remains within the 37 // SyncedSessionTracker. 38 // Returns true if we had foreign sessions to fill it with, false otherwise. 39 bool LookupAllForeignSessions(std::vector<const SyncedSession*>* sessions) 40 const; 41 42 // Attempts to look up the session windows associatd with the session given 43 // by |session_tag|. Ownership Of SessionWindows stays within the 44 // SyncedSessionTracker. 45 // If lookup succeeds: 46 // - Fills windows with the SessionWindow pointers, returns true. 47 // Else 48 // - Returns false. 49 bool LookupSessionWindows(const std::string& session_tag, 50 std::vector<const SessionWindow*>* windows) const; 51 52 // Attempts to look up the tab associated with the given tag and tab id. 53 // Ownership of the SessionTab remains within the SyncedSessionTracker. 54 // If lookup succeeds: 55 // - Sets tab to point to the SessionTab, and returns true. 56 // Else 57 // - Returns false, tab is set to NULL. 58 bool LookupSessionTab(const std::string& session_tag, 59 SessionID::id_type tab_id, 60 const SessionTab** tab) const; 61 62 // Allows retrieval of existing data for the local session. Unlike GetSession 63 // this won't create-if-not-present. 64 bool LookupLocalSession(const SyncedSession** output) const; 65 66 // Returns a pointer to the SyncedSession object associated with 67 // |session_tag|. If none exists, creates one. Ownership of the 68 // SyncedSession remains within the SyncedSessionTracker. 69 SyncedSession* GetSession(const std::string& session_tag); 70 71 // Deletes the session associated with |session_tag| if it exists. 72 // Returns true if the session existed and was deleted, false otherwise. 73 bool DeleteSession(const std::string& session_tag); 74 75 // Resets the tracking information for the session specified by |session_tag|. 76 // This involves clearing all the windows and tabs from the session, while 77 // keeping pointers saved in the synced_window_map_ and synced_tab_map_. 78 // Once reset, all calls to PutWindowInSession and PutTabInWindow will denote 79 // that the requested windows and tabs are owned (by setting the boolean 80 // in their SessionWindowWrapper/SessionTabWrapper to true) and add them back 81 // to their session. The next call to CleanupSession(...) will delete those 82 // windows and tabs not owned. 83 void ResetSessionTracking(const std::string& session_tag); 84 85 // Deletes those windows and tabs associated with |session_tag| that are no 86 // longer owned. 87 // See ResetSessionTracking(...). 88 void CleanupSession(const std::string& session_tag); 89 90 // Adds the window with id |window_id| to the session specified by 91 // |session_tag|, and markes the window as being owned. If none existed for 92 // that session, creates one. Similarly, if the session did not exist yet, 93 // creates it. Ownership of the SessionWindow remains within the 94 // SyncedSessionTracker. 95 void PutWindowInSession(const std::string& session_tag, 96 SessionID::id_type window_id); 97 98 // Adds the tab with id |tab_id| to the window |window_id|, and marks it as 99 // being owned. If none existed for that session, creates one. Ownership of 100 // the SessionTab remains within the SyncedSessionTracker. 101 // Note: GetSession(..) must have already been called with |session_tag| to 102 // ensure we having mapping information for this session. 103 void PutTabInWindow(const std::string& session_tag, 104 SessionID::id_type window_id, 105 SessionID::id_type tab_id, 106 size_t tab_index); 107 108 // Returns a pointer to the SessionTab object associated with |tab_id| for 109 // the session specified with |session_tag|. If none exists, creates one. 110 // Ownership of the SessionTab remains within the SyncedSessionTracker. 111 // |tab_node_id| must be a valid node id for the node backing this tab. 112 SessionTab* GetTab(const std::string& session_tag, 113 SessionID::id_type tab_id, 114 int tab_node_id); 115 116 // Fills |tab_node_ids| with the tab node ids (see GetTab) for all the tabs* 117 // associated with the session having tag |session_tag|. 118 // Returns false if we don't have any record of the session. If no tabs were 119 // found as part of the session, the return value will be true but 120 // |tab_node_ids| will be empty. 121 // 122 // * - note that this only returns the ids we're aware of; it's possible we 123 // don't have the latest tab state from a foreign session and it's also 124 // possible we just haven't updated the tab_node_id for a tab yet, so the 125 // result list should not be treated as authoritative. 126 bool LookupTabNodeIds(const std::string& session_tag, 127 std::set<int>* tab_node_ids); 128 129 // Free the memory for all dynamically allocated objects and clear the 130 // tracking structures. 131 void Clear(); 132 Empty()133 bool Empty() const { 134 return synced_tab_map_.empty() && synced_session_map_.empty(); 135 } 136 137 // Includes both foreign sessions and the local session. num_synced_sessions()138 size_t num_synced_sessions() const { 139 return synced_session_map_.size(); 140 } 141 142 // Returns the number of tabs associated with the specified session tag. num_synced_tabs(const std::string & session_tag)143 size_t num_synced_tabs(const std::string& session_tag) const { 144 SyncedTabMap::const_iterator iter = synced_tab_map_.find(session_tag); 145 if (iter != synced_tab_map_.end()) { 146 return iter->second.size(); 147 } else { 148 return 0; 149 } 150 } 151 private: 152 // Datatypes for accessing session data. Neither of the *Wrappers actually 153 // have ownership of the Windows/Tabs, they just provide id-based access to 154 // them. The ownership remains within its containing session (for windows and 155 // mapped tabs, unmapped tabs are owned by the unmapped_tabs_ container). 156 // Note, we pair pointers with bools so that we can track what is owned and 157 // what can be deleted (see ResetSessionTracking(..) and CleanupSession(..) 158 // above). 159 // The wrappers also serve as a convenient place to augment state stored in 160 // SessionTab for sync purposes, such as |tab_node_id|. 161 // IsOwned is used as a wrapper constructor parameter for readability. 162 enum OwnedState { 163 IS_OWNED, 164 NOT_OWNED 165 }; 166 struct SessionTabWrapper { SessionTabWrapperSessionTabWrapper167 SessionTabWrapper() : tab_ptr(NULL), 168 owned(false), 169 tab_node_id(TabNodePool::kInvalidTabNodeID) {} SessionTabWrapperSessionTabWrapper170 SessionTabWrapper(SessionTab* tab_ptr, OwnedState owned, int tab_node_id) 171 : tab_ptr(tab_ptr), 172 owned(owned == IS_OWNED), 173 tab_node_id(tab_node_id) {} 174 SessionTab* tab_ptr; 175 176 // This is used as part of a mark-and-sweep approach to garbage 177 // collection for closed tabs that are no longer "in use", or "owned". 178 // ResetSessionTracking will clear |owned| bits, and if it is not claimed 179 // by a window by the time CleanupSession is called it will be deleted. 180 bool owned; 181 182 // This lets us identify the sync node that is "backing" this tab in the 183 // sync model, whether it is part of a local or foreign session. The 184 // "tab node id" is described in session_specifics.proto. 185 int tab_node_id; 186 }; 187 typedef std::map<SessionID::id_type, SessionTabWrapper> IDToSessionTabMap; 188 typedef std::map<std::string, IDToSessionTabMap> SyncedTabMap; 189 190 struct SessionWindowWrapper { SessionWindowWrapperSessionWindowWrapper191 SessionWindowWrapper() : window_ptr(NULL), owned(false) {} SessionWindowWrapperSessionWindowWrapper192 SessionWindowWrapper(SessionWindow* window_ptr, OwnedState owned) 193 : window_ptr(window_ptr), 194 owned(owned == IS_OWNED) {} 195 SessionWindow* window_ptr; 196 bool owned; 197 }; 198 typedef std::map<SessionID::id_type, SessionWindowWrapper> 199 IDToSessionWindowMap; 200 typedef std::map<std::string, IDToSessionWindowMap> SyncedWindowMap; 201 202 typedef std::map<std::string, SyncedSession*> SyncedSessionMap; 203 204 // Helper methods for deleting SessionWindows and SessionTabs without owners. 205 bool DeleteOldSessionWindowIfNecessary(SessionWindowWrapper window_wrapper); 206 bool DeleteOldSessionTabIfNecessary(SessionTabWrapper tab_wrapper); 207 208 // Implementation for GetTab(...) above, permits invalid tab_node_id. 209 SessionTab* GetTabImpl(const std::string& session_tag, 210 SessionID::id_type tab_id, 211 int tab_node_id); 212 213 // Per client mapping of tab id's to their SessionTab objects. 214 // Key: session tag. 215 // Value: Tab id to SessionTabWrapper map. 216 SyncedTabMap synced_tab_map_; 217 218 // Per client mapping of the window id's to their SessionWindow objects. 219 // Key: session_tag 220 // Value: Window id to SessionWindowWrapper map. 221 SyncedWindowMap synced_window_map_; 222 223 // Per client mapping synced session objects. 224 // Key: session tag. 225 // Value: SyncedSession object pointer. 226 SyncedSessionMap synced_session_map_; 227 228 // The set of tabs that we have seen, and created SessionTab objects for, but 229 // have not yet mapped to SyncedSessions. These are temporarily orphaned 230 // tabs, and won't be deleted if we delete synced_session_map_, but are still 231 // owned by the SyncedSessionTracker itself (and deleted on Clear()). 232 std::set<SessionTab*> unmapped_tabs_; 233 234 // The tag for this machine's local session, so we can distinguish the foreign 235 // sessions. 236 std::string local_session_tag_; 237 238 DISALLOW_COPY_AND_ASSIGN(SyncedSessionTracker); 239 }; 240 241 } // namespace browser_sync 242 243 #endif // CHROME_BROWSER_SYNC_GLUE_SYNCED_SESSION_TRACKER_H_ 244