diff options
Diffstat (limited to 'chrome/browser/sync/engine/syncapi.cc')
-rw-r--r-- | chrome/browser/sync/engine/syncapi.cc | 458 |
1 files changed, 107 insertions, 351 deletions
diff --git a/chrome/browser/sync/engine/syncapi.cc b/chrome/browser/sync/engine/syncapi.cc index a90b658..018c5cf 100644 --- a/chrome/browser/sync/engine/syncapi.cc +++ b/chrome/browser/sync/engine/syncapi.cc @@ -4,11 +4,9 @@ #include "chrome/browser/sync/engine/syncapi.h" -#include <algorithm> #include <bitset> #include <iomanip> #include <list> -#include <queue> #include <string> #include <vector> @@ -54,7 +52,6 @@ #include "chrome/browser/sync/sessions/sync_session_context.h" #include "chrome/browser/sync/syncable/autofill_migration.h" #include "chrome/browser/sync/syncable/directory_manager.h" -#include "chrome/browser/sync/syncable/nigori_util.h" #include "chrome/browser/sync/syncable/syncable.h" #include "chrome/browser/sync/util/crypto_helpers.h" #include "chrome/common/deprecated/event_sys.h" @@ -195,11 +192,8 @@ sync_pb::PasswordSpecificsData* DecryptPasswordSpecifics( const sync_pb::EntitySpecifics& specifics, Cryptographer* crypto) { if (!specifics.HasExtension(sync_pb::password)) return NULL; - const sync_pb::PasswordSpecifics& password_specifics = - specifics.GetExtension(sync_pb::password); - if (!password_specifics.has_encrypted()) - return NULL; - const sync_pb::EncryptedData& encrypted = password_specifics.encrypted(); + const sync_pb::EncryptedData& encrypted = + specifics.GetExtension(sync_pb::password).encrypted(); scoped_ptr<sync_pb::PasswordSpecificsData> data( new sync_pb::PasswordSpecificsData); if (!crypto->Decrypt(encrypted, data.get())) @@ -208,51 +202,19 @@ sync_pb::PasswordSpecificsData* DecryptPasswordSpecifics( } bool BaseNode::DecryptIfNecessary(Entry* entry) { - if (GetIsFolder()) return true; // Ignore the top-level datatype folder. + if (GetIsFolder()) return true; // Ignore the top-level password folder. const sync_pb::EntitySpecifics& specifics = entry->Get(syncable::SPECIFICS); if (specifics.HasExtension(sync_pb::password)) { - // Passwords have their own legacy encryption structure. scoped_ptr<sync_pb::PasswordSpecificsData> data(DecryptPasswordSpecifics( specifics, GetTransaction()->GetCryptographer())); if (!data.get()) return false; password_data_.swap(data); - return true; - } - - // We assume any node with the encrypted field set has encrypted data. - if (!specifics.has_encrypted()) - return true; - - const sync_pb::EncryptedData& encrypted = - specifics.encrypted(); - std::string plaintext_data = GetTransaction()->GetCryptographer()-> - DecryptToString(encrypted); - if (plaintext_data.length() == 0) - return false; - if (!unencrypted_data_.ParseFromString(plaintext_data)) { - LOG(ERROR) << "Failed to decrypt encrypted node of type " << - syncable::ModelTypeToString(entry->GetModelType()) << "."; - return false; } return true; } -const sync_pb::EntitySpecifics& BaseNode::GetUnencryptedSpecifics( - const syncable::Entry* entry) const { - const sync_pb::EntitySpecifics& specifics = entry->Get(SPECIFICS); - if (specifics.has_encrypted()) { - DCHECK(syncable::GetModelTypeFromSpecifics(unencrypted_data_) != - syncable::UNSPECIFIED); - return unencrypted_data_; - } else { - DCHECK(syncable::GetModelTypeFromSpecifics(unencrypted_data_) == - syncable::UNSPECIFIED); - return specifics; - } -} - int64 BaseNode::GetParentId() const { return IdToMetahandle(GetTransaction()->GetWrappedTrans(), GetEntry()->Get(syncable::PARENT_ID)); @@ -354,79 +316,59 @@ int64 BaseNode::GetExternalId() const { } const sync_pb::AppSpecifics& BaseNode::GetAppSpecifics() const { - DCHECK_EQ(syncable::APPS, GetModelType()); - const sync_pb::EntitySpecifics& unencrypted = - GetUnencryptedSpecifics(GetEntry()); - return unencrypted.GetExtension(sync_pb::app); + DCHECK(GetModelType() == syncable::APPS); + return GetEntry()->Get(SPECIFICS).GetExtension(sync_pb::app); } const sync_pb::AutofillSpecifics& BaseNode::GetAutofillSpecifics() const { - DCHECK_EQ(syncable::AUTOFILL, GetModelType()); - const sync_pb::EntitySpecifics& unencrypted = - GetUnencryptedSpecifics(GetEntry()); - return unencrypted.GetExtension(sync_pb::autofill); + DCHECK(GetModelType() == syncable::AUTOFILL); + return GetEntry()->Get(SPECIFICS).GetExtension(sync_pb::autofill); } const AutofillProfileSpecifics& BaseNode::GetAutofillProfileSpecifics() const { DCHECK_EQ(GetModelType(), syncable::AUTOFILL_PROFILE); - const sync_pb::EntitySpecifics& unencrypted = - GetUnencryptedSpecifics(GetEntry()); - return unencrypted.GetExtension(sync_pb::autofill_profile); + return GetEntry()->Get(SPECIFICS).GetExtension(sync_pb::autofill_profile); } const sync_pb::BookmarkSpecifics& BaseNode::GetBookmarkSpecifics() const { - DCHECK_EQ(syncable::BOOKMARKS, GetModelType()); - const sync_pb::EntitySpecifics& unencrypted = - GetUnencryptedSpecifics(GetEntry()); - return unencrypted.GetExtension(sync_pb::bookmark); + DCHECK(GetModelType() == syncable::BOOKMARKS); + return GetEntry()->Get(SPECIFICS).GetExtension(sync_pb::bookmark); } const sync_pb::NigoriSpecifics& BaseNode::GetNigoriSpecifics() const { - DCHECK_EQ(syncable::NIGORI, GetModelType()); - const sync_pb::EntitySpecifics& unencrypted = - GetUnencryptedSpecifics(GetEntry()); - return unencrypted.GetExtension(sync_pb::nigori); + DCHECK(GetModelType() == syncable::NIGORI); + return GetEntry()->Get(SPECIFICS).GetExtension(sync_pb::nigori); } const sync_pb::PasswordSpecificsData& BaseNode::GetPasswordSpecifics() const { - DCHECK_EQ(syncable::PASSWORDS, GetModelType()); + DCHECK(GetModelType() == syncable::PASSWORDS); DCHECK(password_data_.get()); return *password_data_; } const sync_pb::PreferenceSpecifics& BaseNode::GetPreferenceSpecifics() const { - DCHECK_EQ(syncable::PREFERENCES, GetModelType()); - const sync_pb::EntitySpecifics& unencrypted = - GetUnencryptedSpecifics(GetEntry()); - return unencrypted.GetExtension(sync_pb::preference); + DCHECK(GetModelType() == syncable::PREFERENCES); + return GetEntry()->Get(SPECIFICS).GetExtension(sync_pb::preference); } const sync_pb::ThemeSpecifics& BaseNode::GetThemeSpecifics() const { - DCHECK_EQ(syncable::THEMES, GetModelType()); - const sync_pb::EntitySpecifics& unencrypted = - GetUnencryptedSpecifics(GetEntry()); - return unencrypted.GetExtension(sync_pb::theme); + DCHECK(GetModelType() == syncable::THEMES); + return GetEntry()->Get(SPECIFICS).GetExtension(sync_pb::theme); } const sync_pb::TypedUrlSpecifics& BaseNode::GetTypedUrlSpecifics() const { - DCHECK_EQ(syncable::TYPED_URLS, GetModelType()); - const sync_pb::EntitySpecifics& unencrypted = - GetUnencryptedSpecifics(GetEntry()); - return unencrypted.GetExtension(sync_pb::typed_url); + DCHECK(GetModelType() == syncable::TYPED_URLS); + return GetEntry()->Get(SPECIFICS).GetExtension(sync_pb::typed_url); } const sync_pb::ExtensionSpecifics& BaseNode::GetExtensionSpecifics() const { - DCHECK_EQ(syncable::EXTENSIONS, GetModelType()); - const sync_pb::EntitySpecifics& unencrypted = - GetUnencryptedSpecifics(GetEntry()); - return unencrypted.GetExtension(sync_pb::extension); + DCHECK(GetModelType() == syncable::EXTENSIONS); + return GetEntry()->Get(SPECIFICS).GetExtension(sync_pb::extension); } const sync_pb::SessionSpecifics& BaseNode::GetSessionSpecifics() const { - DCHECK_EQ(syncable::SESSIONS, GetModelType()); - const sync_pb::EntitySpecifics& unencrypted = - GetUnencryptedSpecifics(GetEntry()); - return unencrypted.GetExtension(sync_pb::session); + DCHECK(GetModelType() == syncable::SESSIONS); + return GetEntry()->Get(SPECIFICS).GetExtension(sync_pb::session); } syncable::ModelType BaseNode::GetModelType() const { @@ -435,40 +377,6 @@ syncable::ModelType BaseNode::GetModelType() const { //////////////////////////////////// // WriteNode member definitions -void WriteNode::EncryptIfNecessary(sync_pb::EntitySpecifics* unencrypted) { - syncable::ModelType type = syncable::GetModelTypeFromSpecifics(*unencrypted); - DCHECK_NE(type, syncable::UNSPECIFIED); - DCHECK_NE(type, syncable::PASSWORDS); // Passwords use their own encryption. - DCHECK_NE(type, syncable::NIGORI); // Nigori is encrypted separately. - - syncable::ModelTypeSet encrypted_types = - GetEncryptedDataTypes(GetTransaction()->GetWrappedTrans()); - if (encrypted_types.count(type) == 0) { - // This datatype does not require encryption. - return; - } - - if (unencrypted->has_encrypted()) { - // This specifics is already encrypted, our work is done. - LOG(WARNING) << "Attempted to encrypt an already encrypted entity" - << " specifics of type " << syncable::ModelTypeToString(type) - << ". Dropping."; - return; - } - sync_pb::EntitySpecifics encrypted; - syncable::AddDefaultExtensionValue(type, &encrypted); - VLOG(2) << "Encrypted specifics of type " << syncable::ModelTypeToString(type) - << " with content: " << unencrypted->SerializeAsString() << "\n"; - if (!GetTransaction()->GetCryptographer()->Encrypt( - *unencrypted, - encrypted.mutable_encrypted())) { - LOG(ERROR) << "Could not encrypt data for node of type " << - syncable::ModelTypeToString(type); - NOTREACHED(); - } - unencrypted->CopyFrom(encrypted); -} - void WriteNode::SetIsFolder(bool folder) { if (entry_->Get(syncable::IS_DIR) == folder) return; // Skip redundant changes. @@ -498,13 +406,13 @@ void WriteNode::SetURL(const GURL& url) { void WriteNode::SetAppSpecifics( const sync_pb::AppSpecifics& new_value) { - DCHECK_EQ(syncable::APPS, GetModelType()); + DCHECK(GetModelType() == syncable::APPS); PutAppSpecificsAndMarkForSyncing(new_value); } void WriteNode::SetAutofillSpecifics( const sync_pb::AutofillSpecifics& new_value) { - DCHECK_EQ(syncable::AUTOFILL, GetModelType()); + DCHECK(GetModelType() == syncable::AUTOFILL); PutAutofillSpecificsAndMarkForSyncing(new_value); } @@ -512,7 +420,6 @@ void WriteNode::PutAutofillSpecificsAndMarkForSyncing( const sync_pb::AutofillSpecifics& new_value) { sync_pb::EntitySpecifics entity_specifics; entity_specifics.MutableExtension(sync_pb::autofill)->CopyFrom(new_value); - EncryptIfNecessary(&entity_specifics); PutSpecificsAndMarkForSyncing(entity_specifics); } @@ -527,13 +434,12 @@ void WriteNode::PutAutofillProfileSpecificsAndMarkForSyncing( sync_pb::EntitySpecifics entity_specifics; entity_specifics.MutableExtension(sync_pb::autofill_profile)->CopyFrom( new_value); - EncryptIfNecessary(&entity_specifics); PutSpecificsAndMarkForSyncing(entity_specifics); } void WriteNode::SetBookmarkSpecifics( const sync_pb::BookmarkSpecifics& new_value) { - DCHECK_EQ(syncable::BOOKMARKS, GetModelType()); + DCHECK(GetModelType() == syncable::BOOKMARKS); PutBookmarkSpecificsAndMarkForSyncing(new_value); } @@ -541,13 +447,12 @@ void WriteNode::PutBookmarkSpecificsAndMarkForSyncing( const sync_pb::BookmarkSpecifics& new_value) { sync_pb::EntitySpecifics entity_specifics; entity_specifics.MutableExtension(sync_pb::bookmark)->CopyFrom(new_value); - EncryptIfNecessary(&entity_specifics); PutSpecificsAndMarkForSyncing(entity_specifics); } void WriteNode::SetNigoriSpecifics( const sync_pb::NigoriSpecifics& new_value) { - DCHECK_EQ(syncable::NIGORI, GetModelType()); + DCHECK(GetModelType() == syncable::NIGORI); PutNigoriSpecificsAndMarkForSyncing(new_value); } @@ -560,40 +465,36 @@ void WriteNode::PutNigoriSpecificsAndMarkForSyncing( void WriteNode::SetPasswordSpecifics( const sync_pb::PasswordSpecificsData& data) { - DCHECK_EQ(syncable::PASSWORDS, GetModelType()); + DCHECK(GetModelType() == syncable::PASSWORDS); + sync_pb::PasswordSpecifics new_value; if (!GetTransaction()->GetCryptographer()->Encrypt( data, new_value.mutable_encrypted())) { NOTREACHED(); } + PutPasswordSpecificsAndMarkForSyncing(new_value); } void WriteNode::SetPreferenceSpecifics( const sync_pb::PreferenceSpecifics& new_value) { - DCHECK_EQ(syncable::PREFERENCES, GetModelType()); + DCHECK(GetModelType() == syncable::PREFERENCES); PutPreferenceSpecificsAndMarkForSyncing(new_value); } void WriteNode::SetThemeSpecifics( const sync_pb::ThemeSpecifics& new_value) { - DCHECK_EQ(syncable::THEMES, GetModelType()); + DCHECK(GetModelType() == syncable::THEMES); PutThemeSpecificsAndMarkForSyncing(new_value); } void WriteNode::SetSessionSpecifics( const sync_pb::SessionSpecifics& new_value) { - DCHECK_EQ(syncable::SESSIONS, GetModelType()); + DCHECK(GetModelType() == syncable::SESSIONS); PutSessionSpecificsAndMarkForSyncing(new_value); } -void WriteNode::ResetFromSpecifics() { - sync_pb::EntitySpecifics new_data; - new_data.CopyFrom(GetUnencryptedSpecifics(GetEntry())); - EncryptIfNecessary(&new_data); - PutSpecificsAndMarkForSyncing(new_data); -} void WriteNode::PutPasswordSpecificsAndMarkForSyncing( const sync_pb::PasswordSpecifics& new_value) { @@ -606,19 +507,18 @@ void WriteNode::PutPreferenceSpecificsAndMarkForSyncing( const sync_pb::PreferenceSpecifics& new_value) { sync_pb::EntitySpecifics entity_specifics; entity_specifics.MutableExtension(sync_pb::preference)->CopyFrom(new_value); - EncryptIfNecessary(&entity_specifics); PutSpecificsAndMarkForSyncing(entity_specifics); } void WriteNode::SetTypedUrlSpecifics( const sync_pb::TypedUrlSpecifics& new_value) { - DCHECK_EQ(syncable::TYPED_URLS, GetModelType()); + DCHECK(GetModelType() == syncable::TYPED_URLS); PutTypedUrlSpecificsAndMarkForSyncing(new_value); } void WriteNode::SetExtensionSpecifics( const sync_pb::ExtensionSpecifics& new_value) { - DCHECK_EQ(syncable::EXTENSIONS, GetModelType()); + DCHECK(GetModelType() == syncable::EXTENSIONS); PutExtensionSpecificsAndMarkForSyncing(new_value); } @@ -626,7 +526,6 @@ void WriteNode::PutAppSpecificsAndMarkForSyncing( const sync_pb::AppSpecifics& new_value) { sync_pb::EntitySpecifics entity_specifics; entity_specifics.MutableExtension(sync_pb::app)->CopyFrom(new_value); - EncryptIfNecessary(&entity_specifics); PutSpecificsAndMarkForSyncing(entity_specifics); } @@ -634,7 +533,6 @@ void WriteNode::PutThemeSpecificsAndMarkForSyncing( const sync_pb::ThemeSpecifics& new_value) { sync_pb::EntitySpecifics entity_specifics; entity_specifics.MutableExtension(sync_pb::theme)->CopyFrom(new_value); - EncryptIfNecessary(&entity_specifics); PutSpecificsAndMarkForSyncing(entity_specifics); } @@ -642,7 +540,6 @@ void WriteNode::PutTypedUrlSpecificsAndMarkForSyncing( const sync_pb::TypedUrlSpecifics& new_value) { sync_pb::EntitySpecifics entity_specifics; entity_specifics.MutableExtension(sync_pb::typed_url)->CopyFrom(new_value); - EncryptIfNecessary(&entity_specifics); PutSpecificsAndMarkForSyncing(entity_specifics); } @@ -650,18 +547,18 @@ void WriteNode::PutExtensionSpecificsAndMarkForSyncing( const sync_pb::ExtensionSpecifics& new_value) { sync_pb::EntitySpecifics entity_specifics; entity_specifics.MutableExtension(sync_pb::extension)->CopyFrom(new_value); - EncryptIfNecessary(&entity_specifics); PutSpecificsAndMarkForSyncing(entity_specifics); } + void WriteNode::PutSessionSpecificsAndMarkForSyncing( const sync_pb::SessionSpecifics& new_value) { sync_pb::EntitySpecifics entity_specifics; entity_specifics.MutableExtension(sync_pb::session)->CopyFrom(new_value); - EncryptIfNecessary(&entity_specifics); PutSpecificsAndMarkForSyncing(entity_specifics); } + void WriteNode::PutSpecificsAndMarkForSyncing( const sync_pb::EntitySpecifics& specifics) { // Skip redundant changes. @@ -726,7 +623,7 @@ bool WriteNode::InitByTagLookup(const std::string& tag) { if (entry_->Get(syncable::IS_DEL)) return false; syncable::ModelType model_type = GetModelType(); - DCHECK_EQ(syncable::NIGORI, model_type); + DCHECK(model_type == syncable::NIGORI); return true; } @@ -739,7 +636,7 @@ void WriteNode::PutModelType(syncable::ModelType model_type) { sync_pb::EntitySpecifics specifics; syncable::AddDefaultExtensionValue(model_type, &specifics); PutSpecificsAndMarkForSyncing(specifics); - DCHECK_EQ(model_type, GetModelType()); + DCHECK(GetModelType() == model_type); } // Create a new node with default properties, and bind this WriteNode to it. @@ -1037,6 +934,8 @@ syncable::BaseTransaction* WriteTransaction::GetWrappedTrans() const { return transaction_; } +SyncManager::ExtraChangeRecordData::~ExtraChangeRecordData() {} + SyncManager::ChangeRecord::ChangeRecord() : id(kInvalidId), action(ACTION_ADD) {} @@ -1086,12 +985,9 @@ DictionaryValue* SyncManager::ChangeRecord::ToValue( return value; } -SyncManager::ExtraPasswordChangeRecordData::ExtraPasswordChangeRecordData() {} - SyncManager::ExtraPasswordChangeRecordData::ExtraPasswordChangeRecordData( const sync_pb::PasswordSpecificsData& data) - : unencrypted_(data) { -} + : unencrypted_(data) {} SyncManager::ExtraPasswordChangeRecordData::~ExtraPasswordChangeRecordData() {} @@ -1164,9 +1060,6 @@ class SyncManager::SyncInternal // Whether or not the Nigori node is encrypted using an explicit passphrase. bool IsUsingExplicitPassphrase(); - // Set the datatypes we want to encrypt and encrypt any nodes as necessary. - void EncryptDataTypes(const syncable::ModelTypeSet& encrypted_types); - // Try to set the current passphrase to |passphrase|, and record whether // it is an explicit passphrase or implicitly using gaia in the Nigori // node. @@ -1242,9 +1135,6 @@ class SyncManager::SyncInternal return initialized_; } - // If this is a deletion for a password, sets the legacy - // ExtraPasswordChangeRecordData field of |buffer|. Otherwise sets - // |buffer|'s specifics field to contain the unencrypted data. void SetExtraChangeRecordData(int64 id, syncable::ModelType type, ChangeReorderBuffer* buffer, @@ -1370,8 +1260,7 @@ class SyncManager::SyncInternal // differ between the versions of an entry stored in |a| and |b|. A return // value of false means that it should be OK to ignore this change. static bool VisiblePropertiesDiffer(const syncable::EntryKernel& a, - const syncable::Entry& b, - Cryptographer* cryptographer) { + const syncable::Entry& b) { syncable::ModelType model_type = b.GetModelType(); // Suppress updates to items that aren't tracked by any browser model. if (model_type == syncable::UNSPECIFIED || @@ -1382,21 +1271,8 @@ class SyncManager::SyncInternal return true; if (a.ref(syncable::IS_DIR) != b.Get(syncable::IS_DIR)) return true; - // Check if data has changed (account for encryption). - std::string a_str, b_str; - if (a.ref(SPECIFICS).has_encrypted()) { - const sync_pb::EncryptedData& encrypted = a.ref(SPECIFICS).encrypted(); - a_str = cryptographer->DecryptToString(encrypted); - } else { - a_str = a.ref(SPECIFICS).SerializeAsString(); - } - if (b.Get(SPECIFICS).has_encrypted()) { - const sync_pb::EncryptedData& encrypted = b.Get(SPECIFICS).encrypted(); - b_str = cryptographer->DecryptToString(encrypted); - } else { - b_str = b.Get(SPECIFICS).SerializeAsString(); - } - if (a_str != b_str) { + if (a.ref(SPECIFICS).SerializeAsString() != + b.Get(SPECIFICS).SerializeAsString()) { return true; } if (VisiblePositionsDiffer(a, b)) @@ -1601,11 +1477,6 @@ void SyncManager::SetPassphrase(const std::string& passphrase, data_->SetPassphrase(passphrase, is_explicit); } -void SyncManager::EncryptDataTypes( - const syncable::ModelTypeSet& encrypted_types) { - data_->EncryptDataTypes(encrypted_types); -} - bool SyncManager::IsUsingExplicitPassphrase() { return data_ && data_->IsUsingExplicitPassphrase(); } @@ -1711,33 +1582,23 @@ void SyncManager::SyncInternal::BootstrapEncryption( Cryptographer* cryptographer = share_.dir_manager->cryptographer(); cryptographer->Bootstrap(restored_key_for_bootstrapping); - sync_pb::NigoriSpecifics nigori; - { - ReadTransaction trans(GetUserShare()); - ReadNode node(&trans); - if (!node.InitByTagLookup(kNigoriTag)) { - NOTREACHED(); - return; - } + ReadTransaction trans(GetUserShare()); + ReadNode node(&trans); + if (!node.InitByTagLookup(kNigoriTag)) { + NOTREACHED(); + return; + } - 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(true)); - } + const sync_pb::NigoriSpecifics& nigori = 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(true)); } } - - // Refresh list of encrypted datatypes. - syncable::ModelTypeSet encrypted_types = - syncable::GetEncryptedDataTypesFromNigori(nigori); - - // Ensure any datatypes that need encryption are encrypted. - EncryptDataTypes(encrypted_types); } void SyncManager::SyncInternal::StartSyncing() { @@ -1848,7 +1709,7 @@ bool SyncManager::SyncInternal::SignIn(const SyncCredentials& credentials) { void SyncManager::SyncInternal::UpdateCredentials( const SyncCredentials& credentials) { DCHECK_EQ(MessageLoop::current(), core_message_loop_); - DCHECK_EQ(credentials.email, share_.name); + DCHECK(share_.name == credentials.email); connection_manager()->set_auth_token(credentials.sync_token); TalkMediatorLogin(credentials.email, credentials.sync_token); CheckServerReachable(); @@ -1942,8 +1803,8 @@ void SyncManager::SyncInternal::SetPassphrase( if (is_explicit) SetUsingExplicitPassphrasePrefForMigration(); - // Nudge the syncer so that encrypted datatype updates that were waiting for - // this passphrase get applied as soon as possible. + // Nudge the syncer so that passwords updates that were waiting for this + // passphrase get applied as soon as possible. sync_manager_->RequestNudge(); } else { WriteTransaction trans(GetUserShare()); @@ -1965,8 +1826,7 @@ void SyncManager::SyncInternal::SetPassphrase( // messing with the Nigori node, because we can't call SetPassphrase until // download conditions are met vs Cryptographer init. It seems like it's // safe to defer this work. - sync_pb::NigoriSpecifics specifics(node.GetNigoriSpecifics()); - specifics.clear_encrypted(); + sync_pb::NigoriSpecifics specifics; cryptographer->GetKeys(specifics.mutable_encrypted()); specifics.set_using_explicit_passphrase(is_explicit); node.SetNigoriSpecifics(specifics); @@ -1991,109 +1851,28 @@ bool SyncManager::SyncInternal::IsUsingExplicitPassphrase() { return node.GetNigoriSpecifics().using_explicit_passphrase(); } -void SyncManager::SyncInternal::EncryptDataTypes( - const syncable::ModelTypeSet& encrypted_types) { - // Verify the encrypted types are all enabled. - ModelSafeRoutingInfo routes; - registrar_->GetModelSafeRoutingInfo(&routes); - for (syncable::ModelTypeSet::const_iterator iter = encrypted_types.begin(); - iter != encrypted_types.end(); ++iter) { - if (routes.count(*iter) == 0) { - LOG(WARNING) << "Attempted to encrypt non-enabled datatype " - << syncable::ModelTypeToString(*iter) << ", dropping type."; - routes.erase(*iter); - } - } - - WriteTransaction trans(GetUserShare()); - WriteNode node(&trans); - if (!node.InitByTagLookup(kNigoriTag)) { - LOG(ERROR) << "Unable to set encrypted datatypes because Nigori node not " - << "found."; - NOTREACHED(); +void SyncManager::SyncInternal::ReEncryptEverything(WriteTransaction* trans) { + // TODO(tim): bug 59242. We shouldn't lookup by data type and instead use + // a protocol flag or existence of an EncryptedData message, but for now, + // encryption is on if-and-only-if the type is passwords, and we haven't + // ironed out the protocol for generic encryption. + static const char* passwords_tag = "google_chrome_passwords"; + ReadNode passwords_root(trans); + if (!passwords_root.InitByTagLookup(passwords_tag)) { + LOG(WARNING) << "No passwords to reencrypt."; return; } - // Update the Nigori node set of encrypted datatypes so other machines notice. - sync_pb::NigoriSpecifics nigori; - nigori.CopyFrom(node.GetNigoriSpecifics()); - syncable::FillNigoriEncryptedTypes(encrypted_types, &nigori); - node.SetNigoriSpecifics(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). - ReEncryptEverything(&trans); - return; -} - -void SyncManager::SyncInternal::ReEncryptEverything(WriteTransaction* trans) { - syncable::ModelTypeSet encrypted_types = - GetEncryptedDataTypes(trans->GetWrappedTrans()); - ModelSafeRoutingInfo routes; - registrar_->GetModelSafeRoutingInfo(&routes); - std::string tag; - for (syncable::ModelTypeSet::iterator iter = encrypted_types.begin(); - iter != encrypted_types.end(); ++iter) { - if (*iter == syncable::PASSWORDS || routes.count(*iter) == 0) - continue; - ReadNode type_root(trans); - tag = syncable::ModelTypeToRootTag(*iter); - if (!type_root.InitByTagLookup(tag)) { + int64 child_id = passwords_root.GetFirstChildId(); + while (child_id != kInvalidId) { + WriteNode child(trans); + if (!child.InitByIdLookup(child_id)) { NOTREACHED(); return; } - - // Iterate through all children of this datatype. - std::queue<int64> to_visit; - int64 child_id = type_root.GetFirstChildId(); - to_visit.push(child_id); - while (!to_visit.empty()) { - child_id = to_visit.front(); - to_visit.pop(); - if (child_id == kInvalidId) - continue; - - WriteNode child(trans); - if (!child.InitByIdLookup(child_id)) { - NOTREACHED(); - return; - } - if (child.GetIsFolder()) { - to_visit.push(child.GetFirstChildId()); - } else { - // Rewrite the specifics of the node with encrypted data if necessary. - child.ResetFromSpecifics(); - } - to_visit.push(child.GetSuccessorId()); - } + child.SetPasswordSpecifics(child.GetPasswordSpecifics()); + child_id = child.GetSuccessorId(); } - - if (routes.count(syncable::PASSWORDS) > 0) { - // Passwords are encrypted with their own legacy scheme. - encrypted_types.insert(syncable::PASSWORDS); - ReadNode passwords_root(trans); - std::string passwords_tag = - syncable::ModelTypeToRootTag(syncable::PASSWORDS); - if (!passwords_root.InitByTagLookup(passwords_tag)) { - LOG(WARNING) << "No passwords to reencrypt."; - return; - } - - int64 child_id = passwords_root.GetFirstChildId(); - while (child_id != kInvalidId) { - WriteNode child(trans); - if (!child.InitByIdLookup(child_id)) { - NOTREACHED(); - return; - } - child.SetPasswordSpecifics(child.GetPasswordSpecifics()); - child_id = child.GetSuccessorId(); - } - } - - FOR_EACH_OBSERVER(SyncManager::Observer, observers_, - OnEncryptionComplete(encrypted_types)); } SyncManager::~SyncManager() { @@ -2341,29 +2120,20 @@ void SyncManager::SyncInternal::SetExtraChangeRecordData(int64 id, syncable::ModelType type, ChangeReorderBuffer* buffer, Cryptographer* cryptographer, const syncable::EntryKernel& original, bool existed_before, bool exists_now) { - // If this is a deletion and the datatype was encrypted, we need to decrypt it - // and attach it to the buffer. + // If this is a deletion, attach the entity specifics as extra data + // so that the delete can be processed. if (!exists_now && existed_before) { - sync_pb::EntitySpecifics original_specifics(original.ref(SPECIFICS)); + buffer->SetSpecificsForId(id, original.ref(SPECIFICS)); if (type == syncable::PASSWORDS) { - // Passwords must use their own legacy ExtraPasswordChangeRecordData. + // Need to dig a bit deeper as passwords are encrypted. scoped_ptr<sync_pb::PasswordSpecificsData> data( - DecryptPasswordSpecifics(original_specifics, cryptographer)); + DecryptPasswordSpecifics(original.ref(SPECIFICS), cryptographer)); if (!data.get()) { NOTREACHED(); return; } buffer->SetExtraDataForId(id, new ExtraPasswordChangeRecordData(*data)); - } else if (original_specifics.has_encrypted()) { - // All other datatypes can just create a new unencrypted specifics and - // attach it. - const sync_pb::EncryptedData& encrypted = original_specifics.encrypted(); - if (!cryptographer->Decrypt(encrypted, &original_specifics)) { - NOTREACHED(); - return; - } } - buffer->SetSpecificsForId(id, original_specifics); } } @@ -2394,10 +2164,8 @@ void SyncManager::SyncInternal::HandleCalculateChangesChangeEventFromSyncer( change_buffers_[type].PushAddedItem(id); else if (!exists_now && existed_before) change_buffers_[type].PushDeletedItem(id); - else if (exists_now && existed_before && - VisiblePropertiesDiffer(*i, e, dir_manager()->cryptographer())) { + else if (exists_now && existed_before && VisiblePropertiesDiffer(*i, e)) change_buffers_[type].PushUpdatedItem(id, VisiblePositionsDiffer(*i, e)); - } SetExtraChangeRecordData(id, type, &change_buffers_[type], dir_manager()->cryptographer(), *i, @@ -2424,44 +2192,32 @@ void SyncManager::SyncInternal::OnSyncEngineEvent( if (event.what_happened == SyncEngineEvent::SYNC_CYCLE_ENDED) { ModelSafeRoutingInfo enabled_types; registrar_->GetModelSafeRoutingInfo(&enabled_types); - { - // 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); - // If passwords are enabled, they're automatically considered encrypted. - if (enabled_types.count(syncable::PASSWORDS) > 0) - encrypted_types.insert(syncable::PASSWORDS); - if (encrypted_types.size() > 0) { - Cryptographer* cryptographer = - GetUserShare()->dir_manager->cryptographer(); - if (!cryptographer->is_ready() && !cryptographer->has_pending_keys()) { - if (!nigori.encrypted().blob().empty()) { - DCHECK(!cryptographer->CanDecrypt(nigori.encrypted())); - cryptographer->SetPendingKeys(nigori.encrypted()); - } + if (enabled_types.count(syncable::PASSWORDS) > 0) { + Cryptographer* cryptographer = + GetUserShare()->dir_manager->cryptographer(); + if (!cryptographer->is_ready() && !cryptographer->has_pending_keys()) { + sync_api::ReadTransaction trans(GetUserShare()); + sync_api::ReadNode node(&trans); + if (!node.InitByTagLookup(kNigoriTag)) { + DCHECK(!event.snapshot->is_share_usable); + return; } - - // If we've completed a sync cycle and the cryptographer isn't ready - // yet, prompt the user for a passphrase. - if (cryptographer->has_pending_keys()) { - FOR_EACH_OBSERVER(SyncManager::Observer, observers_, - OnPassphraseRequired(true)); - } else if (!cryptographer->is_ready()) { - FOR_EACH_OBSERVER(SyncManager::Observer, observers_, - OnPassphraseRequired(false)); - } else { - FOR_EACH_OBSERVER(SyncManager::Observer, observers_, - OnEncryptionComplete(encrypted_types)); + const sync_pb::NigoriSpecifics& nigori = node.GetNigoriSpecifics(); + if (!nigori.encrypted().blob().empty()) { + DCHECK(!cryptographer->CanDecrypt(nigori.encrypted())); + cryptographer->SetPendingKeys(nigori.encrypted()); } } + + // If we've completed a sync cycle and the cryptographer isn't ready yet, + // prompt the user for a passphrase. + if (cryptographer->has_pending_keys()) { + FOR_EACH_OBSERVER(SyncManager::Observer, observers_, + OnPassphraseRequired(true)); + } else if (!cryptographer->is_ready()) { + FOR_EACH_OBSERVER(SyncManager::Observer, observers_, + OnPassphraseRequired(false)); + } } if (!initialized()) |