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 "chrome/browser/sync/glue/device_info_sync_service.h" | 5 #include "chrome/browser/sync/glue/device_info_sync_service.h" |
| 6 | 6 |
| 7 #include "base/strings/stringprintf.h" | 7 #include "base/strings/stringprintf.h" |
| 8 #include "chrome/browser/sync/glue/local_device_info_provider.h" | 8 #include "chrome/browser/sync/glue/local_device_info_provider.h" |
| 9 #include "sync/api/sync_change.h" | 9 #include "sync/api/sync_change.h" |
| 10 #include "sync/protocol/sync.pb.h" | 10 #include "sync/protocol/sync.pb.h" |
| 11 #include "sync/util/time.h" | |
| 11 | 12 |
| 12 namespace browser_sync { | 13 namespace browser_sync { |
| 13 | 14 |
| 14 using syncer::ModelType; | 15 using syncer::ModelType; |
| 15 using syncer::SyncChange; | 16 using syncer::SyncChange; |
| 16 using syncer::SyncChangeList; | 17 using syncer::SyncChangeList; |
| 17 using syncer::SyncChangeProcessor; | 18 using syncer::SyncChangeProcessor; |
| 18 using syncer::SyncData; | 19 using syncer::SyncData; |
| 19 using syncer::SyncDataList; | 20 using syncer::SyncDataList; |
| 20 using syncer::SyncErrorFactory; | 21 using syncer::SyncErrorFactory; |
| 21 using syncer::SyncMergeResult; | 22 using syncer::SyncMergeResult; |
| 22 | 23 |
| 23 DeviceInfoSyncService::DeviceInfoSyncService( | 24 DeviceInfoSyncService::DeviceInfoSyncService( |
| 24 LocalDeviceInfoProvider* local_device_info_provider) | 25 LocalDeviceInfoProvider* local_device_info_provider) |
| 25 : local_device_info_provider_(local_device_info_provider) { | 26 : local_device_backup_time_(-1), |
| 27 local_device_info_provider_(local_device_info_provider) { | |
| 26 DCHECK(local_device_info_provider); | 28 DCHECK(local_device_info_provider); |
| 27 } | 29 } |
| 28 | 30 |
| 29 DeviceInfoSyncService::~DeviceInfoSyncService() { | 31 DeviceInfoSyncService::~DeviceInfoSyncService() { |
| 30 } | 32 } |
| 31 | 33 |
| 32 SyncMergeResult DeviceInfoSyncService::MergeDataAndStartSyncing( | 34 SyncMergeResult DeviceInfoSyncService::MergeDataAndStartSyncing( |
| 33 ModelType type, | 35 ModelType type, |
| 34 const SyncDataList& initial_sync_data, | 36 const SyncDataList& initial_sync_data, |
| 35 scoped_ptr<SyncChangeProcessor> sync_processor, | 37 scoped_ptr<SyncChangeProcessor> sync_processor, |
| 36 scoped_ptr<SyncErrorFactory> error_handler) { | 38 scoped_ptr<SyncErrorFactory> error_handler) { |
| 37 DCHECK(sync_processor.get()); | 39 DCHECK(sync_processor.get()); |
| 38 DCHECK(error_handler.get()); | 40 DCHECK(error_handler.get()); |
| 39 DCHECK_EQ(type, syncer::DEVICE_INFO); | 41 DCHECK_EQ(type, syncer::DEVICE_INFO); |
| 40 | 42 |
| 41 DCHECK(all_data_.empty()); | 43 DCHECK(all_data_.empty()); |
| 42 | 44 |
| 43 sync_processor_ = sync_processor.Pass(); | 45 sync_processor_ = sync_processor.Pass(); |
| 44 error_handler_ = error_handler.Pass(); | 46 error_handler_ = error_handler.Pass(); |
| 45 | 47 |
| 48 // Initialization should be completed before this type is enabled | |
| 49 // and local device info must be available. | |
| 50 const DeviceInfo* local_device_info = | |
| 51 local_device_info_provider_->GetLocalDeviceInfo(); | |
| 52 DCHECK(local_device_info != NULL); | |
| 53 | |
| 54 // Indicates whether a local device has been added or updated. | |
| 55 // |change_type| defaults to ADD and might be changed to | |
| 56 // UPDATE to INVALID down below if the initial data contains | |
| 57 // data matching the local device ID. | |
| 58 SyncChange::SyncChangeType change_type = SyncChange::ACTION_ADD; | |
| 59 size_t num_items_new = 0; | |
| 60 size_t num_items_updated = 0; | |
| 61 | |
| 46 // Iterate over all initial sync data and copy it to the cache. | 62 // Iterate over all initial sync data and copy it to the cache. |
| 47 for (SyncDataList::const_iterator iter = initial_sync_data.begin(); | 63 for (SyncDataList::const_iterator iter = initial_sync_data.begin(); |
| 48 iter != initial_sync_data.end(); | 64 iter != initial_sync_data.end(); |
| 49 ++iter) { | 65 ++iter) { |
| 50 DCHECK_EQ(syncer::DEVICE_INFO, iter->GetDataType()); | 66 DCHECK_EQ(syncer::DEVICE_INFO, iter->GetDataType()); |
| 51 StoreSyncData(iter->GetSpecifics().device_info().cache_guid(), *iter); | |
| 52 } | |
| 53 | 67 |
| 54 size_t num_items_new = initial_sync_data.size(); | 68 const std::string& id = iter->GetSpecifics().device_info().cache_guid(); |
| 55 size_t num_items_updated = 0; | |
| 56 // Indicates whether a local device has been added or updated. | |
| 57 SyncChange::SyncChangeType change_type = SyncChange::ACTION_INVALID; | |
| 58 | 69 |
| 59 // Initialization should be completed before this type is enabled | 70 if (id == local_device_info->guid()) { |
| 60 // and local device info must be available. | 71 // |initial_sync_data| contains data matching the local device. |
| 61 const DeviceInfo* local_device_info = | 72 scoped_ptr<DeviceInfo> synced_local_device_info = |
| 62 local_device_info_provider_->GetLocalDeviceInfo(); | 73 make_scoped_ptr(CreateDeviceInfo(*iter)); |
| 63 DCHECK(local_device_info != NULL); | |
| 64 // Before storing the local device info check if the data with | |
| 65 // the same guid has already been synced. This attempts to retrieve | |
| 66 // DeviceInfo from the cached data initialized above. | |
| 67 scoped_ptr<DeviceInfo> synced_local_device_info = | |
| 68 GetDeviceInfo(local_device_info->guid()); | |
| 69 | 74 |
| 70 if (synced_local_device_info.get()) { | 75 // Retrieve local device backup timestamp value from the sync data. |
| 71 // Local device info has been synced and exists in the cache. | 76 bool has_synced_backup_time = |
| 72 // |num_items_new| and |num_items_updated| need to be updated to | 77 iter->GetSpecifics().device_info().has_backup_timestamp(); |
| 73 // reflect that. | 78 int64 synced_backup_time = |
| 74 num_items_new--; | 79 has_synced_backup_time |
| 75 // Overwrite the synced device info with the local data only if | 80 ? iter->GetSpecifics().device_info().backup_timestamp() |
| 76 // it is different. | 81 : -1; |
| 77 if (!synced_local_device_info->Equals(*local_device_info)) { | 82 |
| 78 num_items_updated++; | 83 // Overwrite |local_device_backup_time_| with this value if it |
| 79 change_type = SyncChange::ACTION_UPDATE; | 84 // hasn't been set yet. |
| 85 if (!has_local_device_backup_time() && has_synced_backup_time) { | |
| 86 set_local_device_backup_time(synced_backup_time); | |
| 87 } | |
| 88 | |
| 89 // Store the synced device info for the local device only | |
| 90 // it is the same as the local info. Otherwise store the local | |
| 91 // device info and issue a change further below after finishing | |
| 92 // processing the |initial_sync_data|. | |
| 93 if (synced_local_device_info->Equals(*local_device_info) && | |
| 94 synced_backup_time == local_device_backup_time()) { | |
| 95 change_type = SyncChange::ACTION_INVALID; | |
| 96 } else { | |
| 97 num_items_updated++; | |
| 98 change_type = SyncChange::ACTION_UPDATE; | |
| 99 continue; | |
| 100 } | |
| 101 } else { | |
| 102 // A new device that doesn't match the local device. | |
| 103 num_items_new++; | |
| 80 } | 104 } |
| 81 } else { | 105 |
| 82 // Local device info doesn't yet exist in the cache and | 106 StoreSyncData(id, *iter); |
| 83 // will be added further below. | |
| 84 // |num_items_new| and |num_items_updated| are already correct. | |
| 85 change_type = SyncChange::ACTION_ADD; | |
| 86 } | 107 } |
| 87 | 108 |
| 88 syncer::SyncMergeResult result(type); | 109 syncer::SyncMergeResult result(type); |
| 89 | 110 |
| 90 // Update SyncData from device info if it is new or different than | 111 // Add SyncData for the local deviceif it is new or different than |
|
pavely
2014/09/17 23:05:32
deviceif => device if
| |
| 91 // the synced one, and also add it to the |change_list|. | 112 // the synced one, and also add it to the |change_list|. |
| 92 if (change_type != SyncChange::ACTION_INVALID) { | 113 if (change_type != SyncChange::ACTION_INVALID) { |
| 93 SyncData local_data = CreateLocalData(local_device_info); | 114 SyncData local_data = CreateLocalData(local_device_info); |
| 94 StoreSyncData(local_device_info->guid(), local_data); | 115 StoreSyncData(local_device_info->guid(), local_data); |
| 95 | 116 |
| 96 SyncChangeList change_list; | 117 SyncChangeList change_list; |
| 97 change_list.push_back(SyncChange(FROM_HERE, change_type, local_data)); | 118 change_list.push_back(SyncChange(FROM_HERE, change_type, local_data)); |
| 98 result.set_error( | 119 result.set_error( |
| 99 sync_processor_->ProcessSyncChanges(FROM_HERE, change_list)); | 120 sync_processor_->ProcessSyncChanges(FROM_HERE, change_list)); |
| 100 } | 121 } |
| 101 | 122 |
| 102 result.set_num_items_before_association(1); | 123 result.set_num_items_before_association(1); |
| 103 result.set_num_items_after_association(all_data_.size()); | 124 result.set_num_items_after_association(all_data_.size()); |
| 104 result.set_num_items_added(num_items_new); | 125 result.set_num_items_added(num_items_new); |
| 105 result.set_num_items_modified(num_items_updated); | 126 result.set_num_items_modified(num_items_updated); |
| 106 result.set_num_items_deleted(0); | 127 result.set_num_items_deleted(0); |
| 107 | 128 |
| 108 NotifyObservers(); | 129 NotifyObservers(); |
| 109 | 130 |
| 110 return result; | 131 return result; |
| 111 } | 132 } |
| 112 | 133 |
| 113 void DeviceInfoSyncService::StopSyncing(syncer::ModelType type) { | 134 void DeviceInfoSyncService::StopSyncing(syncer::ModelType type) { |
| 114 all_data_.clear(); | 135 all_data_.clear(); |
| 115 sync_processor_.reset(); | 136 sync_processor_.reset(); |
| 116 error_handler_.reset(); | 137 error_handler_.reset(); |
| 138 clear_local_device_backup_time(); | |
| 117 } | 139 } |
| 118 | 140 |
| 119 SyncDataList DeviceInfoSyncService::GetAllSyncData( | 141 SyncDataList DeviceInfoSyncService::GetAllSyncData( |
| 120 syncer::ModelType type) const { | 142 syncer::ModelType type) const { |
| 121 SyncDataList list; | 143 SyncDataList list; |
| 122 | 144 |
| 123 for (SyncDataMap::const_iterator iter = all_data_.begin(); | 145 for (SyncDataMap::const_iterator iter = all_data_.begin(); |
| 124 iter != all_data_.end(); | 146 iter != all_data_.end(); |
| 125 ++iter) { | 147 ++iter) { |
| 126 list.push_back(iter->second); | 148 list.push_back(iter->second); |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 201 } | 223 } |
| 202 | 224 |
| 203 void DeviceInfoSyncService::RemoveObserver(Observer* observer) { | 225 void DeviceInfoSyncService::RemoveObserver(Observer* observer) { |
| 204 observers_.RemoveObserver(observer); | 226 observers_.RemoveObserver(observer); |
| 205 } | 227 } |
| 206 | 228 |
| 207 void DeviceInfoSyncService::NotifyObservers() { | 229 void DeviceInfoSyncService::NotifyObservers() { |
| 208 FOR_EACH_OBSERVER(Observer, observers_, OnDeviceInfoChange()); | 230 FOR_EACH_OBSERVER(Observer, observers_, OnDeviceInfoChange()); |
| 209 } | 231 } |
| 210 | 232 |
| 233 void DeviceInfoSyncService::UpdateLocalDeviceBackupTime( | |
| 234 base::Time backup_time) { | |
| 235 set_local_device_backup_time(syncer::TimeToProtoTime(backup_time)); | |
| 236 | |
| 237 if (sync_processor_.get()) { | |
| 238 // Local device info must be available in advance | |
| 239 DCHECK(local_device_info_provider_->GetLocalDeviceInfo()); | |
| 240 const std::string& local_id = | |
| 241 local_device_info_provider_->GetLocalDeviceInfo()->guid(); | |
| 242 | |
| 243 SyncDataMap::iterator iter = all_data_.find(local_id); | |
| 244 DCHECK(iter != all_data_.end()); | |
| 245 | |
| 246 if (UpdateBackupTime(iter->second)) { | |
| 247 // Local device backup time has changed. | |
| 248 // Push changes to the server via the |sync_processor_|. | |
| 249 SyncChangeList change_list; | |
| 250 change_list.push_back(SyncChange( | |
| 251 FROM_HERE, syncer::SyncChange::ACTION_UPDATE, iter->second)); | |
| 252 sync_processor_->ProcessSyncChanges(FROM_HERE, change_list); | |
| 253 } | |
| 254 } | |
| 255 } | |
| 256 | |
| 257 bool DeviceInfoSyncService::UpdateBackupTime(syncer::SyncData& sync_data) { | |
|
pavely
2014/09/17 23:04:38
nit: Pass sync_data as pointer (http://google-styl
| |
| 258 DCHECK(has_local_device_backup_time()); | |
| 259 DCHECK(sync_data.GetSpecifics().has_device_info()); | |
| 260 const sync_pb::DeviceInfoSpecifics& source_specifics = | |
| 261 sync_data.GetSpecifics().device_info(); | |
| 262 | |
| 263 if (!source_specifics.has_backup_timestamp() || | |
| 264 source_specifics.backup_timestamp() != local_device_backup_time()) { | |
| 265 sync_pb::EntitySpecifics entity(sync_data.GetSpecifics()); | |
| 266 entity.mutable_device_info()->set_backup_timestamp( | |
| 267 local_device_backup_time()); | |
| 268 sync_data = CreateLocalData(entity); | |
| 269 | |
| 270 return true; | |
| 271 } | |
| 272 | |
| 273 return false; | |
| 274 } | |
| 275 | |
| 276 base::Time DeviceInfoSyncService::GetLocalDeviceBackupTime() const { | |
| 277 return has_local_device_backup_time() | |
| 278 ? syncer::ProtoTimeToTime(local_device_backup_time()) | |
| 279 : base::Time(); | |
| 280 } | |
| 281 | |
| 211 SyncData DeviceInfoSyncService::CreateLocalData(const DeviceInfo* info) { | 282 SyncData DeviceInfoSyncService::CreateLocalData(const DeviceInfo* info) { |
| 212 sync_pb::EntitySpecifics entity; | 283 sync_pb::EntitySpecifics entity; |
| 213 sync_pb::DeviceInfoSpecifics& specifics = *entity.mutable_device_info(); | 284 sync_pb::DeviceInfoSpecifics& specifics = *entity.mutable_device_info(); |
| 214 | 285 |
| 215 specifics.set_cache_guid(info->guid()); | 286 specifics.set_cache_guid(info->guid()); |
| 216 specifics.set_client_name(info->client_name()); | 287 specifics.set_client_name(info->client_name()); |
| 217 specifics.set_chrome_version(info->chrome_version()); | 288 specifics.set_chrome_version(info->chrome_version()); |
| 218 specifics.set_sync_user_agent(info->sync_user_agent()); | 289 specifics.set_sync_user_agent(info->sync_user_agent()); |
| 219 specifics.set_device_type(info->device_type()); | 290 specifics.set_device_type(info->device_type()); |
| 220 specifics.set_signin_scoped_device_id(info->signin_scoped_device_id()); | 291 specifics.set_signin_scoped_device_id(info->signin_scoped_device_id()); |
| 221 | 292 |
| 293 if (has_local_device_backup_time()) { | |
| 294 specifics.set_backup_timestamp(local_device_backup_time()); | |
| 295 } | |
| 296 | |
| 297 return CreateLocalData(entity); | |
| 298 } | |
| 299 | |
| 300 SyncData DeviceInfoSyncService::CreateLocalData( | |
| 301 const sync_pb::EntitySpecifics& entity) { | |
| 302 const sync_pb::DeviceInfoSpecifics& specifics = entity.device_info(); | |
| 303 | |
| 222 std::string local_device_tag = | 304 std::string local_device_tag = |
| 223 base::StringPrintf("DeviceInfo_%s", info->guid().c_str()); | 305 base::StringPrintf("DeviceInfo_%s", specifics.cache_guid().c_str()); |
| 224 | 306 |
| 225 return SyncData::CreateLocalData( | 307 return SyncData::CreateLocalData( |
| 226 local_device_tag, info->client_name(), entity); | 308 local_device_tag, specifics.client_name(), entity); |
| 227 } | 309 } |
| 228 | 310 |
| 229 DeviceInfo* DeviceInfoSyncService::CreateDeviceInfo( | 311 DeviceInfo* DeviceInfoSyncService::CreateDeviceInfo( |
| 230 const syncer::SyncData sync_data) { | 312 const syncer::SyncData sync_data) { |
| 231 const sync_pb::DeviceInfoSpecifics& specifics = | 313 const sync_pb::DeviceInfoSpecifics& specifics = |
| 232 sync_data.GetSpecifics().device_info(); | 314 sync_data.GetSpecifics().device_info(); |
| 233 | 315 |
| 234 return new DeviceInfo(specifics.cache_guid(), | 316 return new DeviceInfo(specifics.cache_guid(), |
| 235 specifics.client_name(), | 317 specifics.client_name(), |
| 236 specifics.chrome_version(), | 318 specifics.chrome_version(), |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 251 SyncDataMap::iterator iter = all_data_.find(client_id); | 333 SyncDataMap::iterator iter = all_data_.find(client_id); |
| 252 if (iter != all_data_.end()) { | 334 if (iter != all_data_.end()) { |
| 253 DVLOG(1) << "Deleting DEVICE_INFO for " | 335 DVLOG(1) << "Deleting DEVICE_INFO for " |
| 254 << iter->second.GetSpecifics().device_info().client_name() | 336 << iter->second.GetSpecifics().device_info().client_name() |
| 255 << " with ID " << client_id; | 337 << " with ID " << client_id; |
| 256 all_data_.erase(iter); | 338 all_data_.erase(iter); |
| 257 } | 339 } |
| 258 } | 340 } |
| 259 | 341 |
| 260 } // namespace browser_sync | 342 } // namespace browser_sync |
| OLD | NEW |