summaryrefslogtreecommitdiffstats
path: root/sync/engine
diff options
context:
space:
mode:
Diffstat (limited to 'sync/engine')
-rw-r--r--sync/engine/cryptographer_provider.cc42
-rw-r--r--sync/engine/cryptographer_provider.h64
-rw-r--r--sync/engine/directory_cryptographer_provider.cc38
-rw-r--r--sync/engine/directory_cryptographer_provider.h51
-rw-r--r--sync/engine/model_type_entity.cc3
-rw-r--r--sync/engine/model_type_sync_proxy_impl.cc3
-rw-r--r--sync/engine/model_type_sync_worker_impl.cc123
-rw-r--r--sync/engine/model_type_sync_worker_impl.h25
-rw-r--r--sync/engine/model_type_sync_worker_impl_unittest.cc95
9 files changed, 151 insertions, 293 deletions
diff --git a/sync/engine/cryptographer_provider.cc b/sync/engine/cryptographer_provider.cc
deleted file mode 100644
index 2c16bc4..0000000
--- a/sync/engine/cryptographer_provider.cc
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "sync/engine/cryptographer_provider.h"
-
-namespace syncer {
-
-CryptographerProvider::CryptographerProvider() {
-}
-
-CryptographerProvider::~CryptographerProvider() {
-}
-
-ScopedCryptographerRef::ScopedCryptographerRef() {
-}
-
-ScopedCryptographerRef::~ScopedCryptographerRef() {
-}
-
-bool ScopedCryptographerRef::Initialize(ScopedCryptographerInternal* impl) {
- scoped_cryptographer_internal_.reset(impl);
- return IsValid();
-}
-
-bool ScopedCryptographerRef::IsValid() const {
- return !!Get();
-}
-
-Cryptographer* ScopedCryptographerRef::Get() const {
- if (!scoped_cryptographer_internal_)
- return NULL;
- return scoped_cryptographer_internal_->Get();
-}
-
-ScopedCryptographerInternal::ScopedCryptographerInternal() {
-}
-
-ScopedCryptographerInternal::~ScopedCryptographerInternal() {
-}
-
-} // namespace syncer
diff --git a/sync/engine/cryptographer_provider.h b/sync/engine/cryptographer_provider.h
deleted file mode 100644
index f38bd185..0000000
--- a/sync/engine/cryptographer_provider.h
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SYNC_ENGINE_CRYPTOGRAPHER_PROVIDER_H_
-#define SYNC_ENGINE_CRYPTOGRAPHER_PROVIDER_H_
-
-#include "base/memory/scoped_ptr.h"
-#include "sync/base/sync_export.h"
-
-namespace syncer {
-
-class Cryptographer;
-class ScopedCryptographerRef;
-class ScopedCryptographerInternal;
-
-// An interface for providing clients with a ScopedCryptographerRef.
-//
-// Used to expose the syncable::Directory's cryptographer to clients that
-// would otherwise not have access to the Directory.
-class SYNC_EXPORT_PRIVATE CryptographerProvider {
- public:
- CryptographerProvider();
- virtual ~CryptographerProvider();
-
- virtual bool InitScopedCryptographerRef(ScopedCryptographerRef* scoped) = 0;
-};
-
-// A concrete class representing a reference to a cryptographer.
-//
-// Access to the cryptographer is lost when this class goes out of scope.
-class SYNC_EXPORT_PRIVATE ScopedCryptographerRef {
- public:
- ScopedCryptographerRef();
- ~ScopedCryptographerRef();
-
- bool Initialize(ScopedCryptographerInternal* impl);
- bool IsValid() const;
- Cryptographer* Get() const;
-
- private:
- scoped_ptr<ScopedCryptographerInternal> scoped_cryptographer_internal_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedCryptographerRef);
-};
-
-// An interface class used in the implementation of the ScopedCryptographerRef.
-//
-// We use this class to allow different implementations of
-// CryptographerProvider to implement InitScopedCryptographer in different
-// ways. The ScopedCryptographerRef itself must be stack-allocated, so it
-// can't vary depending on which kind of CryptographerProvider is used to
-// intialize it.
-class SYNC_EXPORT_PRIVATE ScopedCryptographerInternal {
- public:
- ScopedCryptographerInternal();
- virtual ~ScopedCryptographerInternal();
-
- virtual Cryptographer* Get() const = 0;
-};
-
-} // namespace syncer
-
-#endif // SYNC_ENGINE_CRYPTOGRAPHER_PROVIDER_H_
diff --git a/sync/engine/directory_cryptographer_provider.cc b/sync/engine/directory_cryptographer_provider.cc
deleted file mode 100644
index a9cd2a2..0000000
--- a/sync/engine/directory_cryptographer_provider.cc
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "sync/engine/directory_cryptographer_provider.h"
-
-#include "sync/syncable/directory.h"
-#include "sync/syncable/syncable_read_transaction.h"
-
-namespace syncer {
-
-DirectoryCryptographerProvider::DirectoryCryptographerProvider(
- syncable::Directory* dir)
- : dir_(dir) {
-}
-
-DirectoryCryptographerProvider::~DirectoryCryptographerProvider() {
-}
-
-bool DirectoryCryptographerProvider::InitScopedCryptographerRef(
- ScopedCryptographerRef* scoped) {
- scoped->Initialize(new ScopedDirectoryCryptographerInternal(dir_));
- return scoped->IsValid();
-}
-
-ScopedDirectoryCryptographerInternal::ScopedDirectoryCryptographerInternal(
- syncable::Directory* dir)
- : dir_(dir), trans_(FROM_HERE, dir) {
-}
-
-ScopedDirectoryCryptographerInternal::~ScopedDirectoryCryptographerInternal() {
-}
-
-Cryptographer* ScopedDirectoryCryptographerInternal::Get() const {
- return dir_->GetCryptographer(&trans_);
-}
-
-} // namespace syncer
diff --git a/sync/engine/directory_cryptographer_provider.h b/sync/engine/directory_cryptographer_provider.h
deleted file mode 100644
index 36b1c0f..0000000
--- a/sync/engine/directory_cryptographer_provider.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SYNC_ENGINE_DIRECTORY_CRYPTOGRAPHER_PROVIDER_H_
-#define SYNC_ENGINE_DIRECTORY_CRYPTOGRAPHER_PROVIDER_H_
-
-#include "sync/engine/cryptographer_provider.h"
-
-#include "sync/syncable/syncable_read_transaction.h"
-
-namespace syncer {
-
-namespace syncable {
-class Directory;
-}
-
-// Provides access to the Directory's cryptographer through the
-// CryptographerProvider interface.
-class DirectoryCryptographerProvider : public CryptographerProvider {
- public:
- DirectoryCryptographerProvider(syncable::Directory* dir);
- virtual ~DirectoryCryptographerProvider();
-
- virtual bool InitScopedCryptographerRef(
- ScopedCryptographerRef* scoped) OVERRIDE;
-
- private:
- syncable::Directory* dir_;
-};
-
-// An implementation detail of the DirectoryCryptographerProvider. Contains
-// the ReadTransaction used to safely access the Cryptographer.
-class ScopedDirectoryCryptographerInternal
- : public ScopedCryptographerInternal {
- public:
- ScopedDirectoryCryptographerInternal(syncable::Directory* dir);
- virtual ~ScopedDirectoryCryptographerInternal();
-
- virtual Cryptographer* Get() const OVERRIDE;
-
- private:
- syncable::Directory* dir_;
- syncable::ReadTransaction trans_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedDirectoryCryptographerInternal);
-};
-
-} // namespace syncer
-
-#endif // SYNC_ENGINE_DIRECTORY_CRYPTOGRAPHER_PROVIDER_H_
diff --git a/sync/engine/model_type_entity.cc b/sync/engine/model_type_entity.cc
index 2f758a8..3249a16 100644
--- a/sync/engine/model_type_entity.cc
+++ b/sync/engine/model_type_entity.cc
@@ -131,6 +131,9 @@ void ModelTypeEntity::UpdateDesiredEncryptionKey(const std::string& name) {
if (encryption_key_name_ == name)
return;
+ DVLOG(2) << id_ << ": Encryption triggered commit: " << encryption_key_name_
+ << " -> " << name;
+
// Schedule commit with the expectation that the worker will re-encrypt with
// the latest encryption key as it does.
sequence_number_++;
diff --git a/sync/engine/model_type_sync_proxy_impl.cc b/sync/engine/model_type_sync_proxy_impl.cc
index 7ea5d52..d3e1d77 100644
--- a/sync/engine/model_type_sync_proxy_impl.cc
+++ b/sync/engine/model_type_sync_proxy_impl.cc
@@ -240,6 +240,9 @@ void ModelTypeSyncProxyImpl::OnUpdateReceived(
// commit to fix it.
if (data_type_state_.encryption_key_name !=
response_data.encryption_key_name) {
+ DVLOG(2) << ModelTypeToString(type_) << ": Requesting re-encrypt commit "
+ << response_data.encryption_key_name << " -> "
+ << data_type_state_.encryption_key_name;
EntityMap::iterator it2 = entities_.find(client_tag_hash);
it2->second->UpdateDesiredEncryptionKey(
data_type_state_.encryption_key_name);
diff --git a/sync/engine/model_type_sync_worker_impl.cc b/sync/engine/model_type_sync_worker_impl.cc
index a58400f4..5a47f5e 100644
--- a/sync/engine/model_type_sync_worker_impl.cc
+++ b/sync/engine/model_type_sync_worker_impl.cc
@@ -22,13 +22,13 @@ ModelTypeSyncWorkerImpl::ModelTypeSyncWorkerImpl(
ModelType type,
const DataTypeState& initial_state,
const UpdateResponseDataList& saved_pending_updates,
- CryptographerProvider* cryptographer_provider,
+ scoped_ptr<Cryptographer> cryptographer,
NudgeHandler* nudge_handler,
scoped_ptr<ModelTypeSyncProxy> type_sync_proxy)
: type_(type),
data_type_state_(initial_state),
type_sync_proxy_(type_sync_proxy.Pass()),
- cryptographer_provider_(cryptographer_provider),
+ cryptographer_(cryptographer.Pass()),
nudge_handler_(nudge_handler),
entities_deleter_(&entities_),
weak_ptr_factory_(this) {
@@ -47,7 +47,11 @@ ModelTypeSyncWorkerImpl::ModelTypeSyncWorkerImpl(
entities_.insert(std::make_pair(it->client_tag_hash, entity_tracker));
}
- TryDecryptPendingUpdates();
+ if (cryptographer_) {
+ DVLOG(1) << ModelTypeToString(type_) << ": Starting with encryption key "
+ << cryptographer_->GetDefaultNigoriKeyName();
+ OnCryptographerUpdated();
+ }
}
ModelTypeSyncWorkerImpl::~ModelTypeSyncWorkerImpl() {
@@ -59,29 +63,19 @@ ModelType ModelTypeSyncWorkerImpl::GetModelType() const {
}
bool ModelTypeSyncWorkerImpl::IsEncryptionRequired() const {
- return !data_type_state_.encryption_key_name.empty();
+ return !!cryptographer_;
}
-void ModelTypeSyncWorkerImpl::SetEncryptionKeyName(const std::string& name) {
- if (data_type_state_.encryption_key_name == name)
- return;
-
- data_type_state_.encryption_key_name = name;
-
- // Pretend to send an update. This will cause the TypeSyncProxy to notice
- // the new encryption key and take appropriate action.
- type_sync_proxy_->OnUpdateReceived(
- data_type_state_, UpdateResponseDataList(), UpdateResponseDataList());
-}
+void ModelTypeSyncWorkerImpl::UpdateCryptographer(
+ scoped_ptr<Cryptographer> cryptographer) {
+ DCHECK(cryptographer);
+ cryptographer_ = cryptographer.Pass();
-void ModelTypeSyncWorkerImpl::OnCryptographerStateChanged() {
- TryDecryptPendingUpdates();
+ // Update our state and that of the proxy.
+ OnCryptographerUpdated();
- ScopedCryptographerRef scoped_cryptographer_ref;
- cryptographer_provider_->InitScopedCryptographerRef(
- &scoped_cryptographer_ref);
- Cryptographer* cryptographer = scoped_cryptographer_ref.Get();
- if (CanCommitItems(cryptographer))
+ // Nudge the scheduler if we're now allowed to commit.
+ if (CanCommitItems())
nudge_handler_->NudgeForCommit(type_);
}
@@ -109,12 +103,6 @@ SyncerError ModelTypeSyncWorkerImpl::ProcessGetUpdatesResponse(
data_type_state_.type_context = mutated_context;
data_type_state_.progress_marker = progress_marker;
- ScopedCryptographerRef scoped_cryptographer_ref;
- cryptographer_provider_->InitScopedCryptographerRef(
- &scoped_cryptographer_ref);
- Cryptographer* cryptographer = scoped_cryptographer_ref.Get();
- DCHECK(cryptographer);
-
UpdateResponseDataList response_datas;
UpdateResponseDataList pending_updates;
@@ -166,17 +154,18 @@ SyncerError ModelTypeSyncWorkerImpl::ProcessGetUpdatesResponse(
entity_tracker->ReceiveUpdate(update_entity->version());
response_data.specifics = specifics;
response_datas.push_back(response_data);
- } else if (specifics.has_encrypted() &&
- cryptographer->CanDecrypt(specifics.encrypted())) {
+ } else if (specifics.has_encrypted() && cryptographer_ &&
+ cryptographer_->CanDecrypt(specifics.encrypted())) {
// Encrypted, but we know the key.
if (DecryptSpecifics(
- cryptographer, specifics, &response_data.specifics)) {
+ cryptographer_.get(), specifics, &response_data.specifics)) {
entity_tracker->ReceiveUpdate(update_entity->version());
response_data.encryption_key_name = specifics.encrypted().key_name();
response_datas.push_back(response_data);
}
} else if (specifics.has_encrypted() &&
- !cryptographer->CanDecrypt(specifics.encrypted())) {
+ (!cryptographer_ ||
+ !cryptographer_->CanDecrypt(specifics.encrypted()))) {
// Can't decrypt right now. Ask the entity tracker to handle it.
response_data.specifics = specifics;
if (entity_tracker->ReceivePendingUpdate(response_data)) {
@@ -188,6 +177,12 @@ SyncerError ModelTypeSyncWorkerImpl::ProcessGetUpdatesResponse(
}
}
+ DVLOG(1) << ModelTypeToString(type_) << ": "
+ << base::StringPrintf(
+ "Delivering %zd applicable and %zd pending updates.",
+ response_datas.size(),
+ pending_updates.size());
+
// Forward these updates to the model thread so it can do the rest.
type_sync_proxy_->OnUpdateReceived(
data_type_state_, response_datas, pending_updates);
@@ -202,6 +197,8 @@ void ModelTypeSyncWorkerImpl::ApplyUpdates(sessions::StatusController* status) {
// cycle, we should update our state so the ModelTypeSyncProxy knows that
// it's safe to commit items now.
if (!data_type_state_.initial_sync_done) {
+ DVLOG(1) << "Delivering 'initial sync done' ping.";
+
data_type_state_.initial_sync_done = true;
type_sync_proxy_->OnUpdateReceived(
@@ -230,11 +227,7 @@ void ModelTypeSyncWorkerImpl::EnqueueForCommit(
StorePendingCommit(*it);
}
- ScopedCryptographerRef scoped_cryptographer_ref;
- cryptographer_provider_->InitScopedCryptographerRef(
- &scoped_cryptographer_ref);
- Cryptographer* cryptographer = scoped_cryptographer_ref.Get();
- if (CanCommitItems(cryptographer))
+ if (CanCommitItems())
nudge_handler_->NudgeForCommit(type_);
}
@@ -247,12 +240,7 @@ scoped_ptr<CommitContribution> ModelTypeSyncWorkerImpl::GetContribution(
std::vector<int64> sequence_numbers;
google::protobuf::RepeatedPtrField<sync_pb::SyncEntity> commit_entities;
- ScopedCryptographerRef scoped_cryptographer_ref;
- cryptographer_provider_->InitScopedCryptographerRef(
- &scoped_cryptographer_ref);
- Cryptographer* cryptographer = scoped_cryptographer_ref.Get();
-
- if (!CanCommitItems(cryptographer))
+ if (!CanCommitItems())
return scoped_ptr<CommitContribution>();
// TODO(rlarocque): Avoid iterating here.
@@ -265,7 +253,7 @@ scoped_ptr<CommitContribution> ModelTypeSyncWorkerImpl::GetContribution(
int64 sequence_number = -1;
entity->PrepareCommitProto(commit_entity, &sequence_number);
- HelpInitializeCommitEntity(cryptographer, commit_entity);
+ HelpInitializeCommitEntity(commit_entity);
sequence_numbers.push_back(sequence_number);
space_remaining--;
@@ -350,17 +338,15 @@ bool ModelTypeSyncWorkerImpl::IsTypeInitialized() const {
data_type_state_.initial_sync_done;
}
-bool ModelTypeSyncWorkerImpl::CanCommitItems(
- Cryptographer* cryptographer) const {
+bool ModelTypeSyncWorkerImpl::CanCommitItems() const {
// We can't commit anything until we know the type's parent node.
// We'll get it in the first update response.
if (!IsTypeInitialized())
return false;
// Don't commit if we should be encrypting but don't have the required keys.
- if (IsEncryptionRequired() && (!cryptographer || !cryptographer->is_ready() ||
- cryptographer->GetDefaultNigoriKeyName() !=
- data_type_state_.encryption_key_name)) {
+ if (IsEncryptionRequired() &&
+ (!cryptographer_ || !cryptographer_->is_ready())) {
return false;
}
@@ -368,8 +354,9 @@ bool ModelTypeSyncWorkerImpl::CanCommitItems(
}
void ModelTypeSyncWorkerImpl::HelpInitializeCommitEntity(
- Cryptographer* cryptographer,
sync_pb::SyncEntity* sync_entity) {
+ DCHECK(CanCommitItems());
+
// Initial commits need our help to generate a client ID.
if (!sync_entity->has_id_string()) {
DCHECK_EQ(kUncommittedVersion, sync_entity->version());
@@ -380,9 +367,12 @@ void ModelTypeSyncWorkerImpl::HelpInitializeCommitEntity(
// Encrypt the specifics and hide the title if necessary.
if (IsEncryptionRequired()) {
+ // IsEncryptionRequired() && CanCommitItems() implies
+ // that the cryptographer is valid and ready to encrypt.
sync_pb::EntitySpecifics encrypted_specifics;
- cryptographer->Encrypt(sync_entity->specifics(),
- encrypted_specifics.mutable_encrypted());
+ bool result = cryptographer_->Encrypt(
+ sync_entity->specifics(), encrypted_specifics.mutable_encrypted());
+ DCHECK(result);
sync_entity->mutable_specifics()->CopyFrom(encrypted_specifics);
sync_entity->set_name("encrypted");
}
@@ -395,14 +385,21 @@ void ModelTypeSyncWorkerImpl::HelpInitializeCommitEntity(
sync_entity->set_parent_id_string(data_type_state_.type_root_id);
}
-void ModelTypeSyncWorkerImpl::TryDecryptPendingUpdates() {
+void ModelTypeSyncWorkerImpl::OnCryptographerUpdated() {
+ DCHECK(cryptographer_);
+
+ bool new_encryption_key = false;
UpdateResponseDataList response_datas;
- ScopedCryptographerRef scoped_cryptographer_ref;
- cryptographer_provider_->InitScopedCryptographerRef(
- &scoped_cryptographer_ref);
- Cryptographer* cryptographer = scoped_cryptographer_ref.Get();
- DCHECK(cryptographer);
+ const std::string& new_key_name = cryptographer_->GetDefaultNigoriKeyName();
+
+ // Handle a change in encryption key.
+ if (data_type_state_.encryption_key_name != new_key_name) {
+ DVLOG(1) << ModelTypeToString(type_) << ": Updating encryption key "
+ << data_type_state_.encryption_key_name << " -> " << new_key_name;
+ data_type_state_.encryption_key_name = new_key_name;
+ new_encryption_key = true;
+ }
for (EntityMap::const_iterator it = entities_.begin(); it != entities_.end();
++it) {
@@ -413,9 +410,9 @@ void ModelTypeSyncWorkerImpl::TryDecryptPendingUpdates() {
// don't have the key.
DCHECK(saved_pending.specifics.has_encrypted());
- if (cryptographer->CanDecrypt(saved_pending.specifics.encrypted())) {
+ if (cryptographer_->CanDecrypt(saved_pending.specifics.encrypted())) {
UpdateResponseData decrypted_response = saved_pending;
- if (DecryptSpecifics(cryptographer,
+ if (DecryptSpecifics(cryptographer_.get(),
saved_pending.specifics,
&decrypted_response.specifics)) {
decrypted_response.encryption_key_name =
@@ -428,7 +425,11 @@ void ModelTypeSyncWorkerImpl::TryDecryptPendingUpdates() {
}
}
- if (!response_datas.empty()) {
+ if (new_encryption_key || response_datas.size() > 0) {
+ DVLOG(1) << ModelTypeToString(type_) << ": "
+ << base::StringPrintf(
+ "Delivering encryption key and %zd decrypted updates.",
+ response_datas.size());
type_sync_proxy_->OnUpdateReceived(
data_type_state_, response_datas, UpdateResponseDataList());
}
diff --git a/sync/engine/model_type_sync_worker_impl.h b/sync/engine/model_type_sync_worker_impl.h
index f2df976..10aa080 100644
--- a/sync/engine/model_type_sync_worker_impl.h
+++ b/sync/engine/model_type_sync_worker_impl.h
@@ -10,7 +10,6 @@
#include "base/threading/non_thread_safe.h"
#include "sync/base/sync_export.h"
#include "sync/engine/commit_contributor.h"
-#include "sync/engine/cryptographer_provider.h"
#include "sync/engine/model_type_sync_worker.h"
#include "sync/engine/nudge_handler.h"
#include "sync/engine/update_handler.h"
@@ -18,6 +17,7 @@
#include "sync/internal_api/public/non_blocking_sync_common.h"
#include "sync/internal_api/public/sync_encryption_handler.h"
#include "sync/protocol/sync.pb.h"
+#include "sync/util/cryptographer.h"
namespace base {
class SingleThreadTaskRunner;
@@ -56,7 +56,7 @@ class SYNC_EXPORT ModelTypeSyncWorkerImpl : public UpdateHandler,
ModelTypeSyncWorkerImpl(ModelType type,
const DataTypeState& initial_state,
const UpdateResponseDataList& saved_pending_updates,
- CryptographerProvider* cryptographer_provider,
+ scoped_ptr<Cryptographer> cryptographer,
NudgeHandler* nudge_handler,
scoped_ptr<ModelTypeSyncProxy> type_sync_proxy);
virtual ~ModelTypeSyncWorkerImpl();
@@ -64,9 +64,7 @@ class SYNC_EXPORT ModelTypeSyncWorkerImpl : public UpdateHandler,
ModelType GetModelType() const;
bool IsEncryptionRequired() const;
- void SetEncryptionKeyName(const std::string& name);
-
- void OnCryptographerStateChanged();
+ void UpdateCryptographer(scoped_ptr<Cryptographer> cryptographer);
// UpdateHandler implementation.
virtual void GetDownloadProgress(
@@ -109,19 +107,19 @@ class SYNC_EXPORT ModelTypeSyncWorkerImpl : public UpdateHandler,
// Returns true if this type is prepared to commit items. Currently, this
// depends on having downloaded the initial data and having the encryption
// settings in a good state.
- bool CanCommitItems(Cryptographer* cryptographer) const;
+ bool CanCommitItems() const;
// Initializes the parts of a commit entity that are the responsibility of
// this class, and not the EntityTracker. Some fields, like the
// client-assigned ID, can only be set by an entity with knowledge of the
// entire data type's state.
- void HelpInitializeCommitEntity(Cryptographer* cryptographer,
- sync_pb::SyncEntity* commit_entity);
+ void HelpInitializeCommitEntity(sync_pb::SyncEntity* commit_entity);
// Attempts to decrypt pending updates stored in the EntityMap. If
// successful, will remove the update from the its EntityTracker and forward
- // it to the proxy thread for application.
- void TryDecryptPendingUpdates();
+ // it to the proxy thread for application. Will forward any new encryption
+ // keys to the proxy to trigger re-encryption if necessary.
+ void OnCryptographerUpdated();
// Attempts to decrypt the given specifics and return them in the |out|
// parameter. Assumes cryptographer->CanDecrypt(specifics) returned true.
@@ -145,9 +143,10 @@ class SYNC_EXPORT ModelTypeSyncWorkerImpl : public UpdateHandler,
// This is NULL when no proxy is connected..
scoped_ptr<ModelTypeSyncProxy> type_sync_proxy_;
- // A helper to provide access to the syncable::Directory's cryptographer.
- // Not owned.
- CryptographerProvider* cryptographer_provider_;
+ // A private copy of the most recent cryptographer known to sync.
+ // Initialized at construction time and updated with UpdateCryptographer().
+ // NULL if encryption is not enabled for this type.
+ scoped_ptr<Cryptographer> cryptographer_;
// Interface used to access and send nudges to the sync scheduler. Not owned.
NudgeHandler* nudge_handler_;
diff --git a/sync/engine/model_type_sync_worker_impl_unittest.cc b/sync/engine/model_type_sync_worker_impl_unittest.cc
index df2ed66..5c62c9a 100644
--- a/sync/engine/model_type_sync_worker_impl_unittest.cc
+++ b/sync/engine/model_type_sync_worker_impl_unittest.cc
@@ -14,7 +14,6 @@
#include "sync/syncable/syncable_util.h"
#include "sync/test/engine/mock_model_type_sync_proxy.h"
#include "sync/test/engine/mock_nudge_handler.h"
-#include "sync/test/engine/simple_cryptographer_provider.h"
#include "sync/test/engine/single_type_mock_server.h"
#include "sync/test/fake_encryptor.h"
@@ -40,6 +39,7 @@ namespace syncer {
// - Commit requests from the model thread.
// - Update responses from the server.
// - Commit responses from the server.
+// - The cryptographer, if encryption is enabled.
//
// Outputs:
// - Commit requests to the server.
@@ -168,6 +168,11 @@ class ModelTypeSyncWorkerImplTest : public ::testing::Test {
// Returns the number of initial sync nudges sent to the mock nudge handler.
int GetNumInitialDownloadNudges() const;
+ // Returns the name of the encryption key in the cryptographer last passed to
+ // the ModelTypeSyncWorker. Returns an empty string if no crypgorapher is
+ // in use. See also: UpdateLocalCryptographer().
+ std::string GetLocalCryptographerKeyName() const;
+
// Helpers for building various messages and structures.
static std::string GenerateTagHash(const std::string& tag);
static sync_pb::EntitySpecifics GenerateSpecifics(const std::string& tag,
@@ -192,11 +197,8 @@ class ModelTypeSyncWorkerImplTest : public ::testing::Test {
// An encryptor for our cryptographer.
FakeEncryptor fake_encryptor_;
- // The cryptographer itself.
- Cryptographer cryptographer_;
-
- // A CryptographerProvider for the ModelTypeSyncWorkerImpl.
- SimpleCryptographerProvider cryptographer_provider_;
+ // The cryptographer itself. NULL if we're not encrypting the type.
+ scoped_ptr<Cryptographer> cryptographer_;
// The number of the most recent foreign encryption key known to our
// cryptographer. Note that not all of these will be decryptable.
@@ -224,9 +226,7 @@ class ModelTypeSyncWorkerImplTest : public ::testing::Test {
};
ModelTypeSyncWorkerImplTest::ModelTypeSyncWorkerImplTest()
- : cryptographer_(&fake_encryptor_),
- cryptographer_provider_(&cryptographer_),
- foreign_encryption_key_index_(0),
+ : foreign_encryption_key_index_(0),
update_encryption_filter_index_(0),
mock_type_sync_proxy_(NULL),
mock_server_(kModelType) {
@@ -273,15 +273,24 @@ void ModelTypeSyncWorkerImplTest::InitializeWithState(
mock_type_sync_proxy_ = new MockModelTypeSyncProxy();
scoped_ptr<ModelTypeSyncProxy> proxy(mock_type_sync_proxy_);
+ scoped_ptr<Cryptographer> cryptographer_copy;
+ if (cryptographer_) {
+ cryptographer_copy.reset(new Cryptographer(*cryptographer_));
+ }
+
worker_.reset(new ModelTypeSyncWorkerImpl(kModelType,
state,
initial_pending_updates,
- &cryptographer_provider_,
+ cryptographer_copy.Pass(),
&mock_nudge_handler_,
proxy.Pass()));
}
void ModelTypeSyncWorkerImplTest::NewForeignEncryptionKey() {
+ if (!cryptographer_) {
+ cryptographer_.reset(new Cryptographer(&fake_encryptor_));
+ }
+
foreign_encryption_key_index_++;
sync_pb::NigoriKeyBag bag;
@@ -314,20 +323,29 @@ void ModelTypeSyncWorkerImplTest::NewForeignEncryptionKey() {
last_nigori.Encrypt(serialized_bag, encrypted.mutable_blob());
// Update the cryptographer with new pending keys.
- cryptographer_.SetPendingKeys(encrypted);
+ cryptographer_->SetPendingKeys(encrypted);
- // Update the worker with the latest encryption key name.
- if (worker_)
- worker_->SetEncryptionKeyName(encrypted.key_name());
+ // Update the worker with the latest cryptographer.
+ if (worker_) {
+ worker_->UpdateCryptographer(
+ make_scoped_ptr<Cryptographer>(new Cryptographer(*cryptographer_)));
+ }
}
void ModelTypeSyncWorkerImplTest::UpdateLocalCryptographer() {
+ if (!cryptographer_) {
+ cryptographer_.reset(new Cryptographer(&fake_encryptor_));
+ }
+
KeyParams params = GetNthKeyParams(foreign_encryption_key_index_);
- bool success = cryptographer_.DecryptPendingKeys(params);
+ bool success = cryptographer_->DecryptPendingKeys(params);
DCHECK(success);
- if (worker_)
- worker_->OnCryptographerStateChanged();
+ // Update the worker with the latest cryptographer.
+ if (worker_) {
+ worker_->UpdateCryptographer(
+ make_scoped_ptr<Cryptographer>(new Cryptographer(*cryptographer_)));
+ }
}
void ModelTypeSyncWorkerImplTest::SetUpdateEncryptionFilter(int n) {
@@ -558,6 +576,14 @@ int ModelTypeSyncWorkerImplTest::GetNumInitialDownloadNudges() const {
return mock_nudge_handler_.GetNumInitialDownloadNudges();
}
+std::string ModelTypeSyncWorkerImplTest::GetLocalCryptographerKeyName() const {
+ if (!cryptographer_) {
+ return std::string();
+ }
+
+ return cryptographer_->GetDefaultNigoriKeyName();
+}
+
// static.
std::string ModelTypeSyncWorkerImplTest::GenerateTagHash(
const std::string& tag) {
@@ -829,9 +855,15 @@ TEST_F(ModelTypeSyncWorkerImplTest, ReceiveUpdates) {
TEST_F(ModelTypeSyncWorkerImplTest, EncryptedCommit) {
NormalInitialize();
+ ASSERT_EQ(0U, GetNumModelThreadUpdateResponses());
+
NewForeignEncryptionKey();
UpdateLocalCryptographer();
+ ASSERT_EQ(1U, GetNumModelThreadUpdateResponses());
+ EXPECT_EQ(GetLocalCryptographerKeyName(),
+ GetNthModelThreadUpdateState(0).encryption_key_name);
+
// Normal commit request stuff.
CommitRequest("tag1", "value1");
DoSuccessfulCommit();
@@ -917,27 +949,42 @@ TEST_F(ModelTypeSyncWorkerImplTest, ReceiveDecryptableEntities) {
EXPECT_FALSE(update2.encryption_key_name.empty());
}
+// Test initializing a ModelTypeSyncWorker with a cryptographer at startup.
+TEST_F(ModelTypeSyncWorkerImplTest, InitializeWithCryptographer) {
+ // Set up some encryption state.
+ NewForeignEncryptionKey();
+ UpdateLocalCryptographer();
+
+ // Then initialize.
+ NormalInitialize();
+
+ // The worker should tell the model thread about encryption as soon as
+ // possible, so that it will have the chance to re-encrypt local data if
+ // necessary.
+ ASSERT_EQ(1U, GetNumModelThreadUpdateResponses());
+ EXPECT_EQ(GetLocalCryptographerKeyName(),
+ GetNthModelThreadUpdateState(0).encryption_key_name);
+}
+
// Receive updates that are initially undecryptable, then ensure they get
// delivered to the model thread when decryption becomes possible.
TEST_F(ModelTypeSyncWorkerImplTest, ReceiveUndecryptableEntries) {
NormalInitialize();
- // Set a new encryption key. The model thread will be notified of the new
- // encryption key through a faked update response.
+ // Receive a new foreign encryption key that we can't decrypt.
NewForeignEncryptionKey();
- EXPECT_EQ(1U, GetNumModelThreadUpdateResponses());
- // Send an update using that new key.
+ // Receive an encrypted with that new key, which we can't access.
SetUpdateEncryptionFilter(1);
TriggerUpdateFromServer(10, "tag1", "value1");
// At this point, the cryptographer does not have access to the key, so the
// updates will be undecryptable. They'll be transfered to the model thread
// for safe-keeping as pending updates.
- ASSERT_EQ(2U, GetNumModelThreadUpdateResponses());
- UpdateResponseDataList updates_list = GetNthModelThreadUpdateResponse(1);
+ ASSERT_EQ(1U, GetNumModelThreadUpdateResponses());
+ UpdateResponseDataList updates_list = GetNthModelThreadUpdateResponse(0);
EXPECT_EQ(0U, updates_list.size());
- UpdateResponseDataList pending_updates = GetNthModelThreadPendingUpdates(1);
+ UpdateResponseDataList pending_updates = GetNthModelThreadPendingUpdates(0);
EXPECT_EQ(1U, pending_updates.size());
// The update will be delivered as soon as decryption becomes possible.