| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "sync/engine/download.h" | 5 #include "sync/engine/download.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "sync/engine/process_updates_command.h" | 10 #include "sync/engine/process_updates_util.h" |
| 11 #include "sync/engine/store_timestamps_command.h" | 11 #include "sync/engine/sync_directory_update_handler.h" |
| 12 #include "sync/engine/syncer.h" | 12 #include "sync/engine/syncer.h" |
| 13 #include "sync/engine/syncer_proto_util.h" | 13 #include "sync/engine/syncer_proto_util.h" |
| 14 #include "sync/sessions/nudge_tracker.h" | 14 #include "sync/sessions/nudge_tracker.h" |
| 15 #include "sync/syncable/directory.h" | 15 #include "sync/syncable/directory.h" |
| 16 #include "sync/syncable/nigori_handler.h" | 16 #include "sync/syncable/nigori_handler.h" |
| 17 #include "sync/syncable/syncable_read_transaction.h" | 17 #include "sync/syncable/syncable_read_transaction.h" |
| 18 | 18 |
| 19 using sync_pb::DebugInfo; | 19 using sync_pb::DebugInfo; |
| 20 | 20 |
| 21 namespace syncer { | 21 namespace syncer { |
| 22 | 22 |
| 23 using sessions::StatusController; | 23 using sessions::StatusController; |
| 24 using sessions::SyncSession; | 24 using sessions::SyncSession; |
| 25 using sessions::SyncSessionContext; | 25 using sessions::SyncSessionContext; |
| 26 using std::string; | 26 using std::string; |
| 27 | 27 |
| 28 namespace { | 28 namespace { |
| 29 | 29 |
| 30 typedef std::map<ModelType, const sync_pb::DataTypeProgressMarker*> |
| 31 TypeProgressMarkerMap; |
| 32 |
| 30 SyncerError HandleGetEncryptionKeyResponse( | 33 SyncerError HandleGetEncryptionKeyResponse( |
| 31 const sync_pb::ClientToServerResponse& update_response, | 34 const sync_pb::ClientToServerResponse& update_response, |
| 32 syncable::Directory* dir) { | 35 syncable::Directory* dir) { |
| 33 bool success = false; | 36 bool success = false; |
| 34 if (update_response.get_updates().encryption_keys_size() == 0) { | 37 if (update_response.get_updates().encryption_keys_size() == 0) { |
| 35 LOG(ERROR) << "Failed to receive encryption key from server."; | 38 LOG(ERROR) << "Failed to receive encryption key from server."; |
| 36 return SERVER_RESPONSE_VALIDATION_FAILED; | 39 return SERVER_RESPONSE_VALIDATION_FAILED; |
| 37 } | 40 } |
| 38 syncable::ReadTransaction trans(FROM_HERE, dir); | 41 syncable::ReadTransaction trans(FROM_HERE, dir); |
| 39 syncable::NigoriHandler* nigori_handler = dir->GetNigoriHandler(); | 42 syncable::NigoriHandler* nigori_handler = dir->GetNigoriHandler(); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 128 for (ModelTypeSet::Iterator it = request_types.First(); | 131 for (ModelTypeSet::Iterator it = request_types.First(); |
| 129 it.Good(); it.Inc()) { | 132 it.Good(); it.Inc()) { |
| 130 if (ProxyTypes().Has(it.Get())) | 133 if (ProxyTypes().Has(it.Get())) |
| 131 continue; | 134 continue; |
| 132 sync_pb::DataTypeProgressMarker* progress_marker = | 135 sync_pb::DataTypeProgressMarker* progress_marker = |
| 133 get_updates->add_from_progress_marker(); | 136 get_updates->add_from_progress_marker(); |
| 134 dir->GetDownloadProgress(it.Get(), progress_marker); | 137 dir->GetDownloadProgress(it.Get(), progress_marker); |
| 135 } | 138 } |
| 136 } | 139 } |
| 137 | 140 |
| 141 // Builds a map of ModelTypes to pointers to progress markers in the given |
| 142 // update response. The map is returned in the |marker_map| parameter. |
| 143 void PartitionProgressMarkersByType( |
| 144 const sync_pb::GetUpdatesResponse& gu_response, |
| 145 ModelTypeSet request_types, |
| 146 TypeProgressMarkerMap* marker_map) { |
| 147 for (int i = 0; i < gu_response.new_progress_marker_size(); ++i) { |
| 148 int field_number = gu_response.new_progress_marker(i).data_type_id(); |
| 149 ModelType model_type = GetModelTypeFromSpecificsFieldNumber(field_number); |
| 150 if (!IsRealDataType(model_type)) { |
| 151 DLOG(WARNING) << "Unknown field number " << field_number; |
| 152 continue; |
| 153 } |
| 154 if (!request_types.Has(model_type)) { |
| 155 DLOG(WARNING) |
| 156 << "Skipping unexpected progress marker for non-enabled type " |
| 157 << ModelTypeToString(model_type); |
| 158 continue; |
| 159 } |
| 160 marker_map->insert( |
| 161 std::make_pair(model_type, &gu_response.new_progress_marker(i))); |
| 162 } |
| 163 } |
| 164 |
| 165 // Examines the contents of the GetUpdates response message and forwards |
| 166 // relevant data to the UpdateHandlers for processing and persisting. |
| 167 bool ProcessUpdateResponseMessage( |
| 168 const sync_pb::GetUpdatesResponse& gu_response, |
| 169 ModelTypeSet proto_request_types, |
| 170 UpdateHandlerMap* handler_map, |
| 171 StatusController* status) { |
| 172 TypeSyncEntityMap updates_by_type; |
| 173 PartitionUpdatesByType(gu_response, proto_request_types, &updates_by_type); |
| 174 DCHECK_EQ(proto_request_types.Size(), updates_by_type.size()); |
| 175 |
| 176 TypeProgressMarkerMap progress_by_type; |
| 177 PartitionProgressMarkersByType(gu_response, |
| 178 proto_request_types, |
| 179 &progress_by_type); |
| 180 if (proto_request_types.Size() != progress_by_type.size()) { |
| 181 NOTREACHED() << "Missing progress markers in GetUpdates response."; |
| 182 return false; |
| 183 } |
| 184 |
| 185 // Iterate over these maps in parallel, processing updates for each type. |
| 186 TypeProgressMarkerMap::iterator pm_it = progress_by_type.begin(); |
| 187 TypeSyncEntityMap::iterator up_it = updates_by_type.begin(); |
| 188 for ( ; pm_it != progress_by_type.end() && up_it != updates_by_type.end(); |
| 189 ++pm_it, ++up_it) { |
| 190 DCHECK_EQ(pm_it->first, up_it->first); |
| 191 ModelType type = pm_it->first; |
| 192 |
| 193 UpdateHandlerMap::iterator uh_it = handler_map->find(type); |
| 194 |
| 195 if (uh_it != handler_map->end()) { |
| 196 uh_it->second->ProcessGetUpdatesResponse(*pm_it->second, |
| 197 up_it->second, |
| 198 status); |
| 199 } else { |
| 200 DLOG(WARNING) |
| 201 << "Ignoring received updates of a type we can't handle. " |
| 202 << "Type is: " << ModelTypeToString(type); |
| 203 continue; |
| 204 } |
| 205 } |
| 206 DCHECK(pm_it == progress_by_type.end() && up_it == updates_by_type.end()); |
| 207 |
| 208 return true; |
| 209 } |
| 210 |
| 138 } // namespace | 211 } // namespace |
| 139 | 212 |
| 140 void BuildNormalDownloadUpdates( | 213 void BuildNormalDownloadUpdates( |
| 141 SyncSession* session, | 214 SyncSession* session, |
| 142 bool create_mobile_bookmarks_folder, | 215 bool create_mobile_bookmarks_folder, |
| 143 ModelTypeSet request_types, | 216 ModelTypeSet request_types, |
| 144 const sessions::NudgeTracker& nudge_tracker, | 217 const sessions::NudgeTracker& nudge_tracker, |
| 145 sync_pb::ClientToServerMessage* client_to_server_message) { | 218 sync_pb::ClientToServerMessage* client_to_server_message) { |
| 146 InitDownloadUpdatesRequest( | 219 InitDownloadUpdatesRequest( |
| 147 session, | 220 session, |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 227 | 300 |
| 228 // Set legacy GetUpdatesMessage.GetUpdatesCallerInfo information. | 301 // Set legacy GetUpdatesMessage.GetUpdatesCallerInfo information. |
| 229 get_updates->mutable_caller_info()->set_source( | 302 get_updates->mutable_caller_info()->set_source( |
| 230 sync_pb::GetUpdatesCallerInfo::PERIODIC); | 303 sync_pb::GetUpdatesCallerInfo::PERIODIC); |
| 231 | 304 |
| 232 // Set the new and improved version of source, too. | 305 // Set the new and improved version of source, too. |
| 233 get_updates->set_get_updates_origin(sync_pb::SyncEnums::PERIODIC); | 306 get_updates->set_get_updates_origin(sync_pb::SyncEnums::PERIODIC); |
| 234 } | 307 } |
| 235 | 308 |
| 236 SyncerError ExecuteDownloadUpdates( | 309 SyncerError ExecuteDownloadUpdates( |
| 310 ModelTypeSet request_types, |
| 237 SyncSession* session, | 311 SyncSession* session, |
| 238 sync_pb::ClientToServerMessage* msg) { | 312 sync_pb::ClientToServerMessage* msg) { |
| 239 sync_pb::ClientToServerResponse update_response; | 313 sync_pb::ClientToServerResponse update_response; |
| 240 StatusController* status = session->mutable_status_controller(); | 314 StatusController* status = session->mutable_status_controller(); |
| 241 bool need_encryption_key = ShouldRequestEncryptionKey(session->context()); | 315 bool need_encryption_key = ShouldRequestEncryptionKey(session->context()); |
| 242 | 316 |
| 243 SyncerError result = SyncerProtoUtil::PostClientToServerMessage( | 317 SyncerError result = SyncerProtoUtil::PostClientToServerMessage( |
| 244 msg, | 318 msg, |
| 245 &update_response, | 319 &update_response, |
| 246 session); | 320 session); |
| 247 | 321 |
| 248 DVLOG(2) << SyncerProtoUtil::ClientToServerResponseDebugString( | 322 DVLOG(2) << SyncerProtoUtil::ClientToServerResponseDebugString( |
| 249 update_response); | 323 update_response); |
| 250 | 324 |
| 251 if (result != SYNCER_OK) { | 325 if (result != SYNCER_OK) { |
| 252 status->mutable_updates_response()->Clear(); | 326 status->mutable_updates_response()->Clear(); |
| 253 LOG(ERROR) << "PostClientToServerMessage() failed during GetUpdates"; | 327 LOG(ERROR) << "PostClientToServerMessage() failed during GetUpdates"; |
| 254 } else { | 328 return result; |
| 255 status->mutable_updates_response()->CopyFrom(update_response); | |
| 256 | |
| 257 DVLOG(1) << "GetUpdates " | |
| 258 << " returned " << update_response.get_updates().entries_size() | |
| 259 << " updates and indicated " | |
| 260 << update_response.get_updates().changes_remaining() | |
| 261 << " updates left on server."; | |
| 262 | |
| 263 if (need_encryption_key || | |
| 264 update_response.get_updates().encryption_keys_size() > 0) { | |
| 265 syncable::Directory* dir = session->context()->directory(); | |
| 266 status->set_last_get_key_result( | |
| 267 HandleGetEncryptionKeyResponse(update_response, dir)); | |
| 268 } | |
| 269 } | 329 } |
| 270 | 330 |
| 271 ProcessUpdatesCommand process_updates; | 331 status->mutable_updates_response()->CopyFrom(update_response); |
| 272 process_updates.Execute(session); | |
| 273 | 332 |
| 274 StoreTimestampsCommand store_timestamps; | 333 DVLOG(1) << "GetUpdates " |
| 275 store_timestamps.Execute(session); | 334 << " returned " << update_response.get_updates().entries_size() |
| 335 << " updates and indicated " |
| 336 << update_response.get_updates().changes_remaining() |
| 337 << " updates left on server."; |
| 276 | 338 |
| 277 return result; | 339 if (need_encryption_key || |
| 340 update_response.get_updates().encryption_keys_size() > 0) { |
| 341 syncable::Directory* dir = session->context()->directory(); |
| 342 status->set_last_get_key_result( |
| 343 HandleGetEncryptionKeyResponse(update_response, dir)); |
| 344 } |
| 345 |
| 346 const sync_pb::GetUpdatesResponse& gu_response = |
| 347 update_response.get_updates(); |
| 348 status->increment_num_updates_downloaded_by(gu_response.entries_size()); |
| 349 DCHECK(gu_response.has_changes_remaining()); |
| 350 status->set_num_server_changes_remaining(gu_response.changes_remaining()); |
| 351 |
| 352 const ModelTypeSet proto_request_types = |
| 353 Intersection(request_types, ProtocolTypes()); |
| 354 |
| 355 if (!ProcessUpdateResponseMessage(gu_response, |
| 356 proto_request_types, |
| 357 session->context()->update_handler_map(), |
| 358 status)) { |
| 359 return SERVER_RESPONSE_VALIDATION_FAILED; |
| 360 } else { |
| 361 return result; |
| 362 } |
| 278 } | 363 } |
| 279 | 364 |
| 280 } // namespace syncer | 365 } // namespace syncer |
| OLD | NEW |