Chromium Code Reviews| 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_service.h" | 5 #include "components/sync/device_info/device_info_service.h" |
| 6 | 6 |
| 7 #include <stdint.h> | |
| 8 | |
| 7 #include <algorithm> | 9 #include <algorithm> |
| 8 #include <set> | 10 #include <set> |
| 9 #include <utility> | 11 #include <utility> |
| 10 | 12 |
| 11 #include "base/bind.h" | 13 #include "base/bind.h" |
| 12 #include "base/location.h" | 14 #include "base/location.h" |
| 13 #include "base/memory/ptr_util.h" | 15 #include "base/memory/ptr_util.h" |
| 14 #include "base/strings/string_util.h" | 16 #include "base/strings/string_util.h" |
| 15 #include "components/sync/base/time.h" | 17 #include "components/sync/base/time.h" |
| 16 #include "components/sync/device_info/device_info_util.h" | 18 #include "components/sync/device_info/device_info_util.h" |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 27 using base::TimeDelta; | 29 using base::TimeDelta; |
| 28 using sync_pb::DeviceInfoSpecifics; | 30 using sync_pb::DeviceInfoSpecifics; |
| 29 using sync_pb::EntitySpecifics; | 31 using sync_pb::EntitySpecifics; |
| 30 using sync_pb::ModelTypeState; | 32 using sync_pb::ModelTypeState; |
| 31 | 33 |
| 32 using Record = ModelTypeStore::Record; | 34 using Record = ModelTypeStore::Record; |
| 33 using RecordList = ModelTypeStore::RecordList; | 35 using RecordList = ModelTypeStore::RecordList; |
| 34 using Result = ModelTypeStore::Result; | 36 using Result = ModelTypeStore::Result; |
| 35 using WriteBatch = ModelTypeStore::WriteBatch; | 37 using WriteBatch = ModelTypeStore::WriteBatch; |
| 36 | 38 |
| 39 namespace { | |
| 40 | |
| 41 // Find the timestamp for the last time this |device_info| was edited. | |
| 42 Time GetLastUpdateTime(const DeviceInfoSpecifics& specifics) { | |
|
maxbogue
2016/10/28 20:20:01
I genuinely find it more confusing to see just Tim
skym
2016/10/28 20:46:16
Why? Is there some other 'Time' object you think I
| |
| 43 if (specifics.has_last_updated_timestamp()) { | |
| 44 return ProtoTimeToTime(specifics.last_updated_timestamp()); | |
| 45 } else { | |
| 46 return Time(); | |
| 47 } | |
| 48 } | |
| 49 | |
| 50 // Converts DeviceInfoSpecifics into a freshly allocated DeviceInfo. | |
| 51 std::unique_ptr<DeviceInfo> SpecificsToModel( | |
|
maxbogue
2016/10/28 20:20:01
Here as well I find Model to be vague. I think Spe
skym
2016/10/28 20:46:16
DeviceInfo describes everything going on here. Dev
| |
| 52 const DeviceInfoSpecifics& specifics) { | |
| 53 return base::MakeUnique<DeviceInfo>( | |
| 54 specifics.cache_guid(), specifics.client_name(), | |
| 55 specifics.chrome_version(), specifics.sync_user_agent(), | |
| 56 specifics.device_type(), specifics.signin_scoped_device_id()); | |
| 57 } | |
| 58 | |
| 59 // Allocate a EntityData and copies |specifics| into it. | |
| 60 std::unique_ptr<EntityData> CopyToEntityData( | |
| 61 const DeviceInfoSpecifics& specifics) { | |
| 62 auto entity_data = base::MakeUnique<EntityData>(); | |
| 63 *entity_data->specifics.mutable_device_info() = specifics; | |
| 64 entity_data->non_unique_name = specifics.client_name(); | |
| 65 return entity_data; | |
| 66 } | |
| 67 | |
| 68 // Converts DeviceInfo into a freshly allocated DeviceInfoSpecifics. Takes | |
| 69 // |last_updated_timestamp| to set because the model object does not contain | |
| 70 // this concept. | |
| 71 std::unique_ptr<DeviceInfoSpecifics> ModelToSpecifics( | |
| 72 const DeviceInfo& info, | |
| 73 int64_t last_updated_timestamp) { | |
| 74 auto specifics = base::MakeUnique<DeviceInfoSpecifics>(); | |
| 75 specifics->set_cache_guid(info.guid()); | |
| 76 specifics->set_client_name(info.client_name()); | |
| 77 specifics->set_chrome_version(info.chrome_version()); | |
| 78 specifics->set_sync_user_agent(info.sync_user_agent()); | |
| 79 specifics->set_device_type(info.device_type()); | |
| 80 specifics->set_signin_scoped_device_id(info.signin_scoped_device_id()); | |
| 81 specifics->set_last_updated_timestamp(last_updated_timestamp); | |
| 82 return specifics; | |
| 83 } | |
| 84 | |
| 85 } // namespace | |
| 86 | |
| 37 DeviceInfoService::DeviceInfoService( | 87 DeviceInfoService::DeviceInfoService( |
| 38 LocalDeviceInfoProvider* local_device_info_provider, | 88 LocalDeviceInfoProvider* local_device_info_provider, |
| 39 const StoreFactoryFunction& callback, | 89 const StoreFactoryFunction& callback, |
| 40 const ChangeProcessorFactory& change_processor_factory) | 90 const ChangeProcessorFactory& change_processor_factory) |
| 41 : ModelTypeService(change_processor_factory, DEVICE_INFO), | 91 : ModelTypeService(change_processor_factory, DEVICE_INFO), |
| 42 local_device_info_provider_(local_device_info_provider) { | 92 local_device_info_provider_(local_device_info_provider) { |
| 43 DCHECK(local_device_info_provider); | 93 DCHECK(local_device_info_provider); |
| 44 | 94 |
| 45 // This is not threadsafe, but presuably the provider initializes on the same | 95 // This is not threadsafe, but presuably the provider initializes on the same |
| 46 // thread as us so we're okay. | 96 // thread as us so we're okay. |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 83 const DeviceInfo* local_info = | 133 const DeviceInfo* local_info = |
| 84 local_device_info_provider_->GetLocalDeviceInfo(); | 134 local_device_info_provider_->GetLocalDeviceInfo(); |
| 85 std::string local_guid = local_info->guid(); | 135 std::string local_guid = local_info->guid(); |
| 86 std::unique_ptr<WriteBatch> batch = store_->CreateWriteBatch(); | 136 std::unique_ptr<WriteBatch> batch = store_->CreateWriteBatch(); |
| 87 for (const auto& kv : entity_data_map) { | 137 for (const auto& kv : entity_data_map) { |
| 88 const DeviceInfoSpecifics& specifics = | 138 const DeviceInfoSpecifics& specifics = |
| 89 kv.second.value().specifics.device_info(); | 139 kv.second.value().specifics.device_info(); |
| 90 DCHECK_EQ(kv.first, specifics.cache_guid()); | 140 DCHECK_EQ(kv.first, specifics.cache_guid()); |
| 91 if (specifics.cache_guid() == local_guid) { | 141 if (specifics.cache_guid() == local_guid) { |
| 92 // Don't Put local data if it's the same as the remote copy. | 142 // Don't Put local data if it's the same as the remote copy. |
| 93 if (local_info->Equals(*CopyToModel(specifics))) { | 143 if (local_info->Equals(*SpecificsToModel(specifics))) { |
| 94 local_guids_to_put.erase(local_guid); | 144 local_guids_to_put.erase(local_guid); |
| 95 } else { | 145 } else { |
| 96 // This device is valid right now and this entry is about to be | 146 // This device is valid right now and this entry is about to be |
| 97 // committed, use this as an opportunity to refresh the timestamp. | 147 // committed, use this as an opportunity to refresh the timestamp. |
| 98 all_data_[local_guid]->set_last_updated_timestamp( | 148 all_data_[local_guid]->set_last_updated_timestamp( |
| 99 TimeToProtoTime(Time::Now())); | 149 TimeToProtoTime(Time::Now())); |
| 100 } | 150 } |
| 101 } else { | 151 } else { |
| 102 // Remote data wins conflicts. | 152 // Remote data wins conflicts. |
| 103 local_guids_to_put.erase(specifics.cache_guid()); | 153 local_guids_to_put.erase(specifics.cache_guid()); |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 208 bool DeviceInfoService::IsSyncing() const { | 258 bool DeviceInfoService::IsSyncing() const { |
| 209 return !all_data_.empty(); | 259 return !all_data_.empty(); |
| 210 } | 260 } |
| 211 | 261 |
| 212 std::unique_ptr<DeviceInfo> DeviceInfoService::GetDeviceInfo( | 262 std::unique_ptr<DeviceInfo> DeviceInfoService::GetDeviceInfo( |
| 213 const std::string& client_id) const { | 263 const std::string& client_id) const { |
| 214 const ClientIdToSpecifics::const_iterator iter = all_data_.find(client_id); | 264 const ClientIdToSpecifics::const_iterator iter = all_data_.find(client_id); |
| 215 if (iter == all_data_.end()) { | 265 if (iter == all_data_.end()) { |
| 216 return std::unique_ptr<DeviceInfo>(); | 266 return std::unique_ptr<DeviceInfo>(); |
| 217 } | 267 } |
| 218 return CopyToModel(*iter->second); | 268 return SpecificsToModel(*iter->second); |
| 219 } | 269 } |
| 220 | 270 |
| 221 std::vector<std::unique_ptr<DeviceInfo>> DeviceInfoService::GetAllDeviceInfo() | 271 std::vector<std::unique_ptr<DeviceInfo>> DeviceInfoService::GetAllDeviceInfo() |
| 222 const { | 272 const { |
| 223 std::vector<std::unique_ptr<DeviceInfo>> list; | 273 std::vector<std::unique_ptr<DeviceInfo>> list; |
| 224 for (ClientIdToSpecifics::const_iterator iter = all_data_.begin(); | 274 for (ClientIdToSpecifics::const_iterator iter = all_data_.begin(); |
| 225 iter != all_data_.end(); ++iter) { | 275 iter != all_data_.end(); ++iter) { |
| 226 list.push_back(CopyToModel(*iter->second)); | 276 list.push_back(SpecificsToModel(*iter->second)); |
| 227 } | 277 } |
| 228 return list; | 278 return list; |
| 229 } | 279 } |
| 230 | 280 |
| 231 void DeviceInfoService::AddObserver(Observer* observer) { | 281 void DeviceInfoService::AddObserver(Observer* observer) { |
| 232 observers_.AddObserver(observer); | 282 observers_.AddObserver(observer); |
| 233 } | 283 } |
| 234 | 284 |
| 235 void DeviceInfoService::RemoveObserver(Observer* observer) { | 285 void DeviceInfoService::RemoveObserver(Observer* observer) { |
| 236 observers_.RemoveObserver(observer); | 286 observers_.RemoveObserver(observer); |
| 237 } | 287 } |
| 238 | 288 |
| 239 int DeviceInfoService::CountActiveDevices() const { | 289 int DeviceInfoService::CountActiveDevices() const { |
| 240 return CountActiveDevices(Time::Now()); | 290 return CountActiveDevices(Time::Now()); |
| 241 } | 291 } |
| 242 | 292 |
| 243 void DeviceInfoService::NotifyObservers() { | 293 void DeviceInfoService::NotifyObservers() { |
| 244 for (auto& observer : observers_) | 294 for (auto& observer : observers_) |
| 245 observer.OnDeviceInfoChange(); | 295 observer.OnDeviceInfoChange(); |
| 246 } | 296 } |
| 247 | 297 |
| 248 // Static. | |
| 249 std::unique_ptr<DeviceInfoSpecifics> DeviceInfoService::CopyToSpecifics( | |
| 250 const DeviceInfo& info) { | |
| 251 std::unique_ptr<DeviceInfoSpecifics> specifics = | |
| 252 base::WrapUnique(new DeviceInfoSpecifics); | |
| 253 specifics->set_cache_guid(info.guid()); | |
| 254 specifics->set_client_name(info.client_name()); | |
| 255 specifics->set_chrome_version(info.chrome_version()); | |
| 256 specifics->set_sync_user_agent(info.sync_user_agent()); | |
| 257 specifics->set_device_type(info.device_type()); | |
| 258 specifics->set_signin_scoped_device_id(info.signin_scoped_device_id()); | |
| 259 return specifics; | |
| 260 } | |
| 261 | |
| 262 // Static. | |
| 263 std::unique_ptr<DeviceInfo> DeviceInfoService::CopyToModel( | |
| 264 const DeviceInfoSpecifics& specifics) { | |
| 265 return base::MakeUnique<DeviceInfo>( | |
| 266 specifics.cache_guid(), specifics.client_name(), | |
| 267 specifics.chrome_version(), specifics.sync_user_agent(), | |
| 268 specifics.device_type(), specifics.signin_scoped_device_id()); | |
| 269 } | |
| 270 | |
| 271 // Static. | |
| 272 std::unique_ptr<EntityData> DeviceInfoService::CopyToEntityData( | |
| 273 const DeviceInfoSpecifics& specifics) { | |
| 274 std::unique_ptr<EntityData> entity_data(new EntityData()); | |
| 275 *entity_data->specifics.mutable_device_info() = specifics; | |
| 276 entity_data->non_unique_name = specifics.client_name(); | |
| 277 return entity_data; | |
| 278 } | |
| 279 | |
| 280 void DeviceInfoService::StoreSpecifics( | 298 void DeviceInfoService::StoreSpecifics( |
| 281 std::unique_ptr<DeviceInfoSpecifics> specifics, | 299 std::unique_ptr<DeviceInfoSpecifics> specifics, |
| 282 WriteBatch* batch) { | 300 WriteBatch* batch) { |
| 283 const std::string guid = specifics->cache_guid(); | 301 const std::string guid = specifics->cache_guid(); |
| 284 DVLOG(1) << "Storing DEVICE_INFO for " << specifics->client_name() | |
| 285 << " with ID " << guid; | |
| 286 store_->WriteData(batch, guid, specifics->SerializeAsString()); | 302 store_->WriteData(batch, guid, specifics->SerializeAsString()); |
| 287 all_data_[guid] = std::move(specifics); | 303 all_data_[guid] = std::move(specifics); |
| 288 } | 304 } |
| 289 | 305 |
| 290 bool DeviceInfoService::DeleteSpecifics(const std::string& guid, | 306 bool DeviceInfoService::DeleteSpecifics(const std::string& guid, |
| 291 WriteBatch* batch) { | 307 WriteBatch* batch) { |
| 292 ClientIdToSpecifics::const_iterator iter = all_data_.find(guid); | 308 ClientIdToSpecifics::const_iterator iter = all_data_.find(guid); |
| 293 if (iter != all_data_.end()) { | 309 if (iter != all_data_.end()) { |
| 294 DVLOG(1) << "Deleting DEVICE_INFO for " << iter->second->client_name() | |
| 295 << " with ID " << guid; | |
| 296 store_->DeleteData(batch, guid); | 310 store_->DeleteData(batch, guid); |
| 297 all_data_.erase(iter); | 311 all_data_.erase(iter); |
| 298 return true; | 312 return true; |
| 299 } else { | 313 } else { |
| 300 return false; | 314 return false; |
| 301 } | 315 } |
| 302 } | 316 } |
| 303 | 317 |
| 304 void DeviceInfoService::OnProviderInitialized() { | 318 void DeviceInfoService::OnProviderInitialized() { |
| 305 // Now that the provider has initialized, remove the subscription. The service | 319 // Now that the provider has initialized, remove the subscription. The service |
| 306 // should only need to give the processor metadata upon initialization. If | 320 // should only need to give the processor metadata upon initialization. If |
| 307 // sync is disabled and enabled, our provider will try to retrigger this | 321 // sync is disabled and enabled, our provider will try to retrigger this |
| 308 // event, but we do not want to send any more metadata to the processor. | 322 // event, but we do not want to send any more metadata to the processor. |
| 309 subscription_.reset(); | 323 subscription_.reset(); |
| 310 | 324 |
| 311 has_provider_initialized_ = true; | 325 has_provider_initialized_ = true; |
| 312 LoadMetadataIfReady(); | 326 LoadMetadataIfReady(); |
| 313 } | 327 } |
| 314 | 328 |
| 315 void DeviceInfoService::OnStoreCreated(Result result, | 329 void DeviceInfoService::OnStoreCreated(Result result, |
| 316 std::unique_ptr<ModelTypeStore> store) { | 330 std::unique_ptr<ModelTypeStore> store) { |
| 317 if (result == Result::SUCCESS) { | 331 if (result == Result::SUCCESS) { |
| 318 std::swap(store_, store); | 332 std::swap(store_, store); |
| 319 store_->ReadAllData( | 333 store_->ReadAllData( |
| 320 base::Bind(&DeviceInfoService::OnReadAllData, base::AsWeakPtr(this))); | 334 base::Bind(&DeviceInfoService::OnReadAllData, base::AsWeakPtr(this))); |
| 321 } else { | 335 } else { |
| 322 ReportStartupErrorToSync("ModelTypeStore creation failed."); | 336 ReportStartupErrorToSync("ModelTypeStore creation failed."); |
| 323 // TODO(skym, crbug.com/582460): Handle unrecoverable initialization | |
| 324 // failure. | |
| 325 } | 337 } |
| 326 } | 338 } |
| 327 | 339 |
| 328 void DeviceInfoService::OnReadAllData(Result result, | 340 void DeviceInfoService::OnReadAllData(Result result, |
| 329 std::unique_ptr<RecordList> record_list) { | 341 std::unique_ptr<RecordList> record_list) { |
| 330 if (result != Result::SUCCESS) { | 342 if (result != Result::SUCCESS) { |
| 331 ReportStartupErrorToSync("Initial load of data failed."); | 343 ReportStartupErrorToSync("Initial load of data failed."); |
| 332 // TODO(skym, crbug.com/582460): Handle unrecoverable initialization | |
| 333 // failure. | |
| 334 return; | 344 return; |
| 335 } | 345 } |
| 336 | 346 |
| 337 for (const Record& r : *record_list.get()) { | 347 for (const Record& r : *record_list.get()) { |
| 338 std::unique_ptr<DeviceInfoSpecifics> specifics = | 348 std::unique_ptr<DeviceInfoSpecifics> specifics = |
| 339 base::MakeUnique<DeviceInfoSpecifics>(); | 349 base::MakeUnique<DeviceInfoSpecifics>(); |
| 340 if (specifics->ParseFromString(r.value)) { | 350 if (specifics->ParseFromString(r.value)) { |
| 341 all_data_[specifics->cache_guid()] = std::move(specifics); | 351 all_data_[specifics->cache_guid()] = std::move(specifics); |
| 342 } else { | 352 } else { |
| 343 ReportStartupErrorToSync("Failed to deserialize specifics."); | 353 ReportStartupErrorToSync("Failed to deserialize specifics."); |
| 344 // TODO(skym, crbug.com/582460): Handle unrecoverable initialization | |
| 345 // failure. | |
| 346 } | 354 } |
| 347 } | 355 } |
| 348 | 356 |
| 349 has_data_loaded_ = true; | 357 has_data_loaded_ = true; |
| 350 LoadMetadataIfReady(); | 358 LoadMetadataIfReady(); |
| 351 } | 359 } |
| 352 | 360 |
| 353 void DeviceInfoService::LoadMetadataIfReady() { | 361 void DeviceInfoService::LoadMetadataIfReady() { |
| 354 if (has_data_loaded_ && has_provider_initialized_) { | 362 if (has_data_loaded_ && has_provider_initialized_) { |
| 355 store_->ReadAllMetadata(base::Bind(&DeviceInfoService::OnReadAllMetadata, | 363 store_->ReadAllMetadata(base::Bind(&DeviceInfoService::OnReadAllMetadata, |
| 356 base::AsWeakPtr(this))); | 364 base::AsWeakPtr(this))); |
| 357 } | 365 } |
| 358 } | 366 } |
| 359 | 367 |
| 360 void DeviceInfoService::OnReadAllMetadata( | 368 void DeviceInfoService::OnReadAllMetadata( |
| 361 Result result, | 369 Result result, |
| 362 std::unique_ptr<RecordList> metadata_records, | 370 std::unique_ptr<RecordList> metadata_records, |
| 363 const std::string& global_metadata) { | 371 const std::string& global_metadata) { |
| 364 if (result != Result::SUCCESS) { | 372 if (result != Result::SUCCESS) { |
| 365 // Store has encountered some serious error. We should still be able to | |
| 366 // continue as a read only service, since if we got this far we must have | |
| 367 // loaded all data out succesfully. | |
| 368 ReportStartupErrorToSync("Load of metadata completely failed."); | 373 ReportStartupErrorToSync("Load of metadata completely failed."); |
| 369 return; | 374 return; |
| 370 } | 375 } |
| 371 | 376 |
| 372 std::unique_ptr<MetadataBatch> batch(new MetadataBatch()); | 377 auto batch = base::MakeUnique<MetadataBatch>(); |
| 373 ModelTypeState state; | 378 ModelTypeState state; |
| 374 if (state.ParseFromString(global_metadata)) { | 379 if (state.ParseFromString(global_metadata)) { |
| 375 batch->SetModelTypeState(state); | 380 batch->SetModelTypeState(state); |
| 376 } else { | 381 } else { |
| 377 // TODO(skym): How bad is this scenario? We may be able to just give an | 382 ReportStartupErrorToSync("Failed to deserialize global metadata."); |
| 378 // empty batch to the processor and we'll treat corrupted data type state | 383 return; |
| 379 // as no data type state at all. The question is do we want to add any of | |
| 380 // the entity metadata to the batch or completely skip that step? We're | |
| 381 // going to have to perform a merge shortly. Does this decision/logic even | |
| 382 // belong in this service? | |
| 383 change_processor()->OnMetadataLoaded( | |
| 384 change_processor()->CreateAndUploadError( | |
| 385 FROM_HERE, "Failed to deserialize global metadata."), | |
| 386 nullptr); | |
| 387 } | 384 } |
| 385 | |
| 388 for (const Record& r : *metadata_records.get()) { | 386 for (const Record& r : *metadata_records.get()) { |
| 389 sync_pb::EntityMetadata entity_metadata; | 387 sync_pb::EntityMetadata entity_metadata; |
| 390 if (entity_metadata.ParseFromString(r.value)) { | 388 if (entity_metadata.ParseFromString(r.value)) { |
| 391 batch->AddMetadata(r.id, entity_metadata); | 389 batch->AddMetadata(r.id, entity_metadata); |
| 392 } else { | 390 } else { |
| 393 // TODO(skym): This really isn't too bad. We just want to regenerate | 391 ReportStartupErrorToSync("Failed to deserialize entity metadata."); |
| 394 // metadata for this particular entity. Unfortunately there isn't a | |
| 395 // convenient way to tell the processor to do this. | |
| 396 LOG(WARNING) << "Failed to deserialize entity metadata."; | |
| 397 } | 392 } |
| 398 } | 393 } |
| 394 | |
| 399 change_processor()->OnMetadataLoaded(SyncError(), std::move(batch)); | 395 change_processor()->OnMetadataLoaded(SyncError(), std::move(batch)); |
| 400 ReconcileLocalAndStored(); | 396 ReconcileLocalAndStored(); |
| 401 } | 397 } |
| 402 | 398 |
| 403 void DeviceInfoService::OnCommit(Result result) { | 399 void DeviceInfoService::OnCommit(Result result) { |
| 404 if (result != Result::SUCCESS) { | 400 if (result != Result::SUCCESS) { |
| 405 LOG(WARNING) << "Failed a write to store."; | 401 change_processor()->CreateAndUploadError(FROM_HERE, |
| 402 "Failed a write to store."); | |
| 406 } | 403 } |
| 407 } | 404 } |
| 408 | 405 |
| 409 void DeviceInfoService::ReconcileLocalAndStored() { | 406 void DeviceInfoService::ReconcileLocalAndStored() { |
| 410 // On initial syncing we will have a change processor here, but it will not be | 407 // On initial syncing we will have a change processor here, but it will not be |
| 411 // tracking changes. We need to persist a copy of our local device info to | 408 // tracking changes. We need to persist a copy of our local device info to |
| 412 // disk, but the Put call to the processor will be ignored. That should be | 409 // disk, but the Put call to the processor will be ignored. That should be |
| 413 // fine however, as the discrepancy will be picked up later in merge. We don't | 410 // fine however, as the discrepancy will be picked up later in merge. We don't |
| 414 // bother trying to track this case and act intelligently because simply not | 411 // bother trying to track this case and act intelligently because simply not |
| 415 // much of a benefit in doing so. | 412 // much of a benefit in doing so. |
| 416 DCHECK(has_provider_initialized_); | 413 DCHECK(has_provider_initialized_); |
| 417 | 414 |
| 418 const DeviceInfo* current_info = | 415 const DeviceInfo* current_info = |
| 419 local_device_info_provider_->GetLocalDeviceInfo(); | 416 local_device_info_provider_->GetLocalDeviceInfo(); |
| 420 auto iter = all_data_.find(current_info->guid()); | 417 auto iter = all_data_.find(current_info->guid()); |
| 421 | 418 |
| 422 // Convert to DeviceInfo for Equals function. | 419 // Convert to DeviceInfo for Equals function. |
| 423 if (iter != all_data_.end() && | 420 if (iter != all_data_.end() && |
| 424 current_info->Equals(*CopyToModel(*iter->second))) { | 421 current_info->Equals(*SpecificsToModel(*iter->second))) { |
| 425 const TimeDelta pulse_delay(DeviceInfoUtil::CalculatePulseDelay( | 422 const TimeDelta pulse_delay(DeviceInfoUtil::CalculatePulseDelay( |
| 426 GetLastUpdateTime(*iter->second), Time::Now())); | 423 GetLastUpdateTime(*iter->second), Time::Now())); |
| 427 if (!pulse_delay.is_zero()) { | 424 if (!pulse_delay.is_zero()) { |
| 428 pulse_timer_.Start(FROM_HERE, pulse_delay, | 425 pulse_timer_.Start(FROM_HERE, pulse_delay, |
| 429 base::Bind(&DeviceInfoService::SendLocalData, | 426 base::Bind(&DeviceInfoService::SendLocalData, |
| 430 base::Unretained(this))); | 427 base::Unretained(this))); |
| 431 return; | 428 return; |
| 432 } | 429 } |
| 433 } | 430 } |
| 434 SendLocalData(); | 431 SendLocalData(); |
| 435 } | 432 } |
| 436 | 433 |
| 437 void DeviceInfoService::SendLocalData() { | 434 void DeviceInfoService::SendLocalData() { |
| 438 DCHECK(has_provider_initialized_); | 435 DCHECK(has_provider_initialized_); |
| 439 | 436 |
| 440 // It is possible that the provider no longer has data for us, such as when | 437 // It is possible that the provider no longer has data for us, such as when |
| 441 // the user signs out. No-op this pulse, but keep the timer going in case sync | 438 // the user signs out. No-op this pulse, but keep the timer going in case sync |
| 442 // is enabled later. | 439 // is enabled later. |
| 443 if (local_device_info_provider_->GetLocalDeviceInfo() != nullptr) { | 440 if (local_device_info_provider_->GetLocalDeviceInfo() != nullptr) { |
| 444 std::unique_ptr<DeviceInfoSpecifics> specifics = | 441 std::unique_ptr<DeviceInfoSpecifics> specifics = |
| 445 CopyToSpecifics(*local_device_info_provider_->GetLocalDeviceInfo()); | 442 ModelToSpecifics(*local_device_info_provider_->GetLocalDeviceInfo(), |
| 446 specifics->set_last_updated_timestamp(TimeToProtoTime(Time::Now())); | 443 TimeToProtoTime(Time::Now())); |
| 447 | |
| 448 std::unique_ptr<MetadataChangeList> metadata_change_list = | 444 std::unique_ptr<MetadataChangeList> metadata_change_list = |
| 449 CreateMetadataChangeList(); | 445 CreateMetadataChangeList(); |
| 450 if (change_processor()->IsTrackingMetadata()) { | 446 if (change_processor()->IsTrackingMetadata()) { |
| 451 change_processor()->Put(specifics->cache_guid(), | 447 change_processor()->Put(specifics->cache_guid(), |
| 452 CopyToEntityData(*specifics), | 448 CopyToEntityData(*specifics), |
| 453 metadata_change_list.get()); | 449 metadata_change_list.get()); |
| 454 } | 450 } |
| 455 | 451 |
| 456 std::unique_ptr<WriteBatch> batch = store_->CreateWriteBatch(); | 452 std::unique_ptr<WriteBatch> batch = store_->CreateWriteBatch(); |
| 457 StoreSpecifics(std::move(specifics), batch.get()); | 453 StoreSpecifics(std::move(specifics), batch.get()); |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 485 }); | 481 }); |
| 486 } | 482 } |
| 487 | 483 |
| 488 void DeviceInfoService::ReportStartupErrorToSync(const std::string& msg) { | 484 void DeviceInfoService::ReportStartupErrorToSync(const std::string& msg) { |
| 489 // TODO(skym): Shouldn't need to log this here, reporting should always log. | 485 // TODO(skym): Shouldn't need to log this here, reporting should always log. |
| 490 LOG(WARNING) << msg; | 486 LOG(WARNING) << msg; |
| 491 change_processor()->OnMetadataLoaded( | 487 change_processor()->OnMetadataLoaded( |
| 492 change_processor()->CreateAndUploadError(FROM_HERE, msg), nullptr); | 488 change_processor()->CreateAndUploadError(FROM_HERE, msg), nullptr); |
| 493 } | 489 } |
| 494 | 490 |
| 495 // static | |
| 496 Time DeviceInfoService::GetLastUpdateTime( | |
| 497 const DeviceInfoSpecifics& specifics) { | |
| 498 if (specifics.has_last_updated_timestamp()) { | |
| 499 return ProtoTimeToTime(specifics.last_updated_timestamp()); | |
| 500 } else { | |
| 501 return Time(); | |
| 502 } | |
| 503 } | |
| 504 | |
| 505 } // namespace syncer | 491 } // namespace syncer |
| OLD | NEW |