Index: chrome/browser/sync/engine/syncapi.cc |
=================================================================== |
--- chrome/browser/sync/engine/syncapi.cc (revision 75295) |
+++ chrome/browser/sync/engine/syncapi.cc (working copy) |
@@ -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 @@ |
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 @@ |
} |
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 @@ |
} |
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 @@ |
//////////////////////////////////// |
// 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::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 @@ |
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 @@ |
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 @@ |
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::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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
return transaction_; |
} |
+SyncManager::ExtraChangeRecordData::~ExtraChangeRecordData() {} |
+ |
SyncManager::ChangeRecord::ChangeRecord() |
: id(kInvalidId), action(ACTION_ADD) {} |
@@ -1086,12 +985,9 @@ |
return value; |
} |
-SyncManager::ExtraPasswordChangeRecordData::ExtraPasswordChangeRecordData() {} |
- |
SyncManager::ExtraPasswordChangeRecordData::ExtraPasswordChangeRecordData( |
const sync_pb::PasswordSpecificsData& data) |
- : unencrypted_(data) { |
-} |
+ : unencrypted_(data) {} |
SyncManager::ExtraPasswordChangeRecordData::~ExtraPasswordChangeRecordData() {} |
@@ -1164,9 +1060,6 @@ |
// 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 @@ |
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 @@ |
// 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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
// 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 @@ |
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 @@ |
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 @@ |
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 @@ |
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()) |