| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/device_info/device_info_sync_bridge.h" | 5 #include "components/sync/device_info/device_info_sync_bridge.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <set> | 10 #include <set> |
| 11 #include <utility> | 11 #include <utility> |
| 12 | 12 |
| 13 #include "base/bind.h" | 13 #include "base/bind.h" |
| 14 #include "base/location.h" | 14 #include "base/location.h" |
| 15 #include "base/memory/ptr_util.h" | 15 #include "base/memory/ptr_util.h" |
| 16 #include "base/strings/string_util.h" | 16 #include "base/strings/string_util.h" |
| 17 #include "components/sync/base/time.h" | 17 #include "components/sync/base/time.h" |
| 18 #include "components/sync/device_info/device_info_util.h" | 18 #include "components/sync/device_info/device_info_util.h" |
| 19 #include "components/sync/model/entity_change.h" | 19 #include "components/sync/model/entity_change.h" |
| 20 #include "components/sync/model/metadata_batch.h" | 20 #include "components/sync/model/metadata_batch.h" |
| 21 #include "components/sync/model/model_error.h" |
| 21 #include "components/sync/model/mutable_data_batch.h" | 22 #include "components/sync/model/mutable_data_batch.h" |
| 22 #include "components/sync/model/sync_error.h" | |
| 23 #include "components/sync/protocol/model_type_state.pb.h" | 23 #include "components/sync/protocol/model_type_state.pb.h" |
| 24 #include "components/sync/protocol/sync.pb.h" | 24 #include "components/sync/protocol/sync.pb.h" |
| 25 | 25 |
| 26 namespace syncer { | 26 namespace syncer { |
| 27 | 27 |
| 28 using base::Time; | 28 using base::Time; |
| 29 using base::TimeDelta; | 29 using base::TimeDelta; |
| 30 using sync_pb::DeviceInfoSpecifics; | 30 using sync_pb::DeviceInfoSpecifics; |
| 31 using sync_pb::EntitySpecifics; | 31 using sync_pb::EntitySpecifics; |
| 32 using sync_pb::ModelTypeState; | 32 using sync_pb::ModelTypeState; |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 106 base::Bind(&DeviceInfoSyncBridge::OnStoreCreated, base::AsWeakPtr(this))); | 106 base::Bind(&DeviceInfoSyncBridge::OnStoreCreated, base::AsWeakPtr(this))); |
| 107 } | 107 } |
| 108 | 108 |
| 109 DeviceInfoSyncBridge::~DeviceInfoSyncBridge() {} | 109 DeviceInfoSyncBridge::~DeviceInfoSyncBridge() {} |
| 110 | 110 |
| 111 std::unique_ptr<MetadataChangeList> | 111 std::unique_ptr<MetadataChangeList> |
| 112 DeviceInfoSyncBridge::CreateMetadataChangeList() { | 112 DeviceInfoSyncBridge::CreateMetadataChangeList() { |
| 113 return WriteBatch::CreateMetadataChangeList(); | 113 return WriteBatch::CreateMetadataChangeList(); |
| 114 } | 114 } |
| 115 | 115 |
| 116 SyncError DeviceInfoSyncBridge::MergeSyncData( | 116 ModelError DeviceInfoSyncBridge::MergeSyncData( |
| 117 std::unique_ptr<MetadataChangeList> metadata_change_list, | 117 std::unique_ptr<MetadataChangeList> metadata_change_list, |
| 118 EntityDataMap entity_data_map) { | 118 EntityDataMap entity_data_map) { |
| 119 DCHECK(has_provider_initialized_); | 119 DCHECK(has_provider_initialized_); |
| 120 DCHECK(change_processor()->IsTrackingMetadata()); | 120 DCHECK(change_processor()->IsTrackingMetadata()); |
| 121 const DeviceInfo* local_info = | 121 const DeviceInfo* local_info = |
| 122 local_device_info_provider_->GetLocalDeviceInfo(); | 122 local_device_info_provider_->GetLocalDeviceInfo(); |
| 123 // If our dependency was yanked out from beneath us, we cannot correctly | 123 // If our dependency was yanked out from beneath us, we cannot correctly |
| 124 // handle this request, and all our data will be deleted soon. | 124 // handle this request, and all our data will be deleted soon. |
| 125 if (local_info == nullptr) { | 125 if (local_info == nullptr) { |
| 126 return SyncError(); | 126 return ModelError(); |
| 127 } | 127 } |
| 128 | 128 |
| 129 // Local data should typically be near empty, with the only possible value | 129 // Local data should typically be near empty, with the only possible value |
| 130 // corresponding to this device. This is because on signout all device info | 130 // corresponding to this device. This is because on signout all device info |
| 131 // data is blown away. However, this simplification is being ignored here and | 131 // data is blown away. However, this simplification is being ignored here and |
| 132 // a full difference is going to be calculated to explore what other bridge | 132 // a full difference is going to be calculated to explore what other bridge |
| 133 // implementations may look like. | 133 // implementations may look like. |
| 134 std::set<std::string> local_guids_to_put; | 134 std::set<std::string> local_guids_to_put; |
| 135 for (const auto& kv : all_data_) { | 135 for (const auto& kv : all_data_) { |
| 136 local_guids_to_put.insert(kv.first); | 136 local_guids_to_put.insert(kv.first); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 157 } | 157 } |
| 158 } | 158 } |
| 159 | 159 |
| 160 for (const std::string& guid : local_guids_to_put) { | 160 for (const std::string& guid : local_guids_to_put) { |
| 161 change_processor()->Put(guid, CopyToEntityData(*all_data_[guid]), | 161 change_processor()->Put(guid, CopyToEntityData(*all_data_[guid]), |
| 162 metadata_change_list.get()); | 162 metadata_change_list.get()); |
| 163 } | 163 } |
| 164 | 164 |
| 165 batch->TransferMetadataChanges(std::move(metadata_change_list)); | 165 batch->TransferMetadataChanges(std::move(metadata_change_list)); |
| 166 CommitAndNotify(std::move(batch), has_changes); | 166 CommitAndNotify(std::move(batch), has_changes); |
| 167 return SyncError(); | 167 return ModelError(); |
| 168 } | 168 } |
| 169 | 169 |
| 170 SyncError DeviceInfoSyncBridge::ApplySyncChanges( | 170 ModelError DeviceInfoSyncBridge::ApplySyncChanges( |
| 171 std::unique_ptr<MetadataChangeList> metadata_change_list, | 171 std::unique_ptr<MetadataChangeList> metadata_change_list, |
| 172 EntityChangeList entity_changes) { | 172 EntityChangeList entity_changes) { |
| 173 DCHECK(has_provider_initialized_); | 173 DCHECK(has_provider_initialized_); |
| 174 const DeviceInfo* local_info = | 174 const DeviceInfo* local_info = |
| 175 local_device_info_provider_->GetLocalDeviceInfo(); | 175 local_device_info_provider_->GetLocalDeviceInfo(); |
| 176 // If our dependency was yanked out from beneath us, we cannot correctly | 176 // If our dependency was yanked out from beneath us, we cannot correctly |
| 177 // handle this request, and all our data will be deleted soon. | 177 // handle this request, and all our data will be deleted soon. |
| 178 if (local_info == nullptr) { | 178 if (local_info == nullptr) { |
| 179 return SyncError(); | 179 return ModelError(); |
| 180 } | 180 } |
| 181 | 181 |
| 182 std::unique_ptr<WriteBatch> batch = store_->CreateWriteBatch(); | 182 std::unique_ptr<WriteBatch> batch = store_->CreateWriteBatch(); |
| 183 bool has_changes = false; | 183 bool has_changes = false; |
| 184 for (EntityChange& change : entity_changes) { | 184 for (EntityChange& change : entity_changes) { |
| 185 const std::string guid = change.storage_key(); | 185 const std::string guid = change.storage_key(); |
| 186 // Each device is the authoritative source for itself, ignore any remote | 186 // Each device is the authoritative source for itself, ignore any remote |
| 187 // changes that have our local cache guid. | 187 // changes that have our local cache guid. |
| 188 if (guid == local_info->guid()) { | 188 if (guid == local_info->guid()) { |
| 189 continue; | 189 continue; |
| 190 } | 190 } |
| 191 | 191 |
| 192 if (change.type() == EntityChange::ACTION_DELETE) { | 192 if (change.type() == EntityChange::ACTION_DELETE) { |
| 193 has_changes |= DeleteSpecifics(guid, batch.get()); | 193 has_changes |= DeleteSpecifics(guid, batch.get()); |
| 194 } else { | 194 } else { |
| 195 const DeviceInfoSpecifics& specifics = | 195 const DeviceInfoSpecifics& specifics = |
| 196 change.data().specifics.device_info(); | 196 change.data().specifics.device_info(); |
| 197 DCHECK(guid == specifics.cache_guid()); | 197 DCHECK(guid == specifics.cache_guid()); |
| 198 StoreSpecifics(base::MakeUnique<DeviceInfoSpecifics>(specifics), | 198 StoreSpecifics(base::MakeUnique<DeviceInfoSpecifics>(specifics), |
| 199 batch.get()); | 199 batch.get()); |
| 200 has_changes = true; | 200 has_changes = true; |
| 201 } | 201 } |
| 202 } | 202 } |
| 203 | 203 |
| 204 batch->TransferMetadataChanges(std::move(metadata_change_list)); | 204 batch->TransferMetadataChanges(std::move(metadata_change_list)); |
| 205 CommitAndNotify(std::move(batch), has_changes); | 205 CommitAndNotify(std::move(batch), has_changes); |
| 206 return SyncError(); | 206 return ModelError(); |
| 207 } | 207 } |
| 208 | 208 |
| 209 void DeviceInfoSyncBridge::GetData(StorageKeyList storage_keys, | 209 void DeviceInfoSyncBridge::GetData(StorageKeyList storage_keys, |
| 210 DataCallback callback) { | 210 DataCallback callback) { |
| 211 auto batch = base::MakeUnique<MutableDataBatch>(); | 211 auto batch = base::MakeUnique<MutableDataBatch>(); |
| 212 for (const auto& key : storage_keys) { | 212 for (const auto& key : storage_keys) { |
| 213 const auto& iter = all_data_.find(key); | 213 const auto& iter = all_data_.find(key); |
| 214 if (iter != all_data_.end()) { | 214 if (iter != all_data_.end()) { |
| 215 DCHECK_EQ(key, iter->second->cache_guid()); | 215 DCHECK_EQ(key, iter->second->cache_guid()); |
| 216 batch->Put(key, CopyToEntityData(*iter->second)); | 216 batch->Put(key, CopyToEntityData(*iter->second)); |
| 217 } | 217 } |
| 218 } | 218 } |
| 219 callback.Run(SyncError(), std::move(batch)); | 219 callback.Run(std::move(batch)); |
| 220 } | 220 } |
| 221 | 221 |
| 222 void DeviceInfoSyncBridge::GetAllData(DataCallback callback) { | 222 void DeviceInfoSyncBridge::GetAllData(DataCallback callback) { |
| 223 auto batch = base::MakeUnique<MutableDataBatch>(); | 223 auto batch = base::MakeUnique<MutableDataBatch>(); |
| 224 for (const auto& kv : all_data_) { | 224 for (const auto& kv : all_data_) { |
| 225 batch->Put(kv.first, CopyToEntityData(*kv.second)); | 225 batch->Put(kv.first, CopyToEntityData(*kv.second)); |
| 226 } | 226 } |
| 227 callback.Run(SyncError(), std::move(batch)); | 227 callback.Run(std::move(batch)); |
| 228 } | 228 } |
| 229 | 229 |
| 230 std::string DeviceInfoSyncBridge::GetClientTag(const EntityData& entity_data) { | 230 std::string DeviceInfoSyncBridge::GetClientTag(const EntityData& entity_data) { |
| 231 DCHECK(entity_data.specifics.has_device_info()); | 231 DCHECK(entity_data.specifics.has_device_info()); |
| 232 return DeviceInfoUtil::SpecificsToTag(entity_data.specifics.device_info()); | 232 return DeviceInfoUtil::SpecificsToTag(entity_data.specifics.device_info()); |
| 233 } | 233 } |
| 234 | 234 |
| 235 std::string DeviceInfoSyncBridge::GetStorageKey(const EntityData& entity_data) { | 235 std::string DeviceInfoSyncBridge::GetStorageKey(const EntityData& entity_data) { |
| 236 DCHECK(entity_data.specifics.has_device_info()); | 236 DCHECK(entity_data.specifics.has_device_info()); |
| 237 return entity_data.specifics.device_info().cache_guid(); | 237 return entity_data.specifics.device_info().cache_guid(); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 336 } | 336 } |
| 337 | 337 |
| 338 void DeviceInfoSyncBridge::OnStoreCreated( | 338 void DeviceInfoSyncBridge::OnStoreCreated( |
| 339 Result result, | 339 Result result, |
| 340 std::unique_ptr<ModelTypeStore> store) { | 340 std::unique_ptr<ModelTypeStore> store) { |
| 341 if (result == Result::SUCCESS) { | 341 if (result == Result::SUCCESS) { |
| 342 std::swap(store_, store); | 342 std::swap(store_, store); |
| 343 store_->ReadAllData(base::Bind(&DeviceInfoSyncBridge::OnReadAllData, | 343 store_->ReadAllData(base::Bind(&DeviceInfoSyncBridge::OnReadAllData, |
| 344 base::AsWeakPtr(this))); | 344 base::AsWeakPtr(this))); |
| 345 } else { | 345 } else { |
| 346 ReportStartupErrorToSync("ModelTypeStore creation failed."); | 346 change_processor()->ReportError(FROM_HERE, |
| 347 "ModelTypeStore creation failed."); |
| 347 } | 348 } |
| 348 } | 349 } |
| 349 | 350 |
| 350 void DeviceInfoSyncBridge::OnReadAllData( | 351 void DeviceInfoSyncBridge::OnReadAllData( |
| 351 Result result, | 352 Result result, |
| 352 std::unique_ptr<RecordList> record_list) { | 353 std::unique_ptr<RecordList> record_list) { |
| 353 if (result != Result::SUCCESS) { | 354 if (result != Result::SUCCESS) { |
| 354 ReportStartupErrorToSync("Initial load of data failed."); | 355 change_processor()->ReportError(FROM_HERE, "Initial load of data failed."); |
| 355 return; | 356 return; |
| 356 } | 357 } |
| 357 | 358 |
| 358 for (const Record& r : *record_list.get()) { | 359 for (const Record& r : *record_list.get()) { |
| 359 std::unique_ptr<DeviceInfoSpecifics> specifics = | 360 std::unique_ptr<DeviceInfoSpecifics> specifics = |
| 360 base::MakeUnique<DeviceInfoSpecifics>(); | 361 base::MakeUnique<DeviceInfoSpecifics>(); |
| 361 if (specifics->ParseFromString(r.value)) { | 362 if (specifics->ParseFromString(r.value)) { |
| 362 all_data_[specifics->cache_guid()] = std::move(specifics); | 363 all_data_[specifics->cache_guid()] = std::move(specifics); |
| 363 } else { | 364 } else { |
| 364 ReportStartupErrorToSync("Failed to deserialize specifics."); | 365 change_processor()->ReportError(FROM_HERE, |
| 366 "Failed to deserialize specifics."); |
| 367 return; |
| 365 } | 368 } |
| 366 } | 369 } |
| 367 | 370 |
| 368 has_data_loaded_ = true; | 371 has_data_loaded_ = true; |
| 369 LoadMetadataIfReady(); | 372 LoadMetadataIfReady(); |
| 370 } | 373 } |
| 371 | 374 |
| 372 void DeviceInfoSyncBridge::LoadMetadataIfReady() { | 375 void DeviceInfoSyncBridge::LoadMetadataIfReady() { |
| 373 if (has_data_loaded_ && has_provider_initialized_) { | 376 if (has_data_loaded_ && has_provider_initialized_) { |
| 374 store_->ReadAllMetadata(base::Bind(&DeviceInfoSyncBridge::OnReadAllMetadata, | 377 store_->ReadAllMetadata(base::Bind(&DeviceInfoSyncBridge::OnReadAllMetadata, |
| 375 base::AsWeakPtr(this))); | 378 base::AsWeakPtr(this))); |
| 376 } | 379 } |
| 377 } | 380 } |
| 378 | 381 |
| 379 void DeviceInfoSyncBridge::OnReadAllMetadata( | 382 void DeviceInfoSyncBridge::OnReadAllMetadata( |
| 380 SyncError error, | 383 ModelError error, |
| 381 std::unique_ptr<MetadataBatch> metadata_batch) { | 384 std::unique_ptr<MetadataBatch> metadata_batch) { |
| 382 change_processor()->OnMetadataLoaded(error, std::move(metadata_batch)); | 385 if (error.IsSet()) { |
| 386 change_processor()->ReportError(error); |
| 387 return; |
| 388 } |
| 389 |
| 390 change_processor()->OnMetadataLoaded(std::move(metadata_batch)); |
| 383 ReconcileLocalAndStored(); | 391 ReconcileLocalAndStored(); |
| 384 } | 392 } |
| 385 | 393 |
| 386 void DeviceInfoSyncBridge::OnCommit(Result result) { | 394 void DeviceInfoSyncBridge::OnCommit(Result result) { |
| 387 if (result != Result::SUCCESS) { | 395 if (result != Result::SUCCESS) { |
| 388 change_processor()->CreateAndUploadError(FROM_HERE, | 396 change_processor()->ReportError(FROM_HERE, "Failed a write to store."); |
| 389 "Failed a write to store."); | |
| 390 } | 397 } |
| 391 } | 398 } |
| 392 | 399 |
| 393 void DeviceInfoSyncBridge::ReconcileLocalAndStored() { | 400 void DeviceInfoSyncBridge::ReconcileLocalAndStored() { |
| 394 // On initial syncing we will have a change processor here, but it will not be | 401 // On initial syncing we will have a change processor here, but it will not be |
| 395 // tracking changes. We need to persist a copy of our local device info to | 402 // tracking changes. We need to persist a copy of our local device info to |
| 396 // disk, but the Put call to the processor will be ignored. That should be | 403 // disk, but the Put call to the processor will be ignored. That should be |
| 397 // fine however, as the discrepancy will be picked up later in merge. We don't | 404 // fine however, as the discrepancy will be picked up later in merge. We don't |
| 398 // bother trying to track this case and act intelligently because simply not | 405 // bother trying to track this case and act intelligently because simply not |
| 399 // much of a benefit in doing so. | 406 // much of a benefit in doing so. |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 465 } | 472 } |
| 466 | 473 |
| 467 int DeviceInfoSyncBridge::CountActiveDevices(const Time now) const { | 474 int DeviceInfoSyncBridge::CountActiveDevices(const Time now) const { |
| 468 return std::count_if(all_data_.begin(), all_data_.end(), | 475 return std::count_if(all_data_.begin(), all_data_.end(), |
| 469 [now](ClientIdToSpecifics::const_reference pair) { | 476 [now](ClientIdToSpecifics::const_reference pair) { |
| 470 return DeviceInfoUtil::IsActive( | 477 return DeviceInfoUtil::IsActive( |
| 471 GetLastUpdateTime(*pair.second), now); | 478 GetLastUpdateTime(*pair.second), now); |
| 472 }); | 479 }); |
| 473 } | 480 } |
| 474 | 481 |
| 475 void DeviceInfoSyncBridge::ReportStartupErrorToSync(const std::string& msg) { | |
| 476 // TODO(skym): Shouldn't need to log this here, reporting should always log. | |
| 477 LOG(WARNING) << msg; | |
| 478 change_processor()->OnMetadataLoaded( | |
| 479 change_processor()->CreateAndUploadError(FROM_HERE, msg), nullptr); | |
| 480 } | |
| 481 | |
| 482 } // namespace syncer | 482 } // namespace syncer |
| OLD | NEW |