| 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/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 85 const base::Closure& sessions_updated_callback, | 85 const base::Closure& sessions_updated_callback, |
| 86 const base::Closure& datatype_refresh_callback) | 86 const base::Closure& datatype_refresh_callback) |
| 87 : sessions_client_(sessions_client), | 87 : sessions_client_(sessions_client), |
| 88 session_tracker_(sessions_client), | 88 session_tracker_(sessions_client), |
| 89 favicon_cache_(sessions_client->GetFaviconService(), | 89 favicon_cache_(sessions_client->GetFaviconService(), |
| 90 sessions_client->GetHistoryService(), | 90 sessions_client->GetHistoryService(), |
| 91 kMaxSyncFavicons), | 91 kMaxSyncFavicons), |
| 92 local_tab_pool_out_of_sync_(true), | 92 local_tab_pool_out_of_sync_(true), |
| 93 sync_prefs_(sync_prefs), | 93 sync_prefs_(sync_prefs), |
| 94 local_device_(local_device), | 94 local_device_(local_device), |
| 95 current_device_type_(sync_pb::SyncEnums_DeviceType_TYPE_OTHER), |
| 95 local_session_header_node_id_(TabNodePool::kInvalidTabNodeID), | 96 local_session_header_node_id_(TabNodePool::kInvalidTabNodeID), |
| 96 stale_session_threshold_days_(kDefaultStaleSessionThresholdDays), | 97 stale_session_threshold_days_(kDefaultStaleSessionThresholdDays), |
| 97 local_event_router_(std::move(router)), | 98 local_event_router_(std::move(router)), |
| 98 page_revisit_broadcaster_(this, sessions_client), | 99 page_revisit_broadcaster_(this, sessions_client), |
| 99 sessions_updated_callback_(sessions_updated_callback), | 100 sessions_updated_callback_(sessions_updated_callback), |
| 100 datatype_refresh_callback_(datatype_refresh_callback) {} | 101 datatype_refresh_callback_(datatype_refresh_callback) {} |
| 101 | 102 |
| 102 SessionsSyncManager::~SessionsSyncManager() {} | 103 SessionsSyncManager::~SessionsSyncManager() {} |
| 103 | 104 |
| 104 // Returns the GUID-based string that should be used for | 105 // Returns the GUID-based string that should be used for |
| 105 // |SessionsSyncManager::current_machine_tag_|. | 106 // |SessionsSyncManager::current_machine_tag_|. |
| 106 static std::string BuildMachineTag(const std::string& cache_guid) { | 107 static std::string BuildMachineTag(const std::string& cache_guid) { |
| 107 std::string machine_tag = "session_sync"; | 108 std::string machine_tag = "session_sync"; |
| 108 machine_tag.append(cache_guid); | 109 machine_tag.append(cache_guid); |
| 109 return machine_tag; | 110 return machine_tag; |
| 110 } | 111 } |
| 111 | 112 |
| 112 syncer::SyncMergeResult SessionsSyncManager::MergeDataAndStartSyncing( | 113 syncer::SyncMergeResult SessionsSyncManager::MergeDataAndStartSyncing( |
| 113 syncer::ModelType type, | 114 syncer::ModelType type, |
| 114 const syncer::SyncDataList& initial_sync_data, | 115 const syncer::SyncDataList& initial_sync_data, |
| 115 std::unique_ptr<syncer::SyncChangeProcessor> sync_processor, | 116 std::unique_ptr<syncer::SyncChangeProcessor> sync_processor, |
| 116 std::unique_ptr<syncer::SyncErrorFactory> error_handler) { | 117 std::unique_ptr<syncer::SyncErrorFactory> error_handler) { |
| 117 syncer::SyncMergeResult merge_result(type); | 118 syncer::SyncMergeResult merge_result(type); |
| 118 DCHECK(session_tracker_.Empty()); | 119 DCHECK(session_tracker_.Empty()); |
| 119 DCHECK_EQ(0U, local_tab_pool_.Capacity()); | 120 DCHECK_EQ(0U, local_tab_pool_.Capacity()); |
| 120 | 121 |
| 121 error_handler_ = std::move(error_handler); | 122 error_handler_ = std::move(error_handler); |
| 122 sync_processor_ = std::move(sync_processor); | 123 sync_processor_ = std::move(sync_processor); |
| 123 | 124 |
| 125 // SessionDataTypeController ensures that the local device info |
| 126 // is available before activating this datatype. |
| 127 DCHECK(local_device_); |
| 128 const DeviceInfo* local_device_info = local_device_->GetLocalDeviceInfo(); |
| 129 if (!local_device_info) { |
| 130 merge_result.set_error(error_handler_->CreateAndUploadError( |
| 131 FROM_HERE, "Failed to get local device info.")); |
| 132 return merge_result; |
| 133 } |
| 134 |
| 135 current_session_name_ = local_device_info->client_name(); |
| 136 current_device_type_ = local_device_info->device_type(); |
| 137 |
| 124 // It's possible(via RebuildAssociations) for lost_navigations_recorder_ to | 138 // It's possible(via RebuildAssociations) for lost_navigations_recorder_ to |
| 125 // persist between sync being stopped and started. If it did persist, it's | 139 // persist between sync being stopped and started. If it did persist, it's |
| 126 // already associated with |sync_processor|, so leave it alone. | 140 // already associated with |sync_processor|, so leave it alone. |
| 127 if (!lost_navigations_recorder_.get()) { | 141 if (!lost_navigations_recorder_.get()) { |
| 128 lost_navigations_recorder_ = | 142 lost_navigations_recorder_ = |
| 129 base::MakeUnique<sync_sessions::LostNavigationsRecorder>(); | 143 base::MakeUnique<sync_sessions::LostNavigationsRecorder>(); |
| 130 sync_processor_->AddLocalChangeObserver(lost_navigations_recorder_.get()); | 144 sync_processor_->AddLocalChangeObserver(lost_navigations_recorder_.get()); |
| 131 } | 145 } |
| 132 | 146 |
| 133 local_session_header_node_id_ = TabNodePool::kInvalidTabNodeID; | 147 local_session_header_node_id_ = TabNodePool::kInvalidTabNodeID; |
| 134 | 148 |
| 135 // Make sure we have a machine tag. We do this now (versus earlier) as it's | 149 // Make sure we have a machine tag. We do this now (versus earlier) as it's |
| 136 // a conveniently safe time to assert sync is ready and the cache_guid is | 150 // a conveniently safe time to assert sync is ready and the cache_guid is |
| 137 // initialized. | 151 // initialized. |
| 138 if (current_machine_tag_.empty()) { | 152 if (current_machine_tag_.empty()) { |
| 139 InitializeCurrentMachineTag(); | 153 InitializeCurrentMachineTag(local_device_->GetLocalSyncCacheGUID()); |
| 140 } | |
| 141 | |
| 142 // SessionDataTypeController ensures that the local device info | |
| 143 // is available before activating this datatype. | |
| 144 DCHECK(local_device_); | |
| 145 const DeviceInfo* local_device_info = local_device_->GetLocalDeviceInfo(); | |
| 146 if (local_device_info) { | |
| 147 current_session_name_ = local_device_info->client_name(); | |
| 148 } else { | |
| 149 merge_result.set_error(error_handler_->CreateAndUploadError( | |
| 150 FROM_HERE, "Failed to get local device info.")); | |
| 151 return merge_result; | |
| 152 } | 154 } |
| 153 | 155 |
| 154 session_tracker_.SetLocalSessionTag(current_machine_tag_); | 156 session_tracker_.SetLocalSessionTag(current_machine_tag_); |
| 155 | 157 |
| 156 syncer::SyncChangeList new_changes; | 158 syncer::SyncChangeList new_changes; |
| 157 | 159 |
| 158 // First, we iterate over sync data to update our session_tracker_. | 160 // First, we iterate over sync data to update our session_tracker_. |
| 159 syncer::SyncDataList restored_tabs; | 161 syncer::SyncDataList restored_tabs; |
| 160 if (!InitFromSyncModel(initial_sync_data, &restored_tabs, &new_changes)) { | 162 if (!InitFromSyncModel(initial_sync_data, &restored_tabs, &new_changes)) { |
| 161 // The sync db didn't have a header node for us. Create one. | 163 // The sync db didn't have a header node for us. Create one. |
| 162 sync_pb::EntitySpecifics specifics; | 164 sync_pb::EntitySpecifics specifics; |
| 163 sync_pb::SessionSpecifics* base_specifics = specifics.mutable_session(); | 165 sync_pb::SessionSpecifics* base_specifics = specifics.mutable_session(); |
| 164 base_specifics->set_session_tag(current_machine_tag()); | 166 base_specifics->set_session_tag(current_machine_tag()); |
| 165 sync_pb::SessionHeader* header_s = base_specifics->mutable_header(); | 167 sync_pb::SessionHeader* header_s = base_specifics->mutable_header(); |
| 166 header_s->set_client_name(current_session_name_); | 168 header_s->set_client_name(current_session_name_); |
| 167 header_s->set_device_type(local_device_info->device_type()); | 169 header_s->set_device_type(current_device_type_); |
| 168 syncer::SyncData data = syncer::SyncData::CreateLocalData( | 170 syncer::SyncData data = syncer::SyncData::CreateLocalData( |
| 169 current_machine_tag(), current_session_name_, specifics); | 171 current_machine_tag(), current_session_name_, specifics); |
| 170 new_changes.push_back( | 172 new_changes.push_back( |
| 171 syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_ADD, data)); | 173 syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_ADD, data)); |
| 172 } | 174 } |
| 173 | 175 |
| 174 #if defined(OS_ANDROID) | 176 #if defined(OS_ANDROID) |
| 175 std::string sync_machine_tag( | 177 std::string sync_machine_tag( |
| 176 BuildMachineTag(local_device_->GetLocalSyncCacheGUID())); | 178 BuildMachineTag(local_device_->GetLocalSyncCacheGUID())); |
| 177 if (current_machine_tag_.compare(sync_machine_tag) != 0) | 179 if (current_machine_tag_.compare(sync_machine_tag) != 0) |
| (...skipping 15 matching lines...) Expand all Loading... |
| 193 ReloadTabsOption option, | 195 ReloadTabsOption option, |
| 194 const syncer::SyncDataList& restored_tabs, | 196 const syncer::SyncDataList& restored_tabs, |
| 195 syncer::SyncChangeList* change_output) { | 197 syncer::SyncChangeList* change_output) { |
| 196 const std::string local_tag = current_machine_tag(); | 198 const std::string local_tag = current_machine_tag(); |
| 197 sync_pb::SessionSpecifics specifics; | 199 sync_pb::SessionSpecifics specifics; |
| 198 specifics.set_session_tag(local_tag); | 200 specifics.set_session_tag(local_tag); |
| 199 sync_pb::SessionHeader* header_s = specifics.mutable_header(); | 201 sync_pb::SessionHeader* header_s = specifics.mutable_header(); |
| 200 SyncedSession* current_session = session_tracker_.GetSession(local_tag); | 202 SyncedSession* current_session = session_tracker_.GetSession(local_tag); |
| 201 current_session->modified_time = base::Time::Now(); | 203 current_session->modified_time = base::Time::Now(); |
| 202 header_s->set_client_name(current_session_name_); | 204 header_s->set_client_name(current_session_name_); |
| 203 // SessionDataTypeController ensures that the local device info | 205 header_s->set_device_type(current_device_type_); |
| 204 // is available before activating this datatype. | |
| 205 DCHECK(local_device_); | |
| 206 const DeviceInfo* local_device_info = local_device_->GetLocalDeviceInfo(); | |
| 207 header_s->set_device_type(local_device_info->device_type()); | |
| 208 | 206 |
| 209 session_tracker_.ResetSessionTracking(local_tag); | 207 session_tracker_.ResetSessionTracking(local_tag); |
| 210 std::set<const SyncedWindowDelegate*> windows = | 208 std::set<const SyncedWindowDelegate*> windows = |
| 211 synced_window_delegates_getter()->GetSyncedWindowDelegates(); | 209 synced_window_delegates_getter()->GetSyncedWindowDelegates(); |
| 212 | 210 |
| 213 if (option == RELOAD_TABS) { | 211 if (option == RELOAD_TABS) { |
| 214 UMA_HISTOGRAM_COUNTS("Sync.SessionWindows", windows.size()); | 212 UMA_HISTOGRAM_COUNTS("Sync.SessionWindows", windows.size()); |
| 215 } | 213 } |
| 216 if (windows.size() == 0) { | 214 if (windows.size() == 0) { |
| 217 // Assume that the window hasn't loaded. Attempting to associate now would | 215 // Assume that the window hasn't loaded. Attempting to associate now would |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 382 favicon_cache_.OnFaviconVisited(new_url, | 380 favicon_cache_.OnFaviconVisited(new_url, |
| 383 tab->GetFaviconURLAtIndex(current_index)); | 381 tab->GetFaviconURLAtIndex(current_index)); |
| 384 page_revisit_broadcaster_.OnPageVisit( | 382 page_revisit_broadcaster_.OnPageVisit( |
| 385 new_url, tab->GetTransitionAtIndex(current_index)); | 383 new_url, tab->GetTransitionAtIndex(current_index)); |
| 386 } | 384 } |
| 387 | 385 |
| 388 session_tracker_.GetSession(current_machine_tag())->modified_time = | 386 session_tracker_.GetSession(current_machine_tag())->modified_time = |
| 389 base::Time::Now(); | 387 base::Time::Now(); |
| 390 } | 388 } |
| 391 | 389 |
| 392 void SessionsSyncManager::RebuildAssociations() { | 390 bool SessionsSyncManager::RebuildAssociations() { |
| 393 syncer::SyncDataList data(sync_processor_->GetAllSyncData(syncer::SESSIONS)); | 391 syncer::SyncDataList data(sync_processor_->GetAllSyncData(syncer::SESSIONS)); |
| 394 std::unique_ptr<syncer::SyncErrorFactory> error_handler( | 392 std::unique_ptr<syncer::SyncErrorFactory> error_handler( |
| 395 std::move(error_handler_)); | 393 std::move(error_handler_)); |
| 396 std::unique_ptr<syncer::SyncChangeProcessor> processor( | 394 std::unique_ptr<syncer::SyncChangeProcessor> processor( |
| 397 std::move(sync_processor_)); | 395 std::move(sync_processor_)); |
| 398 | 396 |
| 399 StopSyncing(syncer::SESSIONS); | 397 StopSyncing(syncer::SESSIONS); |
| 400 MergeDataAndStartSyncing(syncer::SESSIONS, data, std::move(processor), | 398 syncer::SyncMergeResult merge_result = MergeDataAndStartSyncing( |
| 401 std::move(error_handler)); | 399 syncer::SESSIONS, data, std::move(processor), std::move(error_handler)); |
| 400 return !merge_result.error().IsSet(); |
| 402 } | 401 } |
| 403 | 402 |
| 404 bool SessionsSyncManager::IsValidSessionHeader( | 403 bool SessionsSyncManager::IsValidSessionHeader( |
| 405 const sync_pb::SessionHeader& header) { | 404 const sync_pb::SessionHeader& header) { |
| 406 // Verify that tab IDs appear only once within a session. | 405 // Verify that tab IDs appear only once within a session. |
| 407 // Intended to prevent http://crbug.com/360822. | 406 // Intended to prevent http://crbug.com/360822. |
| 408 std::set<int> session_tab_ids; | 407 std::set<int> session_tab_ids; |
| 409 for (int i = 0; i < header.window_size(); ++i) { | 408 for (int i = 0; i < header.window_size(); ++i) { |
| 410 const sync_pb::SessionWindow& window = header.window(i); | 409 const sync_pb::SessionWindow& window = header.window(i); |
| 411 for (int j = 0; j < window.tab_size(); ++j) { | 410 for (int j = 0; j < window.tab_size(); ++j) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 427 virtual_url.spec() == kNTPOpenTabSyncURL) { | 426 virtual_url.spec() == kNTPOpenTabSyncURL) { |
| 428 DVLOG(1) << "Triggering sync refresh for sessions datatype."; | 427 DVLOG(1) << "Triggering sync refresh for sessions datatype."; |
| 429 if (!datatype_refresh_callback_.is_null()) | 428 if (!datatype_refresh_callback_.is_null()) |
| 430 datatype_refresh_callback_.Run(); | 429 datatype_refresh_callback_.Run(); |
| 431 } | 430 } |
| 432 } | 431 } |
| 433 | 432 |
| 434 if (local_tab_pool_out_of_sync_) { | 433 if (local_tab_pool_out_of_sync_) { |
| 435 // If our tab pool is corrupt, pay the price of a full re-association to | 434 // If our tab pool is corrupt, pay the price of a full re-association to |
| 436 // fix things up. This takes care of the new tab modification as well. | 435 // fix things up. This takes care of the new tab modification as well. |
| 437 RebuildAssociations(); | 436 bool rebuild_association_succeeded = RebuildAssociations(); |
| 438 DCHECK(!local_tab_pool_out_of_sync_); | 437 DCHECK(!rebuild_association_succeeded || !local_tab_pool_out_of_sync_); |
| 439 return; | 438 return; |
| 440 } | 439 } |
| 441 | 440 |
| 442 syncer::SyncChangeList changes; | 441 syncer::SyncChangeList changes; |
| 443 AssociateTab(modified_tab, &changes); | 442 AssociateTab(modified_tab, &changes); |
| 444 // Note, we always associate windows because it's possible a tab became | 443 // 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 | 444 // "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 | 445 // to the window's tab information. Similarly, if a tab became |
| 447 // "uninteresting", we remove it from the window's tab information. | 446 // "uninteresting", we remove it from the window's tab information. |
| 448 AssociateWindows(DONT_RELOAD_TABS, syncer::SyncDataList(), &changes); | 447 AssociateWindows(DONT_RELOAD_TABS, syncer::SyncDataList(), &changes); |
| (...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 760 | 759 |
| 761 // Update the last modified time. | 760 // Update the last modified time. |
| 762 if (foreign_session->modified_time < modification_time) | 761 if (foreign_session->modified_time < modification_time) |
| 763 foreign_session->modified_time = modification_time; | 762 foreign_session->modified_time = modification_time; |
| 764 } else { | 763 } else { |
| 765 LOG(WARNING) << "Ignoring foreign session node with missing header/tab " | 764 LOG(WARNING) << "Ignoring foreign session node with missing header/tab " |
| 766 << "fields and tag " << foreign_session_tag << "."; | 765 << "fields and tag " << foreign_session_tag << "."; |
| 767 } | 766 } |
| 768 } | 767 } |
| 769 | 768 |
| 770 void SessionsSyncManager::InitializeCurrentMachineTag() { | 769 void SessionsSyncManager::InitializeCurrentMachineTag( |
| 770 const std::string& cache_guid) { |
| 771 DCHECK(current_machine_tag_.empty()); | 771 DCHECK(current_machine_tag_.empty()); |
| 772 std::string persisted_guid; | 772 std::string persisted_guid; |
| 773 persisted_guid = sync_prefs_->GetSyncSessionsGUID(); | 773 persisted_guid = sync_prefs_->GetSyncSessionsGUID(); |
| 774 if (!persisted_guid.empty()) { | 774 if (!persisted_guid.empty()) { |
| 775 current_machine_tag_ = persisted_guid; | 775 current_machine_tag_ = persisted_guid; |
| 776 DVLOG(1) << "Restoring persisted session sync guid: " << persisted_guid; | 776 DVLOG(1) << "Restoring persisted session sync guid: " << persisted_guid; |
| 777 } else { | 777 } else { |
| 778 DCHECK(local_device_); | |
| 779 std::string cache_guid = local_device_->GetLocalSyncCacheGUID(); | |
| 780 DCHECK(!cache_guid.empty()); | 778 DCHECK(!cache_guid.empty()); |
| 781 current_machine_tag_ = BuildMachineTag(cache_guid); | 779 current_machine_tag_ = BuildMachineTag(cache_guid); |
| 782 DVLOG(1) << "Creating session sync guid: " << current_machine_tag_; | 780 DVLOG(1) << "Creating session sync guid: " << current_machine_tag_; |
| 783 sync_prefs_->SetSyncSessionsGUID(current_machine_tag_); | 781 sync_prefs_->SetSyncSessionsGUID(current_machine_tag_); |
| 784 } | 782 } |
| 785 | 783 |
| 786 local_tab_pool_.SetMachineTag(current_machine_tag_); | 784 local_tab_pool_.SetMachineTag(current_machine_tag_); |
| 787 } | 785 } |
| 788 | 786 |
| 789 // static | 787 // static |
| (...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1132 } | 1130 } |
| 1133 | 1131 |
| 1134 // static | 1132 // static |
| 1135 std::string SessionsSyncManager::TagHashFromSpecifics( | 1133 std::string SessionsSyncManager::TagHashFromSpecifics( |
| 1136 const sync_pb::SessionSpecifics& specifics) { | 1134 const sync_pb::SessionSpecifics& specifics) { |
| 1137 return syncer::GenerateSyncableHash(syncer::SESSIONS, | 1135 return syncer::GenerateSyncableHash(syncer::SESSIONS, |
| 1138 TagFromSpecifics(specifics)); | 1136 TagFromSpecifics(specifics)); |
| 1139 } | 1137 } |
| 1140 | 1138 |
| 1141 }; // namespace sync_sessions | 1139 }; // namespace sync_sessions |
| OLD | NEW |