[email protected] | 27684f3 | 2012-04-25 18:28:43 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
zea | c2f678e | 2015-10-28 06:16:10 | [diff] [blame] | 5 | #include "components/sync_sessions/synced_session_tracker.h" |
droger | 6a11863 | 2015-06-23 17:59:45 | [diff] [blame] | 6 | |
Mikel Astiz | f82416e90 | 2018-02-27 16:11:13 | [diff] [blame] | 7 | #include <algorithm> |
skym | 6d5ecf8 | 2016-10-04 17:43:45 | [diff] [blame] | 8 | #include <utility> |
| 9 | |
[email protected] | 35d849dc | 2011-10-21 23:49:05 | [diff] [blame] | 10 | #include "base/logging.h" |
[email protected] | e309f31 | 2013-06-07 21:50:08 | [diff] [blame] | 11 | #include "base/strings/utf_string_conversions.h" |
Mikel Astiz | f82416e90 | 2018-02-27 16:11:13 | [diff] [blame] | 12 | #include "components/sync/protocol/session_specifics.pb.h" |
zea | f09345c | 2015-10-27 05:29:50 | [diff] [blame] | 13 | #include "components/sync_sessions/sync_sessions_client.h" |
pnoland | 1901afa5 | 2017-03-23 21:24:00 | [diff] [blame] | 14 | #include "components/sync_sessions/synced_tab_delegate.h" |
Mikel Astiz | f82416e90 | 2018-02-27 16:11:13 | [diff] [blame] | 15 | |
maxbogue | a79d99b7 | 2016-09-15 15:59:16 | [diff] [blame] | 16 | namespace sync_sessions { |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 17 | |
zea | f09345c | 2015-10-27 05:29:50 | [diff] [blame] | 18 | namespace { |
| 19 | |
| 20 | // Helper for iterating through all tabs within a window, and all navigations |
| 21 | // within a tab, to find if there's a valid syncable url. |
maxbogue | a79d99b7 | 2016-09-15 15:59:16 | [diff] [blame] | 22 | bool ShouldSyncSessionWindow(SyncSessionsClient* sessions_client, |
zea | f09345c | 2015-10-27 05:29:50 | [diff] [blame] | 23 | const sessions::SessionWindow& window) { |
avi | 498cabca | 2016-09-21 19:03:50 | [diff] [blame] | 24 | for (const auto& tab : window.tabs) { |
zea | f09345c | 2015-10-27 05:29:50 | [diff] [blame] | 25 | for (const sessions::SerializedNavigationEntry& navigation : |
| 26 | tab->navigations) { |
| 27 | if (sessions_client->ShouldSyncURL(navigation.virtual_url())) { |
| 28 | return true; |
| 29 | } |
| 30 | } |
| 31 | } |
| 32 | return false; |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 33 | } |
| 34 | |
skym | 199c7fd | 2016-04-14 19:26:42 | [diff] [blame] | 35 | // Presentable means |foreign_session| must have syncable content. |
maxbogue | a79d99b7 | 2016-09-15 15:59:16 | [diff] [blame] | 36 | bool IsPresentable(SyncSessionsClient* sessions_client, |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 37 | const SyncedSession& foreign_session) { |
| 38 | for (auto iter = foreign_session.windows.begin(); |
| 39 | iter != foreign_session.windows.end(); ++iter) { |
zea | 325508e | 2017-03-29 20:11:22 | [diff] [blame] | 40 | if (ShouldSyncSessionWindow(sessions_client, |
| 41 | iter->second->wrapped_window)) { |
skym | 199c7fd | 2016-04-14 19:26:42 | [diff] [blame] | 42 | return true; |
| 43 | } |
| 44 | } |
| 45 | return false; |
| 46 | } |
| 47 | |
Mikel Astiz | f82416e90 | 2018-02-27 16:11:13 | [diff] [blame] | 48 | // Verify that tab IDs appear only once within a session. Intended to prevent |
| 49 | // http://crbug.com/360822. |
| 50 | bool IsValidSessionHeader(const sync_pb::SessionHeader& header) { |
| 51 | std::set<int> session_tab_ids; |
| 52 | for (int i = 0; i < header.window_size(); ++i) { |
| 53 | const sync_pb::SessionWindow& window = header.window(i); |
| 54 | for (int j = 0; j < window.tab_size(); ++j) { |
| 55 | const int tab_id = window.tab(j); |
| 56 | bool success = session_tab_ids.insert(tab_id).second; |
| 57 | if (!success) |
| 58 | return false; |
| 59 | } |
| 60 | } |
| 61 | |
| 62 | return true; |
| 63 | } |
| 64 | |
| 65 | void PopulateSyncedSessionWindowFromSpecifics( |
| 66 | const std::string& session_tag, |
| 67 | const sync_pb::SessionWindow& specifics, |
| 68 | base::Time mtime, |
| 69 | SyncedSessionWindow* synced_session_window, |
| 70 | SyncedSessionTracker* tracker) { |
| 71 | sessions::SessionWindow* session_window = |
| 72 | &synced_session_window->wrapped_window; |
Mikel Astiz | e023c57 | 2018-03-28 07:56:56 | [diff] [blame] | 73 | if (specifics.has_window_id()) { |
| 74 | session_window->window_id = |
| 75 | SessionID::FromSerializedValue(specifics.window_id()); |
| 76 | } |
Mikel Astiz | f82416e90 | 2018-02-27 16:11:13 | [diff] [blame] | 77 | if (specifics.has_selected_tab_index()) |
| 78 | session_window->selected_tab_index = specifics.selected_tab_index(); |
| 79 | synced_session_window->window_type = specifics.browser_type(); |
| 80 | if (specifics.has_browser_type()) { |
| 81 | if (specifics.browser_type() == |
| 82 | sync_pb::SessionWindow_BrowserType_TYPE_TABBED) { |
| 83 | session_window->type = sessions::SessionWindow::TYPE_TABBED; |
| 84 | } else { |
| 85 | // Note: custom tabs are treated like popup windows on restore, as you can |
| 86 | // restore a custom tab on a platform that doesn't support them. |
| 87 | session_window->type = sessions::SessionWindow::TYPE_POPUP; |
| 88 | } |
| 89 | } |
| 90 | session_window->timestamp = mtime; |
| 91 | session_window->tabs.clear(); |
| 92 | for (int i = 0; i < specifics.tab_size(); i++) { |
Mikel Astiz | e023c57 | 2018-03-28 07:56:56 | [diff] [blame] | 93 | SessionID tab_id = SessionID::FromSerializedValue(specifics.tab(i)); |
| 94 | tracker->PutTabInWindow(session_tag, session_window->window_id, tab_id); |
Mikel Astiz | f82416e90 | 2018-02-27 16:11:13 | [diff] [blame] | 95 | } |
| 96 | } |
| 97 | |
| 98 | void PopulateSyncedSessionFromSpecifics( |
| 99 | const std::string& session_tag, |
| 100 | const sync_pb::SessionHeader& header_specifics, |
| 101 | base::Time mtime, |
| 102 | SyncedSession* synced_session, |
| 103 | SyncedSessionTracker* tracker) { |
| 104 | if (header_specifics.has_client_name()) |
| 105 | synced_session->session_name = header_specifics.client_name(); |
| 106 | if (header_specifics.has_device_type()) { |
| 107 | synced_session->device_type = header_specifics.device_type(); |
| 108 | } |
| 109 | synced_session->modified_time = |
| 110 | std::max(mtime, synced_session->modified_time); |
| 111 | |
| 112 | // Process all the windows and their tab information. |
| 113 | int num_windows = header_specifics.window_size(); |
| 114 | DVLOG(1) << "Populating " << session_tag << " with " << num_windows |
| 115 | << " windows."; |
| 116 | |
| 117 | for (int i = 0; i < num_windows; ++i) { |
| 118 | const sync_pb::SessionWindow& window_s = header_specifics.window(i); |
Mikel Astiz | e023c57 | 2018-03-28 07:56:56 | [diff] [blame] | 119 | SessionID window_id = SessionID::FromSerializedValue(window_s.window_id()); |
Mikel Astiz | f82416e90 | 2018-02-27 16:11:13 | [diff] [blame] | 120 | tracker->PutWindowInSession(session_tag, window_id); |
| 121 | PopulateSyncedSessionWindowFromSpecifics( |
| 122 | session_tag, window_s, synced_session->modified_time, |
| 123 | synced_session->windows[window_id].get(), tracker); |
| 124 | } |
| 125 | } |
| 126 | |
zea | f09345c | 2015-10-27 05:29:50 | [diff] [blame] | 127 | } // namespace |
| 128 | |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 129 | SyncedSessionTracker::TrackedSession::TrackedSession() {} |
| 130 | |
| 131 | SyncedSessionTracker::TrackedSession::~TrackedSession() {} |
| 132 | |
maxbogue | a79d99b7 | 2016-09-15 15:59:16 | [diff] [blame] | 133 | SyncedSessionTracker::SyncedSessionTracker(SyncSessionsClient* sessions_client) |
zea | f09345c | 2015-10-27 05:29:50 | [diff] [blame] | 134 | : sessions_client_(sessions_client) {} |
| 135 | |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 136 | SyncedSessionTracker::~SyncedSessionTracker() {} |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 137 | |
Mikel Astiz | 556bf09 | 2018-03-06 13:16:33 | [diff] [blame] | 138 | void SyncedSessionTracker::InitLocalSession( |
| 139 | const std::string& local_session_tag, |
| 140 | const std::string& local_session_name, |
| 141 | sync_pb::SyncEnums::DeviceType local_device_type) { |
zea | 9b42f431 | 2017-03-01 19:15:44 | [diff] [blame] | 142 | DCHECK(local_session_tag_.empty()); |
| 143 | DCHECK(!local_session_tag.empty()); |
[email protected] | 819f753f | 2011-07-15 21:56:02 | [diff] [blame] | 144 | local_session_tag_ = local_session_tag; |
Mikel Astiz | 556bf09 | 2018-03-06 13:16:33 | [diff] [blame] | 145 | |
| 146 | SyncedSession* local_session = GetSession(local_session_tag); |
| 147 | local_session->session_name = local_session_name; |
| 148 | local_session->device_type = local_device_type; |
| 149 | local_session->session_tag = local_session_tag; |
| 150 | } |
| 151 | |
| 152 | const std::string& SyncedSessionTracker::GetLocalSessionTag() const { |
| 153 | return local_session_tag_; |
[email protected] | 819f753f | 2011-07-15 21:56:02 | [diff] [blame] | 154 | } |
| 155 | |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 156 | std::vector<const SyncedSession*> |
| 157 | SyncedSessionTracker::LookupAllForeignSessions(SessionLookup lookup) const { |
| 158 | std::vector<const SyncedSession*> sessions; |
| 159 | for (const auto& session_pair : session_map_) { |
| 160 | const SyncedSession& foreign_session = session_pair.second.synced_session; |
avi | 498cabca | 2016-09-21 19:03:50 | [diff] [blame] | 161 | if (session_pair.first != local_session_tag_ && |
skym | 199c7fd | 2016-04-14 19:26:42 | [diff] [blame] | 162 | (lookup == RAW || IsPresentable(sessions_client_, foreign_session))) { |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 163 | sessions.push_back(&foreign_session); |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 164 | } |
| 165 | } |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 166 | return sessions; |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 167 | } |
| 168 | |
| 169 | bool SyncedSessionTracker::LookupSessionWindows( |
| 170 | const std::string& session_tag, |
skuhne | b7409dcf | 2014-11-14 04:06:55 | [diff] [blame] | 171 | std::vector<const sessions::SessionWindow*>* windows) const { |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 172 | DCHECK(windows); |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 173 | windows->clear(); |
avi | 498cabca | 2016-09-21 19:03:50 | [diff] [blame] | 174 | |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 175 | const TrackedSession* session = LookupTrackedSession(session_tag); |
| 176 | if (!session) |
| 177 | return false; // We have no record of this session. |
| 178 | |
| 179 | for (const auto& window_pair : session->synced_session.windows) |
zea | 325508e | 2017-03-29 20:11:22 | [diff] [blame] | 180 | windows->push_back(&window_pair.second->wrapped_window); |
avi | 498cabca | 2016-09-21 19:03:50 | [diff] [blame] | 181 | |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 182 | return true; |
| 183 | } |
| 184 | |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 185 | const sessions::SessionTab* SyncedSessionTracker::LookupSessionTab( |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 186 | const std::string& tag, |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 187 | SessionID tab_id) const { |
Mikel Astiz | e023c57 | 2018-03-28 07:56:56 | [diff] [blame] | 188 | if (!tab_id.is_valid()) |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 189 | return nullptr; |
zea | 9b42f431 | 2017-03-01 19:15:44 | [diff] [blame] | 190 | |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 191 | const TrackedSession* session = LookupTrackedSession(tag); |
| 192 | if (!session) |
| 193 | return nullptr; // We have no record of this session. |
| 194 | |
| 195 | auto tab_iter = session->synced_tab_map.find(tab_id); |
| 196 | if (tab_iter == session->synced_tab_map.end()) |
| 197 | return nullptr; // We have no record of this tab. |
| 198 | |
| 199 | return tab_iter->second; |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 200 | } |
| 201 | |
zea | 9b42f431 | 2017-03-01 19:15:44 | [diff] [blame] | 202 | void SyncedSessionTracker::LookupForeignTabNodeIds( |
| 203 | const std::string& session_tag, |
| 204 | std::set<int>* tab_node_ids) const { |
[email protected] | 98f589d | 2013-08-01 05:14:01 | [diff] [blame] | 205 | tab_node_ids->clear(); |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 206 | const TrackedSession* session = LookupTrackedSession(session_tag); |
| 207 | if (session) { |
| 208 | tab_node_ids->insert(session->tab_node_ids.begin(), |
| 209 | session->tab_node_ids.end()); |
[email protected] | 98f589d | 2013-08-01 05:14:01 | [diff] [blame] | 210 | } |
avi | 498cabca | 2016-09-21 19:03:50 | [diff] [blame] | 211 | // In case an invalid node id was included, remove it. |
skym | 199c7fd | 2016-04-14 19:26:42 | [diff] [blame] | 212 | tab_node_ids->erase(TabNodePool::kInvalidTabNodeID); |
[email protected] | 98f589d | 2013-08-01 05:14:01 | [diff] [blame] | 213 | } |
| 214 | |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 215 | const SyncedSession* SyncedSessionTracker::LookupLocalSession() const { |
| 216 | const TrackedSession* session = LookupTrackedSession(local_session_tag_); |
| 217 | return session ? &session->synced_session : nullptr; |
[email protected] | 85622cd | 2013-12-18 17:32:27 | [diff] [blame] | 218 | } |
| 219 | |
maxbogue | a79d99b7 | 2016-09-15 15:59:16 | [diff] [blame] | 220 | SyncedSession* SyncedSessionTracker::GetSession( |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 221 | const std::string& session_tag) { |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 222 | return &GetTrackedSession(session_tag)->synced_session; |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 223 | } |
| 224 | |
zea | 9b42f431 | 2017-03-01 19:15:44 | [diff] [blame] | 225 | bool SyncedSessionTracker::DeleteForeignSession( |
| 226 | const std::string& session_tag) { |
| 227 | DCHECK_NE(local_session_tag_, session_tag); |
skym | 199c7fd | 2016-04-14 19:26:42 | [diff] [blame] | 228 | |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 229 | auto iter = session_map_.find(session_tag); |
| 230 | if (iter == session_map_.end()) |
| 231 | return false; |
skym | 199c7fd | 2016-04-14 19:26:42 | [diff] [blame] | 232 | |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 233 | // An implicitly created session that has children tabs but no header node |
| 234 | // will have never had the device_type changed from unset. |
| 235 | const bool header_existed = |
| 236 | iter->second.synced_session.device_type != sync_pb::SyncEnums::TYPE_UNSET; |
| 237 | // SyncedSession's destructor will trigger deletion of windows which will in |
| 238 | // turn trigger the deletion of tabs. This doesn't affect the convenience |
| 239 | // maps. |
| 240 | session_map_.erase(iter); |
skym | 199c7fd | 2016-04-14 19:26:42 | [diff] [blame] | 241 | |
| 242 | return header_existed; |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 243 | } |
| 244 | |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 245 | void SyncedSessionTracker::ResetSessionTracking( |
| 246 | const std::string& session_tag) { |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 247 | TrackedSession* session = GetTrackedSession(session_tag); |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 248 | |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 249 | for (auto& window_pair : session->synced_session.windows) { |
avi | 498cabca | 2016-09-21 19:03:50 | [diff] [blame] | 250 | // First unmap the tabs in the window. |
zea | 325508e | 2017-03-29 20:11:22 | [diff] [blame] | 251 | for (auto& tab : window_pair.second->wrapped_window.tabs) { |
Mikel Astiz | e023c57 | 2018-03-28 07:56:56 | [diff] [blame] | 252 | SessionID tab_id = tab->tab_id; |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 253 | session->unmapped_tabs[tab_id] = std::move(tab); |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 254 | } |
zea | 325508e | 2017-03-29 20:11:22 | [diff] [blame] | 255 | window_pair.second->wrapped_window.tabs.clear(); |
avi | 498cabca | 2016-09-21 19:03:50 | [diff] [blame] | 256 | |
| 257 | // Then unmap the window itself. |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 258 | session->unmapped_windows[window_pair.first] = |
avi | 498cabca | 2016-09-21 19:03:50 | [diff] [blame] | 259 | std::move(window_pair.second); |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 260 | } |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 261 | session->synced_session.windows.clear(); |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 262 | } |
| 263 | |
skym | 199c7fd | 2016-04-14 19:26:42 | [diff] [blame] | 264 | void SyncedSessionTracker::DeleteForeignTab(const std::string& session_tag, |
| 265 | int tab_node_id) { |
zea | 9b42f431 | 2017-03-01 19:15:44 | [diff] [blame] | 266 | DCHECK_NE(local_session_tag_, session_tag); |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 267 | TrackedSession* session = LookupTrackedSession(session_tag); |
| 268 | if (session) |
| 269 | session->tab_node_ids.erase(tab_node_id); |
| 270 | } |
| 271 | |
| 272 | const SyncedSessionTracker::TrackedSession* |
| 273 | SyncedSessionTracker::LookupTrackedSession( |
| 274 | const std::string& session_tag) const { |
| 275 | std::map<std::string, TrackedSession>::const_iterator it = |
| 276 | session_map_.find(session_tag); |
| 277 | return it == session_map_.end() ? nullptr : &it->second; |
| 278 | } |
| 279 | |
| 280 | SyncedSessionTracker::TrackedSession* |
| 281 | SyncedSessionTracker::LookupTrackedSession(const std::string& session_tag) { |
| 282 | std::map<std::string, TrackedSession>::iterator it = |
| 283 | session_map_.find(session_tag); |
| 284 | return it == session_map_.end() ? nullptr : &it->second; |
| 285 | } |
| 286 | |
| 287 | SyncedSessionTracker::TrackedSession* SyncedSessionTracker::GetTrackedSession( |
| 288 | const std::string& session_tag) { |
| 289 | TrackedSession* session = LookupTrackedSession(session_tag); |
| 290 | if (session) |
| 291 | return session; |
| 292 | |
| 293 | session = &session_map_[session_tag]; |
| 294 | DVLOG(1) << "Creating new session with tag " << session_tag << " at " |
| 295 | << session; |
| 296 | session->synced_session.session_tag = session_tag; |
| 297 | return session; |
skym | 199c7fd | 2016-04-14 19:26:42 | [diff] [blame] | 298 | } |
| 299 | |
zea | 9b42f431 | 2017-03-01 19:15:44 | [diff] [blame] | 300 | void SyncedSessionTracker::CleanupSessionImpl(const std::string& session_tag) { |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 301 | TrackedSession* session = LookupTrackedSession(session_tag); |
| 302 | if (!session) |
| 303 | return; |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 304 | |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 305 | for (const auto& window_pair : session->unmapped_windows) |
| 306 | session->synced_window_map.erase(window_pair.first); |
| 307 | session->unmapped_windows.clear(); |
| 308 | |
| 309 | for (const auto& tab_pair : session->unmapped_tabs) |
| 310 | session->synced_tab_map.erase(tab_pair.first); |
| 311 | session->unmapped_tabs.clear(); |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 312 | } |
| 313 | |
Mikel Astiz | e023c57 | 2018-03-28 07:56:56 | [diff] [blame] | 314 | bool SyncedSessionTracker::IsTabUnmappedForTesting(SessionID tab_id) { |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 315 | const TrackedSession* session = LookupTrackedSession(local_session_tag_); |
| 316 | if (!session) |
| 317 | return false; |
| 318 | |
| 319 | return session->unmapped_tabs.count(tab_id) != 0; |
| 320 | } |
| 321 | |
| 322 | std::set<int> SyncedSessionTracker::GetTabNodeIdsForTesting( |
| 323 | const std::string& session_tag) const { |
| 324 | const TrackedSession* session = LookupTrackedSession(session_tag); |
| 325 | return session ? session->tab_node_ids : std::set<int>(); |
zea | 9b42f431 | 2017-03-01 19:15:44 | [diff] [blame] | 326 | } |
| 327 | |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 328 | void SyncedSessionTracker::PutWindowInSession(const std::string& session_tag, |
Mikel Astiz | e023c57 | 2018-03-28 07:56:56 | [diff] [blame] | 329 | SessionID window_id) { |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 330 | TrackedSession* session = GetTrackedSession(session_tag); |
| 331 | if (session->synced_session.windows.count(window_id) != 0) { |
zea | 92d4a10 | 2017-04-18 06:26:07 | [diff] [blame] | 332 | DVLOG(1) << "Window " << window_id << " already added to session " |
| 333 | << session_tag; |
| 334 | return; |
| 335 | } |
zea | 325508e | 2017-03-29 20:11:22 | [diff] [blame] | 336 | std::unique_ptr<SyncedSessionWindow> window; |
avi | 498cabca | 2016-09-21 19:03:50 | [diff] [blame] | 337 | |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 338 | auto iter = session->unmapped_windows.find(window_id); |
| 339 | if (iter != session->unmapped_windows.end()) { |
| 340 | DCHECK_EQ(session->synced_window_map[window_id], iter->second.get()); |
avi | 498cabca | 2016-09-21 19:03:50 | [diff] [blame] | 341 | window = std::move(iter->second); |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 342 | session->unmapped_windows.erase(iter); |
avi | 498cabca | 2016-09-21 19:03:50 | [diff] [blame] | 343 | DVLOG(1) << "Putting seen window " << window_id << " at " << window.get() |
zea | c2f678e | 2015-10-28 06:16:10 | [diff] [blame] | 344 | << "in " << (session_tag == local_session_tag_ ? "local session" |
| 345 | : session_tag); |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 346 | } else { |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 347 | // Create the window. |
Sky Malice | 08a04b7 | 2017-08-24 21:43:24 | [diff] [blame] | 348 | window = std::make_unique<SyncedSessionWindow>(); |
Mikel Astiz | e023c57 | 2018-03-28 07:56:56 | [diff] [blame] | 349 | window->wrapped_window.window_id = window_id; |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 350 | session->synced_window_map[window_id] = window.get(); |
avi | 498cabca | 2016-09-21 19:03:50 | [diff] [blame] | 351 | DVLOG(1) << "Putting new window " << window_id << " at " << window.get() |
zea | c2f678e | 2015-10-28 06:16:10 | [diff] [blame] | 352 | << "in " << (session_tag == local_session_tag_ ? "local session" |
| 353 | : session_tag); |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 354 | } |
Mikel Astiz | e023c57 | 2018-03-28 07:56:56 | [diff] [blame] | 355 | DCHECK_EQ(window->wrapped_window.window_id, window_id); |
avi | 498cabca | 2016-09-21 19:03:50 | [diff] [blame] | 356 | DCHECK(GetSession(session_tag)->windows.end() == |
| 357 | GetSession(session_tag)->windows.find(window_id)); |
| 358 | GetSession(session_tag)->windows[window_id] = std::move(window); |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 359 | } |
| 360 | |
| 361 | void SyncedSessionTracker::PutTabInWindow(const std::string& session_tag, |
Mikel Astiz | e023c57 | 2018-03-28 07:56:56 | [diff] [blame] | 362 | SessionID window_id, |
| 363 | SessionID tab_id) { |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 364 | TrackedSession* session = LookupTrackedSession(session_tag); |
| 365 | DCHECK(session); |
| 366 | |
[email protected] | 98f589d | 2013-08-01 05:14:01 | [diff] [blame] | 367 | // We're called here for two reasons. 1) We've received an update to the |
zea | 9b42f431 | 2017-03-01 19:15:44 | [diff] [blame] | 368 | // SessionWindow information of a SessionHeader node for a session, |
[email protected] | 98f589d | 2013-08-01 05:14:01 | [diff] [blame] | 369 | // and 2) The SessionHeader node for our local session changed. In both cases |
| 370 | // we need to update our tracking state to reflect the change. |
| 371 | // |
| 372 | // Because the SessionHeader nodes are separate from the individual tab nodes |
| 373 | // and we don't store tab_node_ids in the header / SessionWindow specifics, |
zea | 9b42f431 | 2017-03-01 19:15:44 | [diff] [blame] | 374 | // the tab_node_ids are not always available when processing headers. We know |
| 375 | // that we will eventually process (via GetTab) every single tab node in the |
| 376 | // system, so we permit ourselves to just call GetTab and ignore the result, |
| 377 | // creating a placeholder SessionTab in the process. |
| 378 | sessions::SessionTab* tab_ptr = GetTab(session_tag, tab_id); |
[email protected] | abb35c1 | 2014-08-21 20:13:44 | [diff] [blame] | 379 | |
avi | 498cabca | 2016-09-21 19:03:50 | [diff] [blame] | 380 | // The tab should be unmapped. |
| 381 | std::unique_ptr<sessions::SessionTab> tab; |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 382 | auto it = session->unmapped_tabs.find(tab_id); |
| 383 | if (it != session->unmapped_tabs.end()) { |
avi | 498cabca | 2016-09-21 19:03:50 | [diff] [blame] | 384 | tab = std::move(it->second); |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 385 | session->unmapped_tabs.erase(it); |
zea | 9b42f431 | 2017-03-01 19:15:44 | [diff] [blame] | 386 | } else { |
| 387 | // The tab has already been mapped, possibly because of the tab node id |
| 388 | // being reused across tabs. Find the existing tab and move it to the right |
| 389 | // window. |
| 390 | for (auto& window_iter_pair : GetSession(session_tag)->windows) { |
| 391 | auto tab_iter = std::find_if( |
zea | 325508e | 2017-03-29 20:11:22 | [diff] [blame] | 392 | window_iter_pair.second->wrapped_window.tabs.begin(), |
| 393 | window_iter_pair.second->wrapped_window.tabs.end(), |
zea | 9b42f431 | 2017-03-01 19:15:44 | [diff] [blame] | 394 | [&tab_ptr](const std::unique_ptr<sessions::SessionTab>& tab) { |
| 395 | return tab.get() == tab_ptr; |
| 396 | }); |
zea | 325508e | 2017-03-29 20:11:22 | [diff] [blame] | 397 | if (tab_iter != window_iter_pair.second->wrapped_window.tabs.end()) { |
zea | 9b42f431 | 2017-03-01 19:15:44 | [diff] [blame] | 398 | tab = std::move(*tab_iter); |
zea | 325508e | 2017-03-29 20:11:22 | [diff] [blame] | 399 | window_iter_pair.second->wrapped_window.tabs.erase(tab_iter); |
zea | 9b42f431 | 2017-03-01 19:15:44 | [diff] [blame] | 400 | |
| 401 | DVLOG(1) << "Moving tab " << tab_id << " from window " |
| 402 | << window_iter_pair.first << " to " << window_id; |
| 403 | break; |
| 404 | } |
| 405 | } |
| 406 | // TODO(zea): remove this once PutTabInWindow isn't crashing anymore. |
| 407 | CHECK(tab) << " Unable to find tab " << tab_id |
| 408 | << " within unmapped tabs or previously mapped windows." |
Sky Malice | 88982246 | 2018-01-03 00:34:04 | [diff] [blame] | 409 | << " https://crbug.com/639009"; |
avi | 498cabca | 2016-09-21 19:03:50 | [diff] [blame] | 410 | } |
[email protected] | abb35c1 | 2014-08-21 20:13:44 | [diff] [blame] | 411 | |
Mikel Astiz | e023c57 | 2018-03-28 07:56:56 | [diff] [blame] | 412 | tab->window_id = window_id; |
zea | c2f678e | 2015-10-28 06:16:10 | [diff] [blame] | 413 | DVLOG(1) << " - tab " << tab_id << " added to window " << window_id; |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 414 | DCHECK(GetSession(session_tag)->windows.find(window_id) != |
| 415 | GetSession(session_tag)->windows.end()); |
zea | 325508e | 2017-03-29 20:11:22 | [diff] [blame] | 416 | GetSession(session_tag) |
| 417 | ->windows[window_id] |
| 418 | ->wrapped_window.tabs.push_back(std::move(tab)); |
zea | 9b42f431 | 2017-03-01 19:15:44 | [diff] [blame] | 419 | } |
| 420 | |
| 421 | void SyncedSessionTracker::OnTabNodeSeen(const std::string& session_tag, |
| 422 | int tab_node_id) { |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 423 | GetTrackedSession(session_tag)->tab_node_ids.insert(tab_node_id); |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 424 | } |
| 425 | |
zea | 159246f2 | 2016-12-07 00:40:34 | [diff] [blame] | 426 | sessions::SessionTab* SyncedSessionTracker::GetTab( |
[email protected] | 98f589d | 2013-08-01 05:14:01 | [diff] [blame] | 427 | const std::string& session_tag, |
Mikel Astiz | e023c57 | 2018-03-28 07:56:56 | [diff] [blame] | 428 | SessionID tab_id) { |
| 429 | CHECK(tab_id.is_valid()) << "https://crbug.com/639009"; |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 430 | |
| 431 | TrackedSession* session = GetTrackedSession(session_tag); |
skym | 199c7fd | 2016-04-14 19:26:42 | [diff] [blame] | 432 | sessions::SessionTab* tab_ptr = nullptr; |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 433 | auto iter = session->synced_tab_map.find(tab_id); |
| 434 | if (iter != session->synced_tab_map.end()) { |
avi | 498cabca | 2016-09-21 19:03:50 | [diff] [blame] | 435 | tab_ptr = iter->second; |
[email protected] | 98f589d | 2013-08-01 05:14:01 | [diff] [blame] | 436 | |
[email protected] | 35d849dc | 2011-10-21 23:49:05 | [diff] [blame] | 437 | if (VLOG_IS_ON(1)) { |
| 438 | std::string title; |
| 439 | if (tab_ptr->navigations.size() > 0) { |
zea | c2f678e | 2015-10-28 06:16:10 | [diff] [blame] | 440 | title = |
thestig | ee1440b | 2016-07-08 01:06:55 | [diff] [blame] | 441 | " (" + base::UTF16ToUTF8(tab_ptr->navigations.back().title()) + ")"; |
[email protected] | 35d849dc | 2011-10-21 23:49:05 | [diff] [blame] | 442 | } |
[email protected] | 060588c | 2011-11-29 21:38:41 | [diff] [blame] | 443 | DVLOG(1) << "Getting " |
zea | c2f678e | 2015-10-28 06:16:10 | [diff] [blame] | 444 | << (session_tag == local_session_tag_ ? "local session" |
| 445 | : session_tag) |
thestig | ee1440b | 2016-07-08 01:06:55 | [diff] [blame] | 446 | << "'s seen tab " << tab_id << " at " << tab_ptr << " " << title; |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 447 | } |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 448 | } else { |
Sky Malice | 5ecd663 | 2018-01-19 18:03:07 | [diff] [blame] | 449 | auto tab = std::make_unique<sessions::SessionTab>(); |
avi | 498cabca | 2016-09-21 19:03:50 | [diff] [blame] | 450 | tab_ptr = tab.get(); |
Mikel Astiz | e023c57 | 2018-03-28 07:56:56 | [diff] [blame] | 451 | tab->tab_id = tab_id; |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 452 | session->synced_tab_map[tab_id] = tab_ptr; |
| 453 | session->unmapped_tabs[tab_id] = std::move(tab); |
[email protected] | 060588c | 2011-11-29 21:38:41 | [diff] [blame] | 454 | DVLOG(1) << "Getting " |
zea | c2f678e | 2015-10-28 06:16:10 | [diff] [blame] | 455 | << (session_tag == local_session_tag_ ? "local session" |
| 456 | : session_tag) |
| 457 | << "'s new tab " << tab_id << " at " << tab_ptr; |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 458 | } |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 459 | DCHECK(tab_ptr); |
Mikel Astiz | e023c57 | 2018-03-28 07:56:56 | [diff] [blame] | 460 | DCHECK_EQ(tab_ptr->tab_id, tab_id); |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 461 | return tab_ptr; |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 462 | } |
| 463 | |
zea | 92d4a10 | 2017-04-18 06:26:07 | [diff] [blame] | 464 | void SyncedSessionTracker::CleanupSession(const std::string& session_tag) { |
zea | 9b42f431 | 2017-03-01 19:15:44 | [diff] [blame] | 465 | CleanupSessionImpl(session_tag); |
| 466 | } |
| 467 | |
| 468 | void SyncedSessionTracker::CleanupLocalTabs(std::set<int>* deleted_node_ids) { |
| 469 | DCHECK(!local_session_tag_.empty()); |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 470 | TrackedSession* session = GetTrackedSession(local_session_tag_); |
| 471 | for (const auto& tab_pair : session->unmapped_tabs) |
zea | 9b42f431 | 2017-03-01 19:15:44 | [diff] [blame] | 472 | local_tab_pool_.FreeTab(tab_pair.first); |
| 473 | CleanupSessionImpl(local_session_tag_); |
| 474 | local_tab_pool_.CleanupTabNodes(deleted_node_ids); |
| 475 | for (int tab_node_id : *deleted_node_ids) { |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 476 | session->tab_node_ids.erase(tab_node_id); |
zea | 9b42f431 | 2017-03-01 19:15:44 | [diff] [blame] | 477 | } |
| 478 | } |
| 479 | |
Mikel Astiz | e023c57 | 2018-03-28 07:56:56 | [diff] [blame] | 480 | bool SyncedSessionTracker::GetTabNodeFromLocalTabId(SessionID tab_id, |
zea | 9b42f431 | 2017-03-01 19:15:44 | [diff] [blame] | 481 | int* tab_node_id) { |
| 482 | DCHECK(!local_session_tag_.empty()); |
zea | 92d4a10 | 2017-04-18 06:26:07 | [diff] [blame] | 483 | // Ensure a placeholder SessionTab is in place, if not already. Although we |
| 484 | // don't need a SessionTab to fulfill this request, this forces the creation |
| 485 | // of one if it doesn't already exist. This helps to make sure we're tracking |
| 486 | // this |tab_id| if |local_tab_pool_| is, and everyone's data structures are |
| 487 | // kept in sync and as consistent as possible. |
zea | 9b42f431 | 2017-03-01 19:15:44 | [diff] [blame] | 488 | GetTab(local_session_tag_, tab_id); // Ignore result. |
| 489 | |
| 490 | bool reused_existing_tab = |
| 491 | local_tab_pool_.GetTabNodeForTab(tab_id, tab_node_id); |
| 492 | DCHECK_NE(TabNodePool::kInvalidTabNodeID, *tab_node_id); |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 493 | GetTrackedSession(local_session_tag_)->tab_node_ids.insert(*tab_node_id); |
zea | 9b42f431 | 2017-03-01 19:15:44 | [diff] [blame] | 494 | return reused_existing_tab; |
| 495 | } |
| 496 | |
| 497 | bool SyncedSessionTracker::IsLocalTabNodeAssociated(int tab_node_id) { |
| 498 | if (tab_node_id == TabNodePool::kInvalidTabNodeID) |
| 499 | return false; |
Mikel Astiz | e023c57 | 2018-03-28 07:56:56 | [diff] [blame] | 500 | return local_tab_pool_.GetTabIdFromTabNodeId(tab_node_id).is_valid(); |
zea | 9b42f431 | 2017-03-01 19:15:44 | [diff] [blame] | 501 | } |
| 502 | |
| 503 | void SyncedSessionTracker::ReassociateLocalTab(int tab_node_id, |
Mikel Astiz | e023c57 | 2018-03-28 07:56:56 | [diff] [blame] | 504 | SessionID new_tab_id) { |
zea | 9b42f431 | 2017-03-01 19:15:44 | [diff] [blame] | 505 | DCHECK(!local_session_tag_.empty()); |
| 506 | DCHECK_NE(TabNodePool::kInvalidTabNodeID, tab_node_id); |
Mikel Astiz | e023c57 | 2018-03-28 07:56:56 | [diff] [blame] | 507 | DCHECK(new_tab_id.is_valid()); |
zea | 9b42f431 | 2017-03-01 19:15:44 | [diff] [blame] | 508 | |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 509 | TrackedSession* session = LookupTrackedSession(local_session_tag_); |
| 510 | DCHECK(session); |
| 511 | |
Mikel Astiz | e023c57 | 2018-03-28 07:56:56 | [diff] [blame] | 512 | SessionID old_tab_id = local_tab_pool_.GetTabIdFromTabNodeId(tab_node_id); |
zea | 783900c | 2017-05-05 00:46:47 | [diff] [blame] | 513 | if (new_tab_id == old_tab_id) { |
| 514 | return; |
| 515 | } |
| 516 | |
zea | 9b42f431 | 2017-03-01 19:15:44 | [diff] [blame] | 517 | local_tab_pool_.ReassociateTabNode(tab_node_id, new_tab_id); |
| 518 | |
| 519 | sessions::SessionTab* tab_ptr = nullptr; |
| 520 | |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 521 | auto new_tab_iter = session->synced_tab_map.find(new_tab_id); |
| 522 | auto old_tab_iter = session->synced_tab_map.find(old_tab_id); |
| 523 | if (old_tab_id.is_valid() && old_tab_iter != session->synced_tab_map.end()) { |
zea | 9b42f431 | 2017-03-01 19:15:44 | [diff] [blame] | 524 | tab_ptr = old_tab_iter->second; |
zea | 783900c | 2017-05-05 00:46:47 | [diff] [blame] | 525 | DCHECK(tab_ptr); |
| 526 | |
zea | 9b42f431 | 2017-03-01 19:15:44 | [diff] [blame] | 527 | // Remove the tab from the synced tab map under the old id. |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 528 | session->synced_tab_map.erase(old_tab_iter); |
zea | 783900c | 2017-05-05 00:46:47 | [diff] [blame] | 529 | |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 530 | if (new_tab_iter != session->synced_tab_map.end()) { |
zea | 783900c | 2017-05-05 00:46:47 | [diff] [blame] | 531 | // If both the old and the new tab already exist, delete the new tab |
| 532 | // and use the old tab in its place. |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 533 | auto unmapped_tabs_iter = session->unmapped_tabs.find(new_tab_id); |
| 534 | if (unmapped_tabs_iter != session->unmapped_tabs.end()) { |
| 535 | session->unmapped_tabs.erase(unmapped_tabs_iter); |
zea | 783900c | 2017-05-05 00:46:47 | [diff] [blame] | 536 | } else { |
| 537 | sessions::SessionTab* new_tab_ptr = new_tab_iter->second; |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 538 | for (auto& window_iter_pair : session->synced_session.windows) { |
zea | 783900c | 2017-05-05 00:46:47 | [diff] [blame] | 539 | auto& window_tabs = window_iter_pair.second->wrapped_window.tabs; |
| 540 | auto tab_iter = std::find_if( |
| 541 | window_tabs.begin(), window_tabs.end(), |
| 542 | [&new_tab_ptr](const std::unique_ptr<sessions::SessionTab>& tab) { |
| 543 | return tab.get() == new_tab_ptr; |
| 544 | }); |
| 545 | if (tab_iter != window_tabs.end()) { |
| 546 | window_tabs.erase(tab_iter); |
| 547 | break; |
| 548 | } |
| 549 | } |
| 550 | } |
| 551 | |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 552 | session->synced_tab_map.erase(new_tab_iter); |
zea | 783900c | 2017-05-05 00:46:47 | [diff] [blame] | 553 | } |
| 554 | |
| 555 | // If the old tab is unmapped, update the tab id under which it is |
| 556 | // indexed. |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 557 | auto unmapped_tabs_iter = session->unmapped_tabs.find(old_tab_id); |
Mikel Astiz | e023c57 | 2018-03-28 07:56:56 | [diff] [blame] | 558 | if (old_tab_id.is_valid() && |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 559 | unmapped_tabs_iter != session->unmapped_tabs.end()) { |
zea | 783900c | 2017-05-05 00:46:47 | [diff] [blame] | 560 | std::unique_ptr<sessions::SessionTab> tab = |
| 561 | std::move(unmapped_tabs_iter->second); |
| 562 | DCHECK_EQ(tab_ptr, tab.get()); |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 563 | session->unmapped_tabs.erase(unmapped_tabs_iter); |
| 564 | session->unmapped_tabs[new_tab_id] = std::move(tab); |
zea | 783900c | 2017-05-05 00:46:47 | [diff] [blame] | 565 | } |
| 566 | } |
| 567 | |
| 568 | if (tab_ptr == nullptr) { |
zea | 9b42f431 | 2017-03-01 19:15:44 | [diff] [blame] | 569 | // It's possible a placeholder is already in place for the new tab. If so, |
| 570 | // reuse it, otherwise create a new one (which will default to unmapped). |
| 571 | tab_ptr = GetTab(local_session_tag_, new_tab_id); |
| 572 | } |
| 573 | |
zea | 9b42f431 | 2017-03-01 19:15:44 | [diff] [blame] | 574 | // Update the tab id. |
Mikel Astiz | e023c57 | 2018-03-28 07:56:56 | [diff] [blame] | 575 | if (old_tab_id.is_valid()) { |
zea | 9b42f431 | 2017-03-01 19:15:44 | [diff] [blame] | 576 | DVLOG(1) << "Remapped tab " << old_tab_id << " with node " << tab_node_id |
| 577 | << " to tab " << new_tab_id; |
| 578 | } else { |
| 579 | DVLOG(1) << "Mapped new tab node " << tab_node_id << " to tab " |
| 580 | << new_tab_id; |
| 581 | } |
Mikel Astiz | e023c57 | 2018-03-28 07:56:56 | [diff] [blame] | 582 | tab_ptr->tab_id = new_tab_id; |
zea | 9b42f431 | 2017-03-01 19:15:44 | [diff] [blame] | 583 | |
| 584 | // Add the tab back into the tab map with the new id. |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 585 | session->synced_tab_map[new_tab_id] = tab_ptr; |
| 586 | session->tab_node_ids.insert(tab_node_id); |
zea | 9b42f431 | 2017-03-01 19:15:44 | [diff] [blame] | 587 | } |
| 588 | |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 589 | void SyncedSessionTracker::Clear() { |
Mikel Astiz | 6d05289 | 2018-03-29 07:15:55 | [diff] [blame^] | 590 | session_map_.clear(); |
zea | 9b42f431 | 2017-03-01 19:15:44 | [diff] [blame] | 591 | local_tab_pool_.Clear(); |
[email protected] | 819f753f | 2011-07-15 21:56:02 | [diff] [blame] | 592 | local_session_tag_.clear(); |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 593 | } |
| 594 | |
Mikel Astiz | f82416e90 | 2018-02-27 16:11:13 | [diff] [blame] | 595 | void UpdateTrackerWithSpecifics(const sync_pb::SessionSpecifics& specifics, |
| 596 | base::Time modification_time, |
| 597 | SyncedSessionTracker* tracker) { |
| 598 | std::string session_tag = specifics.session_tag(); |
| 599 | SyncedSession* session = tracker->GetSession(session_tag); |
| 600 | if (specifics.has_header()) { |
| 601 | // Read in the header data for this session. Header data is |
| 602 | // essentially a collection of windows, each of which has an ordered id list |
| 603 | // for their tabs. |
| 604 | |
| 605 | if (!IsValidSessionHeader(specifics.header())) { |
| 606 | LOG(WARNING) << "Ignoring session node with invalid header " |
| 607 | << "and tag " << session_tag << "."; |
| 608 | return; |
| 609 | } |
| 610 | |
| 611 | // Load (or create) the SyncedSession object for this client. |
| 612 | const sync_pb::SessionHeader& header = specifics.header(); |
| 613 | |
| 614 | // Reset the tab/window tracking for this session (must do this before |
| 615 | // we start calling PutWindowInSession and PutTabInWindow so that all |
| 616 | // unused tabs/windows get cleared by the CleanupSession(...) call). |
| 617 | tracker->ResetSessionTracking(session_tag); |
| 618 | |
| 619 | PopulateSyncedSessionFromSpecifics(session_tag, header, modification_time, |
| 620 | session, tracker); |
| 621 | |
| 622 | // Delete any closed windows and unused tabs as necessary. |
| 623 | tracker->CleanupSession(session_tag); |
| 624 | } else if (specifics.has_tab()) { |
| 625 | const sync_pb::SessionTab& tab_s = specifics.tab(); |
Mikel Astiz | e023c57 | 2018-03-28 07:56:56 | [diff] [blame] | 626 | SessionID tab_id = SessionID::FromSerializedValue(tab_s.tab_id()); |
Mikel Astiz | f82416e90 | 2018-02-27 16:11:13 | [diff] [blame] | 627 | DVLOG(1) << "Populating " << session_tag << "'s tab id " << tab_id |
| 628 | << " from node " << specifics.tab_node_id(); |
| 629 | |
| 630 | // Ensure the tracker is aware of the tab node id. Deleting foreign sessions |
| 631 | // requires deleting all relevant tab nodes, and it's easier to track the |
| 632 | // tab node ids themselves separately from the tab ids. |
| 633 | // |
| 634 | // Note that TabIDs are not stable across restarts of a client. Consider |
| 635 | // this example with two tabs: |
| 636 | // |
| 637 | // http://a.com TabID1 --> NodeIDA |
| 638 | // http://b.com TabID2 --> NodeIDB |
| 639 | // |
| 640 | // After restart, tab ids are reallocated. e.g, one possibility: |
| 641 | // http://a.com TabID2 --> NodeIDA |
| 642 | // http://b.com TabID1 --> NodeIDB |
| 643 | // |
| 644 | // If that happened on a remote client, here we will see an update to |
| 645 | // TabID1 with tab_node_id changing from NodeIDA to NodeIDB, and TabID2 |
| 646 | // with tab_node_id changing from NodeIDB to NodeIDA. |
| 647 | // |
| 648 | // We can also wind up here if we created this tab as an out-of-order |
| 649 | // update to the header node for this session before actually associating |
| 650 | // the tab itself, so the tab node id wasn't available at the time and |
| 651 | // is currently kInvalidTabNodeID. |
| 652 | // |
| 653 | // In both cases, we can safely throw it into the set of node ids. |
| 654 | tracker->OnTabNodeSeen(session_tag, specifics.tab_node_id()); |
| 655 | sessions::SessionTab* tab = tracker->GetTab(session_tag, tab_id); |
| 656 | if (!tab->timestamp.is_null() && tab->timestamp > modification_time) { |
| 657 | DVLOG(1) << "Ignoring " << session_tag << "'s session tab " << tab_id |
| 658 | << " with earlier modification time: " << tab->timestamp |
| 659 | << " vs " << modification_time; |
| 660 | return; |
| 661 | } |
| 662 | |
| 663 | // Update SessionTab based on protobuf. |
| 664 | tab->SetFromSyncData(tab_s, modification_time); |
| 665 | |
| 666 | // Update the last modified time. |
| 667 | if (session->modified_time < modification_time) |
| 668 | session->modified_time = modification_time; |
| 669 | } else { |
| 670 | LOG(WARNING) << "Ignoring session node with missing header/tab " |
| 671 | << "fields and tag " << session_tag << "."; |
| 672 | } |
| 673 | } |
| 674 | |
maxbogue | a79d99b7 | 2016-09-15 15:59:16 | [diff] [blame] | 675 | } // namespace sync_sessions |