Chromium Code Reviews| Index: sync/engine/apply_control_data_updates_unittest.cc |
| diff --git a/sync/engine/apply_control_data_updates_unittest.cc b/sync/engine/apply_control_data_updates_unittest.cc |
| index 7f1a9fad6e238141526b521613048207adc2c47b..f31230af031b76aa87a3998b4f698d74a05ec741 100644 |
| --- a/sync/engine/apply_control_data_updates_unittest.cc |
| +++ b/sync/engine/apply_control_data_updates_unittest.cc |
| @@ -56,6 +56,8 @@ class ApplyControlDataUpdatesTest : public SyncerCommandTest { |
| DISALLOW_COPY_AND_ASSIGN(ApplyControlDataUpdatesTest); |
| }; |
| +// Verify that applying a nigori node updates sets initial sync ended properly |
|
rlarocque
2012/09/13 22:10:51
typo: "updates sets".
Add comma after properly.
Nicolas Zea
2012/09/13 22:50:14
Done.
|
| +// updates the set of encrypted types, and updates the cryptographer. |
| TEST_F(ApplyControlDataUpdatesTest, NigoriUpdate) { |
| // Storing the cryptographer separately is bad, but for this test we |
| // know it's safe. |
| @@ -63,52 +65,8 @@ TEST_F(ApplyControlDataUpdatesTest, NigoriUpdate) { |
| ModelTypeSet encrypted_types; |
| encrypted_types.Put(PASSWORDS); |
| - // We start with initial_sync_ended == false. This is wrong, since would have |
| - // no nigori node if that were the case. Howerver, it makes it easier to |
| - // verify that ApplyControlDataUpdates sets initial_sync_ended correctly. |
| - EXPECT_FALSE(directory()->initial_sync_ended_types().Has(NIGORI)); |
| - |
| - { |
| - syncable::ReadTransaction trans(FROM_HERE, directory()); |
| - cryptographer = directory()->GetCryptographer(&trans); |
| - EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans) |
| - .Equals(encrypted_types)); |
| - } |
| - |
| - // Nigori node updates should update the Cryptographer. |
| - Cryptographer other_cryptographer(cryptographer->encryptor()); |
| - KeyParams params = {"localhost", "dummy", "foobar"}; |
| - other_cryptographer.AddKey(params); |
| - |
| - sync_pb::EntitySpecifics specifics; |
| - sync_pb::NigoriSpecifics* nigori = specifics.mutable_nigori(); |
| - other_cryptographer.GetKeys(nigori->mutable_encryption_keybag()); |
| - nigori->set_encrypt_everything(true); |
| - entry_factory_->CreateUnappliedNewItem( |
| - ModelTypeToRootTag(NIGORI), specifics, true); |
| - EXPECT_FALSE(cryptographer->has_pending_keys()); |
| - |
| - ApplyControlDataUpdates(directory()); |
| - |
| - EXPECT_FALSE(cryptographer->is_ready()); |
| - EXPECT_TRUE(cryptographer->has_pending_keys()); |
| - { |
| - syncable::ReadTransaction trans(FROM_HERE, directory()); |
| - EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans) |
| - .Equals(ModelTypeSet::All())); |
| - EXPECT_TRUE(directory()->initial_sync_ended_types().Has(NIGORI)); |
| - } |
| -} |
| - |
| -TEST_F(ApplyControlDataUpdatesTest, NigoriUpdateForDisabledTypes) { |
| - // Storing the cryptographer separately is bad, but for this test we |
| - // know it's safe. |
| - Cryptographer* cryptographer; |
| - ModelTypeSet encrypted_types; |
| - encrypted_types.Put(PASSWORDS); |
| - |
| - // We start with initial_sync_ended == false. This is wrong, since would have |
| - // no nigori node if that were the case. Howerver, it makes it easier to |
| + // We start with initial_sync_ended == false. This is wrong, since we would |
| + // have no nigori node if that were the case. However, it makes it easier to |
| // verify that ApplyControlDataUpdates sets initial_sync_ended correctly. |
| EXPECT_FALSE(directory()->initial_sync_ended_types().Has(NIGORI)); |
| @@ -258,6 +216,10 @@ TEST_F(ApplyControlDataUpdatesTest, EncryptUnsyncedChanges) { |
| } |
| } |
| +// Create some local unsynced and unencrypted changes. Receive a new nigori |
| +// node enabling their encryption but also introducing pending keys. Ensure |
| +// we apply the update properly without encrypting the unsynced changes or |
| +// breaking. |
| TEST_F(ApplyControlDataUpdatesTest, CannotEncryptUnsyncedChanges) { |
| // Storing the cryptographer separately is bad, but for this test we |
| // know it's safe. |
| @@ -344,4 +306,573 @@ TEST_F(ApplyControlDataUpdatesTest, CannotEncryptUnsyncedChanges) { |
| } |
| } |
| +// Verify we handle a nigori node conflict by merging encryption keys and |
| +// types, but preserve the custom passphrase state of the server. |
| +// Initial sync ended should be set. |
| +TEST_F(ApplyControlDataUpdatesTest, |
| + NigoriConflictPendingKeysServerEncryptEverythingCustom) { |
| + Cryptographer* cryptographer; |
| + ModelTypeSet encrypted_types(PASSWORDS); |
|
rlarocque
2012/09/13 22:10:51
Consider using SensitiveTypes() here.
Nicolas Zea
2012/09/13 22:50:14
Done.
|
| + KeyParams other_params = {"localhost", "dummy", "foobar"}; |
| + KeyParams local_params = {"localhost", "dummy", "local"}; |
| + { |
| + syncable::ReadTransaction trans(FROM_HERE, directory()); |
| + cryptographer = directory()->GetCryptographer(&trans); |
| + EXPECT_TRUE(encrypted_types.Equals( |
| + directory()->GetNigoriHandler()->GetEncryptedTypes(&trans))); |
| + } |
| + |
| + // Set up a temporary cryptographer to generate new keys with. |
| + Cryptographer other_cryptographer(cryptographer->encryptor()); |
| + other_cryptographer.AddKey(other_params); |
| + |
| + // Create server specifics with pending keys, new encrypted types, |
| + // and a custom passphrase (unmigrated). |
| + sync_pb::EntitySpecifics server_specifics; |
| + sync_pb::NigoriSpecifics* server_nigori = server_specifics.mutable_nigori(); |
| + other_cryptographer.GetKeys(server_nigori->mutable_encryption_keybag()); |
| + server_nigori->set_encrypt_everything(true); |
| + server_nigori->set_keybag_is_frozen(true); |
| + int64 nigori_handle = |
| + entry_factory_->CreateUnappliedNewItem(kNigoriTag, |
| + server_specifics, |
| + true); |
| + |
| + // Initialize the local cryptographer with the local keys. |
| + cryptographer->AddKey(local_params); |
| + EXPECT_TRUE(cryptographer->is_ready()); |
| + |
| + // Set up a local nigori with the local encryptio keys and default encrypted |
|
rlarocque
2012/09/13 22:10:51
encryptio
Nicolas Zea
2012/09/13 22:50:14
Done.
|
| + // types. |
| + sync_pb::EntitySpecifics local_specifics; |
| + sync_pb::NigoriSpecifics* local_nigori = local_specifics.mutable_nigori(); |
| + cryptographer->GetKeys(local_nigori->mutable_encryption_keybag()); |
| + local_nigori->set_encrypt_everything(false); |
| + local_nigori->set_keybag_is_frozen(true); |
| + ASSERT_TRUE(entry_factory_->SetSpecificsForItem( |
| + nigori_handle, LOCAL_SPECIFICS, local_specifics)); |
| + // Apply the update locally so that UpdateFromEncryptedTypes knows what state |
| + // to use. |
| + { |
| + syncable::ReadTransaction trans(FROM_HERE, directory()); |
| + cryptographer = directory()->GetCryptographer(&trans); |
| + directory()->GetNigoriHandler()->ApplyNigoriUpdate( |
| + *local_nigori, |
| + &trans); |
| + } |
| + |
| + EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle)); |
| + EXPECT_TRUE(entry_factory_->GetIsUnappliedForItem(nigori_handle)); |
| + ApplyControlDataUpdates(directory()); |
| + EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle)); |
| + EXPECT_FALSE(entry_factory_->GetIsUnappliedForItem(nigori_handle)); |
| + |
| + EXPECT_FALSE(cryptographer->is_ready()); |
| + EXPECT_TRUE(cryptographer->is_initialized()); |
| + EXPECT_TRUE(cryptographer->has_pending_keys()); |
| + EXPECT_TRUE(other_cryptographer.CanDecryptUsingDefaultKey( |
| + entry_factory_->GetSpecificsForItem(nigori_handle, LOCAL_SPECIFICS). |
| + nigori().encryption_keybag())); |
| + EXPECT_TRUE(entry_factory_->GetSpecificsForItem( |
| + nigori_handle, LOCAL_SPECIFICS).nigori().keybag_is_frozen()); |
| + EXPECT_TRUE( |
| + entry_factory_->GetSpecificsForItem(nigori_handle, LOCAL_SPECIFICS). |
| + nigori().encrypt_everything()); |
| + { |
| + syncable::ReadTransaction trans(FROM_HERE, directory()); |
| + EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans) |
| + .Equals(ModelTypeSet::All())); |
| + EXPECT_TRUE(directory()->initial_sync_ended_types().Has(NIGORI)); |
| + } |
| +} |
| + |
| +// Verify we handle a nigori node conflict by merging encryption keys and |
| +// types, but preserve the custom passphrase state of the server. |
| +// Initial sync ended should be set. |
| +TEST_F(ApplyControlDataUpdatesTest, |
| + NigoriConflictPendingKeysLocalEncryptEverythingCustom) { |
| + Cryptographer* cryptographer; |
| + ModelTypeSet encrypted_types(PASSWORDS); |
| + KeyParams other_params = {"localhost", "dummy", "foobar"}; |
| + KeyParams local_params = {"localhost", "dummy", "local"}; |
| + { |
| + syncable::ReadTransaction trans(FROM_HERE, directory()); |
| + cryptographer = directory()->GetCryptographer(&trans); |
| + EXPECT_TRUE(encrypted_types.Equals( |
| + directory()->GetNigoriHandler()->GetEncryptedTypes(&trans))); |
| + } |
| + |
| + // Set up a temporary cryptographer to generate new keys with. |
| + Cryptographer other_cryptographer(cryptographer->encryptor()); |
| + other_cryptographer.AddKey(other_params); |
| + |
| + // Create server specifics with pending keys, new encrypted types, |
| + // and a custom passphrase (unmigrated). |
| + sync_pb::EntitySpecifics server_specifics; |
| + sync_pb::NigoriSpecifics* server_nigori = server_specifics.mutable_nigori(); |
| + other_cryptographer.GetKeys(server_nigori->mutable_encryption_keybag()); |
| + server_nigori->set_encrypt_everything(false); |
| + server_nigori->set_keybag_is_frozen(false); |
| + int64 nigori_handle = |
| + entry_factory_->CreateUnappliedNewItem(kNigoriTag, |
| + server_specifics, |
| + true); |
| + |
| + // Initialize the local cryptographer with the local keys. |
| + cryptographer->AddKey(local_params); |
| + EXPECT_TRUE(cryptographer->is_ready()); |
| + |
| + // Set up a local nigori with the local encryptio keys and default encrypted |
|
rlarocque
2012/09/13 22:10:51
Typo here, too.
Nicolas Zea
2012/09/13 22:50:14
Done.
|
| + // types. |
| + sync_pb::EntitySpecifics local_specifics; |
| + sync_pb::NigoriSpecifics* local_nigori = local_specifics.mutable_nigori(); |
| + cryptographer->GetKeys(local_nigori->mutable_encryption_keybag()); |
| + local_nigori->set_encrypt_everything(true); |
| + local_nigori->set_keybag_is_frozen(true); |
| + ASSERT_TRUE(entry_factory_->SetSpecificsForItem( |
| + nigori_handle, LOCAL_SPECIFICS, local_specifics)); |
| + // Apply the update locally so that UpdateFromEncryptedTypes knows what state |
| + // to use. |
| + { |
| + syncable::ReadTransaction trans(FROM_HERE, directory()); |
| + cryptographer = directory()->GetCryptographer(&trans); |
| + directory()->GetNigoriHandler()->ApplyNigoriUpdate( |
| + *local_nigori, |
| + &trans); |
| + } |
| + |
| + EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle)); |
| + EXPECT_TRUE(entry_factory_->GetIsUnappliedForItem(nigori_handle)); |
| + ApplyControlDataUpdates(directory()); |
| + EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle)); |
| + EXPECT_FALSE(entry_factory_->GetIsUnappliedForItem(nigori_handle)); |
| + |
| + EXPECT_FALSE(cryptographer->is_ready()); |
| + EXPECT_TRUE(cryptographer->is_initialized()); |
| + EXPECT_TRUE(cryptographer->has_pending_keys()); |
| + EXPECT_TRUE(other_cryptographer.CanDecryptUsingDefaultKey( |
| + entry_factory_->GetSpecificsForItem(nigori_handle, LOCAL_SPECIFICS). |
| + nigori().encryption_keybag())); |
| + EXPECT_FALSE(entry_factory_->GetSpecificsForItem( |
| + nigori_handle, LOCAL_SPECIFICS).nigori().keybag_is_frozen()); |
| + EXPECT_TRUE( |
| + entry_factory_->GetSpecificsForItem(nigori_handle, LOCAL_SPECIFICS). |
| + nigori().encrypt_everything()); |
| + { |
| + syncable::ReadTransaction trans(FROM_HERE, directory()); |
| + EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans) |
| + .Equals(ModelTypeSet::All())); |
| + EXPECT_TRUE(directory()->initial_sync_ended_types().Has(NIGORI)); |
| + } |
| +} |
| + |
| +// If the conflicting nigori has a subset of the local keys, the conflict |
| +// resolution should preserve the full local keys. Initial sync ended should be |
| +// set. |
| +TEST_F(ApplyControlDataUpdatesTest, |
| + NigoriConflictOldKeys) { |
| + Cryptographer* cryptographer; |
| + ModelTypeSet encrypted_types(PASSWORDS); |
| + KeyParams old_params = {"localhost", "dummy", "old"}; |
| + KeyParams new_params = {"localhost", "dummy", "new"}; |
| + { |
| + syncable::ReadTransaction trans(FROM_HERE, directory()); |
| + cryptographer = directory()->GetCryptographer(&trans); |
| + EXPECT_TRUE(encrypted_types.Equals( |
| + directory()->GetNigoriHandler()->GetEncryptedTypes(&trans))); |
| + } |
| + |
| + // Set up the cryptographer with old keys |
| + cryptographer->AddKey(old_params); |
| + |
| + // Create server specifics with old keys and new encrypted types. |
| + sync_pb::EntitySpecifics server_specifics; |
| + sync_pb::NigoriSpecifics* server_nigori = server_specifics.mutable_nigori(); |
| + cryptographer->GetKeys(server_nigori->mutable_encryption_keybag()); |
| + server_nigori->set_encrypt_everything(true); |
| + int64 nigori_handle = |
| + entry_factory_->CreateUnappliedNewItem(kNigoriTag, |
| + server_specifics, |
| + true); |
| + |
| + // Add the new keys to the cryptogrpaher |
| + cryptographer->AddKey(new_params); |
| + EXPECT_TRUE(cryptographer->is_ready()); |
| + |
| + // Set up a local nigori with the superset of keys. |
| + sync_pb::EntitySpecifics local_specifics; |
| + sync_pb::NigoriSpecifics* local_nigori = local_specifics.mutable_nigori(); |
| + cryptographer->GetKeys(local_nigori->mutable_encryption_keybag()); |
| + local_nigori->set_encrypt_everything(false); |
| + ASSERT_TRUE(entry_factory_->SetSpecificsForItem( |
| + nigori_handle, LOCAL_SPECIFICS, local_specifics)); |
| + // Apply the update locally so that UpdateFromEncryptedTypes knows what state |
| + // to use. |
| + { |
| + syncable::ReadTransaction trans(FROM_HERE, directory()); |
| + cryptographer = directory()->GetCryptographer(&trans); |
| + directory()->GetNigoriHandler()->ApplyNigoriUpdate( |
| + *local_nigori, |
| + &trans); |
| + } |
| + |
| + EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle)); |
| + EXPECT_TRUE(entry_factory_->GetIsUnappliedForItem(nigori_handle)); |
| + ApplyControlDataUpdates(directory()); |
| + EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle)); |
| + EXPECT_FALSE(entry_factory_->GetIsUnappliedForItem(nigori_handle)); |
| + |
| + EXPECT_TRUE(cryptographer->is_ready()); |
| + EXPECT_TRUE(cryptographer->CanDecryptUsingDefaultKey( |
| + entry_factory_->GetSpecificsForItem(nigori_handle, LOCAL_SPECIFICS). |
| + nigori().encryption_keybag())); |
| + EXPECT_FALSE(entry_factory_->GetSpecificsForItem( |
| + nigori_handle, LOCAL_SPECIFICS).nigori().keybag_is_frozen()); |
| + EXPECT_TRUE( |
| + entry_factory_->GetSpecificsForItem(nigori_handle, LOCAL_SPECIFICS). |
| + nigori().encrypt_everything()); |
| + { |
| + syncable::ReadTransaction trans(FROM_HERE, directory()); |
| + EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans) |
| + .Equals(ModelTypeSet::All())); |
| + EXPECT_TRUE(directory()->initial_sync_ended_types().Has(NIGORI)); |
| + } |
| +} |
| + |
| +// If both nigoris are migrated, but we also set a custom passphrase locally, |
|
rlarocque
2012/09/13 22:10:51
Are you testing the other side of the if branch an
Nicolas Zea
2012/09/13 22:50:14
Yes, BothMigratedServerCustom hits that case.
|
| +// the local nigori should be preserved. |
| +TEST_F(ApplyControlDataUpdatesTest, |
| + NigoriConflictBothMigratedLocalCustom) { |
| + Cryptographer* cryptographer; |
| + ModelTypeSet encrypted_types(PASSWORDS); |
| + KeyParams old_params = {"localhost", "dummy", "old"}; |
| + KeyParams new_params = {"localhost", "dummy", "new"}; |
| + { |
| + syncable::ReadTransaction trans(FROM_HERE, directory()); |
| + cryptographer = directory()->GetCryptographer(&trans); |
| + EXPECT_TRUE(encrypted_types.Equals( |
| + directory()->GetNigoriHandler()->GetEncryptedTypes(&trans))); |
| + } |
| + |
| + // Set up the cryptographer with new keys |
| + Cryptographer other_cryptographer(cryptographer->encryptor()); |
| + other_cryptographer.AddKey(old_params); |
| + |
| + // Create server specifics with a migrated keystore passphrase type. |
| + sync_pb::EntitySpecifics server_specifics; |
| + sync_pb::NigoriSpecifics* server_nigori = server_specifics.mutable_nigori(); |
| + other_cryptographer.GetKeys(server_nigori->mutable_encryption_keybag()); |
| + server_nigori->set_encrypt_everything(false); |
| + server_nigori->set_keybag_is_frozen(true); |
| + server_nigori->set_passphrase_type( |
| + sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE); |
| + server_nigori->mutable_keystore_decryptor_token(); |
| + int64 nigori_handle = |
| + entry_factory_->CreateUnappliedNewItem(kNigoriTag, |
| + server_specifics, |
| + true); |
| + |
| + // Add the new keys to the cryptographer. |
| + cryptographer->AddKey(old_params); |
| + cryptographer->AddKey(new_params); |
| + EXPECT_TRUE(cryptographer->is_ready()); |
| + |
| + // Set up a local nigori with a migrated custom passphrase type |
| + sync_pb::EntitySpecifics local_specifics; |
| + sync_pb::NigoriSpecifics* local_nigori = local_specifics.mutable_nigori(); |
| + cryptographer->GetKeys(local_nigori->mutable_encryption_keybag()); |
| + local_nigori->set_encrypt_everything(true); |
| + local_nigori->set_keybag_is_frozen(true); |
| + local_nigori->set_passphrase_type( |
| + sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE); |
| + ASSERT_TRUE(entry_factory_->SetSpecificsForItem( |
| + nigori_handle, LOCAL_SPECIFICS, local_specifics)); |
| + // Apply the update locally so that UpdateFromEncryptedTypes knows what state |
| + // to use. |
| + { |
| + syncable::ReadTransaction trans(FROM_HERE, directory()); |
| + cryptographer = directory()->GetCryptographer(&trans); |
| + directory()->GetNigoriHandler()->ApplyNigoriUpdate( |
| + *local_nigori, |
| + &trans); |
| + } |
| + |
| + EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle)); |
| + EXPECT_TRUE(entry_factory_->GetIsUnappliedForItem(nigori_handle)); |
| + ApplyControlDataUpdates(directory()); |
| + EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle)); |
| + EXPECT_FALSE(entry_factory_->GetIsUnappliedForItem(nigori_handle)); |
| + |
| + EXPECT_TRUE(cryptographer->is_ready()); |
| + EXPECT_TRUE(cryptographer->CanDecryptUsingDefaultKey( |
| + entry_factory_->GetSpecificsForItem(nigori_handle, LOCAL_SPECIFICS). |
| + nigori().encryption_keybag())); |
| + EXPECT_TRUE(entry_factory_->GetSpecificsForItem( |
| + nigori_handle, LOCAL_SPECIFICS).nigori().keybag_is_frozen()); |
| + EXPECT_TRUE( |
| + entry_factory_->GetSpecificsForItem(nigori_handle, LOCAL_SPECIFICS). |
| + nigori().encrypt_everything()); |
| + EXPECT_EQ(sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE, |
| + entry_factory_->GetSpecificsForItem(nigori_handle, LOCAL_SPECIFICS). |
| + nigori().passphrase_type()); |
| + { |
| + syncable::ReadTransaction trans(FROM_HERE, directory()); |
| + EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans) |
| + .Equals(ModelTypeSet::All())); |
| + EXPECT_TRUE(directory()->initial_sync_ended_types().Has(NIGORI)); |
| + } |
| +} |
| + |
| +// If both nigoris are migrated, but a custom passphrase with a new key was |
| +// set remotely, the remote nigori should be preserved. |
| +TEST_F(ApplyControlDataUpdatesTest, |
| + NigoriConflictBothMigratedServerCustom) { |
| + Cryptographer* cryptographer; |
| + ModelTypeSet encrypted_types(PASSWORDS); |
| + KeyParams old_params = {"localhost", "dummy", "old"}; |
| + KeyParams new_params = {"localhost", "dummy", "new"}; |
| + { |
| + syncable::ReadTransaction trans(FROM_HERE, directory()); |
| + cryptographer = directory()->GetCryptographer(&trans); |
| + EXPECT_TRUE(encrypted_types.Equals( |
| + directory()->GetNigoriHandler()->GetEncryptedTypes(&trans))); |
| + } |
| + |
| + // Set up the cryptographer with both new keys and old keys. |
| + Cryptographer other_cryptographer(cryptographer->encryptor()); |
| + other_cryptographer.AddKey(old_params); |
| + other_cryptographer.AddKey(new_params); |
| + |
| + // Create server specifics with a migrated custom passphrase type. |
| + sync_pb::EntitySpecifics server_specifics; |
| + sync_pb::NigoriSpecifics* server_nigori = server_specifics.mutable_nigori(); |
| + other_cryptographer.GetKeys(server_nigori->mutable_encryption_keybag()); |
| + server_nigori->set_encrypt_everything(true); |
| + server_nigori->set_keybag_is_frozen(true); |
| + server_nigori->set_passphrase_type( |
| + sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE); |
| + int64 nigori_handle = |
| + entry_factory_->CreateUnappliedNewItem(kNigoriTag, |
| + server_specifics, |
| + true); |
| + |
| + // Add the old keys to the cryptographer. |
| + cryptographer->AddKey(old_params); |
| + EXPECT_TRUE(cryptographer->is_ready()); |
| + |
| + // Set up a local nigori with a migrated keystore passphrase type |
| + sync_pb::EntitySpecifics local_specifics; |
| + sync_pb::NigoriSpecifics* local_nigori = local_specifics.mutable_nigori(); |
| + cryptographer->GetKeys(local_nigori->mutable_encryption_keybag()); |
| + local_nigori->set_encrypt_everything(false); |
| + local_nigori->set_keybag_is_frozen(true); |
| + local_nigori->set_passphrase_type( |
| + sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE); |
| + server_nigori->mutable_keystore_decryptor_token(); |
| + ASSERT_TRUE(entry_factory_->SetSpecificsForItem( |
| + nigori_handle, LOCAL_SPECIFICS, local_specifics)); |
| + // Apply the update locally so that UpdateFromEncryptedTypes knows what state |
| + // to use. |
| + { |
| + syncable::ReadTransaction trans(FROM_HERE, directory()); |
| + cryptographer = directory()->GetCryptographer(&trans); |
| + directory()->GetNigoriHandler()->ApplyNigoriUpdate( |
| + *local_nigori, |
| + &trans); |
| + } |
| + |
| + EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle)); |
| + EXPECT_TRUE(entry_factory_->GetIsUnappliedForItem(nigori_handle)); |
| + ApplyControlDataUpdates(directory()); |
| + EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle)); |
| + EXPECT_FALSE(entry_factory_->GetIsUnappliedForItem(nigori_handle)); |
| + |
| + EXPECT_TRUE(cryptographer->is_initialized()); |
| + EXPECT_TRUE(cryptographer->has_pending_keys()); |
| + EXPECT_TRUE(other_cryptographer.CanDecryptUsingDefaultKey( |
| + entry_factory_->GetSpecificsForItem(nigori_handle, LOCAL_SPECIFICS). |
| + nigori().encryption_keybag())); |
| + EXPECT_TRUE(entry_factory_->GetSpecificsForItem( |
| + nigori_handle, LOCAL_SPECIFICS).nigori().keybag_is_frozen()); |
| + EXPECT_TRUE( |
| + entry_factory_->GetSpecificsForItem(nigori_handle, LOCAL_SPECIFICS). |
| + nigori().encrypt_everything()); |
| + EXPECT_EQ(sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE, |
| + entry_factory_->GetSpecificsForItem(nigori_handle, LOCAL_SPECIFICS). |
| + nigori().passphrase_type()); |
| + { |
| + syncable::ReadTransaction trans(FROM_HERE, directory()); |
| + EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans) |
| + .Equals(ModelTypeSet::All())); |
| + EXPECT_TRUE(directory()->initial_sync_ended_types().Has(NIGORI)); |
| + } |
| +} |
| + |
| +// If the local nigori is migrated but the server is not, preserve the local |
| +// nigori. |
| +TEST_F(ApplyControlDataUpdatesTest, |
| + NigoriConflictLocalMigrated) { |
| + Cryptographer* cryptographer; |
| + ModelTypeSet encrypted_types(PASSWORDS); |
| + KeyParams old_params = {"localhost", "dummy", "old"}; |
| + KeyParams new_params = {"localhost", "dummy", "new"}; |
| + { |
| + syncable::ReadTransaction trans(FROM_HERE, directory()); |
| + cryptographer = directory()->GetCryptographer(&trans); |
| + EXPECT_TRUE(encrypted_types.Equals( |
| + directory()->GetNigoriHandler()->GetEncryptedTypes(&trans))); |
| + } |
| + |
| + // Set up the cryptographer with both new keys and old keys. |
| + Cryptographer other_cryptographer(cryptographer->encryptor()); |
| + other_cryptographer.AddKey(old_params); |
| + |
| + // Create server specifics with an unmigrated implicit passphrase type. |
| + sync_pb::EntitySpecifics server_specifics; |
| + sync_pb::NigoriSpecifics* server_nigori = server_specifics.mutable_nigori(); |
| + other_cryptographer.GetKeys(server_nigori->mutable_encryption_keybag()); |
| + server_nigori->set_encrypt_everything(true); |
| + server_nigori->set_keybag_is_frozen(false); |
| + int64 nigori_handle = |
| + entry_factory_->CreateUnappliedNewItem(kNigoriTag, |
| + server_specifics, |
| + true); |
| + |
| + // Add the old keys to the cryptographer. |
| + cryptographer->AddKey(old_params); |
| + cryptographer->AddKey(new_params); |
| + EXPECT_TRUE(cryptographer->is_ready()); |
| + |
| + // Set up a local nigori with a migrated custom passphrase type |
| + sync_pb::EntitySpecifics local_specifics; |
| + sync_pb::NigoriSpecifics* local_nigori = local_specifics.mutable_nigori(); |
| + cryptographer->GetKeys(local_nigori->mutable_encryption_keybag()); |
| + local_nigori->set_encrypt_everything(true); |
| + local_nigori->set_keybag_is_frozen(true); |
| + local_nigori->set_passphrase_type( |
| + sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE); |
| + ASSERT_TRUE(entry_factory_->SetSpecificsForItem( |
| + nigori_handle, LOCAL_SPECIFICS, local_specifics)); |
| + // Apply the update locally so that UpdateFromEncryptedTypes knows what state |
| + // to use. |
| + { |
| + syncable::ReadTransaction trans(FROM_HERE, directory()); |
| + cryptographer = directory()->GetCryptographer(&trans); |
| + directory()->GetNigoriHandler()->ApplyNigoriUpdate( |
| + *local_nigori, |
| + &trans); |
| + } |
| + |
| + EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle)); |
| + EXPECT_TRUE(entry_factory_->GetIsUnappliedForItem(nigori_handle)); |
| + ApplyControlDataUpdates(directory()); |
| + EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle)); |
| + EXPECT_FALSE(entry_factory_->GetIsUnappliedForItem(nigori_handle)); |
| + |
| + EXPECT_TRUE(cryptographer->is_ready()); |
| + EXPECT_TRUE(cryptographer->CanDecryptUsingDefaultKey( |
| + entry_factory_->GetSpecificsForItem(nigori_handle, LOCAL_SPECIFICS). |
| + nigori().encryption_keybag())); |
| + EXPECT_TRUE(entry_factory_->GetSpecificsForItem( |
| + nigori_handle, LOCAL_SPECIFICS).nigori().keybag_is_frozen()); |
| + EXPECT_TRUE( |
| + entry_factory_->GetSpecificsForItem(nigori_handle, LOCAL_SPECIFICS). |
| + nigori().encrypt_everything()); |
| + EXPECT_EQ(sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE, |
| + entry_factory_->GetSpecificsForItem(nigori_handle, LOCAL_SPECIFICS). |
| + nigori().passphrase_type()); |
| + { |
| + syncable::ReadTransaction trans(FROM_HERE, directory()); |
| + EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans) |
| + .Equals(ModelTypeSet::All())); |
| + EXPECT_TRUE(directory()->initial_sync_ended_types().Has(NIGORI)); |
| + } |
| +} |
| + |
| +// If the server nigori is migrated but the local is not, preserve the server |
| +// nigori. |
| +TEST_F(ApplyControlDataUpdatesTest, |
| + NigoriConflictServerMigrated) { |
| + Cryptographer* cryptographer; |
| + ModelTypeSet encrypted_types(PASSWORDS); |
| + KeyParams old_params = {"localhost", "dummy", "old"}; |
| + KeyParams new_params = {"localhost", "dummy", "new"}; |
| + { |
| + syncable::ReadTransaction trans(FROM_HERE, directory()); |
| + cryptographer = directory()->GetCryptographer(&trans); |
| + EXPECT_TRUE(encrypted_types.Equals( |
| + directory()->GetNigoriHandler()->GetEncryptedTypes(&trans))); |
| + } |
| + |
| + // Set up the cryptographer with both new keys and old keys. |
| + Cryptographer other_cryptographer(cryptographer->encryptor()); |
| + other_cryptographer.AddKey(old_params); |
| + |
| + // Create server specifics with an migrated keystore passphrase type. |
| + sync_pb::EntitySpecifics server_specifics; |
| + sync_pb::NigoriSpecifics* server_nigori = server_specifics.mutable_nigori(); |
| + other_cryptographer.GetKeys(server_nigori->mutable_encryption_keybag()); |
| + server_nigori->set_encrypt_everything(false); |
| + server_nigori->set_keybag_is_frozen(true); |
| + server_nigori->set_passphrase_type( |
| + sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE); |
| + server_nigori->mutable_keystore_decryptor_token(); |
| + int64 nigori_handle = |
| + entry_factory_->CreateUnappliedNewItem(kNigoriTag, |
| + server_specifics, |
| + true); |
| + |
| + // Add the old keys to the cryptographer. |
| + cryptographer->AddKey(old_params); |
| + cryptographer->AddKey(new_params); |
| + EXPECT_TRUE(cryptographer->is_ready()); |
| + |
| + // Set up a local nigori with a migrated custom passphrase type |
| + sync_pb::EntitySpecifics local_specifics; |
| + sync_pb::NigoriSpecifics* local_nigori = local_specifics.mutable_nigori(); |
| + cryptographer->GetKeys(local_nigori->mutable_encryption_keybag()); |
| + local_nigori->set_encrypt_everything(false); |
| + local_nigori->set_keybag_is_frozen(false); |
| + ASSERT_TRUE(entry_factory_->SetSpecificsForItem( |
| + nigori_handle, LOCAL_SPECIFICS, local_specifics)); |
| + // Apply the update locally so that UpdateFromEncryptedTypes knows what state |
| + // to use. |
| + { |
| + syncable::ReadTransaction trans(FROM_HERE, directory()); |
| + cryptographer = directory()->GetCryptographer(&trans); |
| + directory()->GetNigoriHandler()->ApplyNigoriUpdate( |
| + *local_nigori, |
| + &trans); |
| + } |
| + |
| + EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle)); |
| + EXPECT_TRUE(entry_factory_->GetIsUnappliedForItem(nigori_handle)); |
| + ApplyControlDataUpdates(directory()); |
| + EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle)); |
| + EXPECT_FALSE(entry_factory_->GetIsUnappliedForItem(nigori_handle)); |
| + |
| + EXPECT_TRUE(cryptographer->is_ready()); |
| + // Note: we didn't overwrite the encryption keybag with the local keys. The |
| + // sync encryption handler will do that when it detects that the new |
| + // keybag is out of date (and update the keystore bootstrap if necessary). |
| + EXPECT_FALSE(cryptographer->CanDecryptUsingDefaultKey( |
| + entry_factory_->GetSpecificsForItem(nigori_handle, LOCAL_SPECIFICS). |
| + nigori().encryption_keybag())); |
| + EXPECT_TRUE(cryptographer->CanDecrypt( |
| + entry_factory_->GetSpecificsForItem(nigori_handle, LOCAL_SPECIFICS). |
| + nigori().encryption_keybag())); |
| + EXPECT_TRUE(entry_factory_->GetSpecificsForItem( |
| + nigori_handle, LOCAL_SPECIFICS).nigori().keybag_is_frozen()); |
| + EXPECT_TRUE( |
| + entry_factory_->GetSpecificsForItem(nigori_handle, LOCAL_SPECIFICS). |
| + nigori().has_keystore_decryptor_token()); |
| + EXPECT_EQ(sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE, |
| + entry_factory_->GetSpecificsForItem(nigori_handle, LOCAL_SPECIFICS). |
| + nigori().passphrase_type()); |
| + { |
| + syncable::ReadTransaction trans(FROM_HERE, directory()); |
| + EXPECT_TRUE(directory()->initial_sync_ended_types().Has(NIGORI)); |
| + } |
| +} |
| + |
| } // namespace syncer |