synced_session_tracker.h revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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
20namespace 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).
27class 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
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.
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.
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 {
167    SessionTabWrapper() : tab_ptr(NULL),
168                          owned(false),
169                          tab_node_id(TabNodePool::kInvalidTabNodeID) {}
170    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 {
191    SessionWindowWrapper() : window_ptr(NULL), owned(false) {}
192    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