diff options
author | lipalani@chromium.org <lipalani@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-02 18:43:57 +0000 |
---|---|---|
committer | lipalani@chromium.org <lipalani@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-02 18:43:57 +0000 |
commit | 8e8aea77f98f5075b055b818187a84f14c2ee0fd (patch) | |
tree | a20605241796f72301657779dca2656cda725e06 | |
parent | 23f77116cafe9a88819b60c7606453ae0db8f35d (diff) | |
download | chromium_src-8e8aea77f98f5075b055b818187a84f14c2ee0fd.zip chromium_src-8e8aea77f98f5075b055b818187a84f14c2ee0fd.tar.gz chromium_src-8e8aea77f98f5075b055b818187a84f14c2ee0fd.tar.bz2 |
Moving storing of encrypted types in cryptographer.
BUG=84153, 80333
TEST=
Committed: http://src.chromium.org/viewvc/chrome?view=rev&revision=87556
Review URL: http://codereview.chromium.org/7078023
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@87644 0039d316-1c4b-4281-b951-d872f2087c98
31 files changed, 333 insertions, 156 deletions
diff --git a/chrome/browser/sync/backend_migrator.cc b/chrome/browser/sync/backend_migrator.cc index 0f7dd0c..2ab4680 100644 --- a/chrome/browser/sync/backend_migrator.cc +++ b/chrome/browser/sync/backend_migrator.cc @@ -69,7 +69,15 @@ void BackendMigrator::MigrateTypes(const syncable::ModelTypeSet& types) { to_migrate_.begin(), to_migrate_.end(), std::inserter(difference, difference.end())); VLOG(1) << "BackendMigrator disabling types; calling Configure."; - manager_->Configure(difference, sync_api::CONFIGURE_REASON_MIGRATION); + + // Add nigori for config or not based upon if the server told us to migrate + // nigori or not. + if (types.count(syncable::NIGORI) == 0) { + manager_->Configure(difference, sync_api::CONFIGURE_REASON_MIGRATION); + } else { + manager_->ConfigureWithoutNigori(difference, + sync_api::CONFIGURE_REASON_MIGRATION); + } } void BackendMigrator::OnStateChanged() { @@ -99,6 +107,7 @@ void BackendMigrator::OnStateChanged() { ModelTypeSet full_set; service_->GetPreferredDataTypes(&full_set); VLOG(1) << "BackendMigrator re-enabling types."; + // Don't use |to_migrate_| for the re-enabling because the user may have // chosen to disable types during the migration. manager_->Configure(full_set, sync_api::CONFIGURE_REASON_MIGRATION); diff --git a/chrome/browser/sync/backend_migrator_unittest.cc b/chrome/browser/sync/backend_migrator_unittest.cc index 7c8a4f8..2939141 100644 --- a/chrome/browser/sync/backend_migrator_unittest.cc +++ b/chrome/browser/sync/backend_migrator_unittest.cc @@ -114,6 +114,38 @@ TEST_F(BackendMigratorTest, Sanity) { EXPECT_EQ(BackendMigrator::IDLE, migrator.state()); } +// Test that in the normal case with Nigori a migration transitions through +// each state and wind up back in IDLE. +TEST_F(BackendMigratorTest, MigrateNigori) { + BackendMigrator migrator(service(), manager()); + syncable::ModelTypeSet to_migrate, difference; + to_migrate.insert(syncable::NIGORI); + difference.insert(syncable::AUTOFILL); + difference.insert(syncable::BOOKMARKS); + + EXPECT_CALL(*manager(), state()) + .WillOnce(Return(DataTypeManager::CONFIGURED)); + + EXPECT_CALL(*manager(), ConfigureWithoutNigori(_, + sync_api::CONFIGURE_REASON_MIGRATION)); + + migrator.MigrateTypes(to_migrate); + EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator.state()); + + SendConfigureDone(DataTypeManager::OK, difference); + EXPECT_EQ(BackendMigrator::WAITING_FOR_PURGE, migrator.state()); + + ReturnEmptyProgressMarkersInSnapshot(); + EXPECT_CALL(*manager(), Configure(preferred_types(), + sync_api::CONFIGURE_REASON_MIGRATION)); + migrator.OnStateChanged(); + EXPECT_EQ(BackendMigrator::REENABLING_TYPES, migrator.state()); + + SendConfigureDone(DataTypeManager::OK, preferred_types()); + EXPECT_EQ(BackendMigrator::IDLE, migrator.state()); +} + + // Test that the migrator waits for the data type manager to be idle before // starting a migration. TEST_F(BackendMigratorTest, WaitToStart) { diff --git a/chrome/browser/sync/engine/apply_updates_command_unittest.cc b/chrome/browser/sync/engine/apply_updates_command_unittest.cc index 5f05ea2..8bceb39 100644 --- a/chrome/browser/sync/engine/apply_updates_command_unittest.cc +++ b/chrome/browser/sync/engine/apply_updates_command_unittest.cc @@ -25,7 +25,6 @@ namespace browser_sync { using sessions::SyncSession; using std::string; using syncable::Entry; -using syncable::GetEncryptedDataTypes; using syncable::Id; using syncable::MutableEntry; using syncable::ReadTransaction; @@ -344,9 +343,9 @@ TEST_F(ApplyUpdatesCommandTest, NigoriUpdate) { ScopedDirLookup dir(syncdb()->manager(), syncdb()->name()); ASSERT_TRUE(dir.good()); ReadTransaction trans(dir, __FILE__, __LINE__); - EXPECT_EQ(encrypted_types, GetEncryptedDataTypes(&trans)); cryptographer = session()->context()->directory_manager()->GetCryptographer(&trans); + EXPECT_EQ(encrypted_types, cryptographer->GetEncryptedTypes()); } // Nigori node updates should update the Cryptographer. @@ -389,9 +388,10 @@ TEST_F(ApplyUpdatesCommandTest, EncryptUnsyncedChanges) { ScopedDirLookup dir(syncdb()->manager(), syncdb()->name()); ASSERT_TRUE(dir.good()); ReadTransaction trans(dir, __FILE__, __LINE__); - EXPECT_EQ(encrypted_types, GetEncryptedDataTypes(&trans)); cryptographer = session()->context()->directory_manager()->GetCryptographer(&trans); + EXPECT_EQ(encrypted_types, cryptographer->GetEncryptedTypes()); + // With default encrypted_types, this should be true. EXPECT_TRUE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types)); @@ -467,7 +467,7 @@ TEST_F(ApplyUpdatesCommandTest, EncryptUnsyncedChanges) { // If ProcessUnsyncedChangesForEncryption worked, all our unsynced changes // should be encrypted now. - EXPECT_EQ(encrypted_types, GetEncryptedDataTypes(&trans)); + EXPECT_EQ(encrypted_types, cryptographer->GetEncryptedTypes()); EXPECT_TRUE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types)); Syncer::UnsyncedMetaHandles handles; @@ -486,9 +486,10 @@ TEST_F(ApplyUpdatesCommandTest, CannotEncryptUnsyncedChanges) { ScopedDirLookup dir(syncdb()->manager(), syncdb()->name()); ASSERT_TRUE(dir.good()); ReadTransaction trans(dir, __FILE__, __LINE__); - EXPECT_EQ(encrypted_types, GetEncryptedDataTypes(&trans)); cryptographer = session()->context()->directory_manager()->GetCryptographer(&trans); + EXPECT_EQ(encrypted_types, cryptographer->GetEncryptedTypes()); + // With default encrypted_types, this should be true. EXPECT_TRUE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types)); @@ -571,7 +572,8 @@ TEST_F(ApplyUpdatesCommandTest, CannotEncryptUnsyncedChanges) { EXPECT_FALSE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types)); encrypted_types.clear(); encrypted_types.insert(syncable::PASSWORDS); - EXPECT_EQ(encrypted_types, GetEncryptedDataTypes(&trans)); + encrypted_types.insert(syncable::BOOKMARKS); + EXPECT_EQ(encrypted_types, cryptographer->GetEncryptedTypes()); Syncer::UnsyncedMetaHandles handles; SyncerUtil::GetUnsyncedEntries(&trans, &handles); diff --git a/chrome/browser/sync/engine/syncapi.cc b/chrome/browser/sync/engine/syncapi.cc index 37f56ab..40a946f 100644 --- a/chrome/browser/sync/engine/syncapi.cc +++ b/chrome/browser/sync/engine/syncapi.cc @@ -456,7 +456,7 @@ void WriteNode::EncryptIfNecessary(sync_pb::EntitySpecifics* unencrypted) { DCHECK_NE(type, syncable::NIGORI); // Nigori is encrypted separately. syncable::ModelTypeSet encrypted_types = - GetEncryptedDataTypes(GetTransaction()->GetWrappedTrans()); + GetEncryptedTypes(GetTransaction()); if (encrypted_types.count(type) == 0) { // This datatype does not require encryption. return; @@ -1196,6 +1196,12 @@ DictionaryValue* NotificationInfoToValue( } // namespace +syncable::ModelTypeSet GetEncryptedTypes( + const sync_api::BaseTransaction* trans) { + Cryptographer* cryptographer = trans->GetCryptographer(); + return cryptographer->GetEncryptedTypes(); +} + ////////////////////////////////////////////////////////////////////////// // SyncManager's implementation: SyncManager::SyncInternal class SyncManager::SyncInternal @@ -1829,16 +1835,20 @@ void SyncManager::SyncInternal::BootstrapEncryption( return; } - if (!lookup->initial_sync_ended_for_type(syncable::NIGORI)) - return; - sync_pb::NigoriSpecifics nigori; + syncable::ModelTypeSet encrypted_types; { // Cryptographer should only be accessed while holding a transaction. ReadTransaction trans(GetUserShare()); Cryptographer* cryptographer = trans.GetCryptographer(); + + // Set the bootstrap token before bailing out if nigori node is not there. + // This could happen if server asked us to migrate nigri. cryptographer->Bootstrap(restored_key_for_bootstrapping); + if (!lookup->initial_sync_ended_for_type(syncable::NIGORI)) + return; + ReadNode node(&trans); if (!node.InitByTagLookup(kNigoriTag)) { NOTREACHED(); @@ -1846,20 +1856,17 @@ void SyncManager::SyncInternal::BootstrapEncryption( } nigori.CopyFrom(node.GetNigoriSpecifics()); - if (!nigori.encrypted().blob().empty()) { - if (cryptographer->CanDecrypt(nigori.encrypted())) { - cryptographer->SetKeys(nigori.encrypted()); - } else { - cryptographer->SetPendingKeys(nigori.encrypted()); - FOR_EACH_OBSERVER(SyncManager::Observer, observers_, - OnPassphraseRequired(sync_api::REASON_DECRYPTION)); - } + Cryptographer::UpdateResult result = cryptographer->Update(nigori); + if (result == Cryptographer::NEEDS_PASSPHRASE) { + FOR_EACH_OBSERVER(SyncManager::Observer, observers_, + OnPassphraseRequired(sync_api::REASON_DECRYPTION)); } + + // Refresh list of encrypted datatypes. + encrypted_types = GetEncryptedTypes(&trans); } - // Refresh list of encrypted datatypes. - syncable::ModelTypeSet encrypted_types = - syncable::GetEncryptedDataTypesFromNigori(nigori); + // Ensure any datatypes that need encryption are encrypted. EncryptDataTypes(encrypted_types); @@ -2104,13 +2111,14 @@ void SyncManager::SyncInternal::EncryptDataTypes( return; } + Cryptographer* cryptographer = trans.GetCryptographer(); + // Update the Nigori node set of encrypted datatypes so other machines notice. // Note, we merge the current encrypted types with those requested. Once a // datatypes is marked as needing encryption, it is never unmarked. sync_pb::NigoriSpecifics nigori; nigori.CopyFrom(node.GetNigoriSpecifics()); - syncable::ModelTypeSet current_encrypted_types = - syncable::GetEncryptedDataTypesFromNigori(nigori); + syncable::ModelTypeSet current_encrypted_types = GetEncryptedTypes(&trans); syncable::ModelTypeSet newly_encrypted_types; std::set_union(current_encrypted_types.begin(), current_encrypted_types.end(), encrypted_types.begin(), encrypted_types.end(), @@ -2119,6 +2127,8 @@ void SyncManager::SyncInternal::EncryptDataTypes( syncable::FillNigoriEncryptedTypes(newly_encrypted_types, &nigori); node.SetNigoriSpecifics(nigori); + cryptographer->SetEncryptedTypes(nigori); + // TODO(zea): only reencrypt this datatype? ReEncrypting everything is a // safer approach, and should not impact anything that is already encrypted // (redundant changes are ignored). @@ -2174,7 +2184,7 @@ ListValue* SyncManager::SyncInternal::FindNodesContainingString( void SyncManager::SyncInternal::ReEncryptEverything(WriteTransaction* trans) { syncable::ModelTypeSet encrypted_types = - GetEncryptedDataTypes(trans->GetWrappedTrans()); + GetEncryptedTypes(trans); ModelSafeRoutingInfo routes; registrar_->GetModelSafeRoutingInfo(&routes); std::string tag; @@ -2550,14 +2560,7 @@ void SyncManager::SyncInternal::OnSyncEngineEvent( // Check to see if we need to notify the frontend that we have newly // encrypted types or that we require a passphrase. sync_api::ReadTransaction trans(GetUserShare()); - sync_api::ReadNode node(&trans); - if (!node.InitByTagLookup(kNigoriTag)) { - DCHECK(!event.snapshot->is_share_usable); - return; - } - const sync_pb::NigoriSpecifics& nigori = node.GetNigoriSpecifics(); - syncable::ModelTypeSet encrypted_types = - syncable::GetEncryptedDataTypesFromNigori(nigori); + syncable::ModelTypeSet encrypted_types = GetEncryptedTypes(&trans); syncable::ModelTypeSet encrypted_and_enabled_types; for (syncable::ModelTypeSet::iterator iter = encrypted_types.begin(); iter != encrypted_types.end(); @@ -2567,7 +2570,15 @@ void SyncManager::SyncInternal::OnSyncEngineEvent( } if (!encrypted_and_enabled_types.empty()) { Cryptographer* cryptographer = trans.GetCryptographer(); + // TODO(lipalani) : confirm from zea and tim this could be hit only for + // the first sync ever on this profile. if (!cryptographer->is_ready() && !cryptographer->has_pending_keys()) { + sync_api::ReadNode node(&trans); + if (!node.InitByTagLookup(kNigoriTag)) { + DCHECK(!event.snapshot->is_share_usable); + return; + } + const sync_pb::NigoriSpecifics& nigori = node.GetNigoriSpecifics(); if (!nigori.encrypted().blob().empty()) { DCHECK(!cryptographer->CanDecrypt(nigori.encrypted())); cryptographer->SetPendingKeys(nigori.encrypted()); diff --git a/chrome/browser/sync/engine/syncapi.h b/chrome/browser/sync/engine/syncapi.h index 5a0cacd..0e35fff 100644 --- a/chrome/browser/sync/engine/syncapi.h +++ b/chrome/browser/sync/engine/syncapi.h @@ -108,6 +108,10 @@ class HttpPostProviderFactory; class SyncManager; class WriteTransaction; +syncable::ModelTypeSet GetEncryptedTypes( + const sync_api::BaseTransaction* trans); + + // Reasons due to which browser_sync::Cryptographer might require a passphrase. enum PassphraseRequiredReason { REASON_PASSPHRASE_NOT_REQUIRED = 0, // Initial value. diff --git a/chrome/browser/sync/engine/syncapi_unittest.cc b/chrome/browser/sync/engine/syncapi_unittest.cc index 229947b..253cad5 100644 --- a/chrome/browser/sync/engine/syncapi_unittest.cc +++ b/chrome/browser/sync/engine/syncapi_unittest.cc @@ -1171,7 +1171,7 @@ TEST_F(SyncManagerTest, EncryptDataTypesWithNoData) { { ReadTransaction trans(sync_manager_.GetUserShare()); EXPECT_EQ(expected_types, - GetEncryptedDataTypes(trans.GetWrappedTrans())); + GetEncryptedTypes(&trans)); } } @@ -1226,7 +1226,7 @@ TEST_F(SyncManagerTest, EncryptDataTypesWithData) { { ReadTransaction trans(sync_manager_.GetUserShare()); EXPECT_EQ(encrypted_types, - GetEncryptedDataTypes(trans.GetWrappedTrans())); + GetEncryptedTypes(&trans)); EXPECT_TRUE(syncable::VerifyDataTypeEncryption(trans.GetWrappedTrans(), syncable::BOOKMARKS, true /* is encrypted */)); diff --git a/chrome/browser/sync/engine/syncer_util.cc b/chrome/browser/sync/engine/syncer_util.cc index 7340a27..eb6d0bf 100644 --- a/chrome/browser/sync/engine/syncer_util.cc +++ b/chrome/browser/sync/engine/syncer_util.cc @@ -295,17 +295,11 @@ UpdateAttemptResponse SyncerUtil::AttemptToUpdateEntry( if (specifics.HasExtension(sync_pb::nigori)) { const sync_pb::NigoriSpecifics& nigori = specifics.GetExtension(sync_pb::nigori); - if (!nigori.encrypted().blob().empty()) { - if (cryptographer->CanDecrypt(nigori.encrypted())) { - cryptographer->SetKeys(nigori.encrypted()); - } else { - cryptographer->SetPendingKeys(nigori.encrypted()); - } - } + cryptographer->Update(nigori); // Make sure any unsynced changes are properly encrypted as necessary. syncable::ModelTypeSet encrypted_types = - syncable::GetEncryptedDataTypesFromNigori(nigori); + cryptographer->GetEncryptedTypes(); if (!VerifyUnsyncedChangesAreEncrypted(trans, encrypted_types) && (!cryptographer->is_ready() || !syncable::ProcessUnsyncedChangesForEncryption(trans, encrypted_types, diff --git a/chrome/browser/sync/glue/app_model_associator.cc b/chrome/browser/sync/glue/app_model_associator.cc index 1b31570..b2bb54c 100644 --- a/chrome/browser/sync/glue/app_model_associator.cc +++ b/chrome/browser/sync/glue/app_model_associator.cc @@ -65,7 +65,7 @@ bool AppModelAssociator::CryptoReadyIfNecessary() { // We only access the cryptographer while holding a transaction. sync_api::ReadTransaction trans(user_share_); const syncable::ModelTypeSet& encrypted_types = - GetEncryptedDataTypes(trans.GetWrappedTrans()); + sync_api::GetEncryptedTypes(&trans); return encrypted_types.count(traits_.model_type) == 0 || trans.GetCryptographer()->is_ready(); } diff --git a/chrome/browser/sync/glue/bookmark_model_associator.cc b/chrome/browser/sync/glue/bookmark_model_associator.cc index af7c752..9aff7ad 100644 --- a/chrome/browser/sync/glue/bookmark_model_associator.cc +++ b/chrome/browser/sync/glue/bookmark_model_associator.cc @@ -599,7 +599,7 @@ bool BookmarkModelAssociator::CryptoReadyIfNecessary() { // We only access the cryptographer while holding a transaction. sync_api::ReadTransaction trans(user_share_); const syncable::ModelTypeSet& encrypted_types = - GetEncryptedDataTypes(trans.GetWrappedTrans()); + sync_api::GetEncryptedTypes(&trans); return encrypted_types.count(syncable::BOOKMARKS) == 0 || trans.GetCryptographer()->is_ready(); } diff --git a/chrome/browser/sync/glue/data_type_manager.h b/chrome/browser/sync/glue/data_type_manager.h index 7d789d4..eef71a1 100644 --- a/chrome/browser/sync/glue/data_type_manager.h +++ b/chrome/browser/sync/glue/data_type_manager.h @@ -91,6 +91,9 @@ class DataTypeManager { virtual void Configure(const TypeSet& desired_types, sync_api::ConfigureReason reason) = 0; + virtual void ConfigureWithoutNigori(const TypeSet& desired_types, + sync_api::ConfigureReason reason) = 0; + // Synchronously stops all registered data types. If called after // Configure() is called but before it finishes, it will abort the // configure and any data types that have been started will be diff --git a/chrome/browser/sync/glue/data_type_manager_impl.cc b/chrome/browser/sync/glue/data_type_manager_impl.cc index 3a7ca4c..a840259 100644 --- a/chrome/browser/sync/glue/data_type_manager_impl.cc +++ b/chrome/browser/sync/glue/data_type_manager_impl.cc @@ -101,7 +101,18 @@ bool DataTypeManagerImpl::GetControllersNeedingStart( } void DataTypeManagerImpl::Configure(const TypeSet& desired_types, - sync_api::ConfigureReason reason) { + sync_api::ConfigureReason reason) { + ConfigureImpl(desired_types, reason, true); +} + +void DataTypeManagerImpl::ConfigureWithoutNigori(const TypeSet& desired_types, + sync_api::ConfigureReason reason) { + ConfigureImpl(desired_types, reason, false); +} + +void DataTypeManagerImpl::ConfigureImpl(const TypeSet& desired_types, + sync_api::ConfigureReason reason, + bool enable_nigori) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); if (state_ == STOPPING) { // You can not set a configuration while stopping. @@ -116,6 +127,14 @@ void DataTypeManagerImpl::Configure(const TypeSet& desired_types, << "Postponing until current configuration complete."; needs_reconfigure_ = true; last_configure_reason_ = reason; + + // Note we should never be in a state to reconfigure with nigori disabled. + // Reconfigures serve to store teh configure request from the user if + // another one is already in progress. Since enable_nigori is set to false + // only on migration and migration code should not initialize configure + // if there is already one in progress, enable_nigori should always be true + // if we are here. + DCHECK(enable_nigori); return; } @@ -150,10 +169,11 @@ void DataTypeManagerImpl::Configure(const TypeSet& desired_types, // types to start/stop, because it could be that some types haven't // started due to crypto errors but the backend host needs to know that we're // disabling them anyway). - Restart(reason); + Restart(reason, enable_nigori); } -void DataTypeManagerImpl::Restart(sync_api::ConfigureReason reason) { +void DataTypeManagerImpl::Restart(sync_api::ConfigureReason reason, + bool enable_nigori) { VLOG(1) << "Restarting..."; last_restart_time_ = base::Time::Now(); @@ -178,7 +198,8 @@ void DataTypeManagerImpl::Restart(sync_api::ConfigureReason reason) { controllers_, last_requested_types_, reason, - method_factory_.NewRunnableMethod(&DataTypeManagerImpl::DownloadReady)); + method_factory_.NewRunnableMethod(&DataTypeManagerImpl::DownloadReady), + enable_nigori); } void DataTypeManagerImpl::DownloadReady() { diff --git a/chrome/browser/sync/glue/data_type_manager_impl.h b/chrome/browser/sync/glue/data_type_manager_impl.h index bd77074..902bcf8 100644 --- a/chrome/browser/sync/glue/data_type_manager_impl.h +++ b/chrome/browser/sync/glue/data_type_manager_impl.h @@ -29,6 +29,10 @@ class DataTypeManagerImpl : public DataTypeManager { // DataTypeManager interface. virtual void Configure(const TypeSet& desired_types, sync_api::ConfigureReason reason); + + virtual void ConfigureWithoutNigori(const TypeSet& desired_types, + sync_api::ConfigureReason reason); + virtual void Stop(); virtual const DataTypeController::TypeMap& controllers(); virtual State state(); @@ -53,7 +57,7 @@ class DataTypeManagerImpl : public DataTypeManager { bool GetControllersNeedingStart( std::vector<DataTypeController*>* needs_start); - void Restart(sync_api::ConfigureReason reason); + void Restart(sync_api::ConfigureReason reason, bool enable_nigori); void DownloadReady(); void NotifyStart(); void NotifyDone(ConfigureResult result, @@ -64,6 +68,10 @@ class DataTypeManagerImpl : public DataTypeManager { // Restart(). void AddToConfigureTime(); + virtual void ConfigureImpl(const TypeSet& desired_types, + sync_api::ConfigureReason reason, + bool enable_nigori); + SyncBackendHost* backend_; // Map of all data type controllers that are available for sync. // This list is determined at startup by various command line flags. diff --git a/chrome/browser/sync/glue/data_type_manager_impl_unittest.cc b/chrome/browser/sync/glue/data_type_manager_impl_unittest.cc index b4602b0..1f5e3ef 100644 --- a/chrome/browser/sync/glue/data_type_manager_impl_unittest.cc +++ b/chrome/browser/sync/glue/data_type_manager_impl_unittest.cc @@ -180,7 +180,7 @@ TEST_F(DataTypeManagerImplTest, ConfigureOne) { DataTypeControllerMock* bookmark_dtc = MakeBookmarkDTC(); SetStartStopExpectations(bookmark_dtc); controllers_[syncable::BOOKMARKS] = bookmark_dtc; - EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _, _)).Times(1); + EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _, _, _)).Times(1); DataTypeManagerImpl dtm(&backend_, controllers_); types_.insert(syncable::BOOKMARKS); SetConfigureStartExpectation(); @@ -196,7 +196,7 @@ TEST_F(DataTypeManagerImplTest, ConfigureOneStopWhileStarting) { SetBusyStartStopExpectations(bookmark_dtc, DataTypeController::MODEL_STARTING); controllers_[syncable::BOOKMARKS] = bookmark_dtc; - EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _, _)).Times(1); + EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _, _, _)).Times(1); DataTypeManagerImpl dtm(&backend_, controllers_); types_.insert(syncable::BOOKMARKS); SetConfigureStartExpectation(); @@ -211,7 +211,7 @@ TEST_F(DataTypeManagerImplTest, ConfigureOneStopWhileAssociating) { DataTypeControllerMock* bookmark_dtc = MakeBookmarkDTC(); SetBusyStartStopExpectations(bookmark_dtc, DataTypeController::ASSOCIATING); controllers_[syncable::BOOKMARKS] = bookmark_dtc; - EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _, _)).Times(1); + EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _, _, _)).Times(1); DataTypeManagerImpl dtm(&backend_, controllers_); types_.insert(syncable::BOOKMARKS); SetConfigureStartExpectation(); @@ -230,7 +230,7 @@ TEST_F(DataTypeManagerImplTest, OneWaitingForCrypto) { WillOnce(InvokeCallback((DataTypeController::NEEDS_CRYPTO))); controllers_[syncable::PASSWORDS] = password_dtc; - EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _, _)).Times(1); + EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _, _, _)).Times(1); DataTypeManagerImpl dtm(&backend_, controllers_); types_.insert(syncable::PASSWORDS); @@ -250,7 +250,7 @@ TEST_F(DataTypeManagerImplTest, OneWaitingForCrypto) { WillRepeatedly(Return(DataTypeController::RUNNING)); EXPECT_CALL(*password_dtc, Start(_)). WillOnce(InvokeCallback((DataTypeController::OK))); - EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _, _)).Times(1); + EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _, _, _)).Times(1); dtm.Configure(types_, sync_api::CONFIGURE_REASON_RECONFIGURATION); EXPECT_EQ(DataTypeManager::CONFIGURED, dtm.state()); @@ -267,7 +267,7 @@ TEST_F(DataTypeManagerImplTest, ConfigureOneThenAnother) { SetStartStopExpectations(preference_dtc); controllers_[syncable::PREFERENCES] = preference_dtc; - EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _, _)).Times(2); + EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _, _, _)).Times(2); DataTypeManagerImpl dtm(&backend_, controllers_); types_.insert(syncable::BOOKMARKS); @@ -294,7 +294,7 @@ TEST_F(DataTypeManagerImplTest, ConfigureOneThenSwitch) { SetStartStopExpectations(preference_dtc); controllers_[syncable::PREFERENCES] = preference_dtc; - EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _, _)).Times(2); + EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _, _, _)).Times(2); DataTypeManagerImpl dtm(&backend_, controllers_); types_.insert(syncable::BOOKMARKS); @@ -318,7 +318,8 @@ void DoConfigureDataTypes( const DataTypeController::TypeMap& data_type_controllers, const syncable::ModelTypeSet& types, sync_api::ConfigureReason reason, - CancelableTask* ready_task) { + CancelableTask* ready_task, + bool enable_nigori) { ready_task->Run(); delete ready_task; } @@ -350,7 +351,7 @@ TEST_F(DataTypeManagerImplTest, ConfigureWhileOneInFlight) { controllers_[syncable::PREFERENCES] = preference_dtc; DataTypeManagerImpl dtm(&backend_, controllers_); - EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _, _)) + EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _, _, _)) .WillOnce(Invoke(DoConfigureDataTypes)) .WillOnce(DoAll(Invoke(DoConfigureDataTypes), InvokeWithoutArgs(QuitMessageLoop))); @@ -388,7 +389,7 @@ TEST_F(DataTypeManagerImplTest, OneFailingController) { DataTypeManagerImpl dtm(&backend_, controllers_); SetConfigureStartExpectation(); SetConfigureDoneExpectation(DataTypeManager::ASSOCIATION_FAILED); - EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _, _)).Times(1); + EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _, _, _)).Times(1); types_.insert(syncable::BOOKMARKS); dtm.Configure(types_, sync_api::CONFIGURE_REASON_RECONFIGURATION); @@ -412,7 +413,7 @@ TEST_F(DataTypeManagerImplTest, StopWhileInFlight) { DataTypeManagerImpl dtm(&backend_, controllers_); SetConfigureStartExpectation(); SetConfigureDoneExpectation(DataTypeManager::ABORTED); - EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _, _)).Times(1); + EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _, _, _)).Times(1); types_.insert(syncable::BOOKMARKS); types_.insert(syncable::PREFERENCES); @@ -444,7 +445,7 @@ TEST_F(DataTypeManagerImplTest, SecondControllerFails) { DataTypeManagerImpl dtm(&backend_, controllers_); SetConfigureStartExpectation(); SetConfigureDoneExpectation(DataTypeManager::ASSOCIATION_FAILED); - EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _, _)).Times(1); + EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _, _, _)).Times(1); types_.insert(syncable::BOOKMARKS); types_.insert(syncable::PREFERENCES); @@ -467,7 +468,7 @@ TEST_F(DataTypeManagerImplTest, ConfigureWhileDownloadPending) { CancelableTask* task; // Grab the task the first time this is called so we can configure // before it is finished. - EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _, _)). + EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _, _, _)). WillOnce(SaveArg<3>(&task)). WillOnce(DoDefault()); @@ -502,7 +503,7 @@ TEST_F(DataTypeManagerImplTest, StopWhileDownloadPending) { CancelableTask* task; // Grab the task the first time this is called so we can stop // before it is finished. - EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _, _)). + EXPECT_CALL(backend_, ConfigureDataTypes(_, _, _, _, _)). WillOnce(SaveArg<3>(&task)); types_.insert(syncable::BOOKMARKS); diff --git a/chrome/browser/sync/glue/data_type_manager_mock.cc b/chrome/browser/sync/glue/data_type_manager_mock.cc index 9c7041b..1f75b84 100644 --- a/chrome/browser/sync/glue/data_type_manager_mock.cc +++ b/chrome/browser/sync/glue/data_type_manager_mock.cc @@ -13,12 +13,22 @@ DataTypeManagerMock::DataTypeManagerMock() // By default, calling Configure will send a SYNC_CONFIGURE_START // and SYNC_CONFIGURE_DONE notification with a DataTypeManager::OK // detail. - ON_CALL(*this, Configure(testing::_, testing::_)). - WillByDefault(testing::DoAll( - NotifyFromDataTypeManager(this, - NotificationType::SYNC_CONFIGURE_START), - NotifyFromDataTypeManagerWithResult - (this, NotificationType::SYNC_CONFIGURE_DONE, &result_))); + ON_CALL(*this, Configure(testing::_, testing::_)). + WillByDefault(testing::DoAll( + NotifyFromDataTypeManager(this, + NotificationType::SYNC_CONFIGURE_START), + NotifyFromDataTypeManagerWithResult + (this, NotificationType::SYNC_CONFIGURE_DONE, &result_))); + + // By default, calling ConfigureWithoutNigori will send a SYNC_CONFIGURE_START + // and SYNC_CONFIGURE_DONE notification with a DataTypeManager::OK + // detail. + ON_CALL(*this, ConfigureWithoutNigori(testing::_, testing::_)). + WillByDefault(testing::DoAll( + NotifyFromDataTypeManager(this, + NotificationType::SYNC_CONFIGURE_START), + NotifyFromDataTypeManagerWithResult + (this, NotificationType::SYNC_CONFIGURE_DONE, &result_))); } DataTypeManagerMock::~DataTypeManagerMock() {} diff --git a/chrome/browser/sync/glue/data_type_manager_mock.h b/chrome/browser/sync/glue/data_type_manager_mock.h index 9e1dc03..0645164 100644 --- a/chrome/browser/sync/glue/data_type_manager_mock.h +++ b/chrome/browser/sync/glue/data_type_manager_mock.h @@ -35,6 +35,8 @@ class DataTypeManagerMock : public DataTypeManager { virtual ~DataTypeManagerMock(); MOCK_METHOD2(Configure, void(const TypeSet&, sync_api::ConfigureReason)); + MOCK_METHOD2(ConfigureWithoutNigori, + void(const TypeSet&, sync_api::ConfigureReason)); MOCK_METHOD0(Stop, void()); MOCK_METHOD0(controllers, const DataTypeController::TypeMap&()); MOCK_METHOD0(state, State()); diff --git a/chrome/browser/sync/glue/extension_model_associator.cc b/chrome/browser/sync/glue/extension_model_associator.cc index 7754435..6bfbece 100644 --- a/chrome/browser/sync/glue/extension_model_associator.cc +++ b/chrome/browser/sync/glue/extension_model_associator.cc @@ -66,7 +66,7 @@ bool ExtensionModelAssociator::CryptoReadyIfNecessary() { // We only access the cryptographer while holding a transaction. sync_api::ReadTransaction trans(user_share_); const syncable::ModelTypeSet& encrypted_types = - GetEncryptedDataTypes(trans.GetWrappedTrans()); + sync_api::GetEncryptedTypes(&trans); return encrypted_types.count(traits_.model_type) == 0 || trans.GetCryptographer()->is_ready(); } diff --git a/chrome/browser/sync/glue/generic_change_processor.cc b/chrome/browser/sync/glue/generic_change_processor.cc index ba175bf..d2056d2 100644 --- a/chrome/browser/sync/glue/generic_change_processor.cc +++ b/chrome/browser/sync/glue/generic_change_processor.cc @@ -187,7 +187,7 @@ bool GenericChangeProcessor::CryptoReadyIfNecessary(syncable::ModelType type) { // We only access the cryptographer while holding a transaction. sync_api::ReadTransaction trans(share_handle()); const syncable::ModelTypeSet& encrypted_types = - syncable::GetEncryptedDataTypes(trans.GetWrappedTrans()); + GetEncryptedTypes(&trans); return encrypted_types.count(type) == 0 || trans.GetCryptographer()->is_ready(); } diff --git a/chrome/browser/sync/glue/sync_backend_host.cc b/chrome/browser/sync/glue/sync_backend_host.cc index f31d80d..a2952eb 100644 --- a/chrome/browser/sync/glue/sync_backend_host.cc +++ b/chrome/browser/sync/glue/sync_backend_host.cc @@ -160,9 +160,6 @@ std::string SyncBackendHost::RestoreEncryptionBootstrapToken() { bool SyncBackendHost::IsNigoriEnabled() const { base::AutoLock lock(registrar_lock_); - // Note that NIGORI is only ever added/removed from routing_info once, - // during initialization / first configuration, so there is no real 'race' - // possible here or possibility of stale return value. return registrar_.routing_info.find(syncable::NIGORI) != registrar_.routing_info.end(); } @@ -347,14 +344,14 @@ PendingConfigureDataTypesState() : deleted_type(false), SyncBackendHost::PendingConfigureDataTypesState:: ~PendingConfigureDataTypesState() {} -// static SyncBackendHost::PendingConfigureDataTypesState* SyncBackendHost::MakePendingConfigModeState( const DataTypeController::TypeMap& data_type_controllers, const syncable::ModelTypeSet& types, CancelableTask* ready_task, ModelSafeRoutingInfo* routing_info, - sync_api::ConfigureReason reason) { + sync_api::ConfigureReason reason, + bool nigori_enabled) { PendingConfigureDataTypesState* state = new PendingConfigureDataTypesState(); for (DataTypeController::TypeMap::const_iterator it = data_type_controllers.begin(); @@ -374,6 +371,19 @@ SyncBackendHost::PendingConfigureDataTypesState* } } + if (types.count(syncable::NIGORI) == 0) { + if (nigori_enabled) { // Nigori is currently enabled. + state->deleted_type = true; + routing_info->erase(syncable::NIGORI); + } + } else { // Nigori needs to be enabled. + if (!nigori_enabled) { + // Currently it is disabled. So enable it. + (*routing_info)[syncable::NIGORI] = GROUP_PASSIVE; + state->added_types.set(syncable::NIGORI); + } + } + state->ready_task.reset(ready_task); state->initial_types = types; state->reason = reason; @@ -384,7 +394,8 @@ void SyncBackendHost::ConfigureDataTypes( const DataTypeController::TypeMap& data_type_controllers, const syncable::ModelTypeSet& types, sync_api::ConfigureReason reason, - CancelableTask* ready_task) { + CancelableTask* ready_task, + bool enable_nigori) { // Only one configure is allowed at a time. DCHECK(!pending_config_mode_state_.get()); DCHECK(!pending_download_state_.get()); @@ -394,11 +405,17 @@ void SyncBackendHost::ConfigureDataTypes( ConfigureAutofillMigration(); } + syncable::ModelTypeSet types_copy = types; + if (enable_nigori) { + types_copy.insert(syncable::NIGORI); + } + bool nigori_currently_enabled = IsNigoriEnabled(); { base::AutoLock lock(registrar_lock_); pending_config_mode_state_.reset( - MakePendingConfigModeState(data_type_controllers, types, ready_task, - ®istrar_.routing_info, reason)); + MakePendingConfigModeState(data_type_controllers, types_copy, + ready_task, ®istrar_.routing_info, reason, + nigori_currently_enabled)); } StartConfiguration(NewCallback(core_.get(), diff --git a/chrome/browser/sync/glue/sync_backend_host.h b/chrome/browser/sync/glue/sync_backend_host.h index dac1237..9263cb4 100644 --- a/chrome/browser/sync/glue/sync_backend_host.h +++ b/chrome/browser/sync/glue/sync_backend_host.h @@ -168,7 +168,8 @@ class SyncBackendHost : public browser_sync::ModelSafeWorkerRegistrar { const DataTypeController::TypeMap& data_type_controllers, const syncable::ModelTypeSet& types, sync_api::ConfigureReason reason, - CancelableTask* ready_task); + CancelableTask* ready_task, + bool enable_nigori); // Makes an asynchronous call to syncer to switch to config mode. When done // syncer will call us back on FinishConfigureDataTypes. @@ -593,7 +594,8 @@ class SyncBackendHost : public browser_sync::ModelSafeWorkerRegistrar { const syncable::ModelTypeSet& types, CancelableTask* ready_task, ModelSafeRoutingInfo* routing_info, - sync_api::ConfigureReason reason); + sync_api::ConfigureReason reason, + bool nigori_enabled); // A thread we dedicate for use by our Core to perform initialization, // authentication, handle messages from the syncapi, and periodically tell diff --git a/chrome/browser/sync/glue/sync_backend_host_mock.cc b/chrome/browser/sync/glue/sync_backend_host_mock.cc index 738688e..fe7d9b3 100644 --- a/chrome/browser/sync/glue/sync_backend_host_mock.cc +++ b/chrome/browser/sync/glue/sync_backend_host_mock.cc @@ -14,7 +14,7 @@ ACTION(InvokeTask) { SyncBackendHostMock::SyncBackendHostMock() { // By default, invoke the ready callback. ON_CALL(*this, ConfigureDataTypes(testing::_, testing::_, testing::_, - testing::_)). + testing::_, testing::_)). WillByDefault(InvokeTask()); } diff --git a/chrome/browser/sync/glue/sync_backend_host_mock.h b/chrome/browser/sync/glue/sync_backend_host_mock.h index a3dd137..882265c 100644 --- a/chrome/browser/sync/glue/sync_backend_host_mock.h +++ b/chrome/browser/sync/glue/sync_backend_host_mock.h @@ -21,11 +21,12 @@ class SyncBackendHostMock : public SyncBackendHost { SyncBackendHostMock(); virtual ~SyncBackendHostMock(); - MOCK_METHOD4(ConfigureDataTypes, + MOCK_METHOD5(ConfigureDataTypes, void(const DataTypeController::TypeMap&, const std::set<syncable::ModelType>&, sync_api::ConfigureReason, - CancelableTask*)); + CancelableTask*, + bool)); MOCK_METHOD0(StartSyncingWithServer, void()); }; diff --git a/chrome/browser/sync/glue/sync_backend_host_unittest.cc b/chrome/browser/sync/glue/sync_backend_host_unittest.cc index 431e60e..8846982 100644 --- a/chrome/browser/sync/glue/sync_backend_host_unittest.cc +++ b/chrome/browser/sync/glue/sync_backend_host_unittest.cc @@ -118,7 +118,7 @@ TEST_F(SyncBackendHostTest, MakePendingConfigModeState) { scoped_ptr<SyncBackendHost::PendingConfigureDataTypesState> state(SyncBackendHost::MakePendingConfigModeState( data_type_controllers, types, NULL, &routing_info, - sync_api::CONFIGURE_REASON_RECONFIGURATION)); + sync_api::CONFIGURE_REASON_RECONFIGURATION, false)); EXPECT_TRUE(routing_info.empty()); EXPECT_FALSE(state->ready_task.get()); EXPECT_EQ(types, state->initial_types); @@ -133,10 +133,11 @@ TEST_F(SyncBackendHostTest, MakePendingConfigModeState) { syncable::ModelTypeSet types; ModelSafeRoutingInfo routing_info; + types.insert(syncable::NIGORI); scoped_ptr<SyncBackendHost::PendingConfigureDataTypesState> state(SyncBackendHost::MakePendingConfigModeState( data_type_controllers, types, NULL, - &routing_info, sync_api::CONFIGURE_REASON_RECONFIGURATION)); + &routing_info, sync_api::CONFIGURE_REASON_RECONFIGURATION, true)); EXPECT_TRUE(routing_info.empty()); EXPECT_FALSE(state->ready_task.get()); EXPECT_EQ(types, state->initial_types); @@ -150,12 +151,13 @@ TEST_F(SyncBackendHostTest, MakePendingConfigModeState) { data_type_controllers[syncable::BOOKMARKS] = NULL; syncable::ModelTypeSet types; types.insert(syncable::BOOKMARKS); + types.insert(syncable::NIGORI); ModelSafeRoutingInfo routing_info; scoped_ptr<SyncBackendHost::PendingConfigureDataTypesState> state(SyncBackendHost::MakePendingConfigModeState( data_type_controllers, types, NULL, &routing_info, - sync_api::CONFIGURE_REASON_RECONFIGURATION)); + sync_api::CONFIGURE_REASON_RECONFIGURATION, true)); ModelSafeRoutingInfo expected_routing_info; expected_routing_info[syncable::BOOKMARKS] = GROUP_PASSIVE; @@ -175,6 +177,7 @@ TEST_F(SyncBackendHostTest, MakePendingConfigModeState) { data_type_controllers[syncable::BOOKMARKS] = NULL; syncable::ModelTypeSet types; types.insert(syncable::BOOKMARKS); + types.insert(syncable::NIGORI); ModelSafeRoutingInfo routing_info; routing_info[syncable::BOOKMARKS] = GROUP_PASSIVE; ModelSafeRoutingInfo expected_routing_info = routing_info; @@ -182,7 +185,7 @@ TEST_F(SyncBackendHostTest, MakePendingConfigModeState) { scoped_ptr<SyncBackendHost::PendingConfigureDataTypesState> state(SyncBackendHost::MakePendingConfigModeState( data_type_controllers, types, NULL, &routing_info, - sync_api::CONFIGURE_REASON_RECONFIGURATION)); + sync_api::CONFIGURE_REASON_RECONFIGURATION, true)); EXPECT_EQ(expected_routing_info, routing_info); EXPECT_FALSE(state->ready_task.get()); @@ -196,13 +199,14 @@ TEST_F(SyncBackendHostTest, MakePendingConfigModeState) { DataTypeController::TypeMap data_type_controllers; data_type_controllers[syncable::BOOKMARKS] = NULL; syncable::ModelTypeSet types; + types.insert(syncable::NIGORI); ModelSafeRoutingInfo routing_info; routing_info[syncable::BOOKMARKS] = GROUP_PASSIVE; scoped_ptr<SyncBackendHost::PendingConfigureDataTypesState> state(SyncBackendHost::MakePendingConfigModeState( data_type_controllers, types, NULL, &routing_info, - sync_api::CONFIGURE_REASON_RECONFIGURATION)); + sync_api::CONFIGURE_REASON_RECONFIGURATION, true)); ModelSafeRoutingInfo expected_routing_info; EXPECT_EQ(expected_routing_info, routing_info); @@ -211,6 +215,51 @@ TEST_F(SyncBackendHostTest, MakePendingConfigModeState) { EXPECT_TRUE(state->deleted_type); EXPECT_TRUE(state->added_types.none()); } + + // Add Nigori. + { + DataTypeController::TypeMap data_type_controllers; + syncable::ModelTypeSet types; + types.insert(syncable::NIGORI); + ModelSafeRoutingInfo routing_info; + + scoped_ptr<SyncBackendHost::PendingConfigureDataTypesState> + state(SyncBackendHost::MakePendingConfigModeState( + data_type_controllers, types, NULL, &routing_info, + sync_api::CONFIGURE_REASON_RECONFIGURATION, false)); + + ModelSafeRoutingInfo expected_routing_info; + expected_routing_info[syncable::NIGORI] = GROUP_PASSIVE; + EXPECT_EQ(expected_routing_info, routing_info); + EXPECT_FALSE(state->ready_task.get()); + EXPECT_EQ(types, state->initial_types); + EXPECT_FALSE(state->deleted_type); + + syncable::ModelTypeBitSet expected_added_types; + expected_added_types.set(syncable::NIGORI); + EXPECT_EQ(expected_added_types, state->added_types); + } + + // Delete Nigori. + { + DataTypeController::TypeMap data_type_controllers; + syncable::ModelTypeSet types; + ModelSafeRoutingInfo routing_info; + routing_info[syncable::NIGORI] = GROUP_PASSIVE; + + scoped_ptr<SyncBackendHost::PendingConfigureDataTypesState> + state(SyncBackendHost::MakePendingConfigModeState( + data_type_controllers, types, NULL, &routing_info, + sync_api::CONFIGURE_REASON_RECONFIGURATION, true)); + + ModelSafeRoutingInfo expected_routing_info; + EXPECT_EQ(expected_routing_info, routing_info); + EXPECT_FALSE(state->ready_task.get()); + EXPECT_EQ(types, state->initial_types); + EXPECT_TRUE(state->deleted_type); + + EXPECT_TRUE(state->added_types.none()); + } } // TODO(akalin): Write more SyncBackendHost unit tests. diff --git a/chrome/browser/sync/syncable/nigori_util.cc b/chrome/browser/sync/syncable/nigori_util.cc index c13aead..018c87c 100644 --- a/chrome/browser/sync/syncable/nigori_util.cc +++ b/chrome/browser/sync/syncable/nigori_util.cc @@ -13,55 +13,6 @@ #include "chrome/browser/sync/util/cryptographer.h" namespace syncable { - -ModelTypeSet GetEncryptedDataTypes(BaseTransaction* const trans) { - std::string nigori_tag = ModelTypeToRootTag(syncable::NIGORI); - Entry entry(trans, GET_BY_SERVER_TAG, nigori_tag); - if (!entry.good()) { - VLOG(1) << "Nigori node not found, assuming no encrypted datatypes."; - ModelTypeSet encrypted_types; - encrypted_types.insert(syncable::PASSWORDS); - return encrypted_types; - } - if (NIGORI != entry.GetModelType()) { - // Can happen if we fail to apply the nigori node due to a conflict. - VLOG(1) << "Nigori node does not have nigori extension. Assuming no" - << " encrypted datatypes."; - ModelTypeSet encrypted_types; - encrypted_types.insert(syncable::PASSWORDS); - return encrypted_types; - } - const sync_pb::EntitySpecifics& specifics = entry.Get(SPECIFICS); - return GetEncryptedDataTypesFromNigori( - specifics.GetExtension(sync_pb::nigori)); -} - -ModelTypeSet GetEncryptedDataTypesFromNigori( - const sync_pb::NigoriSpecifics& nigori) { - // We don't check NIGORI datatype, it uses its own encryption scheme. - ModelTypeSet encrypted_types; - if (nigori.encrypt_bookmarks()) - encrypted_types.insert(BOOKMARKS); - if (nigori.encrypt_preferences()) - encrypted_types.insert(PREFERENCES); - if (nigori.encrypt_autofill_profile()) - encrypted_types.insert(AUTOFILL_PROFILE); - if (nigori.encrypt_autofill()) - encrypted_types.insert(AUTOFILL); - if (nigori.encrypt_themes()) - encrypted_types.insert(THEMES); - if (nigori.encrypt_typed_urls()) - encrypted_types.insert(TYPED_URLS); - if (nigori.encrypt_extensions()) - encrypted_types.insert(EXTENSIONS); - if (nigori.encrypt_sessions()) - encrypted_types.insert(SESSIONS); - if (nigori.encrypt_apps()) - encrypted_types.insert(APPS); - encrypted_types.insert(PASSWORDS); // Always encrypted. - return encrypted_types; -} - void FillNigoriEncryptedTypes(const ModelTypeSet& types, sync_pb::NigoriSpecifics* nigori) { DCHECK(nigori); diff --git a/chrome/browser/sync/syncable/nigori_util.h b/chrome/browser/sync/syncable/nigori_util.h index 3ad8fcd..f427458 100644 --- a/chrome/browser/sync/syncable/nigori_util.h +++ b/chrome/browser/sync/syncable/nigori_util.h @@ -21,15 +21,6 @@ class BaseTransaction; class ReadTransaction; class WriteTransaction; -// Returns the set of datatypes that require encryption as specified by the -// Sync DB's nigori node. This will never include passwords, as the encryption -// status of that is always on if passwords are enabled.. -ModelTypeSet GetEncryptedDataTypes(BaseTransaction* const trans); - -// Extract the set of encrypted datatypes from a nigori node. -ModelTypeSet GetEncryptedDataTypesFromNigori( - const sync_pb::NigoriSpecifics& nigori); - // Set the encrypted datatypes on the nigori node. void FillNigoriEncryptedTypes(const ModelTypeSet& types, sync_pb::NigoriSpecifics* nigori); diff --git a/chrome/browser/sync/syncable/nigori_util_unittest.cc b/chrome/browser/sync/syncable/nigori_util_unittest.cc index 74f1a27..d7d6789 100644 --- a/chrome/browser/sync/syncable/nigori_util_unittest.cc +++ b/chrome/browser/sync/syncable/nigori_util_unittest.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "chrome/browser/sync/util/cryptographer.h" #include "chrome/browser/sync/syncable/nigori_util.h" #include "testing/gtest/include/gtest/gtest.h" @@ -10,25 +11,29 @@ namespace syncable { typedef testing::Test NigoriUtilTest; TEST_F(NigoriUtilTest, NigoriEncryptionTypes) { + browser_sync::Cryptographer cryptographer; sync_pb::NigoriSpecifics nigori; ModelTypeSet encrypted_types; encrypted_types.insert(syncable::PASSWORDS); FillNigoriEncryptedTypes(encrypted_types, &nigori); - ModelTypeSet test_types = GetEncryptedDataTypesFromNigori(nigori); + cryptographer.SetEncryptedTypes(nigori); + ModelTypeSet test_types = cryptographer.GetEncryptedTypes(); EXPECT_EQ(encrypted_types, test_types); for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) { encrypted_types.insert(ModelTypeFromInt(i)); } FillNigoriEncryptedTypes(encrypted_types, &nigori); - test_types = GetEncryptedDataTypesFromNigori(nigori); + cryptographer.SetEncryptedTypes(nigori); + test_types = cryptographer.GetEncryptedTypes(); encrypted_types.erase(syncable::NIGORI); // Should not get set. EXPECT_EQ(encrypted_types, test_types); encrypted_types.erase(syncable::BOOKMARKS); encrypted_types.erase(syncable::SESSIONS); FillNigoriEncryptedTypes(encrypted_types, &nigori); - test_types = GetEncryptedDataTypesFromNigori(nigori); + cryptographer.SetEncryptedTypes(nigori); + test_types = cryptographer.GetEncryptedTypes(); EXPECT_EQ(encrypted_types, test_types); } diff --git a/chrome/browser/sync/test_profile_sync_service.cc b/chrome/browser/sync/test_profile_sync_service.cc index 6397b0c..9c6010a 100644 --- a/chrome/browser/sync/test_profile_sync_service.cc +++ b/chrome/browser/sync/test_profile_sync_service.cc @@ -46,10 +46,11 @@ void SyncBackendHostForProfileSyncTest::ConfigureDataTypes( const DataTypeController::TypeMap& data_type_controllers, const syncable::ModelTypeSet& types, sync_api::ConfigureReason reason, - CancelableTask* ready_task) { + CancelableTask* ready_task, + bool nigori_enabled) { SetAutofillMigrationState(syncable::MIGRATED); SyncBackendHost::ConfigureDataTypes(data_type_controllers, types, - reason, ready_task); + reason, ready_task, nigori_enabled); } void SyncBackendHostForProfileSyncTest:: diff --git a/chrome/browser/sync/test_profile_sync_service.h b/chrome/browser/sync/test_profile_sync_service.h index 4c3e19d..780560c 100644 --- a/chrome/browser/sync/test_profile_sync_service.h +++ b/chrome/browser/sync/test_profile_sync_service.h @@ -47,7 +47,8 @@ class SyncBackendHostForProfileSyncTest const DataTypeController::TypeMap& data_type_controllers, const syncable::ModelTypeSet& types, sync_api::ConfigureReason reason, - CancelableTask* ready_task); + CancelableTask* ready_task, + bool nigori_enabled); // Called when a nudge comes in. void SimulateSyncCycleCompletedInitialSyncEnded( diff --git a/chrome/browser/sync/util/cryptographer.cc b/chrome/browser/sync/util/cryptographer.cc index 562da35..01f7eb2 100644 --- a/chrome/browser/sync/util/cryptographer.cc +++ b/chrome/browser/sync/util/cryptographer.cc @@ -17,6 +17,7 @@ const char kNigoriTag[] = "google_chrome_nigori"; const char kNigoriKeyName[] = "nigori-key"; Cryptographer::Cryptographer() : default_nigori_(NULL) { + encrypted_types_.insert(syncable::PASSWORDS); } Cryptographer::~Cryptographer() {} @@ -241,6 +242,48 @@ Nigori* Cryptographer::UnpackBootstrapToken(const std::string& token) const { return nigori.release(); } +Cryptographer::UpdateResult Cryptographer::Update( + const sync_pb::NigoriSpecifics& nigori) { + SetEncryptedTypes(nigori); + if (!nigori.encrypted().blob().empty()) { + if (CanDecrypt(nigori.encrypted())) { + SetKeys(nigori.encrypted()); + return Cryptographer::SUCCESS; + } else { + SetPendingKeys(nigori.encrypted()); + return Cryptographer::NEEDS_PASSPHRASE; + } + } + return Cryptographer::SUCCESS; +} + +void Cryptographer::SetEncryptedTypes(const sync_pb::NigoriSpecifics& nigori) { + encrypted_types_.clear(); + if (nigori.encrypt_bookmarks()) + encrypted_types_.insert(syncable::BOOKMARKS); + if (nigori.encrypt_preferences()) + encrypted_types_.insert(syncable::PREFERENCES); + if (nigori.encrypt_autofill_profile()) + encrypted_types_.insert(syncable::AUTOFILL_PROFILE); + if (nigori.encrypt_autofill()) + encrypted_types_.insert(syncable::AUTOFILL); + if (nigori.encrypt_themes()) + encrypted_types_.insert(syncable::THEMES); + if (nigori.encrypt_typed_urls()) + encrypted_types_.insert(syncable::TYPED_URLS); + if (nigori.encrypt_extensions()) + encrypted_types_.insert(syncable::EXTENSIONS); + if (nigori.encrypt_sessions()) + encrypted_types_.insert(syncable::SESSIONS); + if (nigori.encrypt_apps()) + encrypted_types_.insert(syncable::APPS); + encrypted_types_.insert(syncable::PASSWORDS); +} + +syncable::ModelTypeSet Cryptographer::GetEncryptedTypes() const { + return encrypted_types_; +} + void Cryptographer::InstallKeys(const std::string& default_key_name, const sync_pb::NigoriKeyBag& bag) { int key_size = bag.key_size(); diff --git a/chrome/browser/sync/util/cryptographer.h b/chrome/browser/sync/util/cryptographer.h index 843b928e..050ea64 100644 --- a/chrome/browser/sync/util/cryptographer.h +++ b/chrome/browser/sync/util/cryptographer.h @@ -13,6 +13,7 @@ #include "base/memory/linked_ptr.h" #include "base/memory/scoped_ptr.h" #include "chrome/browser/sync/protocol/nigori_specifics.pb.h" +#include "chrome/browser/sync/syncable/model_type.h" #include "chrome/browser/sync/util/nigori.h" namespace browser_sync { @@ -45,6 +46,14 @@ class Cryptographer { Cryptographer(); ~Cryptographer(); + // When update on cryptographer is called this enum tells if the + // cryptographer was succesfully able to update using the nigori node or if + // it needs a key to decrypt the nigori node. + enum UpdateResult { + SUCCESS, + NEEDS_PASSPHRASE + }; + // |restored_bootstrap_token| can be provided via this method to bootstrap // Cryptographer instance into the ready state (is_ready will be true). // It must be a string that was previously built by the @@ -117,6 +126,10 @@ class Cryptographer { // can't be created (i.e. if this Cryptograhper doesn't have valid keys). bool GetBootstrapToken(std::string* token) const; + UpdateResult Update(const sync_pb::NigoriSpecifics& nigori); + void SetEncryptedTypes(const sync_pb::NigoriSpecifics& nigori); + syncable::ModelTypeSet GetEncryptedTypes() const; + private: FRIEND_TEST_ALL_PREFIXES(CryptographerTest, PackUnpack); typedef std::map<std::string, linked_ptr<const Nigori> > NigoriMap; @@ -139,6 +152,8 @@ class Cryptographer { scoped_ptr<sync_pb::EncryptedData> pending_keys_; + syncable::ModelTypeSet encrypted_types_; + DISALLOW_COPY_AND_ASSIGN(Cryptographer); }; diff --git a/chrome/test/live_sync/live_passwords_sync_test.h b/chrome/test/live_sync/live_passwords_sync_test.h index 56ad495..9d0e621 100644 --- a/chrome/test/live_sync/live_passwords_sync_test.h +++ b/chrome/test/live_sync/live_passwords_sync_test.h @@ -92,7 +92,7 @@ class LivePasswordsSyncTest : public LiveSyncTest { // Creates a test password form with a well known fake signon realm used only // by LivePasswordsSyncTest based on |index|. - webkit_glue::PasswordForm CreateTestPasswordForm(int index); + static webkit_glue::PasswordForm CreateTestPasswordForm(int index); private: // Cleans up all password forms ever added by LivePasswordsSyncTest. This is diff --git a/chrome/test/live_sync/migration_errors_test.cc b/chrome/test/live_sync/migration_errors_test.cc index db765e3..e0af843 100644 --- a/chrome/test/live_sync/migration_errors_test.cc +++ b/chrome/test/live_sync/migration_errors_test.cc @@ -193,7 +193,7 @@ IN_PROC_BROWSER_TEST_F(MigrationErrorsTest, MigrationHellWithoutNigori) { // Fails because the client doesn't know how to not sync NIGORI. // TODO(timsteele): Fix http://crbug.com/80333 and re-enable. IN_PROC_BROWSER_TEST_F(TwoClientLivePreferencesSyncTest, - DISABLED_MigrationHellWithNigori) { + MigrationHellWithNigori) { if (!ServerSupportsErrorTriggering()) { LOG(WARNING) << "Test skipped in this server environment."; return; @@ -222,6 +222,10 @@ IN_PROC_BROWSER_TEST_F(TwoClientLivePreferencesSyncTest, TriggerMigrationDoneError(migrate_themes); for (int i = syncable::FIRST_REAL_MODEL_TYPE; i < syncable::MODEL_TYPE_COUNT; ++i) { + // TODO(lipalani): If all types are disabled syncer freaks out. Fix it. + if (i == syncable::BOOKMARKS) { + continue; + } syncable::ModelTypeSet migrate_types; migrate_types.insert(syncable::ModelTypeFromInt(i)); TriggerMigrationDoneError(migrate_types); |