| Index: sync/engine/model_type_sync_proxy_impl.cc
|
| diff --git a/sync/engine/model_type_sync_proxy_impl.cc b/sync/engine/model_type_sync_proxy_impl.cc
|
| index 7b2148ace0c6fec764697d8b2699d5afbc5b1458..7ea5d526214411fa504fb60767b137c325ee1553 100644
|
| --- a/sync/engine/model_type_sync_proxy_impl.cc
|
| +++ b/sync/engine/model_type_sync_proxy_impl.cc
|
| @@ -18,6 +18,7 @@ ModelTypeSyncProxyImpl::ModelTypeSyncProxyImpl(ModelType type)
|
| is_preferred_(false),
|
| is_connected_(false),
|
| entities_deleter_(&entities_),
|
| + pending_updates_map_deleter_(&pending_updates_map_),
|
| weak_ptr_factory_for_ui_(this),
|
| weak_ptr_factory_for_sync_(this) {
|
| }
|
| @@ -51,10 +52,12 @@ void ModelTypeSyncProxyImpl::Enable(
|
| data_type_state_.progress_marker.set_data_type_id(
|
| GetSpecificsFieldNumberFromModelType(type_));
|
|
|
| + UpdateResponseDataList saved_pending_updates = GetPendingUpdates();
|
| sync_context_proxy_ = sync_context_proxy.Pass();
|
| sync_context_proxy_->ConnectTypeToSync(
|
| GetModelType(),
|
| data_type_state_,
|
| + saved_pending_updates,
|
| weak_ptr_factory_for_sync_.GetWeakPtr());
|
| }
|
|
|
| @@ -180,16 +183,18 @@ void ModelTypeSyncProxyImpl::OnCommitCompleted(
|
| } else {
|
| it->second->ReceiveCommitResponse(response_data.id,
|
| response_data.sequence_number,
|
| - response_data.response_version);
|
| + response_data.response_version,
|
| + data_type_state_.encryption_key_name);
|
| }
|
| }
|
| }
|
|
|
| void ModelTypeSyncProxyImpl::OnUpdateReceived(
|
| const DataTypeState& data_type_state,
|
| - const UpdateResponseDataList& response_list) {
|
| - bool initial_sync_just_finished =
|
| - !data_type_state_.initial_sync_done && data_type_state.initial_sync_done;
|
| + const UpdateResponseDataList& response_list,
|
| + const UpdateResponseDataList& pending_updates) {
|
| + bool got_new_encryption_requirements = data_type_state_.encryption_key_name !=
|
| + data_type_state.encryption_key_name;
|
|
|
| data_type_state_ = data_type_state;
|
|
|
| @@ -199,6 +204,14 @@ void ModelTypeSyncProxyImpl::OnUpdateReceived(
|
| const UpdateResponseData& response_data = *list_it;
|
| const std::string& client_tag_hash = response_data.client_tag_hash;
|
|
|
| + UpdateMap::iterator old_it = pending_updates_map_.find(client_tag_hash);
|
| + if (old_it != pending_updates_map_.end()) {
|
| + // If we're being asked to apply an update to this entity, this overrides
|
| + // the previous pending updates.
|
| + delete old_it->second;
|
| + pending_updates_map_.erase(old_it);
|
| + }
|
| +
|
| EntityMap::iterator it = entities_.find(client_tag_hash);
|
| if (it == entities_.end()) {
|
| scoped_ptr<ModelTypeEntity> entity =
|
| @@ -209,22 +222,74 @@ void ModelTypeSyncProxyImpl::OnUpdateReceived(
|
| response_data.specifics,
|
| response_data.deleted,
|
| response_data.ctime,
|
| - response_data.mtime);
|
| + response_data.mtime,
|
| + response_data.encryption_key_name);
|
| entities_.insert(std::make_pair(client_tag_hash, entity.release()));
|
| } else {
|
| ModelTypeEntity* entity = it->second;
|
| entity->ApplyUpdateFromServer(response_data.response_version,
|
| response_data.deleted,
|
| response_data.specifics,
|
| - response_data.mtime);
|
| + response_data.mtime,
|
| + response_data.encryption_key_name);
|
| +
|
| // TODO: Do something special when conflicts are detected.
|
| }
|
| +
|
| + // If the received entity has out of date encryption, we schedule another
|
| + // commit to fix it.
|
| + if (data_type_state_.encryption_key_name !=
|
| + response_data.encryption_key_name) {
|
| + EntityMap::iterator it2 = entities_.find(client_tag_hash);
|
| + it2->second->UpdateDesiredEncryptionKey(
|
| + data_type_state_.encryption_key_name);
|
| + }
|
| }
|
|
|
| - if (initial_sync_just_finished)
|
| - FlushPendingCommitRequests();
|
| + // Save pending updates in the appropriate data structure.
|
| + for (UpdateResponseDataList::const_iterator list_it = pending_updates.begin();
|
| + list_it != pending_updates.end();
|
| + ++list_it) {
|
| + const UpdateResponseData& update = *list_it;
|
| + const std::string& client_tag_hash = update.client_tag_hash;
|
| +
|
| + UpdateMap::iterator lookup_it = pending_updates_map_.find(client_tag_hash);
|
| + if (lookup_it == pending_updates_map_.end()) {
|
| + pending_updates_map_.insert(
|
| + std::make_pair(client_tag_hash, new UpdateResponseData(update)));
|
| + } else if (lookup_it->second->response_version <= update.response_version) {
|
| + delete lookup_it->second;
|
| + pending_updates_map_.erase(lookup_it);
|
| + pending_updates_map_.insert(
|
| + std::make_pair(client_tag_hash, new UpdateResponseData(update)));
|
| + } else {
|
| + // Received update is stale, do not overwrite existing.
|
| + }
|
| + }
|
| +
|
| + if (got_new_encryption_requirements) {
|
| + for (EntityMap::iterator it = entities_.begin(); it != entities_.end();
|
| + ++it) {
|
| + it->second->UpdateDesiredEncryptionKey(
|
| + data_type_state_.encryption_key_name);
|
| + }
|
| + }
|
| +
|
| + // We may have new reasons to commit by the time this function is done.
|
| + FlushPendingCommitRequests();
|
|
|
| // TODO: Inform the model of the new or updated data.
|
| + // TODO: Persist the new data on disk.
|
| +}
|
| +
|
| +UpdateResponseDataList ModelTypeSyncProxyImpl::GetPendingUpdates() {
|
| + UpdateResponseDataList pending_updates_list;
|
| + for (UpdateMap::const_iterator it = pending_updates_map_.begin();
|
| + it != pending_updates_map_.end();
|
| + ++it) {
|
| + pending_updates_list.push_back(*it->second);
|
| + }
|
| + return pending_updates_list;
|
| }
|
|
|
| void ModelTypeSyncProxyImpl::ClearTransientSyncState() {
|
| @@ -239,7 +304,7 @@ void ModelTypeSyncProxyImpl::ClearSyncState() {
|
| ++it) {
|
| it->second->ClearSyncState();
|
| }
|
| -
|
| + STLDeleteValues(&pending_updates_map_);
|
| data_type_state_ = DataTypeState();
|
| }
|
|
|
|
|