Index: components/sync_driver/device_info_service.cc |
diff --git a/components/sync_driver/device_info_service.cc b/components/sync_driver/device_info_service.cc |
index 5f1efcc7665b24c3417a0668350c10d5361d8999..8e478b04dc19d19787a239a179384ade9cad3670 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>(); |
} |