• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_id.h"
16 #include "chrome/browser/sessions/session_types.h"
17 #include "chrome/browser/sync/glue/synced_session.h"
18 #include "chrome/browser/sync/glue/tab_node_pool.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   // Returns a pointer to the SyncedSession object associated with
63   // |session_tag|.  If none exists, creates one. Ownership of the
64   // SyncedSession remains within the SyncedSessionTracker.
65   SyncedSession* GetSession(const std::string& session_tag);
66 
67   // Deletes the session associated with |session_tag| if it exists.
68   // Returns true if the session existed and was deleted, false otherwise.
69   bool DeleteSession(const std::string& session_tag);
70 
71   // Resets the tracking information for the session specified by |session_tag|.
72   // This involves clearing all the windows and tabs from the session, while
73   // keeping pointers saved in the synced_window_map_ and synced_tab_map_.
74   // Once reset, all calls to PutWindowInSession and PutTabInWindow will denote
75   // that the requested windows and tabs are owned (by setting the boolean
76   // in their SessionWindowWrapper/SessionTabWrapper to true) and add them back
77   // to their session. The next call to CleanupSession(...) will delete those
78   // windows and tabs not owned.
79   void ResetSessionTracking(const std::string& session_tag);
80 
81   // Deletes those windows and tabs associated with |session_tag| that are no
82   // longer owned.
83   // See ResetSessionTracking(...).
84   void CleanupSession(const std::string& session_tag);
85 
86   // Adds the window with id |window_id| to the session specified by
87   // |session_tag|, and markes the window as being owned. If none existed for
88   // that session, creates one. Similarly, if the session did not exist yet,
89   // creates it. Ownership of the SessionWindow remains within the
90   // SyncedSessionTracker.
91   void PutWindowInSession(const std::string& session_tag,
92                           SessionID::id_type window_id);
93 
94   // Adds the tab with id |tab_id| to the window |window_id|, and marks it as
95   // being owned. If none existed for that session, creates one. Ownership of
96   // the SessionTab remains within the SyncedSessionTracker.
97   // Note: GetSession(..) must have already been called with |session_tag| to
98   // ensure we having mapping information for this session.
99   void PutTabInWindow(const std::string& session_tag,
100                       SessionID::id_type window_id,
101                       SessionID::id_type tab_id,
102                       size_t tab_index);
103 
104   // Returns a pointer to the SessionTab object associated with |tab_id| for
105   // the session specified with |session_tag|. If none exists, creates one.
106   // Ownership of the SessionTab remains within the SyncedSessionTracker.
107   // |tab_node_id| must be a valid node id for the node backing this tab.
108   SessionTab* GetTab(const std::string& session_tag,
109                      SessionID::id_type tab_id,
110                      int tab_node_id);
111 
112   // Fills |tab_node_ids| with the tab node ids (see GetTab) for all the tabs*
113   // associated with the session having tag |session_tag|.
114   // Returns false if we don't have any record of the session.  If no tabs were
115   // found as part of the session, the return value will be true but
116   // |tab_node_ids| will be empty.
117   //
118   // * - note that this only returns the ids we're aware of; it's possible we
119   // don't have the latest tab state from a foreign session and it's also
120   // possible we just haven't updated the tab_node_id for a tab yet, so the
121   // result list should not be treated as authoritative.
122   bool LookupTabNodeIds(const std::string& session_tag,
123                         std::set<int>* tab_node_ids);
124 
125   // Free the memory for all dynamically allocated objects and clear the
126   // tracking structures.
127   void Clear();
128 
Empty()129   bool Empty() const {
130     return synced_tab_map_.empty() && synced_session_map_.empty();
131   }
132 
133   // Includes both foreign sessions and the local session.
num_synced_sessions()134   size_t num_synced_sessions() const {
135     return synced_session_map_.size();
136   }
137 
138   // Returns the number of tabs associated with the specified session tag.
num_synced_tabs(const std::string & session_tag)139   size_t num_synced_tabs(const std::string& session_tag) const {
140     SyncedTabMap::const_iterator iter = synced_tab_map_.find(session_tag);
141     if (iter != synced_tab_map_.end()) {
142       return iter->second.size();
143     } else {
144       return 0;
145     }
146   }
147  private:
148   // Datatypes for accessing session data. Neither of the *Wrappers actually
149   // have ownership of the Windows/Tabs, they just provide id-based access to
150   // them. The ownership remains within its containing session (for windows and
151   // mapped tabs, unmapped tabs are owned by the unmapped_tabs_ container).
152   // Note, we pair pointers with bools so that we can track what is owned and
153   // what can be deleted (see ResetSessionTracking(..) and CleanupSession(..)
154   // above).
155   // The wrappers also serve as a convenient place to augment state stored in
156   // SessionTab for sync purposes, such as |tab_node_id|.
157   // IsOwned is used as a wrapper constructor parameter for readability.
158   enum OwnedState {
159     IS_OWNED,
160     NOT_OWNED
161   };
162   struct SessionTabWrapper {
SessionTabWrapperSessionTabWrapper163     SessionTabWrapper() : tab_ptr(NULL),
164                           owned(false),
165                           tab_node_id(TabNodePool::kInvalidTabNodeID) {}
SessionTabWrapperSessionTabWrapper166     SessionTabWrapper(SessionTab* tab_ptr, OwnedState owned, int tab_node_id)
167         : tab_ptr(tab_ptr),
168           owned(owned == IS_OWNED),
169           tab_node_id(tab_node_id) {}
170     SessionTab* tab_ptr;
171 
172     // This is used as part of a mark-and-sweep approach to garbage
173     // collection for closed tabs that are no longer "in use", or "owned".
174     // ResetSessionTracking will clear |owned| bits, and if it is not claimed
175     // by a window by the time CleanupSession is called it will be deleted.
176     bool owned;
177 
178     // This lets us identify the sync node that is "backing" this tab in the
179     // sync model, whether it is part of a local or foreign session. The
180     // "tab node id" is described in session_specifics.proto.
181     int tab_node_id;
182   };
183   typedef std::map<SessionID::id_type, SessionTabWrapper> IDToSessionTabMap;
184   typedef std::map<std::string, IDToSessionTabMap> SyncedTabMap;
185 
186   struct SessionWindowWrapper {
SessionWindowWrapperSessionWindowWrapper187     SessionWindowWrapper() : window_ptr(NULL), owned(false) {}
SessionWindowWrapperSessionWindowWrapper188     SessionWindowWrapper(SessionWindow* window_ptr, OwnedState owned)
189         : window_ptr(window_ptr),
190           owned(owned == IS_OWNED) {}
191     SessionWindow* window_ptr;
192     bool owned;
193   };
194   typedef std::map<SessionID::id_type, SessionWindowWrapper>
195       IDToSessionWindowMap;
196   typedef std::map<std::string, IDToSessionWindowMap> SyncedWindowMap;
197 
198   typedef std::map<std::string, SyncedSession*> SyncedSessionMap;
199 
200   // Helper methods for deleting SessionWindows and SessionTabs without owners.
201   bool DeleteOldSessionWindowIfNecessary(SessionWindowWrapper window_wrapper);
202   bool DeleteOldSessionTabIfNecessary(SessionTabWrapper tab_wrapper);
203 
204   // Implementation for GetTab(...) above, permits invalid tab_node_id.
205   SessionTab* GetTabImpl(const std::string& session_tag,
206                          SessionID::id_type tab_id,
207                          int tab_node_id);
208 
209   // Per client mapping of tab id's to their SessionTab objects.
210   // Key: session tag.
211   // Value: Tab id to SessionTabWrapper map.
212   SyncedTabMap synced_tab_map_;
213 
214   // Per client mapping of the window id's to their SessionWindow objects.
215   // Key: session_tag
216   // Value: Window id to SessionWindowWrapper map.
217   SyncedWindowMap synced_window_map_;
218 
219   // Per client mapping synced session objects.
220   // Key: session tag.
221   // Value: SyncedSession object pointer.
222   SyncedSessionMap synced_session_map_;
223 
224   // The set of tabs that we have seen, and created SessionTab objects for, but
225   // have not yet mapped to SyncedSessions. These are temporarily orphaned
226   // tabs, and won't be deleted if we delete synced_session_map_, but are still
227   // owned by the SyncedSessionTracker itself (and deleted on Clear()).
228   std::set<SessionTab*> unmapped_tabs_;
229 
230   // The tag for this machine's local session, so we can distinguish the foreign
231   // sessions.
232   std::string local_session_tag_;
233 
234   DISALLOW_COPY_AND_ASSIGN(SyncedSessionTracker);
235 };
236 
237 }  // namespace browser_sync
238 
239 #endif  // CHROME_BROWSER_SYNC_GLUE_SYNCED_SESSION_TRACKER_H_
240