Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/sync_sessions/sessions_sync_manager.h" | 5 #include "components/sync_sessions/sessions_sync_manager.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/format_macros.h" | |
| 11 #include "base/logging.h" | |
| 10 #include "base/memory/ptr_util.h" | 12 #include "base/memory/ptr_util.h" |
| 11 #include "base/metrics/field_trial.h" | 13 #include "base/metrics/field_trial.h" |
| 12 #include "base/metrics/histogram_macros.h" | 14 #include "base/metrics/histogram_macros.h" |
| 15 #include "base/strings/stringprintf.h" | |
| 13 #include "build/build_config.h" | 16 #include "build/build_config.h" |
| 14 #include "components/sync/base/hash_util.h" | 17 #include "components/sync/base/hash_util.h" |
| 15 #include "components/sync/device_info/local_device_info_provider.h" | 18 #include "components/sync/device_info/local_device_info_provider.h" |
| 16 #include "components/sync/model/sync_error.h" | 19 #include "components/sync/model/sync_error.h" |
| 17 #include "components/sync/model/sync_error_factory.h" | 20 #include "components/sync/model/sync_error_factory.h" |
| 18 #include "components/sync/model/sync_merge_result.h" | 21 #include "components/sync/model/sync_merge_result.h" |
| 19 #include "components/sync/model/time.h" | 22 #include "components/sync/model/time.h" |
| 20 #include "components/sync_sessions/sync_sessions_client.h" | 23 #include "components/sync_sessions/sync_sessions_client.h" |
| 21 #include "components/sync_sessions/synced_tab_delegate.h" | 24 #include "components/sync_sessions/synced_tab_delegate.h" |
| 22 #include "components/sync_sessions/synced_window_delegate.h" | 25 #include "components/sync_sessions/synced_window_delegate.h" |
| 23 #include "components/sync_sessions/synced_window_delegates_getter.h" | 26 #include "components/sync_sessions/synced_window_delegates_getter.h" |
| 27 #include "components/sync_sessions/tab_node_pool.h" | |
| 24 #include "components/variations/variations_associated_data.h" | 28 #include "components/variations/variations_associated_data.h" |
| 25 | 29 |
| 26 using sessions::SerializedNavigationEntry; | 30 using sessions::SerializedNavigationEntry; |
| 27 using syncer::DeviceInfo; | 31 using syncer::DeviceInfo; |
| 28 using syncer::LocalDeviceInfoProvider; | 32 using syncer::LocalDeviceInfoProvider; |
| 29 using syncer::SyncChange; | 33 using syncer::SyncChange; |
| 30 using syncer::SyncData; | 34 using syncer::SyncData; |
| 31 | 35 |
| 32 namespace sync_sessions { | 36 namespace sync_sessions { |
| 33 | 37 |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 55 return t1->timestamp > t2->timestamp; | 59 return t1->timestamp > t2->timestamp; |
| 56 } | 60 } |
| 57 | 61 |
| 58 // Comparator function for use with std::sort that will sort sessions by | 62 // Comparator function for use with std::sort that will sort sessions by |
| 59 // descending modified_time (i.e., most recent first). | 63 // descending modified_time (i.e., most recent first). |
| 60 bool SessionsRecencyComparator(const SyncedSession* s1, | 64 bool SessionsRecencyComparator(const SyncedSession* s1, |
| 61 const SyncedSession* s2) { | 65 const SyncedSession* s2) { |
| 62 return s1->modified_time > s2->modified_time; | 66 return s1->modified_time > s2->modified_time; |
| 63 } | 67 } |
| 64 | 68 |
| 69 std::string TabNodeIdToTag(const std::string& machine_tag, int tab_node_id) { | |
| 70 CHECK_GT(tab_node_id, TabNodePool::kInvalidTabNodeID) << "crbug.com/673618"; | |
| 71 return base::StringPrintf("%s %d", machine_tag.c_str(), tab_node_id); | |
| 72 } | |
| 73 | |
| 65 std::string TagFromSpecifics(const sync_pb::SessionSpecifics& specifics) { | 74 std::string TagFromSpecifics(const sync_pb::SessionSpecifics& specifics) { |
| 66 if (specifics.has_header()) { | 75 if (specifics.has_header()) { |
| 67 return specifics.session_tag(); | 76 return specifics.session_tag(); |
| 68 } else if (specifics.has_tab()) { | 77 } else if (specifics.has_tab()) { |
| 69 return TabNodePool::TabIdToTag(specifics.session_tag(), | 78 return TabNodeIdToTag(specifics.session_tag(), specifics.tab_node_id()); |
| 70 specifics.tab_node_id()); | |
| 71 } else { | 79 } else { |
| 72 return std::string(); | 80 return std::string(); |
| 73 } | 81 } |
| 74 } | 82 } |
| 75 | 83 |
| 84 sync_pb::SessionSpecifics SessionTabToSpecifics( | |
| 85 const sessions::SessionTab& session_tab, | |
| 86 const std::string& local_tag, | |
| 87 int tab_node_id) { | |
| 88 sync_pb::SessionSpecifics specifics; | |
| 89 specifics.mutable_tab()->CopyFrom(session_tab.ToSyncData()); | |
| 90 specifics.set_session_tag(local_tag); | |
| 91 specifics.set_tab_node_id(tab_node_id); | |
| 92 return specifics; | |
| 93 } | |
| 94 | |
| 95 void AppendDeletionsForTabNodes(const std::set<int>& tab_node_ids, | |
| 96 const std::string& machine_tag, | |
| 97 syncer::SyncChangeList* change_output) { | |
| 98 for (std::set<int>::const_iterator it = tab_node_ids.begin(); | |
| 99 it != tab_node_ids.end(); ++it) { | |
| 100 change_output->push_back(syncer::SyncChange( | |
| 101 FROM_HERE, SyncChange::ACTION_DELETE, | |
| 102 SyncData::CreateLocalDelete(TabNodeIdToTag(machine_tag, *it), | |
| 103 syncer::SESSIONS))); | |
| 104 } | |
| 105 } | |
| 106 | |
| 107 // Ensure that the tab id is not invalid. | |
| 108 bool ShouldSyncTabId( | |
| 109 SessionID::id_type tab_id, | |
| 110 const google::protobuf::RepeatedField<int>& synced_tab_ids) { | |
|
skym
2017/02/27 18:22:38
Should this param be removed?
Nicolas Zea
2017/02/28 00:09:01
Woops, yes it should. Done.
| |
| 111 if (tab_id == TabNodePool::kInvalidTabID) | |
| 112 return false; | |
| 113 return true; | |
| 114 } | |
| 115 | |
| 76 } // namespace | 116 } // namespace |
| 77 | 117 |
| 78 // |local_device| is owned by ProfileSyncService, its lifetime exceeds | 118 // |local_device| is owned by ProfileSyncService, its lifetime exceeds |
| 79 // lifetime of SessionSyncManager. | 119 // lifetime of SessionSyncManager. |
| 80 SessionsSyncManager::SessionsSyncManager( | 120 SessionsSyncManager::SessionsSyncManager( |
| 81 sync_sessions::SyncSessionsClient* sessions_client, | 121 sync_sessions::SyncSessionsClient* sessions_client, |
| 82 syncer::SyncPrefs* sync_prefs, | 122 syncer::SyncPrefs* sync_prefs, |
| 83 LocalDeviceInfoProvider* local_device, | 123 LocalDeviceInfoProvider* local_device, |
| 84 std::unique_ptr<LocalSessionEventRouter> router, | 124 std::unique_ptr<LocalSessionEventRouter> router, |
| 85 const base::Closure& sessions_updated_callback, | 125 const base::Closure& sessions_updated_callback, |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 110 return machine_tag; | 150 return machine_tag; |
| 111 } | 151 } |
| 112 | 152 |
| 113 syncer::SyncMergeResult SessionsSyncManager::MergeDataAndStartSyncing( | 153 syncer::SyncMergeResult SessionsSyncManager::MergeDataAndStartSyncing( |
| 114 syncer::ModelType type, | 154 syncer::ModelType type, |
| 115 const syncer::SyncDataList& initial_sync_data, | 155 const syncer::SyncDataList& initial_sync_data, |
| 116 std::unique_ptr<syncer::SyncChangeProcessor> sync_processor, | 156 std::unique_ptr<syncer::SyncChangeProcessor> sync_processor, |
| 117 std::unique_ptr<syncer::SyncErrorFactory> error_handler) { | 157 std::unique_ptr<syncer::SyncErrorFactory> error_handler) { |
| 118 syncer::SyncMergeResult merge_result(type); | 158 syncer::SyncMergeResult merge_result(type); |
| 119 DCHECK(session_tracker_.Empty()); | 159 DCHECK(session_tracker_.Empty()); |
| 120 DCHECK_EQ(0U, local_tab_pool_.Capacity()); | |
| 121 | 160 |
| 122 error_handler_ = std::move(error_handler); | 161 error_handler_ = std::move(error_handler); |
| 123 sync_processor_ = std::move(sync_processor); | 162 sync_processor_ = std::move(sync_processor); |
| 124 | 163 |
| 125 // SessionDataTypeController ensures that the local device info | 164 // SessionDataTypeController ensures that the local device info |
| 126 // is available before activating this datatype. | 165 // is available before activating this datatype. |
| 127 DCHECK(local_device_); | 166 DCHECK(local_device_); |
| 128 const DeviceInfo* local_device_info = local_device_->GetLocalDeviceInfo(); | 167 const DeviceInfo* local_device_info = local_device_->GetLocalDeviceInfo(); |
| 129 if (!local_device_info) { | 168 if (!local_device_info) { |
| 130 merge_result.set_error(error_handler_->CreateAndUploadError( | 169 merge_result.set_error(error_handler_->CreateAndUploadError( |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 146 | 185 |
| 147 local_session_header_node_id_ = TabNodePool::kInvalidTabNodeID; | 186 local_session_header_node_id_ = TabNodePool::kInvalidTabNodeID; |
| 148 | 187 |
| 149 // Make sure we have a machine tag. We do this now (versus earlier) as it's | 188 // Make sure we have a machine tag. We do this now (versus earlier) as it's |
| 150 // a conveniently safe time to assert sync is ready and the cache_guid is | 189 // a conveniently safe time to assert sync is ready and the cache_guid is |
| 151 // initialized. | 190 // initialized. |
| 152 if (current_machine_tag_.empty()) { | 191 if (current_machine_tag_.empty()) { |
| 153 InitializeCurrentMachineTag(local_device_->GetLocalSyncCacheGUID()); | 192 InitializeCurrentMachineTag(local_device_->GetLocalSyncCacheGUID()); |
| 154 } | 193 } |
| 155 | 194 |
| 156 session_tracker_.SetLocalSessionTag(current_machine_tag_); | 195 session_tracker_.SetLocalSessionTag(current_machine_tag()); |
| 157 | 196 |
| 158 syncer::SyncChangeList new_changes; | 197 syncer::SyncChangeList new_changes; |
| 159 | 198 |
| 160 // First, we iterate over sync data to update our session_tracker_. | 199 // First, we iterate over sync data to update our session_tracker_. |
| 161 syncer::SyncDataList restored_tabs; | 200 if (!InitFromSyncModel(initial_sync_data, &new_changes)) { |
| 162 if (!InitFromSyncModel(initial_sync_data, &restored_tabs, &new_changes)) { | |
| 163 // The sync db didn't have a header node for us. Create one. | 201 // The sync db didn't have a header node for us. Create one. |
| 164 sync_pb::EntitySpecifics specifics; | 202 sync_pb::EntitySpecifics specifics; |
| 165 sync_pb::SessionSpecifics* base_specifics = specifics.mutable_session(); | 203 sync_pb::SessionSpecifics* base_specifics = specifics.mutable_session(); |
| 166 base_specifics->set_session_tag(current_machine_tag()); | 204 base_specifics->set_session_tag(current_machine_tag()); |
| 167 sync_pb::SessionHeader* header_s = base_specifics->mutable_header(); | 205 sync_pb::SessionHeader* header_s = base_specifics->mutable_header(); |
| 168 header_s->set_client_name(current_session_name_); | 206 header_s->set_client_name(current_session_name_); |
| 169 header_s->set_device_type(current_device_type_); | 207 header_s->set_device_type(current_device_type_); |
| 170 syncer::SyncData data = syncer::SyncData::CreateLocalData( | 208 syncer::SyncData data = syncer::SyncData::CreateLocalData( |
| 171 current_machine_tag(), current_session_name_, specifics); | 209 current_machine_tag(), current_session_name_, specifics); |
| 172 new_changes.push_back( | 210 new_changes.push_back( |
| 173 syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_ADD, data)); | 211 syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_ADD, data)); |
| 174 } | 212 } |
| 175 | 213 |
| 176 #if defined(OS_ANDROID) | 214 #if defined(OS_ANDROID) |
| 177 std::string sync_machine_tag( | 215 std::string sync_machine_tag( |
| 178 BuildMachineTag(local_device_->GetLocalSyncCacheGUID())); | 216 BuildMachineTag(local_device_->GetLocalSyncCacheGUID())); |
| 179 if (current_machine_tag_.compare(sync_machine_tag) != 0) | 217 if (current_machine_tag().compare(sync_machine_tag) != 0) |
| 180 DeleteForeignSessionInternal(sync_machine_tag, &new_changes); | 218 DeleteForeignSessionInternal(sync_machine_tag, &new_changes); |
| 181 #endif | 219 #endif |
| 182 | 220 |
| 183 // Check if anything has changed on the local client side. | 221 // Check if anything has changed on the local client side. |
| 184 AssociateWindows(RELOAD_TABS, restored_tabs, &new_changes); | 222 AssociateWindows(RELOAD_TABS, &new_changes); |
| 185 local_tab_pool_out_of_sync_ = false; | 223 local_tab_pool_out_of_sync_ = false; |
| 186 | 224 |
| 187 merge_result.set_error( | 225 merge_result.set_error( |
| 188 sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes)); | 226 sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes)); |
| 189 | 227 |
| 190 local_event_router_->StartRoutingTo(this); | 228 local_event_router_->StartRoutingTo(this); |
| 191 return merge_result; | 229 return merge_result; |
| 192 } | 230 } |
| 193 | 231 |
| 194 void SessionsSyncManager::AssociateWindows( | 232 void SessionsSyncManager::AssociateWindows( |
| 195 ReloadTabsOption option, | 233 ReloadTabsOption option, |
| 196 const syncer::SyncDataList& restored_tabs, | |
| 197 syncer::SyncChangeList* change_output) { | 234 syncer::SyncChangeList* change_output) { |
| 198 const std::string local_tag = current_machine_tag(); | 235 const std::string local_tag = current_machine_tag(); |
| 199 sync_pb::SessionSpecifics specifics; | 236 sync_pb::SessionSpecifics specifics; |
| 200 specifics.set_session_tag(local_tag); | 237 specifics.set_session_tag(local_tag); |
| 201 sync_pb::SessionHeader* header_s = specifics.mutable_header(); | 238 sync_pb::SessionHeader* header_s = specifics.mutable_header(); |
| 202 SyncedSession* current_session = session_tracker_.GetSession(local_tag); | 239 SyncedSession* current_session = session_tracker_.GetSession(local_tag); |
| 203 current_session->modified_time = base::Time::Now(); | 240 current_session->modified_time = base::Time::Now(); |
| 204 header_s->set_client_name(current_session_name_); | 241 header_s->set_client_name(current_session_name_); |
| 205 header_s->set_device_type(current_device_type_); | 242 header_s->set_device_type(current_device_type_); |
| 206 | 243 |
| 207 session_tracker_.ResetSessionTracking(local_tag); | 244 session_tracker_.ResetSessionTracking(local_tag); |
| 208 std::set<const SyncedWindowDelegate*> windows = | 245 SyncedWindowDelegatesGetter::SyncedWindowDelegateMap windows = |
| 209 synced_window_delegates_getter()->GetSyncedWindowDelegates(); | 246 synced_window_delegates_getter()->GetSyncedWindowDelegates(); |
| 210 | 247 |
| 211 if (option == RELOAD_TABS) { | 248 if (option == RELOAD_TABS) { |
| 212 UMA_HISTOGRAM_COUNTS("Sync.SessionWindows", windows.size()); | 249 UMA_HISTOGRAM_COUNTS("Sync.SessionWindows", windows.size()); |
| 213 } | 250 } |
| 214 if (windows.size() == 0) { | 251 if (windows.size() == 0) { |
| 215 // Assume that the window hasn't loaded. Attempting to associate now would | 252 // Assume that the window hasn't loaded. Attempting to associate now would |
| 216 // clobber any old windows, so just return. | 253 // clobber any old windows, so just return. |
| 217 LOG(ERROR) << "No windows present, see crbug.com/639009"; | 254 LOG(ERROR) << "No windows present, see crbug.com/639009"; |
| 218 return; | 255 return; |
| 219 } | 256 } |
| 220 for (const SyncedWindowDelegate* window_delegate : windows) { | 257 for (auto window_iter_pair : windows) { |
| 258 const SyncedWindowDelegate* window_delegate = window_iter_pair.second; | |
| 221 if (option == RELOAD_TABS) { | 259 if (option == RELOAD_TABS) { |
| 222 UMA_HISTOGRAM_COUNTS("Sync.SessionTabs", window_delegate->GetTabCount()); | 260 UMA_HISTOGRAM_COUNTS("Sync.SessionTabs", window_delegate->GetTabCount()); |
| 223 } | 261 } |
| 224 | 262 |
| 225 // Make sure the window has tabs and a viewable window. The viewable window | 263 // Make sure the window has tabs and a viewable window. The viewable window |
| 226 // check is necessary because, for example, when a browser is closed the | 264 // check is necessary because, for example, when a browser is closed the |
| 227 // destructor is not necessarily run immediately. This means its possible | 265 // destructor is not necessarily run immediately. This means its possible |
| 228 // for us to get a handle to a browser that is about to be removed. If | 266 // for us to get a handle to a browser that is about to be removed. If |
| 229 // the tab count is 0 or the window is null, the browser is about to be | 267 // the tab count is 0 or the window is null, the browser is about to be |
| 230 // deleted, so we ignore it. | 268 // deleted, so we ignore it. |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 254 | 292 |
| 255 bool found_tabs = false; | 293 bool found_tabs = false; |
| 256 for (int j = 0; j < window_delegate->GetTabCount(); ++j) { | 294 for (int j = 0; j < window_delegate->GetTabCount(); ++j) { |
| 257 SessionID::id_type tab_id = window_delegate->GetTabIdAt(j); | 295 SessionID::id_type tab_id = window_delegate->GetTabIdAt(j); |
| 258 SyncedTabDelegate* synced_tab = window_delegate->GetTabAt(j); | 296 SyncedTabDelegate* synced_tab = window_delegate->GetTabAt(j); |
| 259 | 297 |
| 260 // GetTabAt can return a null tab; in that case just skip it. | 298 // GetTabAt can return a null tab; in that case just skip it. |
| 261 if (!synced_tab) | 299 if (!synced_tab) |
| 262 continue; | 300 continue; |
| 263 | 301 |
| 302 if (!ShouldSyncTabId(tab_id, window_s.tab())) { | |
| 303 LOG(ERROR) << "Not syncing invalid tab with id " << tab_id; | |
| 304 continue; | |
| 305 } | |
| 306 | |
| 307 // Placeholder tabs are those without WebContents, either because they | |
| 308 // were never loaded into memory or they were evicted from memory | |
| 309 // (typically only on Android devices). They only have a tab id, window | |
| 310 // id, and a saved synced id (corresponding to the tab node id). Note | |
| 311 // that only placeholders have this sync id, as it's necessary to | |
| 312 // properly reassociate the tab with the entity that was backing it. | |
| 264 if (synced_tab->IsPlaceholderTab()) { | 313 if (synced_tab->IsPlaceholderTab()) { |
| 265 // For tabs without WebContents update the |tab_id| and |window_id|, | 314 // For tabs without WebContents update the |tab_id| and |window_id|, |
| 266 // as it could have changed after a session restore. | 315 // as it could have changed after a session restore. |
| 267 // Note: We cannot check if a tab is valid if it has no WebContents. | 316 if (synced_tab->GetSyncId() > TabNodePool::kInvalidTabNodeID) { |
| 268 // We assume any such tab is valid and leave the contents of | |
| 269 // corresponding sync node unchanged. | |
| 270 if (synced_tab->GetSyncId() > TabNodePool::kInvalidTabNodeID && | |
| 271 tab_id > TabNodePool::kInvalidTabID) { | |
| 272 AssociateRestoredPlaceholderTab(*synced_tab, tab_id, window_id, | 317 AssociateRestoredPlaceholderTab(*synced_tab, tab_id, window_id, |
| 273 restored_tabs, change_output); | 318 change_output); |
| 274 found_tabs = true; | |
| 275 window_s.add_tab(tab_id); | |
| 276 } | 319 } |
| 277 continue; | 320 } else if (RELOAD_TABS == option) { |
| 321 AssociateTab(synced_tab, change_output); | |
| 278 } | 322 } |
| 279 | 323 |
| 280 if (RELOAD_TABS == option) | 324 // If the tab was syncable, it would have been added to the tracker |
| 281 AssociateTab(synced_tab, change_output); | 325 // either by the above Associate[RestoredPlaceholder]Tab call or by the |
| 282 | 326 // OnLocalTabModified method invoking AssociateTab directly. Therefore, |
| 283 // If the tab is valid, it would have been added to the tracker either | 327 // we can key whether this window has valid tabs based on the tab's |
| 284 // by the above AssociateTab call (at association time), or by the | 328 // presence in the tracker. |
| 285 // change processor calling AssociateTab for all modified tabs. | |
| 286 // Therefore, we can key whether this window has valid tabs based on | |
| 287 // the tab's presence in the tracker. | |
| 288 const sessions::SessionTab* tab = nullptr; | 329 const sessions::SessionTab* tab = nullptr; |
| 289 if (session_tracker_.LookupSessionTab(local_tag, tab_id, &tab)) { | 330 if (session_tracker_.LookupSessionTab(local_tag, tab_id, &tab)) { |
| 290 found_tabs = true; | 331 found_tabs = true; |
| 291 window_s.add_tab(tab_id); | 332 window_s.add_tab(tab_id); |
| 292 } | 333 } |
| 293 } | 334 } |
| 294 if (found_tabs) { | 335 if (found_tabs) { |
| 295 sync_pb::SessionWindow* header_window = header_s->add_window(); | 336 sync_pb::SessionWindow* header_window = header_s->add_window(); |
| 296 *header_window = window_s; | 337 *header_window = window_s; |
| 297 | 338 |
| 298 // Update this window's representation in the synced session tracker. | 339 // Update this window's representation in the synced session tracker. |
| 299 session_tracker_.PutWindowInSession(local_tag, window_id); | 340 session_tracker_.PutWindowInSession(local_tag, window_id); |
| 300 BuildSyncedSessionFromSpecifics( | 341 BuildSyncedSessionFromSpecifics( |
| 301 local_tag, window_s, current_session->modified_time, | 342 local_tag, window_s, current_session->modified_time, |
| 302 current_session->windows[window_id].get()); | 343 current_session->windows[window_id].get()); |
| 303 } | 344 } |
| 304 } | 345 } |
| 305 } | 346 } |
| 306 local_tab_pool_.DeleteUnassociatedTabNodes(change_output); | 347 std::set<int> deleted_tab_node_ids; |
| 307 session_tracker_.CleanupSession(local_tag); | 348 session_tracker_.CleanupLocalTabs(&deleted_tab_node_ids); |
| 349 AppendDeletionsForTabNodes(deleted_tab_node_ids, current_machine_tag(), | |
| 350 change_output); | |
| 308 | 351 |
| 309 // Always update the header. Sync takes care of dropping this update | 352 // Always update the header. Sync takes care of dropping this update |
| 310 // if the entity specifics are identical (i.e windows, client name did | 353 // if the entity specifics are identical (i.e windows, client name did |
| 311 // not change). | 354 // not change). |
| 312 sync_pb::EntitySpecifics entity; | 355 sync_pb::EntitySpecifics entity; |
| 313 entity.mutable_session()->CopyFrom(specifics); | 356 entity.mutable_session()->CopyFrom(specifics); |
| 314 syncer::SyncData data = syncer::SyncData::CreateLocalData( | 357 syncer::SyncData data = syncer::SyncData::CreateLocalData( |
| 315 current_machine_tag(), current_session_name_, entity); | 358 current_machine_tag(), current_session_name_, entity); |
| 316 change_output->push_back( | 359 change_output->push_back( |
| 317 syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_UPDATE, data)); | 360 syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_UPDATE, data)); |
| 318 } | 361 } |
| 319 | 362 |
| 320 void SessionsSyncManager::AssociateTab(SyncedTabDelegate* const tab, | 363 void SessionsSyncManager::AssociateTab(SyncedTabDelegate* const tab_delegate, |
| 321 syncer::SyncChangeList* change_output) { | 364 syncer::SyncChangeList* change_output) { |
| 322 DCHECK(!tab->IsPlaceholderTab()); | 365 DCHECK(!tab_delegate->IsPlaceholderTab()); |
| 323 SessionID::id_type tab_id = tab->GetSessionId(); | |
| 324 | 366 |
| 325 if (tab->IsBeingDestroyed()) { | 367 if (tab_delegate->IsBeingDestroyed()) { |
| 326 // This tab is closing. | 368 // Do nothing. By not proactively adding the tab to the session, it will be |
| 327 TabLinksMap::iterator tab_iter = local_tab_map_.find(tab_id); | 369 // removed if necessary during subsequent cleanup. |
| 328 if (tab_iter == local_tab_map_.end()) { | |
| 329 // We aren't tracking this tab (for example, sync setting page). | |
| 330 return; | |
| 331 } | |
| 332 local_tab_pool_.FreeTabNode(tab_iter->second->tab_node_id(), change_output); | |
| 333 local_tab_map_.erase(tab_iter); | |
| 334 return; | 370 return; |
| 335 } | 371 } |
| 336 | 372 |
| 337 if (!tab->ShouldSync(sessions_client_)) | 373 if (!tab_delegate->ShouldSync(sessions_client_)) |
| 338 return; | 374 return; |
| 339 | 375 |
| 340 TabLinksMap::iterator local_tab_map_iter = local_tab_map_.find(tab_id); | 376 SessionID::id_type tab_id = tab_delegate->GetSessionId(); |
| 341 TabLink* tab_link = nullptr; | 377 DVLOG(1) << "Syncing tab " << tab_id << " from window " |
| 378 << tab_delegate->GetWindowId(); | |
| 342 | 379 |
| 343 if (local_tab_map_iter == local_tab_map_.end()) { | 380 int tab_node_id = TabNodePool::kInvalidTabNodeID; |
| 344 int tab_node_id = tab->GetSyncId(); | 381 bool existing_tab_node = |
| 345 // If there is an old sync node for the tab, reuse it. If this is a new | 382 session_tracker_.GetTabNodeFromLocalTabId(tab_id, &tab_node_id); |
| 346 // tab, get a sync node for it. | 383 CHECK_NE(TabNodePool::kInvalidTabNodeID, tab_node_id) << "crbug.com/673618"; |
| 347 if (!local_tab_pool_.IsUnassociatedTabNode(tab_node_id)) { | 384 tab_delegate->SetSyncId(tab_node_id); |
| 348 tab_node_id = local_tab_pool_.GetFreeTabNode(change_output); | 385 sessions::SessionTab* session_tab = |
| 349 tab->SetSyncId(tab_node_id); | 386 session_tracker_.GetTab(current_machine_tag(), tab_id); |
| 350 } | |
| 351 local_tab_pool_.AssociateTabNode(tab_node_id, tab_id); | |
| 352 tab_link = new TabLink(tab_node_id, tab); | |
| 353 local_tab_map_[tab_id] = make_linked_ptr<TabLink>(tab_link); | |
| 354 } else { | |
| 355 // This tab is already associated with a sync node, reuse it. | |
| 356 // Note: on some platforms the tab object may have changed, so we ensure | |
| 357 // the tab link is up to date. | |
| 358 tab_link = local_tab_map_iter->second.get(); | |
| 359 local_tab_map_iter->second->set_tab(tab); | |
| 360 } | |
| 361 DCHECK(tab_link); | |
| 362 DCHECK_NE(tab_link->tab_node_id(), TabNodePool::kInvalidTabNodeID); | |
| 363 DVLOG(1) << "Reloading tab " << tab_id << " from window " | |
| 364 << tab->GetWindowId(); | |
| 365 | 387 |
| 366 // Write to sync model. | 388 // Get the previously synced url. |
| 367 sync_pb::EntitySpecifics specifics; | 389 int old_index = session_tab->normalized_navigation_index(); |
| 368 LocalTabDelegateToSpecifics(*tab, specifics.mutable_session()); | 390 GURL old_url; |
| 369 syncer::SyncData data = syncer::SyncData::CreateLocalData( | 391 if (session_tab->navigations.size() > static_cast<size_t>(old_index)) |
| 370 TabNodePool::TabIdToTag(current_machine_tag_, tab_link->tab_node_id()), | 392 old_url = session_tab->navigations[old_index].virtual_url(); |
| 371 current_session_name_, specifics); | |
| 372 change_output->push_back( | |
| 373 syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_UPDATE, data)); | |
| 374 | 393 |
| 375 int current_index = tab->GetCurrentEntryIndex(); | 394 // Update the tracker's session representation. |
| 376 const GURL new_url = tab->GetVirtualURLAtIndex(current_index); | 395 SetSessionTabFromDelegate(*tab_delegate, base::Time::Now(), session_tab); |
| 377 if (new_url != tab_link->url()) { | 396 SetVariationIds(session_tab); |
| 378 tab_link->set_url(new_url); | |
| 379 favicon_cache_.OnFaviconVisited(new_url, | |
| 380 tab->GetFaviconURLAtIndex(current_index)); | |
| 381 page_revisit_broadcaster_.OnPageVisit( | |
| 382 new_url, tab->GetTransitionAtIndex(current_index)); | |
| 383 } | |
| 384 | |
| 385 session_tracker_.GetSession(current_machine_tag())->modified_time = | 397 session_tracker_.GetSession(current_machine_tag())->modified_time = |
| 386 base::Time::Now(); | 398 base::Time::Now(); |
| 399 | |
| 400 // Write to the sync model itself. | |
| 401 sync_pb::EntitySpecifics specifics; | |
| 402 specifics.mutable_session()->CopyFrom( | |
| 403 SessionTabToSpecifics(*session_tab, current_machine_tag(), tab_node_id)); | |
| 404 syncer::SyncData data = syncer::SyncData::CreateLocalData( | |
| 405 TabNodeIdToTag(current_machine_tag(), tab_node_id), current_session_name_, | |
| 406 specifics); | |
| 407 change_output->push_back( | |
| 408 syncer::SyncChange(FROM_HERE, | |
| 409 existing_tab_node ? syncer::SyncChange::ACTION_UPDATE | |
| 410 : syncer::SyncChange::ACTION_ADD, | |
| 411 data)); | |
| 412 | |
| 413 int current_index = tab_delegate->GetCurrentEntryIndex(); | |
| 414 const GURL new_url = tab_delegate->GetVirtualURLAtIndex(current_index); | |
| 415 if (new_url != old_url) { | |
| 416 favicon_cache_.OnFaviconVisited( | |
| 417 new_url, tab_delegate->GetFaviconURLAtIndex(current_index)); | |
| 418 page_revisit_broadcaster_.OnPageVisit( | |
| 419 new_url, tab_delegate->GetTransitionAtIndex(current_index)); | |
| 420 } | |
| 387 } | 421 } |
| 388 | 422 |
| 389 bool SessionsSyncManager::RebuildAssociations() { | 423 bool SessionsSyncManager::RebuildAssociations() { |
| 390 syncer::SyncDataList data(sync_processor_->GetAllSyncData(syncer::SESSIONS)); | 424 syncer::SyncDataList data(sync_processor_->GetAllSyncData(syncer::SESSIONS)); |
| 391 std::unique_ptr<syncer::SyncErrorFactory> error_handler( | 425 std::unique_ptr<syncer::SyncErrorFactory> error_handler( |
| 392 std::move(error_handler_)); | 426 std::move(error_handler_)); |
| 393 std::unique_ptr<syncer::SyncChangeProcessor> processor( | 427 std::unique_ptr<syncer::SyncChangeProcessor> processor( |
| 394 std::move(sync_processor_)); | 428 std::move(sync_processor_)); |
| 395 | 429 |
| 396 StopSyncing(syncer::SESSIONS); | 430 StopSyncing(syncer::SESSIONS); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 436 DCHECK(!rebuild_association_succeeded || !local_tab_pool_out_of_sync_); | 470 DCHECK(!rebuild_association_succeeded || !local_tab_pool_out_of_sync_); |
| 437 return; | 471 return; |
| 438 } | 472 } |
| 439 | 473 |
| 440 syncer::SyncChangeList changes; | 474 syncer::SyncChangeList changes; |
| 441 AssociateTab(modified_tab, &changes); | 475 AssociateTab(modified_tab, &changes); |
| 442 // Note, we always associate windows because it's possible a tab became | 476 // Note, we always associate windows because it's possible a tab became |
| 443 // "interesting" by going to a valid URL, in which case it needs to be added | 477 // "interesting" by going to a valid URL, in which case it needs to be added |
| 444 // to the window's tab information. Similarly, if a tab became | 478 // to the window's tab information. Similarly, if a tab became |
| 445 // "uninteresting", we remove it from the window's tab information. | 479 // "uninteresting", we remove it from the window's tab information. |
| 446 AssociateWindows(DONT_RELOAD_TABS, syncer::SyncDataList(), &changes); | 480 AssociateWindows(DONT_RELOAD_TABS, &changes); |
| 447 sync_processor_->ProcessSyncChanges(FROM_HERE, changes); | 481 sync_processor_->ProcessSyncChanges(FROM_HERE, changes); |
| 448 } | 482 } |
| 449 | 483 |
| 450 void SessionsSyncManager::OnFaviconsChanged(const std::set<GURL>& page_urls, | 484 void SessionsSyncManager::OnFaviconsChanged(const std::set<GURL>& page_urls, |
| 451 const GURL& /* icon_url */) { | 485 const GURL& /* icon_url */) { |
| 452 // TODO(zea): consider a separate container for tabs with outstanding favicon | 486 for (const GURL& page_url : page_urls) |
| 453 // loads so we don't have to iterate through all tabs comparing urls. | 487 favicon_cache_.OnPageFaviconUpdated(page_url); |
| 454 for (const GURL& page_url : page_urls) { | |
| 455 for (TabLinksMap::iterator tab_iter = local_tab_map_.begin(); | |
| 456 tab_iter != local_tab_map_.end(); ++tab_iter) { | |
| 457 if (tab_iter->second->url() == page_url) | |
| 458 favicon_cache_.OnPageFaviconUpdated(page_url); | |
| 459 } | |
| 460 } | |
| 461 } | 488 } |
| 462 | 489 |
| 463 void SessionsSyncManager::StopSyncing(syncer::ModelType type) { | 490 void SessionsSyncManager::StopSyncing(syncer::ModelType type) { |
| 464 local_event_router_->Stop(); | 491 local_event_router_->Stop(); |
| 465 if (sync_processor_.get() && lost_navigations_recorder_.get()) { | 492 if (sync_processor_.get() && lost_navigations_recorder_.get()) { |
| 466 sync_processor_->RemoveLocalChangeObserver( | 493 sync_processor_->RemoveLocalChangeObserver( |
| 467 lost_navigations_recorder_.get()); | 494 lost_navigations_recorder_.get()); |
| 468 lost_navigations_recorder_.reset(); | 495 lost_navigations_recorder_.reset(); |
| 469 } | 496 } |
| 470 sync_processor_.reset(nullptr); | 497 sync_processor_.reset(nullptr); |
| 471 error_handler_.reset(); | 498 error_handler_.reset(); |
| 472 session_tracker_.Clear(); | 499 session_tracker_.Clear(); |
| 473 local_tab_map_.clear(); | |
| 474 local_tab_pool_.Clear(); | |
| 475 current_machine_tag_.clear(); | 500 current_machine_tag_.clear(); |
| 476 current_session_name_.clear(); | 501 current_session_name_.clear(); |
| 477 local_session_header_node_id_ = TabNodePool::kInvalidTabNodeID; | 502 local_session_header_node_id_ = TabNodePool::kInvalidTabNodeID; |
| 478 } | 503 } |
| 479 | 504 |
| 480 syncer::SyncDataList SessionsSyncManager::GetAllSyncData( | 505 syncer::SyncDataList SessionsSyncManager::GetAllSyncData( |
| 481 syncer::ModelType type) const { | 506 syncer::ModelType type) const { |
| 482 syncer::SyncDataList list; | 507 syncer::SyncDataList list; |
| 483 const SyncedSession* session = nullptr; | 508 const SyncedSession* session = nullptr; |
| 484 if (!session_tracker_.LookupLocalSession(&session)) | 509 if (!session_tracker_.LookupLocalSession(&session)) |
| 485 return syncer::SyncDataList(); | 510 return syncer::SyncDataList(); |
| 486 | 511 |
| 487 // First construct the header node. | 512 // First construct the header node. |
| 488 sync_pb::EntitySpecifics header_entity; | 513 sync_pb::EntitySpecifics header_entity; |
| 489 header_entity.mutable_session()->set_session_tag(current_machine_tag()); | 514 header_entity.mutable_session()->set_session_tag(current_machine_tag()); |
| 490 sync_pb::SessionHeader* header_specifics = | 515 sync_pb::SessionHeader* header_specifics = |
| 491 header_entity.mutable_session()->mutable_header(); | 516 header_entity.mutable_session()->mutable_header(); |
| 492 header_specifics->MergeFrom(session->ToSessionHeader()); | 517 header_specifics->MergeFrom(session->ToSessionHeader()); |
| 493 syncer::SyncData data = syncer::SyncData::CreateLocalData( | 518 syncer::SyncData data = syncer::SyncData::CreateLocalData( |
| 494 current_machine_tag(), current_session_name_, header_entity); | 519 current_machine_tag(), current_session_name_, header_entity); |
| 495 list.push_back(data); | 520 list.push_back(data); |
| 496 | 521 |
| 497 for (auto win_iter = session->windows.begin(); | 522 for (auto& win_iter : session->windows) { |
| 498 win_iter != session->windows.end(); ++win_iter) { | 523 for (auto& tab : win_iter.second->tabs) { |
| 499 for (auto tabs_iter = win_iter->second->tabs.begin(); | 524 // TODO(zea): replace with with the correct tab node id once there's a |
| 500 tabs_iter != win_iter->second->tabs.end(); ++tabs_iter) { | 525 // sync specific wrapper for SessionTab. This method is only used in |
| 526 // tests though, so it's fine for now. crbug.com/662597 | |
| 527 int tab_node_id = 0; | |
| 501 sync_pb::EntitySpecifics entity; | 528 sync_pb::EntitySpecifics entity; |
| 502 sync_pb::SessionSpecifics* specifics = entity.mutable_session(); | 529 entity.mutable_session()->CopyFrom( |
| 503 specifics->mutable_tab()->MergeFrom((*tabs_iter)->ToSyncData()); | 530 SessionTabToSpecifics(*tab, current_machine_tag(), tab_node_id)); |
| 504 specifics->set_session_tag(current_machine_tag_); | |
| 505 | |
| 506 TabLinksMap::const_iterator tab_map_iter = | |
| 507 local_tab_map_.find((*tabs_iter)->tab_id.id()); | |
| 508 DCHECK(tab_map_iter != local_tab_map_.end()); | |
| 509 specifics->set_tab_node_id(tab_map_iter->second->tab_node_id()); | |
| 510 syncer::SyncData data = syncer::SyncData::CreateLocalData( | 531 syncer::SyncData data = syncer::SyncData::CreateLocalData( |
| 511 TabNodePool::TabIdToTag(current_machine_tag_, | 532 TabNodeIdToTag(current_machine_tag(), tab_node_id), |
| 512 specifics->tab_node_id()), | |
| 513 current_session_name_, entity); | 533 current_session_name_, entity); |
| 514 list.push_back(data); | 534 list.push_back(data); |
| 515 } | 535 } |
| 516 } | 536 } |
| 517 return list; | 537 return list; |
| 518 } | 538 } |
| 519 | 539 |
| 520 bool SessionsSyncManager::GetLocalSession(const SyncedSession** local_session) { | 540 bool SessionsSyncManager::GetLocalSession(const SyncedSession** local_session) { |
| 521 if (current_machine_tag_.empty()) | 541 if (current_machine_tag().empty()) |
| 522 return false; | 542 return false; |
| 523 *local_session = session_tracker_.GetSession(current_machine_tag()); | 543 *local_session = session_tracker_.GetSession(current_machine_tag()); |
| 524 return true; | 544 return true; |
| 525 } | 545 } |
| 526 | 546 |
| 527 syncer::SyncError SessionsSyncManager::ProcessSyncChanges( | 547 syncer::SyncError SessionsSyncManager::ProcessSyncChanges( |
| 528 const tracked_objects::Location& from_here, | 548 const tracked_objects::Location& from_here, |
| 529 const syncer::SyncChangeList& change_list) { | 549 const syncer::SyncChangeList& change_list) { |
| 530 if (!sync_processor_.get()) { | 550 if (!sync_processor_.get()) { |
| 531 syncer::SyncError error(FROM_HERE, syncer::SyncError::DATATYPE_ERROR, | 551 syncer::SyncError error(FROM_HERE, syncer::SyncError::DATATYPE_ERROR, |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 571 break; | 591 break; |
| 572 case syncer::SyncChange::ACTION_ADD: | 592 case syncer::SyncChange::ACTION_ADD: |
| 573 case syncer::SyncChange::ACTION_UPDATE: | 593 case syncer::SyncChange::ACTION_UPDATE: |
| 574 if (current_machine_tag() == session.session_tag()) { | 594 if (current_machine_tag() == session.session_tag()) { |
| 575 // We should only ever receive a change to our own machine's session | 595 // We should only ever receive a change to our own machine's session |
| 576 // info if encryption was turned on. In that case, the data is still | 596 // info if encryption was turned on. In that case, the data is still |
| 577 // the same, so we can ignore. | 597 // the same, so we can ignore. |
| 578 LOG(WARNING) << "Dropping modification to local session."; | 598 LOG(WARNING) << "Dropping modification to local session."; |
| 579 return syncer::SyncError(); | 599 return syncer::SyncError(); |
| 580 } | 600 } |
| 581 UpdateTrackerWithForeignSession( | 601 UpdateTrackerWithSpecifics( |
| 582 session, syncer::SyncDataRemote(it->sync_data()).GetModifiedTime()); | 602 session, syncer::SyncDataRemote(it->sync_data()).GetModifiedTime()); |
| 583 break; | 603 break; |
| 584 default: | 604 default: |
| 585 NOTREACHED() << "Processing sync changes failed, unknown change type."; | 605 NOTREACHED() << "Processing sync changes failed, unknown change type."; |
| 586 } | 606 } |
| 587 } | 607 } |
| 588 | 608 |
| 589 if (!sessions_updated_callback_.is_null()) | 609 if (!sessions_updated_callback_.is_null()) |
| 590 sessions_updated_callback_.Run(); | 610 sessions_updated_callback_.Run(); |
| 591 return syncer::SyncError(); | 611 return syncer::SyncError(); |
| 592 } | 612 } |
| 593 | 613 |
| 594 syncer::SyncChange SessionsSyncManager::TombstoneTab( | 614 syncer::SyncChange SessionsSyncManager::TombstoneTab( |
| 595 const sync_pb::SessionSpecifics& tab) { | 615 const sync_pb::SessionSpecifics& tab) { |
| 596 if (!tab.has_tab_node_id()) { | 616 if (!tab.has_tab_node_id()) { |
| 597 LOG(WARNING) << "Old sessions node without tab node id; can't tombstone."; | 617 LOG(WARNING) << "Old sessions node without tab node id; can't tombstone."; |
| 598 return syncer::SyncChange(); | 618 return syncer::SyncChange(); |
| 599 } else { | 619 } else { |
| 600 return syncer::SyncChange( | 620 return syncer::SyncChange( |
| 601 FROM_HERE, SyncChange::ACTION_DELETE, | 621 FROM_HERE, SyncChange::ACTION_DELETE, |
| 602 SyncData::CreateLocalDelete( | 622 SyncData::CreateLocalDelete( |
| 603 TabNodePool::TabIdToTag(current_machine_tag(), tab.tab_node_id()), | 623 TabNodeIdToTag(current_machine_tag(), tab.tab_node_id()), |
| 604 syncer::SESSIONS)); | 624 syncer::SESSIONS)); |
| 605 } | 625 } |
| 606 } | 626 } |
| 607 | 627 |
| 608 bool SessionsSyncManager::GetAllForeignSessions( | 628 bool SessionsSyncManager::GetAllForeignSessions( |
| 609 std::vector<const SyncedSession*>* sessions) { | 629 std::vector<const SyncedSession*>* sessions) { |
| 610 if (!session_tracker_.LookupAllForeignSessions( | 630 if (!session_tracker_.LookupAllForeignSessions( |
| 611 sessions, SyncedSessionTracker::PRESENTABLE)) | 631 sessions, SyncedSessionTracker::PRESENTABLE)) |
| 612 return false; | 632 return false; |
| 613 std::sort(sessions->begin(), sessions->end(), SessionsRecencyComparator); | 633 std::sort(sessions->begin(), sessions->end(), SessionsRecencyComparator); |
| 614 return true; | 634 return true; |
| 615 } | 635 } |
| 616 | 636 |
| 617 bool SessionsSyncManager::InitFromSyncModel( | 637 bool SessionsSyncManager::InitFromSyncModel( |
| 618 const syncer::SyncDataList& sync_data, | 638 const syncer::SyncDataList& sync_data, |
| 619 syncer::SyncDataList* restored_tabs, | |
| 620 syncer::SyncChangeList* new_changes) { | 639 syncer::SyncChangeList* new_changes) { |
| 621 bool found_current_header = false; | 640 bool found_current_header = false; |
| 622 int bad_foreign_hash_count = 0; | 641 int bad_foreign_hash_count = 0; |
| 623 for (syncer::SyncDataList::const_iterator it = sync_data.begin(); | 642 for (syncer::SyncDataList::const_iterator it = sync_data.begin(); |
| 624 it != sync_data.end(); ++it) { | 643 it != sync_data.end(); ++it) { |
| 625 const syncer::SyncData& data = *it; | 644 const syncer::SyncData& data = *it; |
| 626 DCHECK(data.GetSpecifics().has_session()); | 645 DCHECK(data.GetSpecifics().has_session()); |
| 627 syncer::SyncDataRemote remote(data); | 646 syncer::SyncDataRemote remote(data); |
| 628 const sync_pb::SessionSpecifics& specifics = data.GetSpecifics().session(); | 647 const sync_pb::SessionSpecifics& specifics = data.GetSpecifics().session(); |
| 629 if (specifics.session_tag().empty() || | 648 if (specifics.session_tag().empty() || |
| 630 (specifics.has_tab() && | 649 (specifics.has_tab() && |
| 631 (!specifics.has_tab_node_id() || !specifics.tab().has_tab_id()))) { | 650 (!specifics.has_tab_node_id() || !specifics.tab().has_tab_id()))) { |
| 632 syncer::SyncChange tombstone(TombstoneTab(specifics)); | 651 syncer::SyncChange tombstone(TombstoneTab(specifics)); |
| 633 if (tombstone.IsValid()) | 652 if (tombstone.IsValid()) |
| 634 new_changes->push_back(tombstone); | 653 new_changes->push_back(tombstone); |
| 635 } else if (specifics.session_tag() != current_machine_tag()) { | 654 } else if (specifics.session_tag() != current_machine_tag()) { |
| 636 if (TagHashFromSpecifics(specifics) == remote.GetClientTagHash()) { | 655 if (TagHashFromSpecifics(specifics) == remote.GetClientTagHash()) { |
| 637 UpdateTrackerWithForeignSession(specifics, remote.GetModifiedTime()); | 656 UpdateTrackerWithSpecifics(specifics, remote.GetModifiedTime()); |
| 638 } else { | 657 } else { |
| 639 // In the past, like years ago, we believe that some session data was | 658 // In the past, like years ago, we believe that some session data was |
| 640 // created with bad tag hashes. This causes any change this client makes | 659 // created with bad tag hashes. This causes any change this client makes |
| 641 // to that foreign data (like deletion through garbage collection) to | 660 // to that foreign data (like deletion through garbage collection) to |
| 642 // trigger a data type error because the tag looking mechanism fails. So | 661 // trigger a data type error because the tag looking mechanism fails. So |
| 643 // look for these and delete via remote SyncData, which uses a server id | 662 // look for these and delete via remote SyncData, which uses a server id |
| 644 // lookup mechanism instead, see crbug.com/604657. | 663 // lookup mechanism instead, see crbug.com/604657. |
| 645 bad_foreign_hash_count++; | 664 bad_foreign_hash_count++; |
| 646 new_changes->push_back( | 665 new_changes->push_back( |
| 647 syncer::SyncChange(FROM_HERE, SyncChange::ACTION_DELETE, remote)); | 666 syncer::SyncChange(FROM_HERE, SyncChange::ACTION_DELETE, remote)); |
| 648 } | 667 } |
| 649 } else { | 668 } else { |
| 650 // This is previously stored local session information. | 669 // This is previously stored local session information. |
| 651 if (specifics.has_header() && !found_current_header) { | 670 if (specifics.has_header() && !found_current_header) { |
| 652 // This is our previous header node, reuse it. | 671 // This is our previous header node, reuse it. |
| 653 found_current_header = true; | 672 found_current_header = true; |
| 654 if (specifics.header().has_client_name()) | 673 if (specifics.header().has_client_name()) |
| 655 current_session_name_ = specifics.header().client_name(); | 674 current_session_name_ = specifics.header().client_name(); |
| 675 | |
| 676 // TODO(zea): crbug.com/639009 update the tracker with the specifics | |
| 677 // from the header node as well. This will be necessary to preserve | |
| 678 // the set of open tabs when a custom tab is opened. | |
| 656 } else { | 679 } else { |
| 657 if (specifics.has_header() || !specifics.has_tab()) { | 680 if (specifics.has_header() || !specifics.has_tab()) { |
| 658 LOG(WARNING) << "Found more than one session header node with local " | 681 LOG(WARNING) << "Found more than one session header node with local " |
| 659 << "tag."; | 682 << "tag."; |
| 660 syncer::SyncChange tombstone(TombstoneTab(specifics)); | 683 syncer::SyncChange tombstone(TombstoneTab(specifics)); |
| 661 if (tombstone.IsValid()) | 684 if (tombstone.IsValid()) |
| 662 new_changes->push_back(tombstone); | 685 new_changes->push_back(tombstone); |
| 686 } else if (specifics.tab().tab_id() == TabNodePool::kInvalidTabID) { | |
| 687 LOG(WARNING) << "Found tab node with invalid tab id."; | |
| 688 syncer::SyncChange tombstone(TombstoneTab(specifics)); | |
| 689 if (tombstone.IsValid()) | |
| 690 new_changes->push_back(tombstone); | |
| 663 } else { | 691 } else { |
| 664 // This is a valid old tab node, add it to the pool so it can be | 692 // This is a valid old tab node, add it to the tracker and associate |
| 665 // reused for reassociation. | 693 // it. |
| 666 local_tab_pool_.AddTabNode(specifics.tab_node_id()); | 694 DVLOG(1) << "Associating local tab " << specifics.tab().tab_id() |
| 667 restored_tabs->push_back(*it); | 695 << " with node " << specifics.tab_node_id(); |
| 696 session_tracker_.ReassociateLocalTab(specifics.tab_node_id(), | |
| 697 specifics.tab().tab_id()); | |
| 698 UpdateTrackerWithSpecifics(specifics, remote.GetModifiedTime()); | |
| 668 } | 699 } |
| 669 } | 700 } |
| 670 } | 701 } |
| 671 } | 702 } |
| 672 | 703 |
| 673 // Cleanup all foreign sessions, since orphaned tabs may have been added after | 704 // Cleanup all foreign sessions, since orphaned tabs may have been added after |
| 674 // the header. | 705 // the header. |
| 675 std::vector<const SyncedSession*> sessions; | 706 std::vector<const SyncedSession*> sessions; |
| 676 session_tracker_.LookupAllForeignSessions(&sessions, | 707 session_tracker_.LookupAllForeignSessions(&sessions, |
| 677 SyncedSessionTracker::RAW); | 708 SyncedSessionTracker::RAW); |
| 678 for (const auto* session : sessions) { | 709 for (const auto* session : sessions) { |
| 679 session_tracker_.CleanupSession(session->session_tag); | 710 session_tracker_.CleanupForeignSession(session->session_tag); |
| 680 } | 711 } |
| 681 | 712 |
| 682 UMA_HISTOGRAM_COUNTS_100("Sync.SessionsBadForeignHashOnMergeCount", | 713 UMA_HISTOGRAM_COUNTS_100("Sync.SessionsBadForeignHashOnMergeCount", |
| 683 bad_foreign_hash_count); | 714 bad_foreign_hash_count); |
| 684 | 715 |
| 685 return found_current_header; | 716 return found_current_header; |
| 686 } | 717 } |
| 687 | 718 |
| 688 void SessionsSyncManager::UpdateTrackerWithForeignSession( | 719 void SessionsSyncManager::UpdateTrackerWithSpecifics( |
| 689 const sync_pb::SessionSpecifics& specifics, | 720 const sync_pb::SessionSpecifics& specifics, |
| 690 const base::Time& modification_time) { | 721 const base::Time& modification_time) { |
| 691 std::string foreign_session_tag = specifics.session_tag(); | 722 std::string session_tag = specifics.session_tag(); |
| 692 DCHECK_NE(foreign_session_tag, current_machine_tag()); | 723 SyncedSession* session = session_tracker_.GetSession(session_tag); |
| 693 | |
| 694 SyncedSession* foreign_session = | |
| 695 session_tracker_.GetSession(foreign_session_tag); | |
| 696 if (specifics.has_header()) { | 724 if (specifics.has_header()) { |
| 697 // Read in the header data for this foreign session. Header data is | 725 // Read in the header data for this session. Header data is |
| 698 // essentially a collection of windows, each of which has an ordered id list | 726 // essentially a collection of windows, each of which has an ordered id list |
| 699 // for their tabs. | 727 // for their tabs. |
| 700 | 728 |
| 701 if (!IsValidSessionHeader(specifics.header())) { | 729 if (!IsValidSessionHeader(specifics.header())) { |
| 702 LOG(WARNING) << "Ignoring foreign session node with invalid header " | 730 LOG(WARNING) << "Ignoring session node with invalid header " |
| 703 << "and tag " << foreign_session_tag << "."; | 731 << "and tag " << session_tag << "."; |
| 704 return; | 732 return; |
| 705 } | 733 } |
| 706 | 734 |
| 707 // Load (or create) the SyncedSession object for this client. | 735 // Load (or create) the SyncedSession object for this client. |
| 708 const sync_pb::SessionHeader& header = specifics.header(); | 736 const sync_pb::SessionHeader& header = specifics.header(); |
| 709 PopulateSessionHeaderFromSpecifics(header, modification_time, | 737 PopulateSessionHeaderFromSpecifics(header, modification_time, session); |
| 710 foreign_session); | |
| 711 | 738 |
| 712 // Reset the tab/window tracking for this session (must do this before | 739 // Reset the tab/window tracking for this session (must do this before |
| 713 // we start calling PutWindowInSession and PutTabInWindow so that all | 740 // we start calling PutWindowInSession and PutTabInWindow so that all |
| 714 // unused tabs/windows get cleared by the CleanupSession(...) call). | 741 // unused tabs/windows get cleared by the CleanupSession(...) call). |
| 715 session_tracker_.ResetSessionTracking(foreign_session_tag); | 742 session_tracker_.ResetSessionTracking(session_tag); |
| 716 | 743 |
| 717 // Process all the windows and their tab information. | 744 // Process all the windows and their tab information. |
| 718 int num_windows = header.window_size(); | 745 int num_windows = header.window_size(); |
| 719 DVLOG(1) << "Associating " << foreign_session_tag << " with " << num_windows | 746 DVLOG(1) << "Populating " << session_tag << " with " << num_windows |
| 720 << " windows."; | 747 << " windows."; |
| 721 | 748 |
| 722 for (int i = 0; i < num_windows; ++i) { | 749 for (int i = 0; i < num_windows; ++i) { |
| 723 const sync_pb::SessionWindow& window_s = header.window(i); | 750 const sync_pb::SessionWindow& window_s = header.window(i); |
| 724 SessionID::id_type window_id = window_s.window_id(); | 751 SessionID::id_type window_id = window_s.window_id(); |
| 725 session_tracker_.PutWindowInSession(foreign_session_tag, window_id); | 752 session_tracker_.PutWindowInSession(session_tag, window_id); |
| 726 BuildSyncedSessionFromSpecifics( | 753 BuildSyncedSessionFromSpecifics(session_tag, window_s, modification_time, |
| 727 foreign_session_tag, window_s, modification_time, | 754 session->windows[window_id].get()); |
| 728 foreign_session->windows[window_id].get()); | |
| 729 } | 755 } |
| 730 // Delete any closed windows and unused tabs as necessary. | 756 // Delete any closed windows and unused tabs as necessary. |
| 731 session_tracker_.CleanupSession(foreign_session_tag); | 757 session_tracker_.CleanupForeignSession(session_tag); |
| 732 } else if (specifics.has_tab()) { | 758 } else if (specifics.has_tab()) { |
| 733 const sync_pb::SessionTab& tab_s = specifics.tab(); | 759 const sync_pb::SessionTab& tab_s = specifics.tab(); |
| 734 SessionID::id_type tab_id = tab_s.tab_id(); | 760 SessionID::id_type tab_id = tab_s.tab_id(); |
| 761 DVLOG(1) << "Populating " << session_tag << "'s tab id " << tab_id | |
| 762 << " from node " << specifics.tab_node_id(); | |
| 735 | 763 |
| 736 const sessions::SessionTab* existing_tab; | 764 // Ensure the tracker is aware of the tab node id. Deleting foreign sessions |
| 737 if (session_tracker_.LookupSessionTab(foreign_session_tag, tab_id, | 765 // requires deleting all relevant tab nodes, and it's easier to track the |
| 738 &existing_tab) && | 766 // tab node ids themselves separately from the tab ids. |
| 739 existing_tab->timestamp > modification_time) { | 767 // |
| 740 // Force the tracker to remember this tab node id, even if it isn't | 768 // Note that TabIDs are not stable across restarts of a client. Consider |
| 741 // currently being used. | 769 // this example with two tabs: |
| 742 session_tracker_.GetTab(foreign_session_tag, tab_id, | 770 // |
| 743 specifics.tab_node_id()); | 771 // http://a.com TabID1 --> NodeIDA |
| 744 DVLOG(1) << "Ignoring " << foreign_session_tag << "'s session tab " | 772 // http://b.com TabID2 --> NodeIDB |
| 745 << tab_id << " with earlier modification time"; | 773 // |
| 774 // After restart, tab ids are reallocated. e.g, one possibility: | |
| 775 // http://a.com TabID2 --> NodeIDA | |
| 776 // http://b.com TabID1 --> NodeIDB | |
| 777 // | |
| 778 // If that happened on a remote client, here we will see an update to | |
| 779 // TabID1 with tab_node_id changing from NodeIDA to NodeIDB, and TabID2 | |
| 780 // with tab_node_id changing from NodeIDB to NodeIDA. | |
| 781 // | |
| 782 // We can also wind up here if we created this tab as an out-of-order | |
| 783 // update to the header node for this session before actually associating | |
| 784 // the tab itself, so the tab node id wasn't available at the time and | |
| 785 // is currently kInvalidTabNodeID. | |
| 786 // | |
| 787 // In both cases, we can safely throw it into the set of node ids. | |
| 788 session_tracker_.OnTabNodeSeen(session_tag, specifics.tab_node_id()); | |
| 789 sessions::SessionTab* tab = session_tracker_.GetTab(session_tag, tab_id); | |
| 790 if (!tab->timestamp.is_null() && tab->timestamp > modification_time) { | |
| 791 DVLOG(1) << "Ignoring " << session_tag << "'s session tab " << tab_id | |
| 792 << " with earlier modification time: " << tab->timestamp | |
| 793 << " vs " << modification_time; | |
| 746 return; | 794 return; |
| 747 } | 795 } |
| 748 | 796 |
| 749 sessions::SessionTab* tab = session_tracker_.GetTab( | |
| 750 foreign_session_tag, tab_id, specifics.tab_node_id()); | |
| 751 | |
| 752 // Update SessionTab based on protobuf. | 797 // Update SessionTab based on protobuf. |
| 753 tab->SetFromSyncData(tab_s, modification_time); | 798 tab->SetFromSyncData(tab_s, modification_time); |
| 754 | 799 |
| 755 // If a favicon or favicon urls are present, load the URLs and visit | 800 // If a favicon or favicon urls are present, load the URLs and visit |
| 756 // times into the in-memory favicon cache. | 801 // times into the in-memory favicon cache. |
| 757 RefreshFaviconVisitTimesFromForeignTab(tab_s, modification_time); | 802 RefreshFaviconVisitTimesFromForeignTab(tab_s, modification_time); |
| 758 | 803 |
| 759 // Update the last modified time. | 804 // Update the last modified time. |
| 760 if (foreign_session->modified_time < modification_time) | 805 if (session->modified_time < modification_time) |
| 761 foreign_session->modified_time = modification_time; | 806 session->modified_time = modification_time; |
| 762 } else { | 807 } else { |
| 763 LOG(WARNING) << "Ignoring foreign session node with missing header/tab " | 808 LOG(WARNING) << "Ignoring session node with missing header/tab " |
| 764 << "fields and tag " << foreign_session_tag << "."; | 809 << "fields and tag " << session_tag << "."; |
| 765 } | 810 } |
| 766 } | 811 } |
| 767 | 812 |
| 768 void SessionsSyncManager::InitializeCurrentMachineTag( | 813 void SessionsSyncManager::InitializeCurrentMachineTag( |
| 769 const std::string& cache_guid) { | 814 const std::string& cache_guid) { |
| 770 DCHECK(current_machine_tag_.empty()); | 815 DCHECK(current_machine_tag_.empty()); |
| 771 std::string persisted_guid; | 816 std::string persisted_guid; |
| 772 persisted_guid = sync_prefs_->GetSyncSessionsGUID(); | 817 persisted_guid = sync_prefs_->GetSyncSessionsGUID(); |
| 773 if (!persisted_guid.empty()) { | 818 if (!persisted_guid.empty()) { |
| 774 current_machine_tag_ = persisted_guid; | 819 current_machine_tag_ = persisted_guid; |
| 775 DVLOG(1) << "Restoring persisted session sync guid: " << persisted_guid; | 820 DVLOG(1) << "Restoring persisted session sync guid: " << persisted_guid; |
| 776 } else { | 821 } else { |
| 777 DCHECK(!cache_guid.empty()); | 822 DCHECK(!cache_guid.empty()); |
| 778 current_machine_tag_ = BuildMachineTag(cache_guid); | 823 current_machine_tag_ = BuildMachineTag(cache_guid); |
| 779 DVLOG(1) << "Creating session sync guid: " << current_machine_tag_; | 824 DVLOG(1) << "Creating session sync guid: " << current_machine_tag_; |
| 780 sync_prefs_->SetSyncSessionsGUID(current_machine_tag_); | 825 sync_prefs_->SetSyncSessionsGUID(current_machine_tag_); |
| 781 } | 826 } |
| 782 | |
| 783 local_tab_pool_.SetMachineTag(current_machine_tag_); | |
| 784 } | 827 } |
| 785 | 828 |
| 786 // static | 829 // static |
| 787 void SessionsSyncManager::PopulateSessionHeaderFromSpecifics( | 830 void SessionsSyncManager::PopulateSessionHeaderFromSpecifics( |
| 788 const sync_pb::SessionHeader& header_specifics, | 831 const sync_pb::SessionHeader& header_specifics, |
| 789 base::Time mtime, | 832 base::Time mtime, |
| 790 SyncedSession* session_header) { | 833 SyncedSession* session_header) { |
| 791 if (header_specifics.has_client_name()) | 834 if (header_specifics.has_client_name()) |
| 792 session_header->session_name = header_specifics.client_name(); | 835 session_header->session_name = header_specifics.client_name(); |
| 793 if (header_specifics.has_device_type()) { | 836 if (header_specifics.has_device_type()) { |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 837 if (specifics.browser_type() == | 880 if (specifics.browser_type() == |
| 838 sync_pb::SessionWindow_BrowserType_TYPE_TABBED) { | 881 sync_pb::SessionWindow_BrowserType_TYPE_TABBED) { |
| 839 session_window->type = sessions::SessionWindow::TYPE_TABBED; | 882 session_window->type = sessions::SessionWindow::TYPE_TABBED; |
| 840 } else { | 883 } else { |
| 841 // Note: custom tabs are treated like popup windows on restore, as you can | 884 // Note: custom tabs are treated like popup windows on restore, as you can |
| 842 // restore a custom tab on a platform that doesn't support them. | 885 // restore a custom tab on a platform that doesn't support them. |
| 843 session_window->type = sessions::SessionWindow::TYPE_POPUP; | 886 session_window->type = sessions::SessionWindow::TYPE_POPUP; |
| 844 } | 887 } |
| 845 } | 888 } |
| 846 session_window->timestamp = mtime; | 889 session_window->timestamp = mtime; |
| 847 session_window->tabs.resize(specifics.tab_size()); | 890 session_window->tabs.clear(); |
| 848 for (int i = 0; i < specifics.tab_size(); i++) { | 891 for (int i = 0; i < specifics.tab_size(); i++) { |
| 849 SessionID::id_type tab_id = specifics.tab(i); | 892 SessionID::id_type tab_id = specifics.tab(i); |
| 850 session_tracker_.PutTabInWindow(session_tag, session_window->window_id.id(), | 893 session_tracker_.PutTabInWindow(session_tag, session_window->window_id.id(), |
| 851 tab_id, i); | 894 tab_id); |
| 852 } | 895 } |
| 853 } | 896 } |
| 854 | 897 |
| 855 void SessionsSyncManager::RefreshFaviconVisitTimesFromForeignTab( | 898 void SessionsSyncManager::RefreshFaviconVisitTimesFromForeignTab( |
| 856 const sync_pb::SessionTab& tab, | 899 const sync_pb::SessionTab& tab, |
| 857 const base::Time& modification_time) { | 900 const base::Time& modification_time) { |
| 858 // First go through and iterate over all the navigations, checking if any | 901 // First go through and iterate over all the navigations, checking if any |
| 859 // have valid favicon urls. | 902 // have valid favicon urls. |
| 860 for (int i = 0; i < tab.navigation_size(); ++i) { | 903 for (int i = 0; i < tab.navigation_size(); ++i) { |
| 861 if (!tab.navigation(i).favicon_url().empty()) { | 904 if (!tab.navigation(i).favicon_url().empty()) { |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 883 void SessionsSyncManager::DeleteForeignSessionInternal( | 926 void SessionsSyncManager::DeleteForeignSessionInternal( |
| 884 const std::string& tag, | 927 const std::string& tag, |
| 885 syncer::SyncChangeList* change_output) { | 928 syncer::SyncChangeList* change_output) { |
| 886 if (tag == current_machine_tag()) { | 929 if (tag == current_machine_tag()) { |
| 887 LOG(ERROR) << "Attempting to delete local session. This is not currently " | 930 LOG(ERROR) << "Attempting to delete local session. This is not currently " |
| 888 << "supported."; | 931 << "supported."; |
| 889 return; | 932 return; |
| 890 } | 933 } |
| 891 | 934 |
| 892 std::set<int> tab_node_ids_to_delete; | 935 std::set<int> tab_node_ids_to_delete; |
| 893 session_tracker_.LookupTabNodeIds(tag, &tab_node_ids_to_delete); | 936 session_tracker_.LookupForeignTabNodeIds(tag, &tab_node_ids_to_delete); |
| 894 if (DisassociateForeignSession(tag)) { | 937 if (DisassociateForeignSession(tag)) { |
| 895 // Only tell sync to delete the header if there was one. | 938 // Only tell sync to delete the header if there was one. |
| 896 change_output->push_back( | 939 change_output->push_back( |
| 897 syncer::SyncChange(FROM_HERE, SyncChange::ACTION_DELETE, | 940 syncer::SyncChange(FROM_HERE, SyncChange::ACTION_DELETE, |
| 898 SyncData::CreateLocalDelete(tag, syncer::SESSIONS))); | 941 SyncData::CreateLocalDelete(tag, syncer::SESSIONS))); |
| 899 } | 942 } |
| 900 for (std::set<int>::const_iterator it = tab_node_ids_to_delete.begin(); | 943 AppendDeletionsForTabNodes(tab_node_ids_to_delete, tag, change_output); |
| 901 it != tab_node_ids_to_delete.end(); ++it) { | |
| 902 change_output->push_back(syncer::SyncChange( | |
| 903 FROM_HERE, SyncChange::ACTION_DELETE, | |
| 904 SyncData::CreateLocalDelete(TabNodePool::TabIdToTag(tag, *it), | |
| 905 syncer::SESSIONS))); | |
| 906 } | |
| 907 if (!sessions_updated_callback_.is_null()) | 944 if (!sessions_updated_callback_.is_null()) |
| 908 sessions_updated_callback_.Run(); | 945 sessions_updated_callback_.Run(); |
| 909 } | 946 } |
| 910 | 947 |
| 911 bool SessionsSyncManager::DisassociateForeignSession( | 948 bool SessionsSyncManager::DisassociateForeignSession( |
| 912 const std::string& foreign_session_tag) { | 949 const std::string& foreign_session_tag) { |
| 913 DCHECK_NE(foreign_session_tag, current_machine_tag()); | 950 DCHECK_NE(foreign_session_tag, current_machine_tag()); |
| 914 DVLOG(1) << "Disassociating session " << foreign_session_tag; | 951 DVLOG(1) << "Disassociating session " << foreign_session_tag; |
| 915 return session_tracker_.DeleteSession(foreign_session_tag); | 952 return session_tracker_.DeleteForeignSession(foreign_session_tag); |
| 916 } | 953 } |
| 917 | 954 |
| 918 bool SessionsSyncManager::GetForeignSession( | 955 bool SessionsSyncManager::GetForeignSession( |
| 919 const std::string& tag, | 956 const std::string& tag, |
| 920 std::vector<const sessions::SessionWindow*>* windows) { | 957 std::vector<const sessions::SessionWindow*>* windows) { |
| 921 return session_tracker_.LookupSessionWindows(tag, windows); | 958 return session_tracker_.LookupSessionWindows(tag, windows); |
| 922 } | 959 } |
| 923 | 960 |
| 924 bool SessionsSyncManager::GetForeignSessionTabs( | 961 bool SessionsSyncManager::GetForeignSessionTabs( |
| 925 const std::string& tag, | 962 const std::string& tag, |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 951 bool SessionsSyncManager::GetForeignTab(const std::string& tag, | 988 bool SessionsSyncManager::GetForeignTab(const std::string& tag, |
| 952 const SessionID::id_type tab_id, | 989 const SessionID::id_type tab_id, |
| 953 const sessions::SessionTab** tab) { | 990 const sessions::SessionTab** tab) { |
| 954 const sessions::SessionTab* synced_tab = nullptr; | 991 const sessions::SessionTab* synced_tab = nullptr; |
| 955 bool success = session_tracker_.LookupSessionTab(tag, tab_id, &synced_tab); | 992 bool success = session_tracker_.LookupSessionTab(tag, tab_id, &synced_tab); |
| 956 if (success) | 993 if (success) |
| 957 *tab = synced_tab; | 994 *tab = synced_tab; |
| 958 return success; | 995 return success; |
| 959 } | 996 } |
| 960 | 997 |
| 961 void SessionsSyncManager::LocalTabDelegateToSpecifics( | |
| 962 const SyncedTabDelegate& tab_delegate, | |
| 963 sync_pb::SessionSpecifics* specifics) { | |
| 964 sessions::SessionTab* session_tab = nullptr; | |
| 965 session_tab = session_tracker_.GetTab(current_machine_tag(), | |
| 966 tab_delegate.GetSessionId(), | |
| 967 tab_delegate.GetSyncId()); | |
| 968 SetSessionTabFromDelegate(tab_delegate, base::Time::Now(), session_tab); | |
| 969 SetVariationIds(session_tab); | |
| 970 sync_pb::SessionTab tab_s = session_tab->ToSyncData(); | |
| 971 specifics->set_session_tag(current_machine_tag_); | |
| 972 specifics->set_tab_node_id(tab_delegate.GetSyncId()); | |
| 973 specifics->mutable_tab()->CopyFrom(tab_s); | |
| 974 } | |
| 975 | |
| 976 void SessionsSyncManager::AssociateRestoredPlaceholderTab( | 998 void SessionsSyncManager::AssociateRestoredPlaceholderTab( |
| 977 const SyncedTabDelegate& tab_delegate, | 999 const SyncedTabDelegate& tab_delegate, |
| 978 SessionID::id_type new_tab_id, | 1000 SessionID::id_type new_tab_id, |
| 979 SessionID::id_type new_window_id, | 1001 SessionID::id_type new_window_id, |
| 980 const syncer::SyncDataList& restored_tabs, | |
| 981 syncer::SyncChangeList* change_output) { | 1002 syncer::SyncChangeList* change_output) { |
| 982 DCHECK_NE(tab_delegate.GetSyncId(), TabNodePool::kInvalidTabNodeID); | 1003 DCHECK_NE(tab_delegate.GetSyncId(), TabNodePool::kInvalidTabNodeID); |
| 983 // Rewrite the tab using |restored_tabs| to retrieve the specifics. | 1004 |
| 984 if (restored_tabs.empty()) { | 1005 // It's possible the placeholder tab is associated with a tab node that's |
| 985 DLOG(WARNING) << "Can't Update tab ID."; | 1006 // since been deleted. If that's the case, there's no way to reassociate it, |
| 1007 // so just return now without adding the tab to the session tracker. | |
| 1008 if (!session_tracker_.IsLocalTabNodeAssociated(tab_delegate.GetSyncId())) { | |
| 1009 DVLOG(1) << "Restored placeholder tab's node " << tab_delegate.GetSyncId() | |
| 1010 << " deleted."; | |
| 986 return; | 1011 return; |
| 987 } | 1012 } |
| 988 | 1013 |
| 989 for (syncer::SyncDataList::const_iterator it = restored_tabs.begin(); | 1014 // Update tracker with the new association (and inform it of the tab node |
| 990 it != restored_tabs.end(); ++it) { | 1015 // in the process). |
| 991 if (it->GetSpecifics().session().tab_node_id() != | 1016 session_tracker_.ReassociateLocalTab(tab_delegate.GetSyncId(), new_tab_id); |
| 992 tab_delegate.GetSyncId()) { | |
| 993 continue; | |
| 994 } | |
| 995 | 1017 |
| 996 sync_pb::EntitySpecifics entity; | 1018 // Update the window id on the SessionTab itself. |
| 997 sync_pb::SessionSpecifics* specifics = entity.mutable_session(); | 1019 sessions::SessionTab* local_tab = |
| 998 specifics->CopyFrom(it->GetSpecifics().session()); | 1020 session_tracker_.GetTab(current_machine_tag(), new_tab_id); |
| 999 DCHECK(specifics->has_tab()); | 1021 local_tab->window_id.set_id(new_window_id); |
| 1000 | 1022 |
| 1001 // Update tab node pool with the new association. | 1023 // Rewrite the specifics based on the reassociated SessionTab to preserve |
| 1002 local_tab_pool_.ReassociateTabNode(tab_delegate.GetSyncId(), new_tab_id); | 1024 // the new tab and window ids. |
| 1003 TabLink* tab_link = new TabLink(tab_delegate.GetSyncId(), &tab_delegate); | 1025 sync_pb::EntitySpecifics entity; |
| 1004 local_tab_map_[new_tab_id] = make_linked_ptr<TabLink>(tab_link); | 1026 entity.mutable_session()->CopyFrom(SessionTabToSpecifics( |
| 1005 | 1027 *local_tab, current_machine_tag(), tab_delegate.GetSyncId())); |
| 1006 if (specifics->tab().tab_id() == new_tab_id && | 1028 syncer::SyncData data = syncer::SyncData::CreateLocalData( |
| 1007 specifics->tab().window_id() == new_window_id) | 1029 TabNodeIdToTag(current_machine_tag(), tab_delegate.GetSyncId()), |
| 1008 return; | 1030 current_session_name_, entity); |
| 1009 | 1031 change_output->push_back( |
| 1010 // Either the tab_id or window_id changed (e.g due to session restore), so | 1032 syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_UPDATE, data)); |
| 1011 // update the sync node. | |
| 1012 specifics->mutable_tab()->set_tab_id(new_tab_id); | |
| 1013 specifics->mutable_tab()->set_window_id(new_window_id); | |
| 1014 syncer::SyncData data = syncer::SyncData::CreateLocalData( | |
| 1015 TabNodePool::TabIdToTag(current_machine_tag_, specifics->tab_node_id()), | |
| 1016 current_session_name_, entity); | |
| 1017 change_output->push_back( | |
| 1018 syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_UPDATE, data)); | |
| 1019 return; | |
| 1020 } | |
| 1021 } | 1033 } |
| 1022 | 1034 |
| 1023 // static | 1035 // static |
| 1024 void SessionsSyncManager::SetSessionTabFromDelegate( | 1036 void SessionsSyncManager::SetSessionTabFromDelegate( |
| 1025 const SyncedTabDelegate& tab_delegate, | 1037 const SyncedTabDelegate& tab_delegate, |
| 1026 base::Time mtime, | 1038 base::Time mtime, |
| 1027 sessions::SessionTab* session_tab) { | 1039 sessions::SessionTab* session_tab) { |
| 1028 DCHECK(session_tab); | 1040 DCHECK(session_tab); |
| 1029 session_tab->window_id.set_id(tab_delegate.GetWindowId()); | 1041 session_tab->window_id.set_id(tab_delegate.GetWindowId()); |
| 1030 session_tab->tab_id.set_id(tab_delegate.GetSessionId()); | 1042 session_tab->tab_id.set_id(tab_delegate.GetSessionId()); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1129 } | 1141 } |
| 1130 | 1142 |
| 1131 // static | 1143 // static |
| 1132 std::string SessionsSyncManager::TagHashFromSpecifics( | 1144 std::string SessionsSyncManager::TagHashFromSpecifics( |
| 1133 const sync_pb::SessionSpecifics& specifics) { | 1145 const sync_pb::SessionSpecifics& specifics) { |
| 1134 return syncer::GenerateSyncableHash(syncer::SESSIONS, | 1146 return syncer::GenerateSyncableHash(syncer::SESSIONS, |
| 1135 TagFromSpecifics(specifics)); | 1147 TagFromSpecifics(specifics)); |
| 1136 } | 1148 } |
| 1137 | 1149 |
| 1138 }; // namespace sync_sessions | 1150 }; // namespace sync_sessions |
| OLD | NEW |