Chromium Code Reviews| Index: components/sync/engine_impl/model_type_worker.cc |
| diff --git a/components/sync/engine_impl/model_type_worker.cc b/components/sync/engine_impl/model_type_worker.cc |
| index fa9bea2d044608b5841872afd6f0aa34a6bd8b73..76a74d1e97f14058f7b9988c9ddaae6fce771cc9 100644 |
| --- a/components/sync/engine_impl/model_type_worker.cc |
| +++ b/components/sync/engine_impl/model_type_worker.cc |
| @@ -35,6 +35,7 @@ ModelTypeWorker::ModelTypeWorker( |
| model_type_processor_(std::move(model_type_processor)), |
| cryptographer_(std::move(cryptographer)), |
| nudge_handler_(nudge_handler), |
| + decrypted_everything_(true), |
| weak_ptr_factory_(this) { |
| DCHECK(model_type_processor_); |
| @@ -149,6 +150,7 @@ SyncerError ModelTypeWorker::ProcessGetUpdatesResponse( |
| data.specifics = specifics; |
| response_data.entity = data.PassToPtr(); |
| entity->ReceiveEncryptedUpdate(response_data); |
| + decrypted_everything_ = false; |
| } |
| } |
| @@ -175,11 +177,14 @@ void ModelTypeWorker::PassiveApplyUpdates(StatusController* status) { |
| } |
| void ModelTypeWorker::ApplyPendingUpdates() { |
| - DVLOG(1) << ModelTypeToString(type_) << ": " |
| - << base::StringPrintf("Delivering %" PRIuS " applicable updates.", |
| - pending_updates_.size()); |
| - model_type_processor_->OnUpdateReceived(model_type_state_, pending_updates_); |
| - pending_updates_.clear(); |
| + if (!BlockForEncryption()) { |
| + DVLOG(1) << ModelTypeToString(type_) << ": " |
| + << base::StringPrintf("Delivering %" PRIuS " applicable updates.", |
| + pending_updates_.size()); |
| + model_type_processor_->OnUpdateReceived(model_type_state_, |
| + pending_updates_); |
| + pending_updates_.clear(); |
| + } |
| } |
| void ModelTypeWorker::EnqueueForCommit(const CommitRequestDataList& list) { |
| @@ -204,8 +209,6 @@ void ModelTypeWorker::EnqueueForCommit(const CommitRequestDataList& list) { |
| std::unique_ptr<CommitContribution> ModelTypeWorker::GetContribution( |
| size_t max_entries) { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| - // There shouldn't be a GetUpdates in progress when a commit is triggered. |
| - DCHECK(pending_updates_.empty()); |
| size_t space_remaining = max_entries; |
| google::protobuf::RepeatedPtrField<sync_pb::SyncEntity> commit_entities; |
| @@ -269,14 +272,26 @@ bool ModelTypeWorker::CanCommitItems() const { |
| if (!IsTypeInitialized()) |
| return false; |
| - // Don't commit if we should be encrypting but don't have the required keys. |
| - if (cryptographer_ && !cryptographer_->is_ready()) { |
| + // We shouldn't commit anything if we're missing encryption keys. |
| + if (BlockForEncryption()) |
| return false; |
| - } |
| return true; |
| } |
| +bool ModelTypeWorker::BlockForEncryption() const { |
| + // Should be using encryption, but we do not have the keys. |
| + if (cryptographer_ && !cryptographer_->is_ready()) |
| + return true; |
| + |
| + // Encrypted entities have been returned by the server and decrypting them was |
| + // unsuccessful. This means there is a key we do not have. |
| + if (!decrypted_everything_) |
| + return true; |
| + |
| + return false; |
| +} |
| + |
| void ModelTypeWorker::AdjustCommitProto(sync_pb::SyncEntity* sync_entity) { |
| DCHECK(CanCommitItems()); |
| @@ -318,18 +333,17 @@ void ModelTypeWorker::AdjustCommitProto(sync_pb::SyncEntity* sync_entity) { |
| void ModelTypeWorker::OnCryptographerUpdated() { |
| DCHECK(cryptographer_); |
| - bool new_encryption_key = false; |
| - UpdateResponseDataList response_datas; |
| - |
| - const std::string& new_key_name = cryptographer_->GetDefaultNigoriKeyName(); |
| + // Reset the flag, if anything undecryptable is encountered below this flag |
|
maxbogue
2016/10/11 15:56:39
"Reset the flag. If anything undecryptable is enco
skym
2016/10/11 16:41:00
Done.
|
| + // will be updated back to false. |
| + decrypted_everything_ = true; |
| // Handle a change in encryption key. |
| - if (model_type_state_.encryption_key_name() != new_key_name) { |
| + const std::string& new_key_name = cryptographer_->GetDefaultNigoriKeyName(); |
| + const std::string& old_key_name = model_type_state_.encryption_key_name(); |
| + if (old_key_name != new_key_name) { |
| DVLOG(1) << ModelTypeToString(type_) << ": Updating encryption key " |
| - << model_type_state_.encryption_key_name() << " -> " |
| - << new_key_name; |
| + << old_key_name << " -> " << new_key_name; |
| model_type_state_.set_encryption_key_name(new_key_name); |
| - new_encryption_key = true; |
| } |
| for (const auto& kv : entities_) { |
| @@ -355,21 +369,25 @@ void ModelTypeWorker::OnCryptographerUpdated() { |
| decrypted_update.response_version = encrypted_update.response_version; |
| decrypted_update.encryption_key_name = |
| data.specifics.encrypted().key_name(); |
| - response_datas.push_back(decrypted_update); |
| + pending_updates_.push_back(decrypted_update); |
| entity->ClearEncryptedUpdate(); |
| } |
| + } else { |
| + // It is possible that we could get into a weird state where an entity |
| + // was encrypted with an old key that has since been overwritten. We are |
| + // never going to recieve the new key, and |decrypted_everything_| is |
|
maxbogue
2016/10/11 15:56:39
"receive"
skym
2016/10/11 16:41:00
Done.
|
| + // perpetually stuck false. Every time we start up, we use a really old |
| + // progress marker to download lots of entities, and that old and |
| + // undecryptable entity contiuously blocks progress. This would cause |
|
maxbogue
2016/10/11 15:56:39
"continuously"
skym
2016/10/11 16:41:00
Done.
|
| + // the data type to silently stop working, which is definitely less than |
|
maxbogue
2016/10/11 15:56:39
Should we add a UMA counter to track this case...?
skym
2016/10/11 16:41:00
It would be great to have an UMA counter that help
|
| + // ideal. Hopefully this never happens since nigori updates are rare and |
| + // should be using optimistic locking. |
| + decrypted_everything_ = false; |
| } |
| } |
| } |
| - |
| - if (new_encryption_key || response_datas.size() > 0) { |
| - DVLOG(1) << ModelTypeToString(type_) << ": " |
| - << base::StringPrintf("Delivering encryption key and %" PRIuS |
| - " decrypted updates.", |
| - response_datas.size()); |
| - model_type_processor_->OnUpdateReceived(model_type_state_, response_datas); |
| - } |
| + ApplyPendingUpdates(); |
| } |
| bool ModelTypeWorker::DecryptSpecifics(const sync_pb::EntitySpecifics& in, |