| Index: chrome/browser/sync/engine/syncer_unittest.cc
|
| diff --git a/chrome/browser/sync/engine/syncer_unittest.cc b/chrome/browser/sync/engine/syncer_unittest.cc
|
| index 20fe2d06bd4981a763b14a74a5c0e0cbf7a8a89c..1bf9cc589b2c7f50b78b5ab75ca628690e54c5eb 100644
|
| --- a/chrome/browser/sync/engine/syncer_unittest.cc
|
| +++ b/chrome/browser/sync/engine/syncer_unittest.cc
|
| @@ -32,6 +32,7 @@
|
| #include "chrome/browser/sync/engine/syncproto.h"
|
| #include "chrome/browser/sync/protocol/sync.pb.h"
|
| #include "chrome/browser/sync/protocol/bookmark_specifics.pb.h"
|
| +#include "chrome/browser/sync/protocol/nigori_specifics.pb.h"
|
| #include "chrome/browser/sync/sessions/sync_session_context.h"
|
| #include "chrome/browser/sync/syncable/directory_manager.h"
|
| #include "chrome/browser/sync/syncable/model_type.h"
|
| @@ -41,6 +42,7 @@
|
| #include "chrome/browser/sync/test/engine/test_directory_setter_upper.h"
|
| #include "chrome/browser/sync/test/engine/test_id_factory.h"
|
| #include "chrome/browser/sync/test/engine/test_syncable_utils.h"
|
| +#include "chrome/browser/sync/util/cryptographer.h"
|
| #include "chrome/browser/sync/util/time.h"
|
| #include "testing/gtest/include/gtest/gtest.h"
|
|
|
| @@ -196,6 +198,7 @@ class SyncerTest : public testing::Test,
|
| mock_server_.reset(
|
| new MockConnectionManager(syncdb_.manager(), syncdb_.name()));
|
| EnableDatatype(syncable::BOOKMARKS);
|
| + EnableDatatype(syncable::NIGORI);
|
| worker_ = new FakeModelWorker(GROUP_PASSIVE);
|
| std::vector<SyncEngineEventListener*> listeners;
|
| listeners.push_back(this);
|
| @@ -744,6 +747,136 @@ TEST_F(SyncerTest, GetCommitIdsFiltersUnreadyEntries) {
|
| }
|
| }
|
|
|
| +TEST_F(SyncerTest, NigoriConflicts) {
|
| + ScopedDirLookup dir(syncdb_.manager(), syncdb_.name());
|
| + ASSERT_TRUE(dir.good());
|
| + KeyParams local_key_params = {"localhost", "dummy", "blargle"};
|
| + KeyParams other_key_params = {"localhost", "dummy", "foobar"};
|
| + browser_sync::Cryptographer other_cryptographer;
|
| + other_cryptographer.AddKey(other_key_params);
|
| + syncable::ModelTypeSet encrypted_types(syncable::PASSWORDS, syncable::NIGORI);
|
| + sync_pb::EntitySpecifics initial_nigori_specifics;
|
| + initial_nigori_specifics.MutableExtension(sync_pb::nigori);
|
| + mock_server_->SetNigori(1, 10, 10, initial_nigori_specifics);
|
| +
|
| + // Data for testing encryption/decryption.
|
| + sync_pb::EntitySpecifics other_encrypted_specifics;
|
| + other_encrypted_specifics.MutableExtension(sync_pb::bookmark)->
|
| + set_title("title");
|
| + other_cryptographer.Encrypt(
|
| + other_encrypted_specifics,
|
| + other_encrypted_specifics.mutable_encrypted());
|
| + sync_pb::EntitySpecifics our_encrypted_specifics;
|
| + our_encrypted_specifics.MutableExtension(sync_pb::bookmark)->
|
| + set_title("title2");
|
| +
|
| + // Receive the initial nigori node.
|
| + SyncShareAsDelegate();
|
| + encrypted_types = syncable::ModelTypeSet::All();
|
| + {
|
| + // Local changes with different passphrase, different types, and sync_tabs.
|
| + WriteTransaction wtrans(FROM_HERE, UNITTEST, dir);
|
| + sync_pb::EntitySpecifics specifics;
|
| + sync_pb::NigoriSpecifics* nigori =
|
| + specifics.MutableExtension(sync_pb::nigori);
|
| + syncdb_.manager()->GetCryptographer(&wtrans)->AddKey(local_key_params);
|
| + syncdb_.manager()->GetCryptographer(&wtrans)->Encrypt(
|
| + our_encrypted_specifics,
|
| + our_encrypted_specifics.mutable_encrypted());
|
| + syncdb_.manager()->GetCryptographer(&wtrans)->GetKeys(
|
| + nigori->mutable_encrypted());
|
| + syncdb_.manager()->GetCryptographer(&wtrans)->
|
| + UpdateNigoriFromEncryptedTypes(nigori);
|
| + nigori->set_sync_tabs(true);
|
| + syncdb_.manager()->GetCryptographer(&wtrans)->set_encrypt_everything();
|
| + MutableEntry nigori_entry(&wtrans, GET_BY_SERVER_TAG,
|
| + syncable::ModelTypeToRootTag(syncable::NIGORI));
|
| + ASSERT_TRUE(nigori_entry.good());
|
| + nigori_entry.Put(SPECIFICS, specifics);
|
| + nigori_entry.Put(IS_UNSYNCED, true);
|
| + EXPECT_FALSE(syncdb_.manager()->GetCryptographer(&wtrans)->
|
| + has_pending_keys());
|
| + EXPECT_TRUE(encrypted_types.Equals(
|
| + syncdb_.manager()->GetCryptographer(&wtrans)->GetEncryptedTypes()));
|
| + }
|
| + {
|
| + sync_pb::EntitySpecifics specifics;
|
| + sync_pb::NigoriSpecifics* nigori =
|
| + specifics.MutableExtension(sync_pb::nigori);
|
| + other_cryptographer.GetKeys(nigori->mutable_encrypted());
|
| + nigori->set_encrypt_bookmarks(true);
|
| + nigori->set_encrypt_preferences(true);
|
| + nigori->set_encrypt_everything(false);
|
| + mock_server_->SetNigori(1, 20, 20, specifics);
|
| + }
|
| +
|
| + // Will result in downloading the server nigori, which puts the local nigori
|
| + // in a state of conflict. This is resolved by merging the local and server
|
| + // data (with priority given to the server's encryption keys if they are
|
| + // undecryptable), which we then commit. The cryptographer should have pending
|
| + // keys and merge the set of encrypted types.
|
| + SyncShareAsDelegate(); // Resolve conflict in this cycle.
|
| + SyncShareAsDelegate(); // Commit local change in this cycle.
|
| + {
|
| + // Ensure the nigori data merged (encrypted types, sync_tabs).
|
| + WriteTransaction wtrans(FROM_HERE, UNITTEST, dir);
|
| + MutableEntry nigori_entry(&wtrans, GET_BY_SERVER_TAG,
|
| + syncable::ModelTypeToRootTag(syncable::NIGORI));
|
| + ASSERT_TRUE(nigori_entry.good());
|
| + EXPECT_FALSE(nigori_entry.Get(IS_UNAPPLIED_UPDATE));
|
| + EXPECT_FALSE(nigori_entry.Get(IS_UNSYNCED));
|
| + sync_pb::EntitySpecifics specifics = nigori_entry.Get(SPECIFICS);
|
| + EXPECT_TRUE(syncdb_.manager()->GetCryptographer(&wtrans)->
|
| + has_pending_keys());
|
| + EXPECT_TRUE(encrypted_types.Equals(
|
| + syncdb_.manager()->GetCryptographer(&wtrans)->GetEncryptedTypes()));
|
| + EXPECT_TRUE(syncdb_.manager()->GetCryptographer(&wtrans)->
|
| + encrypt_everything());
|
| + EXPECT_TRUE(specifics.GetExtension(sync_pb::nigori).sync_tabs());
|
| + // Supply the pending keys. Afterwards, we should be able to decrypt both
|
| + // our own encrypted data and data encrypted by the other cryptographer,
|
| + // but the key provided by the other cryptographer should be the default.
|
| + EXPECT_TRUE(syncdb_.manager()->GetCryptographer(&wtrans)->
|
| + DecryptPendingKeys(other_key_params));
|
| + EXPECT_FALSE(syncdb_.manager()->GetCryptographer(&wtrans)->
|
| + has_pending_keys());
|
| + sync_pb::NigoriSpecifics* nigori =
|
| + specifics.MutableExtension(sync_pb::nigori);
|
| + syncdb_.manager()->GetCryptographer(&wtrans)->GetKeys(
|
| + nigori->mutable_encrypted());
|
| + syncdb_.manager()->GetCryptographer(&wtrans)->
|
| + UpdateNigoriFromEncryptedTypes(nigori);
|
| + // Normally this would be written as part of SetPassphrase, but we do it
|
| + // manually for the test.
|
| + nigori_entry.Put(SPECIFICS, specifics);
|
| + nigori_entry.Put(IS_UNSYNCED, true);
|
| + }
|
| +
|
| + SyncShareAsDelegate();
|
| + {
|
| + // Ensure everything is committed and stable now. The cryptographer
|
| + // should be able to decrypt both sets of keys, sync_tabs should be true,
|
| + // and the encrypted types should have been unioned.
|
| + WriteTransaction wtrans(FROM_HERE, UNITTEST, dir);
|
| + MutableEntry nigori_entry(&wtrans, GET_BY_SERVER_TAG,
|
| + syncable::ModelTypeToRootTag(syncable::NIGORI));
|
| + ASSERT_TRUE(nigori_entry.good());
|
| + EXPECT_FALSE(nigori_entry.Get(IS_UNAPPLIED_UPDATE));
|
| + EXPECT_FALSE(nigori_entry.Get(IS_UNSYNCED));
|
| + EXPECT_TRUE(syncdb_.manager()->GetCryptographer(&wtrans)->CanDecrypt(
|
| + our_encrypted_specifics.encrypted()));
|
| + EXPECT_FALSE(syncdb_.manager()->GetCryptographer(&wtrans)->
|
| + CanDecryptUsingDefaultKey(our_encrypted_specifics.encrypted()));
|
| + EXPECT_TRUE(syncdb_.manager()->GetCryptographer(&wtrans)->CanDecrypt(
|
| + other_encrypted_specifics.encrypted()));
|
| + EXPECT_TRUE(syncdb_.manager()->GetCryptographer(&wtrans)->
|
| + CanDecryptUsingDefaultKey(other_encrypted_specifics.encrypted()));
|
| + EXPECT_TRUE(nigori_entry.Get(SPECIFICS).GetExtension(sync_pb::nigori)
|
| + .sync_tabs());
|
| + }
|
| +}
|
| +
|
| +
|
| // TODO(chron): More corner case unit tests around validation.
|
| TEST_F(SyncerTest, TestCommitMetahandleIterator) {
|
| ScopedDirLookup dir(syncdb_.manager(), syncdb_.name());
|
|
|