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) { | |
|
skym
2016/12/03 01:20:46
Is duplicating in anonymous namespaces between .cc
Nicolas Zea
2016/12/06 01:32:55
Given it's just a one-liner with no real logic, it
| |
| 70 return base::StringPrintf("%s %d", machine_tag.c_str(), tab_node_id); | |
| 71 } | |
| 72 | |
| 65 std::string TagFromSpecifics(const sync_pb::SessionSpecifics& specifics) { | 73 std::string TagFromSpecifics(const sync_pb::SessionSpecifics& specifics) { |
| 66 if (specifics.has_header()) { | 74 if (specifics.has_header()) { |
| 67 return specifics.session_tag(); | 75 return specifics.session_tag(); |
| 68 } else if (specifics.has_tab()) { | 76 } else if (specifics.has_tab()) { |
| 69 return TabNodePool::TabIdToTag(specifics.session_tag(), | 77 return TabNodeIdToTag(specifics.session_tag(), specifics.tab_node_id()); |
| 70 specifics.tab_node_id()); | |
| 71 } else { | 78 } else { |
| 72 return std::string(); | 79 return std::string(); |
| 73 } | 80 } |
| 74 } | 81 } |
| 75 | 82 |
| 83 sync_pb::SessionSpecifics SessionTabToSpecifics( | |
| 84 const sessions::SessionTab& session_tab, | |
| 85 const std::string& local_tag, | |
| 86 int tab_node_id) { | |
| 87 sync_pb::SessionSpecifics specifics; | |
| 88 specifics.mutable_tab()->CopyFrom(session_tab.ToSyncData()); | |
| 89 specifics.set_session_tag(local_tag); | |
| 90 specifics.set_tab_node_id(tab_node_id); | |
| 91 return specifics; | |
| 92 } | |
| 93 | |
| 76 } // namespace | 94 } // namespace |
| 77 | 95 |
| 78 // |local_device| is owned by ProfileSyncService, its lifetime exceeds | 96 // |local_device| is owned by ProfileSyncService, its lifetime exceeds |
| 79 // lifetime of SessionSyncManager. | 97 // lifetime of SessionSyncManager. |
| 80 SessionsSyncManager::SessionsSyncManager( | 98 SessionsSyncManager::SessionsSyncManager( |
| 81 sync_sessions::SyncSessionsClient* sessions_client, | 99 sync_sessions::SyncSessionsClient* sessions_client, |
| 82 syncer::SyncPrefs* sync_prefs, | 100 syncer::SyncPrefs* sync_prefs, |
| 83 LocalDeviceInfoProvider* local_device, | 101 LocalDeviceInfoProvider* local_device, |
| 84 std::unique_ptr<LocalSessionEventRouter> router, | 102 std::unique_ptr<LocalSessionEventRouter> router, |
| 85 const base::Closure& sessions_updated_callback, | 103 const base::Closure& sessions_updated_callback, |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 109 return machine_tag; | 127 return machine_tag; |
| 110 } | 128 } |
| 111 | 129 |
| 112 syncer::SyncMergeResult SessionsSyncManager::MergeDataAndStartSyncing( | 130 syncer::SyncMergeResult SessionsSyncManager::MergeDataAndStartSyncing( |
| 113 syncer::ModelType type, | 131 syncer::ModelType type, |
| 114 const syncer::SyncDataList& initial_sync_data, | 132 const syncer::SyncDataList& initial_sync_data, |
| 115 std::unique_ptr<syncer::SyncChangeProcessor> sync_processor, | 133 std::unique_ptr<syncer::SyncChangeProcessor> sync_processor, |
| 116 std::unique_ptr<syncer::SyncErrorFactory> error_handler) { | 134 std::unique_ptr<syncer::SyncErrorFactory> error_handler) { |
| 117 syncer::SyncMergeResult merge_result(type); | 135 syncer::SyncMergeResult merge_result(type); |
| 118 DCHECK(session_tracker_.Empty()); | 136 DCHECK(session_tracker_.Empty()); |
| 119 DCHECK_EQ(0U, local_tab_pool_.Capacity()); | |
| 120 | 137 |
| 121 error_handler_ = std::move(error_handler); | 138 error_handler_ = std::move(error_handler); |
| 122 sync_processor_ = std::move(sync_processor); | 139 sync_processor_ = std::move(sync_processor); |
| 123 | 140 |
| 124 // It's possible(via RebuildAssociations) for lost_navigations_recorder_ to | 141 // It's possible(via RebuildAssociations) for lost_navigations_recorder_ to |
| 125 // persist between sync being stopped and started. If it did persist, it's | 142 // persist between sync being stopped and started. If it did persist, it's |
| 126 // already associated with |sync_processor|, so leave it alone. | 143 // already associated with |sync_processor|, so leave it alone. |
| 127 if (!lost_navigations_recorder_.get()) { | 144 if (!lost_navigations_recorder_.get()) { |
| 128 lost_navigations_recorder_ = | 145 lost_navigations_recorder_ = |
| 129 base::MakeUnique<sync_sessions::LostNavigationsRecorder>(); | 146 base::MakeUnique<sync_sessions::LostNavigationsRecorder>(); |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 144 DCHECK(local_device_); | 161 DCHECK(local_device_); |
| 145 const DeviceInfo* local_device_info = local_device_->GetLocalDeviceInfo(); | 162 const DeviceInfo* local_device_info = local_device_->GetLocalDeviceInfo(); |
| 146 if (local_device_info) { | 163 if (local_device_info) { |
| 147 current_session_name_ = local_device_info->client_name(); | 164 current_session_name_ = local_device_info->client_name(); |
| 148 } else { | 165 } else { |
| 149 merge_result.set_error(error_handler_->CreateAndUploadError( | 166 merge_result.set_error(error_handler_->CreateAndUploadError( |
| 150 FROM_HERE, "Failed to get local device info.")); | 167 FROM_HERE, "Failed to get local device info.")); |
| 151 return merge_result; | 168 return merge_result; |
| 152 } | 169 } |
| 153 | 170 |
| 154 session_tracker_.SetLocalSessionTag(current_machine_tag_); | 171 session_tracker_.SetLocalSessionTag(current_machine_tag()); |
| 155 | 172 |
| 156 syncer::SyncChangeList new_changes; | 173 syncer::SyncChangeList new_changes; |
| 157 | 174 |
| 158 // First, we iterate over sync data to update our session_tracker_. | 175 // First, we iterate over sync data to update our session_tracker_. |
| 159 syncer::SyncDataList restored_tabs; | 176 if (!InitFromSyncModel(initial_sync_data, &new_changes)) { |
| 160 if (!InitFromSyncModel(initial_sync_data, &restored_tabs, &new_changes)) { | |
| 161 // The sync db didn't have a header node for us. Create one. | 177 // The sync db didn't have a header node for us. Create one. |
| 162 sync_pb::EntitySpecifics specifics; | 178 sync_pb::EntitySpecifics specifics; |
| 163 sync_pb::SessionSpecifics* base_specifics = specifics.mutable_session(); | 179 sync_pb::SessionSpecifics* base_specifics = specifics.mutable_session(); |
| 164 base_specifics->set_session_tag(current_machine_tag()); | 180 base_specifics->set_session_tag(current_machine_tag()); |
| 165 sync_pb::SessionHeader* header_s = base_specifics->mutable_header(); | 181 sync_pb::SessionHeader* header_s = base_specifics->mutable_header(); |
| 166 header_s->set_client_name(current_session_name_); | 182 header_s->set_client_name(current_session_name_); |
| 167 header_s->set_device_type(local_device_info->device_type()); | 183 header_s->set_device_type(local_device_info->device_type()); |
| 168 syncer::SyncData data = syncer::SyncData::CreateLocalData( | 184 syncer::SyncData data = syncer::SyncData::CreateLocalData( |
| 169 current_machine_tag(), current_session_name_, specifics); | 185 current_machine_tag(), current_session_name_, specifics); |
| 170 new_changes.push_back( | 186 new_changes.push_back( |
| 171 syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_ADD, data)); | 187 syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_ADD, data)); |
| 172 } | 188 } |
| 173 | 189 |
| 174 #if defined(OS_ANDROID) | 190 #if defined(OS_ANDROID) |
| 175 std::string sync_machine_tag( | 191 std::string sync_machine_tag( |
| 176 BuildMachineTag(local_device_->GetLocalSyncCacheGUID())); | 192 BuildMachineTag(local_device_->GetLocalSyncCacheGUID())); |
| 177 if (current_machine_tag_.compare(sync_machine_tag) != 0) | 193 if (current_machine_tag().compare(sync_machine_tag) != 0) |
| 178 DeleteForeignSessionInternal(sync_machine_tag, &new_changes); | 194 DeleteForeignSessionInternal(sync_machine_tag, &new_changes); |
| 179 #endif | 195 #endif |
| 180 | 196 |
| 181 // Check if anything has changed on the local client side. | 197 // Check if anything has changed on the local client side. |
| 182 AssociateWindows(RELOAD_TABS, restored_tabs, &new_changes); | 198 AssociateWindows(RELOAD_TABS, &new_changes); |
| 183 local_tab_pool_out_of_sync_ = false; | 199 local_tab_pool_out_of_sync_ = false; |
| 184 | 200 |
| 185 merge_result.set_error( | 201 merge_result.set_error( |
| 186 sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes)); | 202 sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes)); |
| 187 | 203 |
| 188 local_event_router_->StartRoutingTo(this); | 204 local_event_router_->StartRoutingTo(this); |
| 189 return merge_result; | 205 return merge_result; |
| 190 } | 206 } |
| 191 | 207 |
| 192 void SessionsSyncManager::AssociateWindows( | 208 void SessionsSyncManager::AssociateWindows( |
| 193 ReloadTabsOption option, | 209 ReloadTabsOption option, |
| 194 const syncer::SyncDataList& restored_tabs, | |
| 195 syncer::SyncChangeList* change_output) { | 210 syncer::SyncChangeList* change_output) { |
| 196 const std::string local_tag = current_machine_tag(); | 211 const std::string local_tag = current_machine_tag(); |
| 197 sync_pb::SessionSpecifics specifics; | 212 sync_pb::SessionSpecifics specifics; |
| 198 specifics.set_session_tag(local_tag); | 213 specifics.set_session_tag(local_tag); |
| 199 sync_pb::SessionHeader* header_s = specifics.mutable_header(); | 214 sync_pb::SessionHeader* header_s = specifics.mutable_header(); |
| 200 SyncedSession* current_session = session_tracker_.GetSession(local_tag); | 215 SyncedSession* current_session = session_tracker_.GetSession(local_tag); |
| 201 current_session->modified_time = base::Time::Now(); | 216 current_session->modified_time = base::Time::Now(); |
| 202 header_s->set_client_name(current_session_name_); | 217 header_s->set_client_name(current_session_name_); |
| 203 // SessionDataTypeController ensures that the local device info | 218 // SessionDataTypeController ensures that the local device info |
| 204 // is available before activating this datatype. | 219 // is available before activating this datatype. |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 266 | 281 |
| 267 if (synced_tab->IsPlaceholderTab()) { | 282 if (synced_tab->IsPlaceholderTab()) { |
| 268 // For tabs without WebContents update the |tab_id| and |window_id|, | 283 // For tabs without WebContents update the |tab_id| and |window_id|, |
| 269 // as it could have changed after a session restore. | 284 // as it could have changed after a session restore. |
| 270 // Note: We cannot check if a tab is valid if it has no WebContents. | 285 // Note: We cannot check if a tab is valid if it has no WebContents. |
| 271 // We assume any such tab is valid and leave the contents of | 286 // We assume any such tab is valid and leave the contents of |
| 272 // corresponding sync node unchanged. | 287 // corresponding sync node unchanged. |
| 273 if (synced_tab->GetSyncId() > TabNodePool::kInvalidTabNodeID && | 288 if (synced_tab->GetSyncId() > TabNodePool::kInvalidTabNodeID && |
| 274 tab_id > TabNodePool::kInvalidTabID) { | 289 tab_id > TabNodePool::kInvalidTabID) { |
| 275 AssociateRestoredPlaceholderTab(*synced_tab, tab_id, window_id, | 290 AssociateRestoredPlaceholderTab(*synced_tab, tab_id, window_id, |
| 276 restored_tabs, change_output); | 291 change_output); |
| 277 found_tabs = true; | 292 found_tabs = true; |
| 278 window_s.add_tab(tab_id); | 293 window_s.add_tab(tab_id); |
| 279 } | 294 } |
| 280 continue; | 295 continue; |
| 281 } | 296 } |
| 282 | 297 |
| 283 if (RELOAD_TABS == option) | 298 if (RELOAD_TABS == option) |
| 284 AssociateTab(synced_tab, change_output); | 299 AssociateTab(synced_tab, change_output); |
| 285 | 300 |
| 286 // If the tab is valid, it would have been added to the tracker either | 301 // If the tab is valid, it would have been added to the tracker either |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 299 *header_window = window_s; | 314 *header_window = window_s; |
| 300 | 315 |
| 301 // Update this window's representation in the synced session tracker. | 316 // Update this window's representation in the synced session tracker. |
| 302 session_tracker_.PutWindowInSession(local_tag, window_id); | 317 session_tracker_.PutWindowInSession(local_tag, window_id); |
| 303 BuildSyncedSessionFromSpecifics( | 318 BuildSyncedSessionFromSpecifics( |
| 304 local_tag, window_s, current_session->modified_time, | 319 local_tag, window_s, current_session->modified_time, |
| 305 current_session->windows[window_id].get()); | 320 current_session->windows[window_id].get()); |
| 306 } | 321 } |
| 307 } | 322 } |
| 308 } | 323 } |
| 309 local_tab_pool_.DeleteUnassociatedTabNodes(change_output); | 324 std::set<int> deleted_tab_node_ids; |
| 310 session_tracker_.CleanupSession(local_tag); | 325 session_tracker_.CleanupLocalTabs(&deleted_tab_node_ids); |
| 326 for (int tab_node_id : deleted_tab_node_ids) { | |
| 327 std::string tab_node_tag = | |
| 328 TabNodeIdToTag(current_machine_tag(), tab_node_id); | |
| 329 change_output->push_back(syncer::SyncChange( | |
| 330 FROM_HERE, syncer::SyncChange::ACTION_DELETE, | |
| 331 syncer::SyncData::CreateLocalDelete(tab_node_tag, syncer::SESSIONS))); | |
| 332 } | |
| 311 | 333 |
| 312 // Always update the header. Sync takes care of dropping this update | 334 // Always update the header. Sync takes care of dropping this update |
| 313 // if the entity specifics are identical (i.e windows, client name did | 335 // if the entity specifics are identical (i.e windows, client name did |
| 314 // not change). | 336 // not change). |
| 315 sync_pb::EntitySpecifics entity; | 337 sync_pb::EntitySpecifics entity; |
| 316 entity.mutable_session()->CopyFrom(specifics); | 338 entity.mutable_session()->CopyFrom(specifics); |
| 317 syncer::SyncData data = syncer::SyncData::CreateLocalData( | 339 syncer::SyncData data = syncer::SyncData::CreateLocalData( |
| 318 current_machine_tag(), current_session_name_, entity); | 340 current_machine_tag(), current_session_name_, entity); |
| 319 change_output->push_back( | 341 change_output->push_back( |
| 320 syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_UPDATE, data)); | 342 syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_UPDATE, data)); |
| 321 } | 343 } |
| 322 | 344 |
| 323 void SessionsSyncManager::AssociateTab(SyncedTabDelegate* const tab, | 345 void SessionsSyncManager::AssociateTab(SyncedTabDelegate* const tab_delegate, |
| 324 syncer::SyncChangeList* change_output) { | 346 syncer::SyncChangeList* change_output) { |
| 325 DCHECK(!tab->IsPlaceholderTab()); | 347 DCHECK(!tab_delegate->IsPlaceholderTab()); |
| 326 SessionID::id_type tab_id = tab->GetSessionId(); | |
| 327 | 348 |
| 328 if (tab->IsBeingDestroyed()) { | 349 if (tab_delegate->IsBeingDestroyed()) { |
| 329 // This tab is closing. | 350 // Do nothing. By not proactively adding the tab to the session, it will be |
| 330 TabLinksMap::iterator tab_iter = local_tab_map_.find(tab_id); | 351 // removed if necessary during subsequent cleanup. |
| 331 if (tab_iter == local_tab_map_.end()) { | |
| 332 // We aren't tracking this tab (for example, sync setting page). | |
| 333 return; | |
| 334 } | |
| 335 local_tab_pool_.FreeTabNode(tab_iter->second->tab_node_id(), change_output); | |
| 336 local_tab_map_.erase(tab_iter); | |
| 337 return; | 352 return; |
| 338 } | 353 } |
| 339 | 354 |
| 340 if (!tab->ShouldSync(sessions_client_)) | 355 if (!tab_delegate->ShouldSync(sessions_client_)) |
| 341 return; | 356 return; |
| 342 | 357 |
| 343 TabLinksMap::iterator local_tab_map_iter = local_tab_map_.find(tab_id); | 358 SessionID::id_type tab_id = tab_delegate->GetSessionId(); |
| 344 TabLink* tab_link = nullptr; | 359 DVLOG(1) << "Reloading tab " << tab_id << " from window " |
| 360 << tab_delegate->GetWindowId(); | |
| 345 | 361 |
| 346 if (local_tab_map_iter == local_tab_map_.end()) { | 362 int tab_node_id = TabNodePool::kInvalidTabNodeID; |
| 347 int tab_node_id = tab->GetSyncId(); | 363 bool existing_tab_node = |
| 348 // If there is an old sync node for the tab, reuse it. If this is a new | 364 session_tracker_.GetTabNodeForLocalTab(tab_id, &tab_node_id); |
| 349 // tab, get a sync node for it. | 365 DCHECK_NE(TabNodePool::kInvalidTabNodeID, tab_node_id); |
| 350 if (!local_tab_pool_.IsUnassociatedTabNode(tab_node_id)) { | 366 sessions::SessionTab* session_tab = |
| 351 tab_node_id = local_tab_pool_.GetFreeTabNode(change_output); | 367 session_tracker_.GetTab(current_machine_tag(), tab_id); |
| 352 tab->SetSyncId(tab_node_id); | |
| 353 } | |
| 354 local_tab_pool_.AssociateTabNode(tab_node_id, tab_id); | |
| 355 tab_link = new TabLink(tab_node_id, tab); | |
| 356 local_tab_map_[tab_id] = make_linked_ptr<TabLink>(tab_link); | |
| 357 } else { | |
| 358 // This tab is already associated with a sync node, reuse it. | |
| 359 // Note: on some platforms the tab object may have changed, so we ensure | |
| 360 // the tab link is up to date. | |
| 361 tab_link = local_tab_map_iter->second.get(); | |
| 362 local_tab_map_iter->second->set_tab(tab); | |
| 363 } | |
| 364 DCHECK(tab_link); | |
| 365 DCHECK_NE(tab_link->tab_node_id(), TabNodePool::kInvalidTabNodeID); | |
| 366 DVLOG(1) << "Reloading tab " << tab_id << " from window " | |
| 367 << tab->GetWindowId(); | |
| 368 | 368 |
| 369 // Write to sync model. | 369 // Get the previously synced url. |
| 370 sync_pb::EntitySpecifics specifics; | 370 int old_index = session_tab->normalized_navigation_index(); |
| 371 LocalTabDelegateToSpecifics(*tab, specifics.mutable_session()); | 371 GURL old_url; |
| 372 syncer::SyncData data = syncer::SyncData::CreateLocalData( | 372 if (session_tab->navigations.size() > static_cast<size_t>(old_index)) |
| 373 TabNodePool::TabIdToTag(current_machine_tag_, tab_link->tab_node_id()), | 373 old_url = session_tab->navigations[old_index].virtual_url(); |
| 374 current_session_name_, specifics); | |
| 375 change_output->push_back( | |
| 376 syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_UPDATE, data)); | |
| 377 | 374 |
| 378 int current_index = tab->GetCurrentEntryIndex(); | 375 // Update the tracker's session representation. |
| 379 const GURL new_url = tab->GetVirtualURLAtIndex(current_index); | 376 SetSessionTabFromDelegate(*tab_delegate, base::Time::Now(), session_tab); |
| 380 if (new_url != tab_link->url()) { | 377 SetVariationIds(session_tab); |
| 381 tab_link->set_url(new_url); | |
| 382 favicon_cache_.OnFaviconVisited(new_url, | |
| 383 tab->GetFaviconURLAtIndex(current_index)); | |
| 384 page_revisit_broadcaster_.OnPageVisit( | |
| 385 new_url, tab->GetTransitionAtIndex(current_index)); | |
| 386 } | |
| 387 | |
| 388 session_tracker_.GetSession(current_machine_tag())->modified_time = | 378 session_tracker_.GetSession(current_machine_tag())->modified_time = |
| 389 base::Time::Now(); | 379 base::Time::Now(); |
| 380 | |
| 381 // Write to the sync model itself. | |
| 382 sync_pb::EntitySpecifics specifics; | |
| 383 specifics.mutable_session()->CopyFrom( | |
| 384 SessionTabToSpecifics(*session_tab, current_machine_tag(), tab_node_id)); | |
| 385 syncer::SyncData data = syncer::SyncData::CreateLocalData( | |
| 386 TabNodeIdToTag(current_machine_tag(), tab_node_id), current_session_name_, | |
| 387 specifics); | |
| 388 change_output->push_back(syncer::SyncChange( | |
| 389 FROM_HERE, existing_tab_node ? syncer::SyncChange::ACTION_UPDATE | |
| 390 : syncer::SyncChange::ACTION_ADD, | |
| 391 data)); | |
| 392 | |
| 393 int current_index = tab_delegate->GetCurrentEntryIndex(); | |
| 394 const GURL new_url = tab_delegate->GetVirtualURLAtIndex(current_index); | |
| 395 if (new_url != old_url) { | |
| 396 favicon_cache_.OnFaviconVisited( | |
| 397 new_url, tab_delegate->GetFaviconURLAtIndex(current_index)); | |
| 398 page_revisit_broadcaster_.OnPageVisit( | |
| 399 new_url, tab_delegate->GetTransitionAtIndex(current_index)); | |
| 400 } | |
| 390 } | 401 } |
| 391 | 402 |
| 392 void SessionsSyncManager::RebuildAssociations() { | 403 void SessionsSyncManager::RebuildAssociations() { |
| 393 syncer::SyncDataList data(sync_processor_->GetAllSyncData(syncer::SESSIONS)); | 404 syncer::SyncDataList data(sync_processor_->GetAllSyncData(syncer::SESSIONS)); |
| 394 std::unique_ptr<syncer::SyncErrorFactory> error_handler( | 405 std::unique_ptr<syncer::SyncErrorFactory> error_handler( |
| 395 std::move(error_handler_)); | 406 std::move(error_handler_)); |
| 396 std::unique_ptr<syncer::SyncChangeProcessor> processor( | 407 std::unique_ptr<syncer::SyncChangeProcessor> processor( |
| 397 std::move(sync_processor_)); | 408 std::move(sync_processor_)); |
| 398 | 409 |
| 399 StopSyncing(syncer::SESSIONS); | 410 StopSyncing(syncer::SESSIONS); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 438 DCHECK(!local_tab_pool_out_of_sync_); | 449 DCHECK(!local_tab_pool_out_of_sync_); |
| 439 return; | 450 return; |
| 440 } | 451 } |
| 441 | 452 |
| 442 syncer::SyncChangeList changes; | 453 syncer::SyncChangeList changes; |
| 443 AssociateTab(modified_tab, &changes); | 454 AssociateTab(modified_tab, &changes); |
| 444 // Note, we always associate windows because it's possible a tab became | 455 // Note, we always associate windows because it's possible a tab became |
| 445 // "interesting" by going to a valid URL, in which case it needs to be added | 456 // "interesting" by going to a valid URL, in which case it needs to be added |
| 446 // to the window's tab information. Similarly, if a tab became | 457 // to the window's tab information. Similarly, if a tab became |
| 447 // "uninteresting", we remove it from the window's tab information. | 458 // "uninteresting", we remove it from the window's tab information. |
| 448 AssociateWindows(DONT_RELOAD_TABS, syncer::SyncDataList(), &changes); | 459 AssociateWindows(DONT_RELOAD_TABS, &changes); |
| 449 sync_processor_->ProcessSyncChanges(FROM_HERE, changes); | 460 sync_processor_->ProcessSyncChanges(FROM_HERE, changes); |
| 450 } | 461 } |
| 451 | 462 |
| 452 void SessionsSyncManager::OnFaviconsChanged(const std::set<GURL>& page_urls, | 463 void SessionsSyncManager::OnFaviconsChanged(const std::set<GURL>& page_urls, |
| 453 const GURL& /* icon_url */) { | 464 const GURL& /* icon_url */) { |
| 454 // TODO(zea): consider a separate container for tabs with outstanding favicon | 465 for (const GURL& page_url : page_urls) |
| 455 // loads so we don't have to iterate through all tabs comparing urls. | 466 favicon_cache_.OnPageFaviconUpdated(page_url); |
| 456 for (const GURL& page_url : page_urls) { | |
| 457 for (TabLinksMap::iterator tab_iter = local_tab_map_.begin(); | |
| 458 tab_iter != local_tab_map_.end(); ++tab_iter) { | |
| 459 if (tab_iter->second->url() == page_url) | |
| 460 favicon_cache_.OnPageFaviconUpdated(page_url); | |
| 461 } | |
| 462 } | |
| 463 } | 467 } |
| 464 | 468 |
| 465 void SessionsSyncManager::StopSyncing(syncer::ModelType type) { | 469 void SessionsSyncManager::StopSyncing(syncer::ModelType type) { |
| 466 local_event_router_->Stop(); | 470 local_event_router_->Stop(); |
| 467 if (sync_processor_.get() && lost_navigations_recorder_.get()) { | 471 if (sync_processor_.get() && lost_navigations_recorder_.get()) { |
| 468 sync_processor_->RemoveLocalChangeObserver( | 472 sync_processor_->RemoveLocalChangeObserver( |
| 469 lost_navigations_recorder_.get()); | 473 lost_navigations_recorder_.get()); |
| 470 lost_navigations_recorder_.reset(); | 474 lost_navigations_recorder_.reset(); |
| 471 } | 475 } |
| 472 sync_processor_.reset(nullptr); | 476 sync_processor_.reset(nullptr); |
| 473 error_handler_.reset(); | 477 error_handler_.reset(); |
| 474 session_tracker_.Clear(); | 478 session_tracker_.Clear(); |
| 475 local_tab_map_.clear(); | |
| 476 local_tab_pool_.Clear(); | |
| 477 current_machine_tag_.clear(); | 479 current_machine_tag_.clear(); |
| 478 current_session_name_.clear(); | 480 current_session_name_.clear(); |
| 479 local_session_header_node_id_ = TabNodePool::kInvalidTabNodeID; | 481 local_session_header_node_id_ = TabNodePool::kInvalidTabNodeID; |
| 480 } | 482 } |
| 481 | 483 |
| 482 syncer::SyncDataList SessionsSyncManager::GetAllSyncData( | 484 syncer::SyncDataList SessionsSyncManager::GetAllSyncData( |
| 483 syncer::ModelType type) const { | 485 syncer::ModelType type) const { |
| 484 syncer::SyncDataList list; | 486 syncer::SyncDataList list; |
| 485 const SyncedSession* session = nullptr; | 487 const SyncedSession* session = nullptr; |
| 486 if (!session_tracker_.LookupLocalSession(&session)) | 488 if (!session_tracker_.LookupLocalSession(&session)) |
| 487 return syncer::SyncDataList(); | 489 return syncer::SyncDataList(); |
| 488 | 490 |
| 489 // First construct the header node. | 491 // First construct the header node. |
| 490 sync_pb::EntitySpecifics header_entity; | 492 sync_pb::EntitySpecifics header_entity; |
| 491 header_entity.mutable_session()->set_session_tag(current_machine_tag()); | 493 header_entity.mutable_session()->set_session_tag(current_machine_tag()); |
| 492 sync_pb::SessionHeader* header_specifics = | 494 sync_pb::SessionHeader* header_specifics = |
| 493 header_entity.mutable_session()->mutable_header(); | 495 header_entity.mutable_session()->mutable_header(); |
| 494 header_specifics->MergeFrom(session->ToSessionHeader()); | 496 header_specifics->MergeFrom(session->ToSessionHeader()); |
| 495 syncer::SyncData data = syncer::SyncData::CreateLocalData( | 497 syncer::SyncData data = syncer::SyncData::CreateLocalData( |
| 496 current_machine_tag(), current_session_name_, header_entity); | 498 current_machine_tag(), current_session_name_, header_entity); |
| 497 list.push_back(data); | 499 list.push_back(data); |
| 498 | 500 |
| 499 for (auto win_iter = session->windows.begin(); | 501 for (auto& win_iter : session->windows) { |
| 500 win_iter != session->windows.end(); ++win_iter) { | 502 for (auto& tab : win_iter.second->tabs) { |
| 501 for (auto tabs_iter = win_iter->second->tabs.begin(); | 503 // TODO(zea): replace with with the correct tab node id once there's a |
| 502 tabs_iter != win_iter->second->tabs.end(); ++tabs_iter) { | 504 // sync specific wrapper for SessionTab. This method is only used in |
| 505 // tests though, so it's fine for now. crbug.com/662597 | |
| 506 int tab_node_id = 0; | |
| 503 sync_pb::EntitySpecifics entity; | 507 sync_pb::EntitySpecifics entity; |
| 504 sync_pb::SessionSpecifics* specifics = entity.mutable_session(); | 508 entity.mutable_session()->CopyFrom( |
| 505 specifics->mutable_tab()->MergeFrom((*tabs_iter)->ToSyncData()); | 509 SessionTabToSpecifics(*tab, current_machine_tag(), tab_node_id)); |
| 506 specifics->set_session_tag(current_machine_tag_); | |
| 507 | |
| 508 TabLinksMap::const_iterator tab_map_iter = | |
| 509 local_tab_map_.find((*tabs_iter)->tab_id.id()); | |
| 510 DCHECK(tab_map_iter != local_tab_map_.end()); | |
| 511 specifics->set_tab_node_id(tab_map_iter->second->tab_node_id()); | |
| 512 syncer::SyncData data = syncer::SyncData::CreateLocalData( | 510 syncer::SyncData data = syncer::SyncData::CreateLocalData( |
| 513 TabNodePool::TabIdToTag(current_machine_tag_, | 511 TabNodeIdToTag(current_machine_tag(), tab_node_id), |
| 514 specifics->tab_node_id()), | |
| 515 current_session_name_, entity); | 512 current_session_name_, entity); |
| 516 list.push_back(data); | 513 list.push_back(data); |
| 517 } | 514 } |
| 518 } | 515 } |
| 519 return list; | 516 return list; |
| 520 } | 517 } |
| 521 | 518 |
| 522 bool SessionsSyncManager::GetLocalSession(const SyncedSession** local_session) { | 519 bool SessionsSyncManager::GetLocalSession(const SyncedSession** local_session) { |
| 523 if (current_machine_tag_.empty()) | 520 if (current_machine_tag().empty()) |
| 524 return false; | 521 return false; |
| 525 *local_session = session_tracker_.GetSession(current_machine_tag()); | 522 *local_session = session_tracker_.GetSession(current_machine_tag()); |
| 526 return true; | 523 return true; |
| 527 } | 524 } |
| 528 | 525 |
| 529 syncer::SyncError SessionsSyncManager::ProcessSyncChanges( | 526 syncer::SyncError SessionsSyncManager::ProcessSyncChanges( |
| 530 const tracked_objects::Location& from_here, | 527 const tracked_objects::Location& from_here, |
| 531 const syncer::SyncChangeList& change_list) { | 528 const syncer::SyncChangeList& change_list) { |
| 532 if (!sync_processor_.get()) { | 529 if (!sync_processor_.get()) { |
| 533 syncer::SyncError error(FROM_HERE, syncer::SyncError::DATATYPE_ERROR, | 530 syncer::SyncError error(FROM_HERE, syncer::SyncError::DATATYPE_ERROR, |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 573 break; | 570 break; |
| 574 case syncer::SyncChange::ACTION_ADD: | 571 case syncer::SyncChange::ACTION_ADD: |
| 575 case syncer::SyncChange::ACTION_UPDATE: | 572 case syncer::SyncChange::ACTION_UPDATE: |
| 576 if (current_machine_tag() == session.session_tag()) { | 573 if (current_machine_tag() == session.session_tag()) { |
| 577 // We should only ever receive a change to our own machine's session | 574 // We should only ever receive a change to our own machine's session |
| 578 // info if encryption was turned on. In that case, the data is still | 575 // info if encryption was turned on. In that case, the data is still |
| 579 // the same, so we can ignore. | 576 // the same, so we can ignore. |
| 580 LOG(WARNING) << "Dropping modification to local session."; | 577 LOG(WARNING) << "Dropping modification to local session."; |
| 581 return syncer::SyncError(); | 578 return syncer::SyncError(); |
| 582 } | 579 } |
| 583 UpdateTrackerWithForeignSession( | 580 UpdateTrackerWithSpecifics( |
| 584 session, syncer::SyncDataRemote(it->sync_data()).GetModifiedTime()); | 581 session, syncer::SyncDataRemote(it->sync_data()).GetModifiedTime()); |
| 585 break; | 582 break; |
| 586 default: | 583 default: |
| 587 NOTREACHED() << "Processing sync changes failed, unknown change type."; | 584 NOTREACHED() << "Processing sync changes failed, unknown change type."; |
| 588 } | 585 } |
| 589 } | 586 } |
| 590 | 587 |
| 591 if (!sessions_updated_callback_.is_null()) | 588 if (!sessions_updated_callback_.is_null()) |
| 592 sessions_updated_callback_.Run(); | 589 sessions_updated_callback_.Run(); |
| 593 return syncer::SyncError(); | 590 return syncer::SyncError(); |
| 594 } | 591 } |
| 595 | 592 |
| 596 syncer::SyncChange SessionsSyncManager::TombstoneTab( | 593 syncer::SyncChange SessionsSyncManager::TombstoneTab( |
| 597 const sync_pb::SessionSpecifics& tab) { | 594 const sync_pb::SessionSpecifics& tab) { |
| 598 if (!tab.has_tab_node_id()) { | 595 if (!tab.has_tab_node_id()) { |
| 599 LOG(WARNING) << "Old sessions node without tab node id; can't tombstone."; | 596 LOG(WARNING) << "Old sessions node without tab node id; can't tombstone."; |
| 600 return syncer::SyncChange(); | 597 return syncer::SyncChange(); |
| 601 } else { | 598 } else { |
| 602 return syncer::SyncChange( | 599 return syncer::SyncChange( |
| 603 FROM_HERE, SyncChange::ACTION_DELETE, | 600 FROM_HERE, SyncChange::ACTION_DELETE, |
| 604 SyncData::CreateLocalDelete( | 601 SyncData::CreateLocalDelete( |
| 605 TabNodePool::TabIdToTag(current_machine_tag(), tab.tab_node_id()), | 602 TabNodeIdToTag(current_machine_tag(), tab.tab_node_id()), |
| 606 syncer::SESSIONS)); | 603 syncer::SESSIONS)); |
| 607 } | 604 } |
| 608 } | 605 } |
| 609 | 606 |
| 610 bool SessionsSyncManager::GetAllForeignSessions( | 607 bool SessionsSyncManager::GetAllForeignSessions( |
| 611 std::vector<const SyncedSession*>* sessions) { | 608 std::vector<const SyncedSession*>* sessions) { |
| 612 if (!session_tracker_.LookupAllForeignSessions( | 609 if (!session_tracker_.LookupAllForeignSessions( |
| 613 sessions, SyncedSessionTracker::PRESENTABLE)) | 610 sessions, SyncedSessionTracker::PRESENTABLE)) |
| 614 return false; | 611 return false; |
| 615 std::sort(sessions->begin(), sessions->end(), SessionsRecencyComparator); | 612 std::sort(sessions->begin(), sessions->end(), SessionsRecencyComparator); |
| 616 return true; | 613 return true; |
| 617 } | 614 } |
| 618 | 615 |
| 619 bool SessionsSyncManager::InitFromSyncModel( | 616 bool SessionsSyncManager::InitFromSyncModel( |
| 620 const syncer::SyncDataList& sync_data, | 617 const syncer::SyncDataList& sync_data, |
| 621 syncer::SyncDataList* restored_tabs, | |
| 622 syncer::SyncChangeList* new_changes) { | 618 syncer::SyncChangeList* new_changes) { |
| 623 bool found_current_header = false; | 619 bool found_current_header = false; |
| 624 int bad_foreign_hash_count = 0; | 620 int bad_foreign_hash_count = 0; |
| 625 for (syncer::SyncDataList::const_iterator it = sync_data.begin(); | 621 for (syncer::SyncDataList::const_iterator it = sync_data.begin(); |
| 626 it != sync_data.end(); ++it) { | 622 it != sync_data.end(); ++it) { |
| 627 const syncer::SyncData& data = *it; | 623 const syncer::SyncData& data = *it; |
| 628 DCHECK(data.GetSpecifics().has_session()); | 624 DCHECK(data.GetSpecifics().has_session()); |
| 629 syncer::SyncDataRemote remote(data); | 625 syncer::SyncDataRemote remote(data); |
| 630 const sync_pb::SessionSpecifics& specifics = data.GetSpecifics().session(); | 626 const sync_pb::SessionSpecifics& specifics = data.GetSpecifics().session(); |
| 631 if (specifics.session_tag().empty() || | 627 if (specifics.session_tag().empty() || |
| 632 (specifics.has_tab() && | 628 (specifics.has_tab() && |
| 633 (!specifics.has_tab_node_id() || !specifics.tab().has_tab_id()))) { | 629 (!specifics.has_tab_node_id() || !specifics.tab().has_tab_id()))) { |
| 634 syncer::SyncChange tombstone(TombstoneTab(specifics)); | 630 syncer::SyncChange tombstone(TombstoneTab(specifics)); |
| 635 if (tombstone.IsValid()) | 631 if (tombstone.IsValid()) |
| 636 new_changes->push_back(tombstone); | 632 new_changes->push_back(tombstone); |
| 637 } else if (specifics.session_tag() != current_machine_tag()) { | 633 } else if (specifics.session_tag() != current_machine_tag()) { |
| 638 if (TagHashFromSpecifics(specifics) == remote.GetClientTagHash()) { | 634 if (TagHashFromSpecifics(specifics) == remote.GetClientTagHash()) { |
| 639 UpdateTrackerWithForeignSession(specifics, remote.GetModifiedTime()); | 635 UpdateTrackerWithSpecifics(specifics, remote.GetModifiedTime()); |
| 640 } else { | 636 } else { |
| 641 // In the past, like years ago, we believe that some session data was | 637 // In the past, like years ago, we believe that some session data was |
| 642 // created with bad tag hashes. This causes any change this client makes | 638 // created with bad tag hashes. This causes any change this client makes |
| 643 // to that foreign data (like deletion through garbage collection) to | 639 // to that foreign data (like deletion through garbage collection) to |
| 644 // trigger a data type error because the tag looking mechanism fails. So | 640 // trigger a data type error because the tag looking mechanism fails. So |
| 645 // look for these and delete via remote SyncData, which uses a server id | 641 // look for these and delete via remote SyncData, which uses a server id |
| 646 // lookup mechanism instead, see crbug.com/604657. | 642 // lookup mechanism instead, see crbug.com/604657. |
| 647 bad_foreign_hash_count++; | 643 bad_foreign_hash_count++; |
| 648 new_changes->push_back( | 644 new_changes->push_back( |
| 649 syncer::SyncChange(FROM_HERE, SyncChange::ACTION_DELETE, remote)); | 645 syncer::SyncChange(FROM_HERE, SyncChange::ACTION_DELETE, remote)); |
| 650 } | 646 } |
| 651 } else { | 647 } else { |
| 652 // This is previously stored local session information. | 648 // This is previously stored local session information. |
| 653 if (specifics.has_header() && !found_current_header) { | 649 if (specifics.has_header() && !found_current_header) { |
| 654 // This is our previous header node, reuse it. | 650 // This is our previous header node, reuse it. |
| 655 found_current_header = true; | 651 found_current_header = true; |
| 656 if (specifics.header().has_client_name()) | 652 if (specifics.header().has_client_name()) |
| 657 current_session_name_ = specifics.header().client_name(); | 653 current_session_name_ = specifics.header().client_name(); |
| 654 | |
| 655 // TODO(zea): crbug.com/639009 update the tracker with the specifics | |
| 656 // from the header node as well. This will be necessary to preserve | |
| 657 // the set of open tabs when a custom tab is opened. | |
| 658 } else { | 658 } else { |
| 659 if (specifics.has_header() || !specifics.has_tab()) { | 659 if (specifics.has_header() || !specifics.has_tab()) { |
| 660 LOG(WARNING) << "Found more than one session header node with local " | 660 LOG(WARNING) << "Found more than one session header node with local " |
| 661 << "tag."; | 661 << "tag."; |
| 662 syncer::SyncChange tombstone(TombstoneTab(specifics)); | 662 syncer::SyncChange tombstone(TombstoneTab(specifics)); |
| 663 if (tombstone.IsValid()) | 663 if (tombstone.IsValid()) |
| 664 new_changes->push_back(tombstone); | 664 new_changes->push_back(tombstone); |
| 665 } else { | 665 } else { |
| 666 // This is a valid old tab node, add it to the pool so it can be | 666 // This is a valid old tab node, add it to the tracker and associate |
| 667 // reused for reassociation. | 667 // it. |
| 668 local_tab_pool_.AddTabNode(specifics.tab_node_id()); | 668 session_tracker_.ReassociateLocalTab(specifics.tab_node_id(), |
|
skym
2016/12/03 01:20:46
Err, is this really correct? What if you've alread
Nicolas Zea
2016/12/06 01:32:55
InitFromSyncModel is called before OnLocalTabModif
| |
| 669 restored_tabs->push_back(*it); | 669 specifics.tab().tab_id()); |
| 670 UpdateTrackerWithSpecifics(specifics, remote.GetModifiedTime()); | |
| 670 } | 671 } |
| 671 } | 672 } |
| 672 } | 673 } |
| 673 } | 674 } |
| 674 | 675 |
| 675 // Cleanup all foreign sessions, since orphaned tabs may have been added after | 676 // Cleanup all foreign sessions, since orphaned tabs may have been added after |
| 676 // the header. | 677 // the header. |
| 677 std::vector<const SyncedSession*> sessions; | 678 std::vector<const SyncedSession*> sessions; |
| 678 session_tracker_.LookupAllForeignSessions(&sessions, | 679 session_tracker_.LookupAllForeignSessions(&sessions, |
| 679 SyncedSessionTracker::RAW); | 680 SyncedSessionTracker::RAW); |
| 680 for (const auto* session : sessions) { | 681 for (const auto* session : sessions) { |
| 681 session_tracker_.CleanupSession(session->session_tag); | 682 session_tracker_.CleanupForeignSession(session->session_tag); |
| 682 } | 683 } |
| 683 | 684 |
| 684 UMA_HISTOGRAM_COUNTS_100("Sync.SessionsBadForeignHashOnMergeCount", | 685 UMA_HISTOGRAM_COUNTS_100("Sync.SessionsBadForeignHashOnMergeCount", |
| 685 bad_foreign_hash_count); | 686 bad_foreign_hash_count); |
| 686 | 687 |
| 687 return found_current_header; | 688 return found_current_header; |
| 688 } | 689 } |
| 689 | 690 |
| 690 void SessionsSyncManager::UpdateTrackerWithForeignSession( | 691 void SessionsSyncManager::UpdateTrackerWithSpecifics( |
| 691 const sync_pb::SessionSpecifics& specifics, | 692 const sync_pb::SessionSpecifics& specifics, |
| 692 const base::Time& modification_time) { | 693 const base::Time& modification_time) { |
| 693 std::string foreign_session_tag = specifics.session_tag(); | 694 std::string session_tag = specifics.session_tag(); |
| 694 DCHECK_NE(foreign_session_tag, current_machine_tag()); | 695 SyncedSession* session = session_tracker_.GetSession(session_tag); |
| 695 | |
| 696 SyncedSession* foreign_session = | |
| 697 session_tracker_.GetSession(foreign_session_tag); | |
| 698 if (specifics.has_header()) { | 696 if (specifics.has_header()) { |
| 699 // Read in the header data for this foreign session. Header data is | 697 // Read in the header data for this session. Header data is |
| 700 // essentially a collection of windows, each of which has an ordered id list | 698 // essentially a collection of windows, each of which has an ordered id list |
| 701 // for their tabs. | 699 // for their tabs. |
| 702 | 700 |
| 703 if (!IsValidSessionHeader(specifics.header())) { | 701 if (!IsValidSessionHeader(specifics.header())) { |
| 704 LOG(WARNING) << "Ignoring foreign session node with invalid header " | 702 LOG(WARNING) << "Ignoring session node with invalid header " |
| 705 << "and tag " << foreign_session_tag << "."; | 703 << "and tag " << session_tag << "."; |
| 706 return; | 704 return; |
| 707 } | 705 } |
| 708 | 706 |
| 709 // Load (or create) the SyncedSession object for this client. | 707 // Load (or create) the SyncedSession object for this client. |
| 710 const sync_pb::SessionHeader& header = specifics.header(); | 708 const sync_pb::SessionHeader& header = specifics.header(); |
| 711 PopulateSessionHeaderFromSpecifics(header, modification_time, | 709 PopulateSessionHeaderFromSpecifics(header, modification_time, session); |
| 712 foreign_session); | |
| 713 | 710 |
| 714 // Reset the tab/window tracking for this session (must do this before | 711 // Reset the tab/window tracking for this session (must do this before |
| 715 // we start calling PutWindowInSession and PutTabInWindow so that all | 712 // we start calling PutWindowInSession and PutTabInWindow so that all |
| 716 // unused tabs/windows get cleared by the CleanupSession(...) call). | 713 // unused tabs/windows get cleared by the CleanupSession(...) call). |
| 717 session_tracker_.ResetSessionTracking(foreign_session_tag); | 714 session_tracker_.ResetSessionTracking(session_tag); |
| 718 | 715 |
| 719 // Process all the windows and their tab information. | 716 // Process all the windows and their tab information. |
| 720 int num_windows = header.window_size(); | 717 int num_windows = header.window_size(); |
| 721 DVLOG(1) << "Associating " << foreign_session_tag << " with " << num_windows | 718 DVLOG(1) << "Associating " << session_tag << " with " << num_windows |
| 722 << " windows."; | 719 << " windows."; |
| 723 | 720 |
| 724 for (int i = 0; i < num_windows; ++i) { | 721 for (int i = 0; i < num_windows; ++i) { |
| 725 const sync_pb::SessionWindow& window_s = header.window(i); | 722 const sync_pb::SessionWindow& window_s = header.window(i); |
| 726 SessionID::id_type window_id = window_s.window_id(); | 723 SessionID::id_type window_id = window_s.window_id(); |
| 727 session_tracker_.PutWindowInSession(foreign_session_tag, window_id); | 724 session_tracker_.PutWindowInSession(session_tag, window_id); |
| 728 BuildSyncedSessionFromSpecifics( | 725 BuildSyncedSessionFromSpecifics(session_tag, window_s, modification_time, |
| 729 foreign_session_tag, window_s, modification_time, | 726 session->windows[window_id].get()); |
| 730 foreign_session->windows[window_id].get()); | |
| 731 } | 727 } |
| 732 // Delete any closed windows and unused tabs as necessary. | 728 // Delete any closed windows and unused tabs as necessary. |
| 733 session_tracker_.CleanupSession(foreign_session_tag); | 729 session_tracker_.CleanupForeignSession(session_tag); |
| 734 } else if (specifics.has_tab()) { | 730 } else if (specifics.has_tab()) { |
| 735 const sync_pb::SessionTab& tab_s = specifics.tab(); | 731 const sync_pb::SessionTab& tab_s = specifics.tab(); |
| 736 SessionID::id_type tab_id = tab_s.tab_id(); | 732 SessionID::id_type tab_id = tab_s.tab_id(); |
| 737 | 733 |
| 734 DVLOG(1) << "Associating tab " << tab_id << " with node " | |
|
skym
2016/12/03 01:20:46
Nit: We only actually associate the tab_id with ta
skym
2016/12/05 19:16:57
Errm, now I'm confused by my comment from last wee
Nicolas Zea
2016/12/06 01:32:55
Are you referring to the if conditional just below
| |
| 735 << specifics.tab_node_id(); | |
| 736 session_tracker_.AddTabNode(session_tag, specifics.tab_node_id()); | |
|
skym
2016/12/05 19:16:57
I think AddX(...) is a much better method name tha
Nicolas Zea
2016/12/06 01:32:55
Cleaned up the comments here. PTAL!
Also re: AddX
skym
2016/12/06 19:37:21
Both options sound good to me.
Nicolas Zea
2016/12/06 22:31:37
Switched to OnTabNodeSeen.
| |
| 737 | |
| 738 const sessions::SessionTab* existing_tab; | 738 const sessions::SessionTab* existing_tab; |
| 739 if (session_tracker_.LookupSessionTab(foreign_session_tag, tab_id, | 739 if (session_tracker_.LookupSessionTab(session_tag, tab_id, &existing_tab) && |
| 740 &existing_tab) && | |
| 741 existing_tab->timestamp > modification_time) { | 740 existing_tab->timestamp > modification_time) { |
| 742 // Force the tracker to remember this tab node id, even if it isn't | 741 DVLOG(1) << "Ignoring " << session_tag << "'s session tab " << tab_id |
| 743 // currently being used. | 742 << " with earlier modification time"; |
| 744 session_tracker_.GetTab(foreign_session_tag, tab_id, | |
| 745 specifics.tab_node_id()); | |
| 746 DVLOG(1) << "Ignoring " << foreign_session_tag << "'s session tab " | |
| 747 << tab_id << " with earlier modification time"; | |
| 748 return; | 743 return; |
| 749 } | 744 } |
| 750 | 745 |
| 751 sessions::SessionTab* tab = session_tracker_.GetTab( | 746 sessions::SessionTab* tab = session_tracker_.GetTab(session_tag, tab_id); |
|
skym
2016/12/05 19:16:57
Without passing tab node id to this call, why do w
Nicolas Zea
2016/12/06 01:32:55
Good point, the calls can be combined. Done.
| |
| 752 foreign_session_tag, tab_id, specifics.tab_node_id()); | |
| 753 | 747 |
| 754 // Update SessionTab based on protobuf. | 748 // Update SessionTab based on protobuf. |
| 755 tab->SetFromSyncData(tab_s, modification_time); | 749 tab->SetFromSyncData(tab_s, modification_time); |
| 756 | 750 |
| 757 // If a favicon or favicon urls are present, load the URLs and visit | 751 // If a favicon or favicon urls are present, load the URLs and visit |
| 758 // times into the in-memory favicon cache. | 752 // times into the in-memory favicon cache. |
| 759 RefreshFaviconVisitTimesFromForeignTab(tab_s, modification_time); | 753 RefreshFaviconVisitTimesFromForeignTab(tab_s, modification_time); |
| 760 | 754 |
| 761 // Update the last modified time. | 755 // Update the last modified time. |
| 762 if (foreign_session->modified_time < modification_time) | 756 if (session->modified_time < modification_time) |
| 763 foreign_session->modified_time = modification_time; | 757 session->modified_time = modification_time; |
| 764 } else { | 758 } else { |
| 765 LOG(WARNING) << "Ignoring foreign session node with missing header/tab " | 759 LOG(WARNING) << "Ignoring session node with missing header/tab " |
| 766 << "fields and tag " << foreign_session_tag << "."; | 760 << "fields and tag " << session_tag << "."; |
| 767 } | 761 } |
| 768 } | 762 } |
| 769 | 763 |
| 770 void SessionsSyncManager::InitializeCurrentMachineTag() { | 764 void SessionsSyncManager::InitializeCurrentMachineTag() { |
| 771 DCHECK(current_machine_tag_.empty()); | 765 DCHECK(current_machine_tag_.empty()); |
| 772 std::string persisted_guid; | 766 std::string persisted_guid; |
| 773 persisted_guid = sync_prefs_->GetSyncSessionsGUID(); | 767 persisted_guid = sync_prefs_->GetSyncSessionsGUID(); |
| 774 if (!persisted_guid.empty()) { | 768 if (!persisted_guid.empty()) { |
| 775 current_machine_tag_ = persisted_guid; | 769 current_machine_tag_ = persisted_guid; |
| 776 DVLOG(1) << "Restoring persisted session sync guid: " << persisted_guid; | 770 DVLOG(1) << "Restoring persisted session sync guid: " << persisted_guid; |
| 777 } else { | 771 } else { |
| 778 DCHECK(local_device_); | 772 DCHECK(local_device_); |
| 779 std::string cache_guid = local_device_->GetLocalSyncCacheGUID(); | 773 std::string cache_guid = local_device_->GetLocalSyncCacheGUID(); |
| 780 DCHECK(!cache_guid.empty()); | 774 DCHECK(!cache_guid.empty()); |
| 781 current_machine_tag_ = BuildMachineTag(cache_guid); | 775 current_machine_tag_ = BuildMachineTag(cache_guid); |
| 782 DVLOG(1) << "Creating session sync guid: " << current_machine_tag_; | 776 DVLOG(1) << "Creating session sync guid: " << current_machine_tag_; |
| 783 sync_prefs_->SetSyncSessionsGUID(current_machine_tag_); | 777 sync_prefs_->SetSyncSessionsGUID(current_machine_tag_); |
| 784 } | 778 } |
| 785 | |
| 786 local_tab_pool_.SetMachineTag(current_machine_tag_); | |
| 787 } | 779 } |
| 788 | 780 |
| 789 // static | 781 // static |
| 790 void SessionsSyncManager::PopulateSessionHeaderFromSpecifics( | 782 void SessionsSyncManager::PopulateSessionHeaderFromSpecifics( |
| 791 const sync_pb::SessionHeader& header_specifics, | 783 const sync_pb::SessionHeader& header_specifics, |
| 792 base::Time mtime, | 784 base::Time mtime, |
| 793 SyncedSession* session_header) { | 785 SyncedSession* session_header) { |
| 794 if (header_specifics.has_client_name()) | 786 if (header_specifics.has_client_name()) |
| 795 session_header->session_name = header_specifics.client_name(); | 787 session_header->session_name = header_specifics.client_name(); |
| 796 if (header_specifics.has_device_type()) { | 788 if (header_specifics.has_device_type()) { |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 886 void SessionsSyncManager::DeleteForeignSessionInternal( | 878 void SessionsSyncManager::DeleteForeignSessionInternal( |
| 887 const std::string& tag, | 879 const std::string& tag, |
| 888 syncer::SyncChangeList* change_output) { | 880 syncer::SyncChangeList* change_output) { |
| 889 if (tag == current_machine_tag()) { | 881 if (tag == current_machine_tag()) { |
| 890 LOG(ERROR) << "Attempting to delete local session. This is not currently " | 882 LOG(ERROR) << "Attempting to delete local session. This is not currently " |
| 891 << "supported."; | 883 << "supported."; |
| 892 return; | 884 return; |
| 893 } | 885 } |
| 894 | 886 |
| 895 std::set<int> tab_node_ids_to_delete; | 887 std::set<int> tab_node_ids_to_delete; |
| 896 session_tracker_.LookupTabNodeIds(tag, &tab_node_ids_to_delete); | 888 session_tracker_.LookupForeignTabNodeIds(tag, &tab_node_ids_to_delete); |
| 897 if (DisassociateForeignSession(tag)) { | 889 if (DisassociateForeignSession(tag)) { |
| 898 // Only tell sync to delete the header if there was one. | 890 // Only tell sync to delete the header if there was one. |
| 899 change_output->push_back( | 891 change_output->push_back( |
| 900 syncer::SyncChange(FROM_HERE, SyncChange::ACTION_DELETE, | 892 syncer::SyncChange(FROM_HERE, SyncChange::ACTION_DELETE, |
| 901 SyncData::CreateLocalDelete(tag, syncer::SESSIONS))); | 893 SyncData::CreateLocalDelete(tag, syncer::SESSIONS))); |
| 902 } | 894 } |
| 903 for (std::set<int>::const_iterator it = tab_node_ids_to_delete.begin(); | 895 for (std::set<int>::const_iterator it = tab_node_ids_to_delete.begin(); |
| 904 it != tab_node_ids_to_delete.end(); ++it) { | 896 it != tab_node_ids_to_delete.end(); ++it) { |
| 905 change_output->push_back(syncer::SyncChange( | 897 change_output->push_back( |
| 906 FROM_HERE, SyncChange::ACTION_DELETE, | 898 syncer::SyncChange(FROM_HERE, SyncChange::ACTION_DELETE, |
| 907 SyncData::CreateLocalDelete(TabNodePool::TabIdToTag(tag, *it), | 899 SyncData::CreateLocalDelete(TabNodeIdToTag(tag, *it), |
| 908 syncer::SESSIONS))); | 900 syncer::SESSIONS))); |
| 909 } | 901 } |
| 910 if (!sessions_updated_callback_.is_null()) | 902 if (!sessions_updated_callback_.is_null()) |
| 911 sessions_updated_callback_.Run(); | 903 sessions_updated_callback_.Run(); |
| 912 } | 904 } |
| 913 | 905 |
| 914 bool SessionsSyncManager::DisassociateForeignSession( | 906 bool SessionsSyncManager::DisassociateForeignSession( |
| 915 const std::string& foreign_session_tag) { | 907 const std::string& foreign_session_tag) { |
| 916 DCHECK_NE(foreign_session_tag, current_machine_tag()); | 908 DCHECK_NE(foreign_session_tag, current_machine_tag()); |
| 917 DVLOG(1) << "Disassociating session " << foreign_session_tag; | 909 DVLOG(1) << "Disassociating session " << foreign_session_tag; |
| 918 return session_tracker_.DeleteSession(foreign_session_tag); | 910 return session_tracker_.DeleteForeignSession(foreign_session_tag); |
| 919 } | 911 } |
| 920 | 912 |
| 921 bool SessionsSyncManager::GetForeignSession( | 913 bool SessionsSyncManager::GetForeignSession( |
| 922 const std::string& tag, | 914 const std::string& tag, |
| 923 std::vector<const sessions::SessionWindow*>* windows) { | 915 std::vector<const sessions::SessionWindow*>* windows) { |
| 924 return session_tracker_.LookupSessionWindows(tag, windows); | 916 return session_tracker_.LookupSessionWindows(tag, windows); |
| 925 } | 917 } |
| 926 | 918 |
| 927 bool SessionsSyncManager::GetForeignSessionTabs( | 919 bool SessionsSyncManager::GetForeignSessionTabs( |
| 928 const std::string& tag, | 920 const std::string& tag, |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 954 bool SessionsSyncManager::GetForeignTab(const std::string& tag, | 946 bool SessionsSyncManager::GetForeignTab(const std::string& tag, |
| 955 const SessionID::id_type tab_id, | 947 const SessionID::id_type tab_id, |
| 956 const sessions::SessionTab** tab) { | 948 const sessions::SessionTab** tab) { |
| 957 const sessions::SessionTab* synced_tab = nullptr; | 949 const sessions::SessionTab* synced_tab = nullptr; |
| 958 bool success = session_tracker_.LookupSessionTab(tag, tab_id, &synced_tab); | 950 bool success = session_tracker_.LookupSessionTab(tag, tab_id, &synced_tab); |
| 959 if (success) | 951 if (success) |
| 960 *tab = synced_tab; | 952 *tab = synced_tab; |
| 961 return success; | 953 return success; |
| 962 } | 954 } |
| 963 | 955 |
| 964 void SessionsSyncManager::LocalTabDelegateToSpecifics( | |
| 965 const SyncedTabDelegate& tab_delegate, | |
| 966 sync_pb::SessionSpecifics* specifics) { | |
| 967 sessions::SessionTab* session_tab = nullptr; | |
| 968 session_tab = session_tracker_.GetTab(current_machine_tag(), | |
| 969 tab_delegate.GetSessionId(), | |
| 970 tab_delegate.GetSyncId()); | |
| 971 SetSessionTabFromDelegate(tab_delegate, base::Time::Now(), session_tab); | |
| 972 SetVariationIds(session_tab); | |
| 973 sync_pb::SessionTab tab_s = session_tab->ToSyncData(); | |
| 974 specifics->set_session_tag(current_machine_tag_); | |
| 975 specifics->set_tab_node_id(tab_delegate.GetSyncId()); | |
| 976 specifics->mutable_tab()->CopyFrom(tab_s); | |
| 977 } | |
| 978 | |
| 979 void SessionsSyncManager::AssociateRestoredPlaceholderTab( | 956 void SessionsSyncManager::AssociateRestoredPlaceholderTab( |
| 980 const SyncedTabDelegate& tab_delegate, | 957 const SyncedTabDelegate& tab_delegate, |
| 981 SessionID::id_type new_tab_id, | 958 SessionID::id_type new_tab_id, |
| 982 SessionID::id_type new_window_id, | 959 SessionID::id_type new_window_id, |
| 983 const syncer::SyncDataList& restored_tabs, | |
| 984 syncer::SyncChangeList* change_output) { | 960 syncer::SyncChangeList* change_output) { |
| 985 DCHECK_NE(tab_delegate.GetSyncId(), TabNodePool::kInvalidTabNodeID); | 961 DCHECK_NE(tab_delegate.GetSyncId(), TabNodePool::kInvalidTabNodeID); |
| 986 // Rewrite the tab using |restored_tabs| to retrieve the specifics. | |
| 987 if (restored_tabs.empty()) { | |
| 988 DLOG(WARNING) << "Can't Update tab ID."; | |
| 989 return; | |
| 990 } | |
| 991 | 962 |
| 992 for (syncer::SyncDataList::const_iterator it = restored_tabs.begin(); | 963 // Update tracker with the new association (and inform it of the tab node |
| 993 it != restored_tabs.end(); ++it) { | 964 // in the process). |
| 994 if (it->GetSpecifics().session().tab_node_id() != | 965 session_tracker_.ReassociateLocalTab(tab_delegate.GetSyncId(), new_tab_id); |
| 995 tab_delegate.GetSyncId()) { | |
| 996 continue; | |
| 997 } | |
| 998 | 966 |
| 999 sync_pb::EntitySpecifics entity; | 967 // Update the window id on the SessionTab itself. |
| 1000 sync_pb::SessionSpecifics* specifics = entity.mutable_session(); | 968 sessions::SessionTab* local_tab = |
| 1001 specifics->CopyFrom(it->GetSpecifics().session()); | 969 session_tracker_.GetTab(current_machine_tag(), new_tab_id); |
| 1002 DCHECK(specifics->has_tab()); | 970 local_tab->window_id.set_id(new_window_id); |
| 1003 | 971 |
| 1004 // Update tab node pool with the new association. | 972 // Rewrite the specifics based on the reassociated SessionTab to preserve |
| 1005 local_tab_pool_.ReassociateTabNode(tab_delegate.GetSyncId(), new_tab_id); | 973 // the new tab and window ids. |
| 1006 TabLink* tab_link = new TabLink(tab_delegate.GetSyncId(), &tab_delegate); | 974 sync_pb::EntitySpecifics entity; |
| 1007 local_tab_map_[new_tab_id] = make_linked_ptr<TabLink>(tab_link); | 975 entity.mutable_session()->CopyFrom(SessionTabToSpecifics( |
| 1008 | 976 *local_tab, current_machine_tag(), tab_delegate.GetSyncId())); |
| 1009 if (specifics->tab().tab_id() == new_tab_id && | 977 syncer::SyncData data = syncer::SyncData::CreateLocalData( |
| 1010 specifics->tab().window_id() == new_window_id) | 978 TabNodeIdToTag(current_machine_tag(), tab_delegate.GetSyncId()), |
| 1011 return; | 979 current_session_name_, entity); |
| 1012 | 980 change_output->push_back( |
| 1013 // Either the tab_id or window_id changed (e.g due to session restore), so | 981 syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_UPDATE, data)); |
| 1014 // update the sync node. | |
| 1015 specifics->mutable_tab()->set_tab_id(new_tab_id); | |
| 1016 specifics->mutable_tab()->set_window_id(new_window_id); | |
| 1017 syncer::SyncData data = syncer::SyncData::CreateLocalData( | |
| 1018 TabNodePool::TabIdToTag(current_machine_tag_, specifics->tab_node_id()), | |
| 1019 current_session_name_, entity); | |
| 1020 change_output->push_back( | |
| 1021 syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_UPDATE, data)); | |
| 1022 return; | |
| 1023 } | |
| 1024 } | 982 } |
| 1025 | 983 |
| 1026 // static | 984 // static |
| 1027 void SessionsSyncManager::SetSessionTabFromDelegate( | 985 void SessionsSyncManager::SetSessionTabFromDelegate( |
| 1028 const SyncedTabDelegate& tab_delegate, | 986 const SyncedTabDelegate& tab_delegate, |
| 1029 base::Time mtime, | 987 base::Time mtime, |
| 1030 sessions::SessionTab* session_tab) { | 988 sessions::SessionTab* session_tab) { |
| 1031 DCHECK(session_tab); | 989 DCHECK(session_tab); |
| 1032 session_tab->window_id.set_id(tab_delegate.GetWindowId()); | 990 session_tab->window_id.set_id(tab_delegate.GetWindowId()); |
| 1033 session_tab->tab_id.set_id(tab_delegate.GetSessionId()); | 991 session_tab->tab_id.set_id(tab_delegate.GetSessionId()); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1132 } | 1090 } |
| 1133 | 1091 |
| 1134 // static | 1092 // static |
| 1135 std::string SessionsSyncManager::TagHashFromSpecifics( | 1093 std::string SessionsSyncManager::TagHashFromSpecifics( |
| 1136 const sync_pb::SessionSpecifics& specifics) { | 1094 const sync_pb::SessionSpecifics& specifics) { |
| 1137 return syncer::GenerateSyncableHash(syncer::SESSIONS, | 1095 return syncer::GenerateSyncableHash(syncer::SESSIONS, |
| 1138 TagFromSpecifics(specifics)); | 1096 TagFromSpecifics(specifics)); |
| 1139 } | 1097 } |
| 1140 | 1098 |
| 1141 }; // namespace sync_sessions | 1099 }; // namespace sync_sessions |
| OLD | NEW |