diff options
Diffstat (limited to 'components/sync_driver/device_info_service.cc')
-rw-r--r-- | components/sync_driver/device_info_service.cc | 64 |
1 files changed, 58 insertions, 6 deletions
diff --git a/components/sync_driver/device_info_service.cc b/components/sync_driver/device_info_service.cc index 8702864..6a63dcb 100644 --- a/components/sync_driver/device_info_service.cc +++ b/components/sync_driver/device_info_service.cc @@ -4,6 +4,7 @@ #include "components/sync_driver/device_info_service.h" +#include <set> #include <utility> #include <vector> @@ -69,8 +70,59 @@ scoped_ptr<MetadataChangeList> DeviceInfoService::CreateMetadataChangeList() { SyncError DeviceInfoService::MergeSyncData( scoped_ptr<MetadataChangeList> metadata_change_list, EntityDataMap entity_data_map) { - // TODO(skym): crbug.com/543406: Implementation. - return SyncError(); + if (!has_provider_initialized_ || !has_data_loaded_ || !change_processor()) { + return SyncError( + FROM_HERE, SyncError::DATATYPE_ERROR, + "Cannot call MergeSyncData without provider, data, and processor.", + syncer::DEVICE_INFO); + } + + // Local data should typically be near empty, with the only possible value + // corresponding to this device. This is because on signout all device info + // data is blown away. However, this simplification is being ignored here and + // a full difference is going to be calculated to explore what other service + // implementations may look like. + std::set<std::string> local_only_tags; + for (const auto& kv : all_data_) { + local_only_tags.insert(kv.first); + } + + bool has_changes = false; + std::string local_tag = + local_device_info_provider_->GetLocalDeviceInfo()->guid(); + scoped_ptr<WriteBatch> batch = store_->CreateWriteBatch(); + for (const auto& kv : entity_data_map) { + const std::string tag = GetClientTag(kv.second.value()); + const DeviceInfoSpecifics& specifics = + kv.second.value().specifics.device_info(); + + // Ignore any remote changes that have our local cache guid. + if (tag == local_tag) { + continue; + } + + // Remote data wins conflicts. + local_only_tags.erase(tag); + StoreSpecifics(make_scoped_ptr(new DeviceInfoSpecifics(specifics)), + batch.get()); + has_changes = true; + } + + for (const std::string& tag : local_only_tags) { + change_processor()->Put(tag, CopyIntoNewEntityData(*all_data_[tag]), + metadata_change_list.get()); + } + + // Transfer at the end because processor Put calls may update metadata. + static_cast<SimpleMetadataChangeList*>(metadata_change_list.get()) + ->TransferChanges(store_.get(), batch.get()); + store_->CommitWriteBatch( + std::move(batch), + base::Bind(&DeviceInfoService::OnCommit, weak_factory_.GetWeakPtr())); + if (has_changes) { + NotifyObservers(); + } + return syncer::SyncError(); } SyncError DeviceInfoService::ApplySyncChanges( @@ -128,8 +180,8 @@ void DeviceInfoService::GetData(ClientTagList client_tags, syncer::SyncError error; scoped_ptr<DataBatchImpl> batch(new DataBatchImpl()); - for (auto& tag : client_tags) { - auto iter = all_data_.find(tag); + for (const auto& tag : client_tags) { + const auto iter = all_data_.find(tag); if (iter != all_data_.end()) { batch->Put(tag, CopyIntoNewEntityData(*iter->second)); } @@ -148,7 +200,7 @@ void DeviceInfoService::GetAllData(DataCallback callback) { syncer::SyncError error; scoped_ptr<DataBatchImpl> batch(new DataBatchImpl()); - for (auto& kv : all_data_) { + for (const auto& kv : all_data_) { batch->Put(kv.first, CopyIntoNewEntityData(*kv.second)); } callback.Run(error, std::move(batch)); @@ -169,7 +221,7 @@ bool DeviceInfoService::IsSyncing() const { scoped_ptr<DeviceInfo> DeviceInfoService::GetDeviceInfo( const std::string& client_id) const { - ClientIdToSpecifics::const_iterator iter = all_data_.find(client_id); + const ClientIdToSpecifics::const_iterator iter = all_data_.find(client_id); if (iter == all_data_.end()) { return scoped_ptr<DeviceInfo>(); } |