| 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 f7292f91336dc9eb89d61ebf238f6d31a777369d..ff084d69a135dc6a357396c9d24af3f53873afaa 100644
|
| --- a/components/sync_driver/device_info_service.cc
|
| +++ b/components/sync_driver/device_info_service.cc
|
| @@ -80,13 +80,9 @@ DeviceInfoService::CreateMetadataChangeList() {
|
| SyncError DeviceInfoService::MergeSyncData(
|
| std::unique_ptr<MetadataChangeList> metadata_change_list,
|
| EntityDataMap entity_data_map) {
|
| - if (!has_provider_initialized_ || !has_metadata_loaded_ ||
|
| - !change_processor()) {
|
| - return SyncError(
|
| - FROM_HERE, SyncError::DATATYPE_ERROR,
|
| - "Cannot call MergeSyncData without provider, data, and processor.",
|
| - syncer::DEVICE_INFO);
|
| - }
|
| + DCHECK(has_provider_initialized_);
|
| + DCHECK(has_metadata_loaded_);
|
| + DCHECK(change_processor());
|
|
|
| // Local data should typically be near empty, with the only possible value
|
| // corresponding to this device. This is because on signout all device info
|
| @@ -134,18 +130,14 @@ SyncError DeviceInfoService::MergeSyncData(
|
|
|
| CommitAndNotify(std::move(batch), std::move(metadata_change_list),
|
| has_changes);
|
| - return syncer::SyncError();
|
| + return SyncError();
|
| }
|
|
|
| SyncError DeviceInfoService::ApplySyncChanges(
|
| std::unique_ptr<MetadataChangeList> metadata_change_list,
|
| EntityChangeList entity_changes) {
|
| - if (!has_provider_initialized_ || !has_metadata_loaded_) {
|
| - return SyncError(
|
| - FROM_HERE, SyncError::DATATYPE_ERROR,
|
| - "Cannot call ApplySyncChanges before provider and data have loaded.",
|
| - syncer::DEVICE_INFO);
|
| - }
|
| + DCHECK(has_provider_initialized_);
|
| + DCHECK(has_metadata_loaded_);
|
|
|
| std::unique_ptr<WriteBatch> batch = store_->CreateWriteBatch();
|
| bool has_changes = false;
|
| @@ -177,14 +169,7 @@ SyncError DeviceInfoService::ApplySyncChanges(
|
|
|
| void DeviceInfoService::GetData(ClientTagList client_tags,
|
| DataCallback callback) {
|
| - if (!has_metadata_loaded_) {
|
| - callback.Run(
|
| - SyncError(FROM_HERE, SyncError::DATATYPE_ERROR,
|
| - "Should not call GetData before metadata has loaded.",
|
| - syncer::DEVICE_INFO),
|
| - std::unique_ptr<DataBatchImpl>());
|
| - return;
|
| - }
|
| + DCHECK(has_metadata_loaded_);
|
|
|
| std::unique_ptr<DataBatchImpl> batch(new DataBatchImpl());
|
| for (const auto& tag : client_tags) {
|
| @@ -194,25 +179,20 @@ void DeviceInfoService::GetData(ClientTagList client_tags,
|
| batch->Put(tag, CopyToEntityData(*iter->second));
|
| }
|
| }
|
| - callback.Run(syncer::SyncError(), std::move(batch));
|
| +
|
| + callback.Run(SyncError(), std::move(batch));
|
| }
|
|
|
| void DeviceInfoService::GetAllData(DataCallback callback) {
|
| - if (!has_metadata_loaded_) {
|
| - callback.Run(
|
| - SyncError(FROM_HERE, SyncError::DATATYPE_ERROR,
|
| - "Should not call GetAllData before metadata has loaded.",
|
| - syncer::DEVICE_INFO),
|
| - std::unique_ptr<DataBatchImpl>());
|
| - return;
|
| - }
|
| + DCHECK(has_metadata_loaded_);
|
|
|
| std::unique_ptr<DataBatchImpl> batch(new DataBatchImpl());
|
| for (const auto& kv : all_data_) {
|
| batch->Put(DeviceInfoUtil::SpecificsToTag(*kv.second),
|
| CopyToEntityData(*kv.second));
|
| }
|
| - callback.Run(syncer::SyncError(), std::move(batch));
|
| +
|
| + callback.Run(SyncError(), std::move(batch));
|
| }
|
|
|
| std::string DeviceInfoService::GetClientTag(const EntityData& entity_data) {
|
| @@ -228,9 +208,9 @@ void DeviceInfoService::OnChangeProcessorSet() {
|
| // have created the processor ourselves because we had no metadata. So there
|
| // must not be any metadata on disk.
|
| if (has_metadata_loaded_) {
|
| - change_processor()->OnMetadataLoaded(syncer::SyncError(),
|
| + change_processor()->OnMetadataLoaded(SyncError(),
|
| base::WrapUnique(new MetadataBatch()));
|
| - TryReconcileLocalAndStored();
|
| + ReconcileLocalAndStored();
|
| }
|
| }
|
|
|
| @@ -333,7 +313,7 @@ bool DeviceInfoService::DeleteSpecifics(const std::string& guid,
|
|
|
| void DeviceInfoService::OnProviderInitialized() {
|
| has_provider_initialized_ = true;
|
| - TryReconcileLocalAndStored();
|
| + LoadMetadataIfReady();
|
| }
|
|
|
| void DeviceInfoService::OnStoreCreated(Result result,
|
| @@ -343,7 +323,7 @@ void DeviceInfoService::OnStoreCreated(Result result,
|
| store_->ReadAllData(base::Bind(&DeviceInfoService::OnReadAllData,
|
| weak_factory_.GetWeakPtr()));
|
| } else {
|
| - LOG(WARNING) << "ModelTypeStore creation failed.";
|
| + ReportStartupErrorToSync("ModelTypeStore creation failed.");
|
| // TODO(skym, crbug.com/582460): Handle unrecoverable initialization
|
| // failure.
|
| }
|
| @@ -352,7 +332,7 @@ void DeviceInfoService::OnStoreCreated(Result result,
|
| void DeviceInfoService::OnReadAllData(Result result,
|
| std::unique_ptr<RecordList> record_list) {
|
| if (result != Result::SUCCESS) {
|
| - LOG(WARNING) << "Initial load of data failed.";
|
| + ReportStartupErrorToSync("Initial load of data failed.");
|
| // TODO(skym, crbug.com/582460): Handle unrecoverable initialization
|
| // failure.
|
| return;
|
| @@ -364,25 +344,34 @@ void DeviceInfoService::OnReadAllData(Result result,
|
| if (specifics->ParseFromString(r.value)) {
|
| all_data_[specifics->cache_guid()] = std::move(specifics);
|
| } else {
|
| - LOG(WARNING) << "Failed to deserialize specifics.";
|
| + ReportStartupErrorToSync("Failed to deserialize specifics.");
|
| // TODO(skym, crbug.com/582460): Handle unrecoverable initialization
|
| // failure.
|
| }
|
| }
|
| - store_->ReadAllMetadata(base::Bind(&DeviceInfoService::OnReadAllMetadata,
|
| - weak_factory_.GetWeakPtr()));
|
| +
|
| + has_data_loaded_ = true;
|
| + LoadMetadataIfReady();
|
| +}
|
| +
|
| +void DeviceInfoService::LoadMetadataIfReady() {
|
| + if (has_data_loaded_ && has_provider_initialized_) {
|
| + store_->ReadAllMetadata(base::Bind(&DeviceInfoService::OnReadAllMetadata,
|
| + weak_factory_.GetWeakPtr()));
|
| + }
|
| }
|
|
|
| void DeviceInfoService::OnReadAllMetadata(
|
| Result result,
|
| std::unique_ptr<RecordList> metadata_records,
|
| const std::string& global_metadata) {
|
| + DCHECK(!has_metadata_loaded_);
|
| +
|
| if (result != Result::SUCCESS) {
|
| // Store has encountered some serious error. We should still be able to
|
| // continue as a read only service, since if we got this far we must have
|
| - // loaded all data out succesfully. TODO(skym): Should we communicate this
|
| - // to sync somehow?
|
| - LOG(WARNING) << "Load of metadata completely failed.";
|
| + // loaded all data out succesfully.
|
| + ReportStartupErrorToSync("Load of metadata completely failed.");
|
| return;
|
| }
|
|
|
| @@ -402,8 +391,8 @@ void DeviceInfoService::OnReadAllMetadata(
|
| has_metadata_loaded_ = true;
|
|
|
| if (!change_processor()) {
|
| - // This means we haven't been told to start sycning and we don't have any
|
| - // local metadata
|
| + // This means we haven't been told to start syncing and we don't have any
|
| + // local metadata.
|
| return;
|
| }
|
|
|
| @@ -418,7 +407,10 @@ void DeviceInfoService::OnReadAllMetadata(
|
| // the entity metadata to the batch or completely skip that step? We're
|
| // going to have to perform a merge shortly. Does this decision/logic even
|
| // belong in this service?
|
| - LOG(WARNING) << "Failed to deserialize global metadata.";
|
| + change_processor()->OnMetadataLoaded(
|
| + change_processor()->CreateAndUploadError(
|
| + FROM_HERE, "Failed to deserialize global metadata."),
|
| + nullptr);
|
| }
|
| for (const Record& r : *metadata_records.get()) {
|
| sync_pb::EntityMetadata entity_metadata;
|
| @@ -427,12 +419,12 @@ void DeviceInfoService::OnReadAllMetadata(
|
| } else {
|
| // TODO(skym): This really isn't too bad. We just want to regenerate
|
| // metadata for this particular entity. Unfortunately there isn't a
|
| - // convinient way to tell the processor to do this.
|
| + // convenient way to tell the processor to do this.
|
| LOG(WARNING) << "Failed to deserialize entity metadata.";
|
| }
|
| }
|
| - change_processor()->OnMetadataLoaded(syncer::SyncError(), std::move(batch));
|
| - TryReconcileLocalAndStored();
|
| + change_processor()->OnMetadataLoaded(SyncError(), std::move(batch));
|
| + ReconcileLocalAndStored();
|
| }
|
|
|
| void DeviceInfoService::OnCommit(Result result) {
|
| @@ -441,57 +433,60 @@ void DeviceInfoService::OnCommit(Result result) {
|
| }
|
| }
|
|
|
| -void DeviceInfoService::TryReconcileLocalAndStored() {
|
| +void DeviceInfoService::ReconcileLocalAndStored() {
|
| // On initial syncing we will have a change processor here, but it will not be
|
| // tracking changes. We need to persist a copy of our local device info to
|
| // disk, but the Put call to the processor will be ignored. That should be
|
| // fine however, as the discrepancy will be picked up later in merge. We don't
|
| // bother trying to track this case and act intelligently because simply not
|
| // much of a benefit in doing so.
|
| - if (has_provider_initialized_ && has_metadata_loaded_ && change_processor()) {
|
| - const DeviceInfo* current_info =
|
| - local_device_info_provider_->GetLocalDeviceInfo();
|
| - auto iter = all_data_.find(current_info->guid());
|
| -
|
| - // Convert to DeviceInfo for Equals function.
|
| - if (iter != all_data_.end() &&
|
| - current_info->Equals(*CopyToModel(*iter->second))) {
|
| - const TimeDelta pulse_delay(DeviceInfoUtil::CalculatePulseDelay(
|
| - GetLastUpdateTime(*iter->second), Time::Now()));
|
| - if (!pulse_delay.is_zero()) {
|
| - pulse_timer_.Start(FROM_HERE, pulse_delay,
|
| - base::Bind(&DeviceInfoService::SendLocalData,
|
| - base::Unretained(this)));
|
| - return;
|
| - }
|
| + DCHECK(has_provider_initialized_);
|
| + DCHECK(has_metadata_loaded_);
|
| + DCHECK(change_processor());
|
| + const DeviceInfo* current_info =
|
| + local_device_info_provider_->GetLocalDeviceInfo();
|
| + auto iter = all_data_.find(current_info->guid());
|
| +
|
| + // Convert to DeviceInfo for Equals function.
|
| + if (iter != all_data_.end() &&
|
| + current_info->Equals(*CopyToModel(*iter->second))) {
|
| + const TimeDelta pulse_delay(DeviceInfoUtil::CalculatePulseDelay(
|
| + GetLastUpdateTime(*iter->second), Time::Now()));
|
| + if (!pulse_delay.is_zero()) {
|
| + pulse_timer_.Start(FROM_HERE, pulse_delay,
|
| + base::Bind(&DeviceInfoService::SendLocalData,
|
| + base::Unretained(this)));
|
| + return;
|
| }
|
| - SendLocalData();
|
| }
|
| + SendLocalData();
|
| }
|
|
|
| void DeviceInfoService::SendLocalData() {
|
| DCHECK(has_provider_initialized_);
|
| // TODO(skym): Handle disconnecting and reconnecting, this will currently halt
|
| // the pulse timer and never restart it.
|
| - if (change_processor()) {
|
| - std::unique_ptr<DeviceInfoSpecifics> specifics =
|
| - CopyToSpecifics(*local_device_info_provider_->GetLocalDeviceInfo());
|
| - specifics->set_last_updated_timestamp(syncer::TimeToProtoTime(Time::Now()));
|
| -
|
| - std::unique_ptr<MetadataChangeList> metadata_change_list =
|
| - CreateMetadataChangeList();
|
| - change_processor()->Put(DeviceInfoUtil::SpecificsToTag(*specifics),
|
| - CopyToEntityData(*specifics),
|
| - metadata_change_list.get());
|
| + if (!change_processor()) {
|
| + return;
|
| + }
|
| +
|
| + std::unique_ptr<DeviceInfoSpecifics> specifics =
|
| + CopyToSpecifics(*local_device_info_provider_->GetLocalDeviceInfo());
|
| + specifics->set_last_updated_timestamp(syncer::TimeToProtoTime(Time::Now()));
|
|
|
| - std::unique_ptr<WriteBatch> batch = store_->CreateWriteBatch();
|
| - StoreSpecifics(std::move(specifics), batch.get());
|
| + std::unique_ptr<MetadataChangeList> metadata_change_list =
|
| + CreateMetadataChangeList();
|
| + change_processor()->Put(DeviceInfoUtil::SpecificsToTag(*specifics),
|
| + CopyToEntityData(*specifics),
|
| + metadata_change_list.get());
|
|
|
| - CommitAndNotify(std::move(batch), std::move(metadata_change_list), true);
|
| - pulse_timer_.Start(
|
| - FROM_HERE, DeviceInfoUtil::kPulseInterval,
|
| - base::Bind(&DeviceInfoService::SendLocalData, base::Unretained(this)));
|
| - }
|
| + std::unique_ptr<WriteBatch> batch = store_->CreateWriteBatch();
|
| + StoreSpecifics(std::move(specifics), batch.get());
|
| +
|
| + CommitAndNotify(std::move(batch), std::move(metadata_change_list), true);
|
| + pulse_timer_.Start(
|
| + FROM_HERE, DeviceInfoUtil::kPulseInterval,
|
| + base::Bind(&DeviceInfoService::SendLocalData, base::Unretained(this)));
|
| }
|
|
|
| void DeviceInfoService::CommitAndNotify(
|
| @@ -516,6 +511,18 @@ int DeviceInfoService::CountActiveDevices(const Time now) const {
|
| });
|
| }
|
|
|
| +void DeviceInfoService::ReportStartupErrorToSync(const std::string& msg) {
|
| + DCHECK(!has_metadata_loaded_);
|
| + LOG(WARNING) << msg;
|
| +
|
| + // Create a processor and give it the error in case sync tries to start.
|
| + if (!change_processor()) {
|
| + CreateChangeProcessor();
|
| + }
|
| + change_processor()->OnMetadataLoaded(
|
| + change_processor()->CreateAndUploadError(FROM_HERE, msg), nullptr);
|
| +}
|
| +
|
| // static
|
| Time DeviceInfoService::GetLastUpdateTime(
|
| const DeviceInfoSpecifics& specifics) {
|
|
|