Index: chrome/browser/sync/glue/device_info_sync_service.cc |
diff --git a/chrome/browser/sync/glue/device_info_sync_service.cc b/chrome/browser/sync/glue/device_info_sync_service.cc |
index 17fd8edf7381882eff4e513dd6fb7ca74c615373..fe7ccc1bfeff053149df22bfa7189a858257cbf0 100644 |
--- a/chrome/browser/sync/glue/device_info_sync_service.cc |
+++ b/chrome/browser/sync/glue/device_info_sync_service.cc |
@@ -8,6 +8,7 @@ |
#include "chrome/browser/sync/glue/local_device_info_provider.h" |
#include "sync/api/sync_change.h" |
#include "sync/protocol/sync.pb.h" |
+#include "sync/util/time.h" |
namespace browser_sync { |
@@ -22,7 +23,8 @@ using syncer::SyncMergeResult; |
DeviceInfoSyncService::DeviceInfoSyncService( |
LocalDeviceInfoProvider* local_device_info_provider) |
- : local_device_info_provider_(local_device_info_provider) { |
+ : local_device_backup_time_(-1), |
+ local_device_info_provider_(local_device_info_provider) { |
DCHECK(local_device_info_provider); |
} |
@@ -43,51 +45,70 @@ SyncMergeResult DeviceInfoSyncService::MergeDataAndStartSyncing( |
sync_processor_ = sync_processor.Pass(); |
error_handler_ = error_handler.Pass(); |
+ // Initialization should be completed before this type is enabled |
+ // and local device info must be available. |
+ const DeviceInfo* local_device_info = |
+ local_device_info_provider_->GetLocalDeviceInfo(); |
+ DCHECK(local_device_info != NULL); |
+ |
+ // Indicates whether a local device has been added or updated. |
+ // |change_type| defaults to ADD and might be changed to |
+ // UPDATE to INVALID down below if the initial data contains |
+ // data matching the local device ID. |
+ SyncChange::SyncChangeType change_type = SyncChange::ACTION_ADD; |
+ size_t num_items_new = 0; |
+ size_t num_items_updated = 0; |
+ |
// Iterate over all initial sync data and copy it to the cache. |
for (SyncDataList::const_iterator iter = initial_sync_data.begin(); |
iter != initial_sync_data.end(); |
++iter) { |
DCHECK_EQ(syncer::DEVICE_INFO, iter->GetDataType()); |
- StoreSyncData(iter->GetSpecifics().device_info().cache_guid(), *iter); |
- } |
- size_t num_items_new = initial_sync_data.size(); |
- size_t num_items_updated = 0; |
- // Indicates whether a local device has been added or updated. |
- SyncChange::SyncChangeType change_type = SyncChange::ACTION_INVALID; |
- |
- // Initialization should be completed before this type is enabled |
- // and local device info must be available. |
- const DeviceInfo* local_device_info = |
- local_device_info_provider_->GetLocalDeviceInfo(); |
- DCHECK(local_device_info != NULL); |
- // Before storing the local device info check if the data with |
- // the same guid has already been synced. This attempts to retrieve |
- // DeviceInfo from the cached data initialized above. |
- scoped_ptr<DeviceInfo> synced_local_device_info = |
- GetDeviceInfo(local_device_info->guid()); |
- |
- if (synced_local_device_info.get()) { |
- // Local device info has been synced and exists in the cache. |
- // |num_items_new| and |num_items_updated| need to be updated to |
- // reflect that. |
- num_items_new--; |
- // Overwrite the synced device info with the local data only if |
- // it is different. |
- if (!synced_local_device_info->Equals(*local_device_info)) { |
- num_items_updated++; |
- change_type = SyncChange::ACTION_UPDATE; |
+ const std::string& id = iter->GetSpecifics().device_info().cache_guid(); |
+ |
+ if (id == local_device_info->guid()) { |
+ // |initial_sync_data| contains data matching the local device. |
+ scoped_ptr<DeviceInfo> synced_local_device_info = |
+ make_scoped_ptr(CreateDeviceInfo(*iter)); |
+ |
+ // Retrieve local device backup timestamp value from the sync data. |
+ bool has_synced_backup_time = |
+ iter->GetSpecifics().device_info().has_backup_timestamp(); |
+ int64 synced_backup_time = |
+ has_synced_backup_time |
+ ? iter->GetSpecifics().device_info().backup_timestamp() |
+ : -1; |
+ |
+ // Overwrite |local_device_backup_time_| with this value if it |
+ // hasn't been set yet. |
+ if (!has_local_device_backup_time() && has_synced_backup_time) { |
+ set_local_device_backup_time(synced_backup_time); |
+ } |
+ |
+ // Store the synced device info for the local device only |
+ // it is the same as the local info. Otherwise store the local |
+ // device info and issue a change further below after finishing |
+ // processing the |initial_sync_data|. |
+ if (synced_local_device_info->Equals(*local_device_info) && |
+ synced_backup_time == local_device_backup_time()) { |
+ change_type = SyncChange::ACTION_INVALID; |
+ } else { |
+ num_items_updated++; |
+ change_type = SyncChange::ACTION_UPDATE; |
+ continue; |
+ } |
+ } else { |
+ // A new device that doesn't match the local device. |
+ num_items_new++; |
} |
- } else { |
- // Local device info doesn't yet exist in the cache and |
- // will be added further below. |
- // |num_items_new| and |num_items_updated| are already correct. |
- change_type = SyncChange::ACTION_ADD; |
+ |
+ StoreSyncData(id, *iter); |
} |
syncer::SyncMergeResult result(type); |
- // Update SyncData from device info if it is new or different than |
+ // Add SyncData for the local device if it is new or different than |
// the synced one, and also add it to the |change_list|. |
if (change_type != SyncChange::ACTION_INVALID) { |
SyncData local_data = CreateLocalData(local_device_info); |
@@ -114,6 +135,7 @@ void DeviceInfoSyncService::StopSyncing(syncer::ModelType type) { |
all_data_.clear(); |
sync_processor_.reset(); |
error_handler_.reset(); |
+ clear_local_device_backup_time(); |
} |
SyncDataList DeviceInfoSyncService::GetAllSyncData( |
@@ -208,6 +230,56 @@ void DeviceInfoSyncService::NotifyObservers() { |
FOR_EACH_OBSERVER(Observer, observers_, OnDeviceInfoChange()); |
} |
+void DeviceInfoSyncService::UpdateLocalDeviceBackupTime( |
+ base::Time backup_time) { |
+ set_local_device_backup_time(syncer::TimeToProtoTime(backup_time)); |
+ |
+ if (sync_processor_.get()) { |
+ // Local device info must be available in advance |
+ DCHECK(local_device_info_provider_->GetLocalDeviceInfo()); |
+ const std::string& local_id = |
+ local_device_info_provider_->GetLocalDeviceInfo()->guid(); |
+ |
+ SyncDataMap::iterator iter = all_data_.find(local_id); |
+ DCHECK(iter != all_data_.end()); |
+ |
+ syncer::SyncData& data = iter->second; |
+ if (UpdateBackupTime(&data)) { |
+ // Local device backup time has changed. |
+ // Push changes to the server via the |sync_processor_|. |
+ SyncChangeList change_list; |
+ change_list.push_back(SyncChange( |
+ FROM_HERE, syncer::SyncChange::ACTION_UPDATE, data)); |
+ sync_processor_->ProcessSyncChanges(FROM_HERE, change_list); |
+ } |
+ } |
+} |
+ |
+bool DeviceInfoSyncService::UpdateBackupTime(syncer::SyncData* sync_data) { |
+ DCHECK(has_local_device_backup_time()); |
+ DCHECK(sync_data->GetSpecifics().has_device_info()); |
+ const sync_pb::DeviceInfoSpecifics& source_specifics = |
+ sync_data->GetSpecifics().device_info(); |
+ |
+ if (!source_specifics.has_backup_timestamp() || |
+ source_specifics.backup_timestamp() != local_device_backup_time()) { |
+ sync_pb::EntitySpecifics entity(sync_data->GetSpecifics()); |
+ entity.mutable_device_info()->set_backup_timestamp( |
+ local_device_backup_time()); |
+ *sync_data = CreateLocalData(entity); |
+ |
+ return true; |
+ } |
+ |
+ return false; |
+} |
+ |
+base::Time DeviceInfoSyncService::GetLocalDeviceBackupTime() const { |
+ return has_local_device_backup_time() |
+ ? syncer::ProtoTimeToTime(local_device_backup_time()) |
+ : base::Time(); |
+} |
+ |
SyncData DeviceInfoSyncService::CreateLocalData(const DeviceInfo* info) { |
sync_pb::EntitySpecifics entity; |
sync_pb::DeviceInfoSpecifics& specifics = *entity.mutable_device_info(); |
@@ -219,11 +291,22 @@ SyncData DeviceInfoSyncService::CreateLocalData(const DeviceInfo* info) { |
specifics.set_device_type(info->device_type()); |
specifics.set_signin_scoped_device_id(info->signin_scoped_device_id()); |
+ if (has_local_device_backup_time()) { |
+ specifics.set_backup_timestamp(local_device_backup_time()); |
+ } |
+ |
+ return CreateLocalData(entity); |
+} |
+ |
+SyncData DeviceInfoSyncService::CreateLocalData( |
+ const sync_pb::EntitySpecifics& entity) { |
+ const sync_pb::DeviceInfoSpecifics& specifics = entity.device_info(); |
+ |
std::string local_device_tag = |
- base::StringPrintf("DeviceInfo_%s", info->guid().c_str()); |
+ base::StringPrintf("DeviceInfo_%s", specifics.cache_guid().c_str()); |
return SyncData::CreateLocalData( |
- local_device_tag, info->client_name(), entity); |
+ local_device_tag, specifics.client_name(), entity); |
} |
DeviceInfo* DeviceInfoSyncService::CreateDeviceInfo( |