OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "chrome/browser/sync/glue/device_info_sync_service.h" | 5 #include "chrome/browser/sync/glue/device_info_sync_service.h" |
6 | 6 |
7 #include "base/strings/stringprintf.h" | 7 #include "base/strings/stringprintf.h" |
8 #include "chrome/browser/sync/glue/local_device_info_provider.h" | 8 #include "chrome/browser/sync/glue/local_device_info_provider.h" |
9 #include "sync/api/sync_change.h" | 9 #include "sync/api/sync_change.h" |
10 #include "sync/protocol/sync.pb.h" | 10 #include "sync/protocol/sync.pb.h" |
| 11 #include "sync/util/time.h" |
11 | 12 |
12 namespace browser_sync { | 13 namespace browser_sync { |
13 | 14 |
14 using syncer::ModelType; | 15 using syncer::ModelType; |
15 using syncer::SyncChange; | 16 using syncer::SyncChange; |
16 using syncer::SyncChangeList; | 17 using syncer::SyncChangeList; |
17 using syncer::SyncChangeProcessor; | 18 using syncer::SyncChangeProcessor; |
18 using syncer::SyncData; | 19 using syncer::SyncData; |
19 using syncer::SyncDataList; | 20 using syncer::SyncDataList; |
20 using syncer::SyncErrorFactory; | 21 using syncer::SyncErrorFactory; |
21 using syncer::SyncMergeResult; | 22 using syncer::SyncMergeResult; |
22 | 23 |
23 DeviceInfoSyncService::DeviceInfoSyncService( | 24 DeviceInfoSyncService::DeviceInfoSyncService( |
24 LocalDeviceInfoProvider* local_device_info_provider) | 25 LocalDeviceInfoProvider* local_device_info_provider) |
25 : local_device_info_provider_(local_device_info_provider) { | 26 : local_device_backup_time_(-1), |
| 27 local_device_info_provider_(local_device_info_provider) { |
26 DCHECK(local_device_info_provider); | 28 DCHECK(local_device_info_provider); |
27 } | 29 } |
28 | 30 |
29 DeviceInfoSyncService::~DeviceInfoSyncService() { | 31 DeviceInfoSyncService::~DeviceInfoSyncService() { |
30 } | 32 } |
31 | 33 |
32 SyncMergeResult DeviceInfoSyncService::MergeDataAndStartSyncing( | 34 SyncMergeResult DeviceInfoSyncService::MergeDataAndStartSyncing( |
33 ModelType type, | 35 ModelType type, |
34 const SyncDataList& initial_sync_data, | 36 const SyncDataList& initial_sync_data, |
35 scoped_ptr<SyncChangeProcessor> sync_processor, | 37 scoped_ptr<SyncChangeProcessor> sync_processor, |
36 scoped_ptr<SyncErrorFactory> error_handler) { | 38 scoped_ptr<SyncErrorFactory> error_handler) { |
37 DCHECK(sync_processor.get()); | 39 DCHECK(sync_processor.get()); |
38 DCHECK(error_handler.get()); | 40 DCHECK(error_handler.get()); |
39 DCHECK_EQ(type, syncer::DEVICE_INFO); | 41 DCHECK_EQ(type, syncer::DEVICE_INFO); |
40 | 42 |
41 DCHECK(all_data_.empty()); | 43 DCHECK(all_data_.empty()); |
42 | 44 |
43 sync_processor_ = sync_processor.Pass(); | 45 sync_processor_ = sync_processor.Pass(); |
44 error_handler_ = error_handler.Pass(); | 46 error_handler_ = error_handler.Pass(); |
45 | 47 |
| 48 // Initialization should be completed before this type is enabled |
| 49 // and local device info must be available. |
| 50 const DeviceInfo* local_device_info = |
| 51 local_device_info_provider_->GetLocalDeviceInfo(); |
| 52 DCHECK(local_device_info != NULL); |
| 53 |
| 54 // Indicates whether a local device has been added or updated. |
| 55 // |change_type| defaults to ADD and might be changed to |
| 56 // UPDATE to INVALID down below if the initial data contains |
| 57 // data matching the local device ID. |
| 58 SyncChange::SyncChangeType change_type = SyncChange::ACTION_ADD; |
| 59 size_t num_items_new = 0; |
| 60 size_t num_items_updated = 0; |
| 61 |
46 // Iterate over all initial sync data and copy it to the cache. | 62 // Iterate over all initial sync data and copy it to the cache. |
47 for (SyncDataList::const_iterator iter = initial_sync_data.begin(); | 63 for (SyncDataList::const_iterator iter = initial_sync_data.begin(); |
48 iter != initial_sync_data.end(); | 64 iter != initial_sync_data.end(); |
49 ++iter) { | 65 ++iter) { |
50 DCHECK_EQ(syncer::DEVICE_INFO, iter->GetDataType()); | 66 DCHECK_EQ(syncer::DEVICE_INFO, iter->GetDataType()); |
51 StoreSyncData(iter->GetSpecifics().device_info().cache_guid(), *iter); | |
52 } | |
53 | 67 |
54 size_t num_items_new = initial_sync_data.size(); | 68 const std::string& id = iter->GetSpecifics().device_info().cache_guid(); |
55 size_t num_items_updated = 0; | |
56 // Indicates whether a local device has been added or updated. | |
57 SyncChange::SyncChangeType change_type = SyncChange::ACTION_INVALID; | |
58 | 69 |
59 // Initialization should be completed before this type is enabled | 70 if (id == local_device_info->guid()) { |
60 // and local device info must be available. | 71 // |initial_sync_data| contains data matching the local device. |
61 const DeviceInfo* local_device_info = | 72 scoped_ptr<DeviceInfo> synced_local_device_info = |
62 local_device_info_provider_->GetLocalDeviceInfo(); | 73 make_scoped_ptr(CreateDeviceInfo(*iter)); |
63 DCHECK(local_device_info != NULL); | |
64 // Before storing the local device info check if the data with | |
65 // the same guid has already been synced. This attempts to retrieve | |
66 // DeviceInfo from the cached data initialized above. | |
67 scoped_ptr<DeviceInfo> synced_local_device_info = | |
68 GetDeviceInfo(local_device_info->guid()); | |
69 | 74 |
70 if (synced_local_device_info.get()) { | 75 // Retrieve local device backup timestamp value from the sync data. |
71 // Local device info has been synced and exists in the cache. | 76 bool has_synced_backup_time = |
72 // |num_items_new| and |num_items_updated| need to be updated to | 77 iter->GetSpecifics().device_info().has_backup_timestamp(); |
73 // reflect that. | 78 int64 synced_backup_time = |
74 num_items_new--; | 79 has_synced_backup_time |
75 // Overwrite the synced device info with the local data only if | 80 ? iter->GetSpecifics().device_info().backup_timestamp() |
76 // it is different. | 81 : -1; |
77 if (!synced_local_device_info->Equals(*local_device_info)) { | 82 |
78 num_items_updated++; | 83 // Overwrite |local_device_backup_time_| with this value if it |
79 change_type = SyncChange::ACTION_UPDATE; | 84 // hasn't been set yet. |
| 85 if (!has_local_device_backup_time() && has_synced_backup_time) { |
| 86 set_local_device_backup_time(synced_backup_time); |
| 87 } |
| 88 |
| 89 // Store the synced device info for the local device only |
| 90 // it is the same as the local info. Otherwise store the local |
| 91 // device info and issue a change further below after finishing |
| 92 // processing the |initial_sync_data|. |
| 93 if (synced_local_device_info->Equals(*local_device_info) && |
| 94 synced_backup_time == local_device_backup_time()) { |
| 95 change_type = SyncChange::ACTION_INVALID; |
| 96 } else { |
| 97 num_items_updated++; |
| 98 change_type = SyncChange::ACTION_UPDATE; |
| 99 continue; |
| 100 } |
| 101 } else { |
| 102 // A new device that doesn't match the local device. |
| 103 num_items_new++; |
80 } | 104 } |
81 } else { | 105 |
82 // Local device info doesn't yet exist in the cache and | 106 StoreSyncData(id, *iter); |
83 // will be added further below. | |
84 // |num_items_new| and |num_items_updated| are already correct. | |
85 change_type = SyncChange::ACTION_ADD; | |
86 } | 107 } |
87 | 108 |
88 syncer::SyncMergeResult result(type); | 109 syncer::SyncMergeResult result(type); |
89 | 110 |
90 // Update SyncData from device info if it is new or different than | 111 // Add SyncData for the local device if it is new or different than |
91 // the synced one, and also add it to the |change_list|. | 112 // the synced one, and also add it to the |change_list|. |
92 if (change_type != SyncChange::ACTION_INVALID) { | 113 if (change_type != SyncChange::ACTION_INVALID) { |
93 SyncData local_data = CreateLocalData(local_device_info); | 114 SyncData local_data = CreateLocalData(local_device_info); |
94 StoreSyncData(local_device_info->guid(), local_data); | 115 StoreSyncData(local_device_info->guid(), local_data); |
95 | 116 |
96 SyncChangeList change_list; | 117 SyncChangeList change_list; |
97 change_list.push_back(SyncChange(FROM_HERE, change_type, local_data)); | 118 change_list.push_back(SyncChange(FROM_HERE, change_type, local_data)); |
98 result.set_error( | 119 result.set_error( |
99 sync_processor_->ProcessSyncChanges(FROM_HERE, change_list)); | 120 sync_processor_->ProcessSyncChanges(FROM_HERE, change_list)); |
100 } | 121 } |
101 | 122 |
102 result.set_num_items_before_association(1); | 123 result.set_num_items_before_association(1); |
103 result.set_num_items_after_association(all_data_.size()); | 124 result.set_num_items_after_association(all_data_.size()); |
104 result.set_num_items_added(num_items_new); | 125 result.set_num_items_added(num_items_new); |
105 result.set_num_items_modified(num_items_updated); | 126 result.set_num_items_modified(num_items_updated); |
106 result.set_num_items_deleted(0); | 127 result.set_num_items_deleted(0); |
107 | 128 |
108 NotifyObservers(); | 129 NotifyObservers(); |
109 | 130 |
110 return result; | 131 return result; |
111 } | 132 } |
112 | 133 |
113 void DeviceInfoSyncService::StopSyncing(syncer::ModelType type) { | 134 void DeviceInfoSyncService::StopSyncing(syncer::ModelType type) { |
114 all_data_.clear(); | 135 all_data_.clear(); |
115 sync_processor_.reset(); | 136 sync_processor_.reset(); |
116 error_handler_.reset(); | 137 error_handler_.reset(); |
| 138 clear_local_device_backup_time(); |
117 } | 139 } |
118 | 140 |
119 SyncDataList DeviceInfoSyncService::GetAllSyncData( | 141 SyncDataList DeviceInfoSyncService::GetAllSyncData( |
120 syncer::ModelType type) const { | 142 syncer::ModelType type) const { |
121 SyncDataList list; | 143 SyncDataList list; |
122 | 144 |
123 for (SyncDataMap::const_iterator iter = all_data_.begin(); | 145 for (SyncDataMap::const_iterator iter = all_data_.begin(); |
124 iter != all_data_.end(); | 146 iter != all_data_.end(); |
125 ++iter) { | 147 ++iter) { |
126 list.push_back(iter->second); | 148 list.push_back(iter->second); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
201 } | 223 } |
202 | 224 |
203 void DeviceInfoSyncService::RemoveObserver(Observer* observer) { | 225 void DeviceInfoSyncService::RemoveObserver(Observer* observer) { |
204 observers_.RemoveObserver(observer); | 226 observers_.RemoveObserver(observer); |
205 } | 227 } |
206 | 228 |
207 void DeviceInfoSyncService::NotifyObservers() { | 229 void DeviceInfoSyncService::NotifyObservers() { |
208 FOR_EACH_OBSERVER(Observer, observers_, OnDeviceInfoChange()); | 230 FOR_EACH_OBSERVER(Observer, observers_, OnDeviceInfoChange()); |
209 } | 231 } |
210 | 232 |
| 233 void DeviceInfoSyncService::UpdateLocalDeviceBackupTime( |
| 234 base::Time backup_time) { |
| 235 set_local_device_backup_time(syncer::TimeToProtoTime(backup_time)); |
| 236 |
| 237 if (sync_processor_.get()) { |
| 238 // Local device info must be available in advance |
| 239 DCHECK(local_device_info_provider_->GetLocalDeviceInfo()); |
| 240 const std::string& local_id = |
| 241 local_device_info_provider_->GetLocalDeviceInfo()->guid(); |
| 242 |
| 243 SyncDataMap::iterator iter = all_data_.find(local_id); |
| 244 DCHECK(iter != all_data_.end()); |
| 245 |
| 246 syncer::SyncData& data = iter->second; |
| 247 if (UpdateBackupTime(&data)) { |
| 248 // Local device backup time has changed. |
| 249 // Push changes to the server via the |sync_processor_|. |
| 250 SyncChangeList change_list; |
| 251 change_list.push_back(SyncChange( |
| 252 FROM_HERE, syncer::SyncChange::ACTION_UPDATE, data)); |
| 253 sync_processor_->ProcessSyncChanges(FROM_HERE, change_list); |
| 254 } |
| 255 } |
| 256 } |
| 257 |
| 258 bool DeviceInfoSyncService::UpdateBackupTime(syncer::SyncData* sync_data) { |
| 259 DCHECK(has_local_device_backup_time()); |
| 260 DCHECK(sync_data->GetSpecifics().has_device_info()); |
| 261 const sync_pb::DeviceInfoSpecifics& source_specifics = |
| 262 sync_data->GetSpecifics().device_info(); |
| 263 |
| 264 if (!source_specifics.has_backup_timestamp() || |
| 265 source_specifics.backup_timestamp() != local_device_backup_time()) { |
| 266 sync_pb::EntitySpecifics entity(sync_data->GetSpecifics()); |
| 267 entity.mutable_device_info()->set_backup_timestamp( |
| 268 local_device_backup_time()); |
| 269 *sync_data = CreateLocalData(entity); |
| 270 |
| 271 return true; |
| 272 } |
| 273 |
| 274 return false; |
| 275 } |
| 276 |
| 277 base::Time DeviceInfoSyncService::GetLocalDeviceBackupTime() const { |
| 278 return has_local_device_backup_time() |
| 279 ? syncer::ProtoTimeToTime(local_device_backup_time()) |
| 280 : base::Time(); |
| 281 } |
| 282 |
211 SyncData DeviceInfoSyncService::CreateLocalData(const DeviceInfo* info) { | 283 SyncData DeviceInfoSyncService::CreateLocalData(const DeviceInfo* info) { |
212 sync_pb::EntitySpecifics entity; | 284 sync_pb::EntitySpecifics entity; |
213 sync_pb::DeviceInfoSpecifics& specifics = *entity.mutable_device_info(); | 285 sync_pb::DeviceInfoSpecifics& specifics = *entity.mutable_device_info(); |
214 | 286 |
215 specifics.set_cache_guid(info->guid()); | 287 specifics.set_cache_guid(info->guid()); |
216 specifics.set_client_name(info->client_name()); | 288 specifics.set_client_name(info->client_name()); |
217 specifics.set_chrome_version(info->chrome_version()); | 289 specifics.set_chrome_version(info->chrome_version()); |
218 specifics.set_sync_user_agent(info->sync_user_agent()); | 290 specifics.set_sync_user_agent(info->sync_user_agent()); |
219 specifics.set_device_type(info->device_type()); | 291 specifics.set_device_type(info->device_type()); |
220 specifics.set_signin_scoped_device_id(info->signin_scoped_device_id()); | 292 specifics.set_signin_scoped_device_id(info->signin_scoped_device_id()); |
221 | 293 |
| 294 if (has_local_device_backup_time()) { |
| 295 specifics.set_backup_timestamp(local_device_backup_time()); |
| 296 } |
| 297 |
| 298 return CreateLocalData(entity); |
| 299 } |
| 300 |
| 301 SyncData DeviceInfoSyncService::CreateLocalData( |
| 302 const sync_pb::EntitySpecifics& entity) { |
| 303 const sync_pb::DeviceInfoSpecifics& specifics = entity.device_info(); |
| 304 |
222 std::string local_device_tag = | 305 std::string local_device_tag = |
223 base::StringPrintf("DeviceInfo_%s", info->guid().c_str()); | 306 base::StringPrintf("DeviceInfo_%s", specifics.cache_guid().c_str()); |
224 | 307 |
225 return SyncData::CreateLocalData( | 308 return SyncData::CreateLocalData( |
226 local_device_tag, info->client_name(), entity); | 309 local_device_tag, specifics.client_name(), entity); |
227 } | 310 } |
228 | 311 |
229 DeviceInfo* DeviceInfoSyncService::CreateDeviceInfo( | 312 DeviceInfo* DeviceInfoSyncService::CreateDeviceInfo( |
230 const syncer::SyncData sync_data) { | 313 const syncer::SyncData sync_data) { |
231 const sync_pb::DeviceInfoSpecifics& specifics = | 314 const sync_pb::DeviceInfoSpecifics& specifics = |
232 sync_data.GetSpecifics().device_info(); | 315 sync_data.GetSpecifics().device_info(); |
233 | 316 |
234 return new DeviceInfo(specifics.cache_guid(), | 317 return new DeviceInfo(specifics.cache_guid(), |
235 specifics.client_name(), | 318 specifics.client_name(), |
236 specifics.chrome_version(), | 319 specifics.chrome_version(), |
(...skipping 14 matching lines...) Expand all Loading... |
251 SyncDataMap::iterator iter = all_data_.find(client_id); | 334 SyncDataMap::iterator iter = all_data_.find(client_id); |
252 if (iter != all_data_.end()) { | 335 if (iter != all_data_.end()) { |
253 DVLOG(1) << "Deleting DEVICE_INFO for " | 336 DVLOG(1) << "Deleting DEVICE_INFO for " |
254 << iter->second.GetSpecifics().device_info().client_name() | 337 << iter->second.GetSpecifics().device_info().client_name() |
255 << " with ID " << client_id; | 338 << " with ID " << client_id; |
256 all_data_.erase(iter); | 339 all_data_.erase(iter); |
257 } | 340 } |
258 } | 341 } |
259 | 342 |
260 } // namespace browser_sync | 343 } // namespace browser_sync |
OLD | NEW |