1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330
|
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_SYNC_SESSIONS_SYNCED_SESSION_TRACKER_H_
#define COMPONENTS_SYNC_SESSIONS_SYNCED_SESSION_TRACKER_H_
#include <stddef.h>
#include <map>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <vector>
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "components/sessions/core/session_id.h"
#include "components/sessions/core/session_types.h"
#include "components/sync_device_info/device_info.h"
#include "components/sync_sessions/synced_session.h"
#include "components/sync_sessions/tab_node_pool.h"
namespace sync_pb {
class SessionSpecifics;
enum SyncEnums_BrowserType : int;
enum SyncEnums_DeviceType : int;
} // namespace sync_pb
namespace sync_sessions {
class SyncSessionsClient;
// Class to manage synced sessions. The tracker will own all SyncedSession
// and SyncedSessionTab objects it creates, and deletes them appropriately on
// destruction.
//
// Note: SyncedSession objects are created for all synced sessions, including
// the local session (whose tag we maintain separately).
class SyncedSessionTracker {
public:
// Different ways to lookup/filter tabs.
enum SessionLookup {
RAW, // Return all foreign sessions.
PRESENTABLE // Have one window with at least one tab with syncable content.
};
explicit SyncedSessionTracker(SyncSessionsClient* sessions_client);
SyncedSessionTracker(const SyncedSessionTracker&) = delete;
SyncedSessionTracker& operator=(const SyncedSessionTracker&) = delete;
~SyncedSessionTracker();
// **** Synced session/tab query methods. ****
// Returns vector with all sessions we're tracking. SyncedSession ownership
// remains within the SyncedSessionTracker. Lookup parameter is used to decide
// which tabs should be included.
std::vector<raw_ptr<const SyncedSession, VectorExperimental>>
LookupAllSessions(SessionLookup lookup) const;
// Returns all foreign sessions we're tracking (skips the local session
// object). SyncedSession ownership remains within the SyncedSessionTracker.
// Lookup parameter is used to decide which foreign tabs should be include.
std::vector<raw_ptr<const SyncedSession, VectorExperimental>>
LookupAllForeignSessions(SessionLookup lookup) const;
// Returns the tab node ids (see GetTab) for all the tabs* associated with the
// session having tag |session_tag|.
std::set<int> LookupTabNodeIds(const std::string& session_tag) const;
// Returns the session windows associated with the session given
// by |session_tag|. Returns an empty vector if there are no windows for
// `session_tag`. Ownership of SessionWindows stays within the
// SyncedSessionTracker.
std::vector<const sessions::SessionWindow*> LookupSessionWindows(
const std::string& session_tag) const;
// Attempts to look up the tab associated with the given tag and tab id.
// Ownership of the SessionTab remains within the SyncedSessionTracker.
// Returns null if lookup fails.
const sessions::SessionTab* LookupSessionTab(const std::string& session_tag,
SessionID tab_id) const;
std::optional<sync_pb::SyncEnums_BrowserType> LookupWindowType(
const std::string& session_tag,
SessionID window_id) const;
// Allows retrieval of existing data for the local session. Unlike GetSession
// this won't create-if-not-present and will return null instead.
const SyncedSession* LookupLocalSession() const;
// **** Methods for manipulating synced sessions and tabs. ****
// Returns a pointer to the SyncedSession object associated with
// |session_tag|. If none exists, returns nullptr. Ownership of the
// SyncedSession remains within the SyncedSessionTracker.
const SyncedSession* LookupSession(const std::string& session_tag) const;
// Returns a pointer to the SyncedSession object associated with
// |session_tag|. If none exists, creates one. Ownership of the
// SyncedSession remains within the SyncedSessionTracker.
SyncedSession* GetSession(const std::string& session_tag);
// Resets the tracking information for the session specified by |session_tag|.
// This involves clearing all the windows and tabs from the session, while
// keeping pointers saved in the synced_window_map_ and synced_tab_map_. Once
// reset, all calls to PutWindowInSession and PutTabInWindow will denote that
// the requested windows and tabs are owned and add them back to their
// session. The next call to CleanupSession(...) will delete those windows and
// tabs not owned.
void ResetSessionTracking(const std::string& session_tag);
// Deletes those windows and tabs associated with |session_tag| that are no
// longer owned. See ResetSessionTracking(...)..
void CleanupSession(const std::string& session_tag);
// Adds the window with id |window_id| to the session specified by
// |session_tag|. If none existed for that session, creates one. Similarly, if
// the session did not exist yet, creates it. Ownership of the SessionWindow
// remains within the SyncedSessionTracker.
// Attempting to add a window to a session multiple times will have no effect
// and in that case the function returns false.
bool PutWindowInSession(const std::string& session_tag, SessionID window_id);
// Adds the tab with id |tab_id| to the window |window_id|. If none existed
// for that session, creates one. Ownership of the SessionTab remains within
// the SyncedSessionTracker.
//
// Note: GetSession(..) must have already been called with |session_tag| to
// ensure we having mapping information for this session.
void PutTabInWindow(const std::string& session_tag,
SessionID window_id,
SessionID tab_id);
// Adds |tab_node_id| to the session specified by |session_tag|, creating that
// session if necessary. This is necessary to ensure that each session has an
// up to date list of tab nodes linked to it for session deletion purposes.
// Note that this won't update the local tab pool, even if the local session
// tag is passed. The tab pool is only updated with new tab nodes when they're
// associated with a tab id (see ReassociateLocalTabNode or
// GetTabNodeFromLocalTabId).
void OnTabNodeSeen(const std::string& session_tag,
int tab_node_id,
SessionID tab_id);
// Returns a pointer to the SessionTab object associated with
// |tab_id| for the session specified with |session_tag|.
// Note: Ownership of the SessionTab remains within the SyncedSessionTracker.
sessions::SessionTab* GetTab(const std::string& session_tag,
SessionID tab_id);
// **** Methods specific to foreign sessions. ****
// Tracks the deletion of a foreign tab by removing the given |tab_node_id|
// from the parent session. Doesn't actually remove any tab objects because
// the header may have or may not have already been updated to no longer
// parent this tab. Regardless, when the header is updated then cleanup will
// remove the actual tab data. However, this method always needs to be called
// upon foreign tab deletion, otherwise LookupTabNodeIds(...) may return
// already deleted tab node ids.
void DeleteForeignTab(const std::string& session_tag, int tab_node_id);
// Deletes the session associated with |session_tag| if it exists.
void DeleteForeignSession(const std::string& session_tag);
// **** Methods specific to the local session. ****
// Set the local session information. Must be called before any other local
// session methods are invoked.
void InitLocalSession(
const std::string& local_session_tag,
const std::string& local_session_name,
sync_pb::SyncEnums_DeviceType local_device_type,
syncer::DeviceInfo::FormFactor local_device_form_factor);
// Populate the start-time of the local session. This should be called once,
// when syncing of sessions gets enabled (and then never again, unless syncing
// of sessions gets disabled and enabled again).
void SetLocalSessionStartTime(base::Time local_session_start_time);
// Gets the session tag previously set with InitLocalSession().
const std::string& GetLocalSessionTag() const;
// Similar to CleanupSession() but also marks unmapped tabs (i.e. closed ones)
// as free tab nodes (which can be reused by future tabs) and triggers garbage
// collection (i.e. deletion) of free tab nodes. It returns the set of locally
// free tab nodes to be deleted. |is_tab_node_unsynced_cb| allows callers to
// prevent tab nodes from being "free" (and hence reusable), which in practice
// is useful to avoid overriding data that hasn't been synced yet.
std::set<int> CleanupLocalTabs(
const base::RepeatingCallback<bool(int /*tab_node_id*/)>&
is_tab_node_unsynced_cb);
// Returns the tab node ID for |tab_id| if an existing tab node was found, or
// kInvalidTabNodeID otherwise.
int LookupTabNodeFromTabId(const std::string& session_tag,
SessionID tab_id) const;
// Returns the tab ID associated to |tab_node_id| or SessionID::InvalidValue()
// if not associated.
SessionID LookupTabIdFromTabNodeId(const std::string& session_tag,
int tab_node_id) const;
// Returns a valid tab node for |tab_id|. Will reuse an existing tab node if
// possible, and otherwise create a new one.
int AssociateLocalTabWithFreeTabNode(SessionID tab_id);
// Reassociates the tab denoted by |tab_node_id| with a new tab id, preserving
// any previous SessionTab object the node was associated with. If
// |new_tab_id| is already associated with a tab object, that tab will be
// overwritten. Reassociating a tab with a node it is already mapped to will
// have no effect.
void ReassociateLocalTab(int tab_node_id, SessionID new_tab_id);
// **** Methods for querying/manipulating overall state ****.
// Free the memory for all dynamically allocated objects and clear the
// tracking structures.
void Clear();
bool Empty() const { return session_map_.empty(); }
// Includes both foreign sessions and the local session.
size_t num_synced_sessions() const { return session_map_.size(); }
// Returns the number of tabs associated with the specified session tag.
size_t num_synced_tabs(const std::string& session_tag) const {
auto iter = session_map_.find(session_tag);
if (iter != session_map_.end()) {
return iter->second.synced_tab_map.size();
} else {
return 0;
}
}
// Returns whether a tab is unmapped or not.
bool IsTabUnmappedForTesting(SessionID tab_id);
private:
friend class SyncedSessionTrackerTest;
struct TrackedSession {
TrackedSession();
~TrackedSession();
// Owns the SyncedSessions, and transitively, all of the windows and tabs
// they contain.
SyncedSession synced_session;
// The mapping of tab/window to their SessionTab/SessionWindow objects.
// The SessionTab/SessionWindow objects referred to may be owned either by
// the session in the |synced_session| or be temporarily unmapped and live
// in the |unmapped_tabs|/|unmapped_windows| collections.
std::map<SessionID, raw_ptr<sessions::SessionTab, CtnExperimental>>
synced_tab_map;
std::map<SessionID, raw_ptr<SyncedSessionWindow, CtnExperimental>>
synced_window_map;
// The collection of tabs/windows not owned by SyncedSession. This is the
// case either because 1. (in the case of tabs) they were newly created by
// GetTab() and not yet added to a session, or 2. they were removed from
// their owning session by a call to ResetSessionTracking() and not yet
// added back.
std::map<SessionID, std::unique_ptr<sessions::SessionTab>> unmapped_tabs;
std::map<SessionID, std::unique_ptr<SyncedSessionWindow>> unmapped_windows;
// Mappings between tab node IDs and tab IDs. For the local session, it also
// knows about available sync nodes associated with this session.
TabNodePool tab_node_pool;
};
// LookupTrackedSession() returns null if the session tag is unknown.
const TrackedSession* LookupTrackedSession(
const std::string& session_tag) const;
TrackedSession* LookupTrackedSession(const std::string& session_tag);
// Creates tracked session if it wasn't known previously. Never returns null.
TrackedSession* GetTrackedSession(const std::string& session_tag);
std::vector<raw_ptr<const SyncedSession, VectorExperimental>> LookupSessions(
SessionLookup lookup,
bool exclude_local_session) const;
// Implementation of CleanupSession()/CleanupLocalTabs().
void CleanupSessionImpl(
const std::string& session_tag,
const base::RepeatingCallback<bool(int /*tab_node_id*/)>&
is_tab_node_unsynced_cb);
// The client of the sync sessions datatype.
const raw_ptr<SyncSessionsClient> sessions_client_;
// Map: session tag -> TrackedSession.
std::map<std::string, TrackedSession> session_map_;
// The tag for this machine's local session, so we can distinguish the foreign
// sessions.
std::string local_session_tag_;
};
// Helper function to load and add window or tab data from synced specifics to
// our internal tracking in SyncedSessionTracker.
void UpdateTrackerWithSpecifics(const sync_pb::SessionSpecifics& specifics,
base::Time modification_time,
SyncedSessionTracker* tracker);
// Generates all sync entities represented by the tracker. Instead of returning
// protos by value, |output_cb| is run for each serialized entity.
void SerializeTrackerToSpecifics(
const SyncedSessionTracker& tracker,
const base::RepeatingCallback<void(const std::string& session_name,
sync_pb::SessionSpecifics* specifics)>&
output_cb);
// Same as above but generates a subset of sync entities represented by the
// tracker, as selected by |session_tag_to_node_ids|. Unknown session tags or
// node IDs will be ignored. kInvalidTabNodeID can be used to request header
// entities.
void SerializePartialTrackerToSpecifics(
const SyncedSessionTracker& tracker,
const std::map<std::string, std::set<int>>& session_tag_to_node_ids,
const base::RepeatingCallback<void(const std::string& session_name,
sync_pb::SessionSpecifics* specifics)>&
output_cb);
} // namespace sync_sessions
#endif // COMPONENTS_SYNC_SESSIONS_SYNCED_SESSION_TRACKER_H_
|