Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3133)

Unified Diff: chrome/browser/sync/engine/syncapi.cc

Issue 2828021: Take 2: sync changes to support encryption (Closed)
Patch Set: fix flaky password test under valgrind Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/sync/engine/syncapi.h ('k') | chrome/browser/sync/engine/syncapi_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/sync/engine/syncapi.cc
diff --git a/chrome/browser/sync/engine/syncapi.cc b/chrome/browser/sync/engine/syncapi.cc
index c242d47d1cf92cee8524b6def29d42694fb3e421..e970c81c35156f02e92735ec868ac1400c1a70ca 100644
--- a/chrome/browser/sync/engine/syncapi.cc
+++ b/chrome/browser/sync/engine/syncapi.cc
@@ -40,6 +40,7 @@
#include "chrome/browser/sync/protocol/password_specifics.pb.h"
#include "chrome/browser/sync/protocol/preference_specifics.pb.h"
#include "chrome/browser/sync/protocol/service_constants.h"
+#include "chrome/browser/sync/protocol/sync.pb.h"
#include "chrome/browser/sync/protocol/theme_specifics.pb.h"
#include "chrome/browser/sync/protocol/typed_url_specifics.pb.h"
#include "chrome/browser/sync/sessions/sync_session_context.h"
@@ -64,6 +65,8 @@ using browser_sync::AllStatus;
using browser_sync::AllStatusEvent;
using browser_sync::AuthWatcher;
using browser_sync::AuthWatcherEvent;
+using browser_sync::Cryptographer;
+using browser_sync::KeyParams;
using browser_sync::ModelSafeRoutingInfo;
using browser_sync::ModelSafeWorker;
using browser_sync::ModelSafeWorkerRegistrar;
@@ -71,6 +74,7 @@ using browser_sync::Syncer;
using browser_sync::SyncerEvent;
using browser_sync::SyncerThread;
using browser_sync::UserSettings;
+using browser_sync::kNigoriTag;
using browser_sync::sessions::SyncSessionContext;
using notifier::TalkMediator;
using notifier::TalkMediatorImpl;
@@ -80,6 +84,7 @@ using std::string;
using std::vector;
using syncable::Directory;
using syncable::DirectoryManager;
+using syncable::Entry;
using syncable::SPECIFICS;
typedef GoogleServiceAuthError AuthError;
@@ -174,6 +179,23 @@ std::string BaseNode::GenerateSyncableHash(
return encode_output;
}
+bool BaseNode::DecryptIfNecessary(Entry* entry) {
+ 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)) {
+ const sync_pb::EncryptedData& encrypted =
+ specifics.GetExtension(sync_pb::password).encrypted();
+ scoped_ptr<sync_pb::PasswordSpecificsData> data(
+ new sync_pb::PasswordSpecificsData);
+ if (!GetTransaction()->GetCryptographer()->Decrypt(encrypted,
+ data.get()))
+ return false;
+ password_data_.swap(data);
+ }
+ return true;
+}
+
int64 BaseNode::GetParentId() const {
return IdToMetahandle(GetTransaction()->GetWrappedTrans(),
GetEntry()->Get(syncable::PARENT_ID));
@@ -249,13 +271,10 @@ const sync_pb::NigoriSpecifics& BaseNode::GetNigoriSpecifics() const {
return GetEntry()->Get(SPECIFICS).GetExtension(sync_pb::nigori);
}
-bool BaseNode::GetPasswordSpecifics(sync_pb::PasswordSpecificsData* data)
- const {
+const sync_pb::PasswordSpecificsData& BaseNode::GetPasswordSpecifics() const {
DCHECK(GetModelType() == syncable::PASSWORDS);
- DCHECK(data);
- const sync_pb::PasswordSpecifics& specifics =
- GetEntry()->Get(SPECIFICS).GetExtension(sync_pb::password);
- return data->ParseFromString(specifics.blob());
+ DCHECK(password_data_.get());
+ return *password_data_;
}
const sync_pb::PreferenceSpecifics& BaseNode::GetPreferenceSpecifics() const {
@@ -356,7 +375,11 @@ void WriteNode::SetPasswordSpecifics(
std::string serialized_data;
data.SerializeToString(&serialized_data);
sync_pb::PasswordSpecifics new_value;
- new_value.set_blob(serialized_data);
+ if (!GetTransaction()->GetCryptographer()->Encrypt(
+ data,
+ new_value.mutable_encrypted()))
+ NOTREACHED();
+
PutPasswordSpecificsAndMarkForSyncing(new_value);
}
@@ -451,7 +474,8 @@ bool WriteNode::InitByIdLookup(int64 id) {
DCHECK_NE(id, kInvalidId);
entry_ = new syncable::MutableEntry(transaction_->GetWrappedWriteTrans(),
syncable::GET_BY_HANDLE, id);
- return (entry_->good() && !entry_->Get(syncable::IS_DEL));
+ return (entry_->good() && !entry_->Get(syncable::IS_DEL) &&
+ DecryptIfNecessary(entry_));
}
// Find a node by client tag, and bind this WriteNode to it.
@@ -467,7 +491,8 @@ bool WriteNode::InitByClientTagLookup(syncable::ModelType model_type,
entry_ = new syncable::MutableEntry(transaction_->GetWrappedWriteTrans(),
syncable::GET_BY_CLIENT_TAG, hash);
- return (entry_->good() && !entry_->Get(syncable::IS_DEL));
+ return (entry_->good() && !entry_->Get(syncable::IS_DEL) &&
+ DecryptIfNecessary(entry_));
}
bool WriteNode::InitByTagLookup(const std::string& tag) {
@@ -703,7 +728,7 @@ bool ReadNode::InitByIdLookup(int64 id) {
LOG_IF(WARNING, model_type == syncable::UNSPECIFIED ||
model_type == syncable::TOP_LEVEL_FOLDER)
<< "SyncAPI InitByIdLookup referencing unusual object.";
- return true;
+ return DecryptIfNecessary(entry_);
}
bool ReadNode::InitByClientTagLookup(syncable::ModelType model_type,
@@ -716,7 +741,8 @@ bool ReadNode::InitByClientTagLookup(syncable::ModelType model_type,
entry_ = new syncable::Entry(transaction_->GetWrappedTrans(),
syncable::GET_BY_CLIENT_TAG, hash);
- return (entry_->good() && !entry_->Get(syncable::IS_DEL));
+ return (entry_->good() && !entry_->Get(syncable::IS_DEL) &&
+ DecryptIfNecessary(entry_));
}
const syncable::Entry* ReadNode::GetEntry() const {
@@ -741,7 +767,7 @@ bool ReadNode::InitByTagLookup(const std::string& tag) {
LOG_IF(WARNING, model_type == syncable::UNSPECIFIED ||
model_type == syncable::TOP_LEVEL_FOLDER)
<< "SyncAPI InitByTagLookup referencing unusually typed object.";
- return true;
+ return DecryptIfNecessary(entry_);
}
//////////////////////////////////////////////////////////////////////////
@@ -891,6 +917,8 @@ class SyncManager::SyncInternal
// Tell the sync engine to start the syncing process.
void StartSyncing();
+ void SetPassphrase(const std::string& passphrase);
+
// Call periodically from a database-safe thread to persist recent changes
// to the syncapi model.
void SaveChanges();
@@ -1215,6 +1243,10 @@ void SyncManager::StartSyncing() {
data_->StartSyncing();
}
+void SyncManager::SetPassphrase(const std::string& passphrase) {
+ data_->SetPassphrase(passphrase);
+}
+
bool SyncManager::RequestPause() {
return data_->syncer_thread()->RequestPause();
}
@@ -1482,6 +1514,25 @@ void SyncManager::SyncInternal::RaiseAuthNeededEvent() {
observer_->OnAuthError(AuthError(auth_problem_));
}
+void SyncManager::SyncInternal::SetPassphrase(
+ const std::string& passphrase) {
+ Cryptographer* cryptographer = dir_manager()->cryptographer();
+ KeyParams params = {"localhost", "dummy", passphrase};
+ if (cryptographer->has_pending_keys()) {
+ if (!cryptographer->DecryptPendingKeys(params)) {
+ observer_->OnPassphraseRequired();
+ return;
+ }
+ // Nudge the syncer so that passwords updates that were waiting for this
+ // passphrase get applied as soon as possible.
+ sync_manager_->RequestNudge();
+ } else {
+ cryptographer->AddKey(params);
+ // TODO(albertb): Update the Nigori node on the server with the new keys.
+ }
+ observer_->OnPassphraseAccepted();
+}
+
SyncManager::~SyncManager() {
delete data_;
}
@@ -1767,7 +1818,6 @@ void SyncManager::SyncInternal::HandleChannelEvent(const SyncerEvent& event) {
// download; if so, we should signal that initialization is complete.
if (event.snapshot->is_share_usable)
MarkAndNotifyInitializationComplete();
- return;
}
if (!observer_)
@@ -1781,6 +1831,38 @@ void SyncManager::SyncInternal::HandleChannelEvent(const SyncerEvent& event) {
// Notifications are sent at the end of every sync cycle, regardless of
// whether we should sync again.
if (event.what_happened == SyncerEvent::SYNC_CYCLE_ENDED) {
+
+ ModelSafeRoutingInfo enabled_types;
+ registrar_->GetModelSafeRoutingInfo(&enabled_types);
+ 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)) {
+ NOTREACHED();
+ return;
+ }
+ 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());
+ }
+ }
+ }
+ // If we've completed a sync cycle and the cryptographer isn't ready yet,
+ // prompt the user for a passphrase.
+ if (!cryptographer->is_ready()) {
+ observer_->OnPassphraseRequired();
+ }
+ }
+
+ if (!initialized())
+ return;
+
if (!event.snapshot->has_more_to_sync) {
observer_->OnSyncCycleCompleted(event.snapshot);
}
@@ -2026,7 +2108,8 @@ BaseTransaction::BaseTransaction(UserShare* share)
: lookup_(NULL) {
DCHECK(share && share->dir_manager.get());
lookup_ = new syncable::ScopedDirLookup(share->dir_manager.get(),
- share->authenticated_name);
+ share->authenticated_name);
+ cryptographer_ = share->dir_manager->cryptographer();
if (!(lookup_->good()))
DCHECK(false) << "ScopedDirLookup failed on valid DirManager.";
}
« no previous file with comments | « chrome/browser/sync/engine/syncapi.h ('k') | chrome/browser/sync/engine/syncapi_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698