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

Unified Diff: chrome/browser/sync/glue/password_change_processor.cc

Issue 1851004: Adding sync support for Passwords (Closed)
Patch Set: Ready for checkin Created 10 years, 7 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
Index: chrome/browser/sync/glue/password_change_processor.cc
diff --git a/chrome/browser/sync/glue/password_change_processor.cc b/chrome/browser/sync/glue/password_change_processor.cc
new file mode 100644
index 0000000000000000000000000000000000000000..57a377de88c4739705492d06c4aa2f6b00d57d96
--- /dev/null
+++ b/chrome/browser/sync/glue/password_change_processor.cc
@@ -0,0 +1,213 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/sync/glue/password_change_processor.h"
+
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/password_manager/password_store.h"
+#include "chrome/browser/password_manager/password_store_change.h"
+#include "chrome/browser/profile.h"
+#include "chrome/browser/sync/glue/password_model_associator.h"
+#include "chrome/browser/sync/profile_sync_service.h"
+#include "chrome/browser/sync/protocol/password_specifics.pb.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/notification_type.h"
+#include "webkit/glue/password_form.h"
+
+namespace browser_sync {
+
+PasswordChangeProcessor::PasswordChangeProcessor(
+ PasswordModelAssociator* model_associator,
+ PasswordStore* password_store,
+ UnrecoverableErrorHandler* error_handler)
+ : ChangeProcessor(error_handler),
+ model_associator_(model_associator),
+ password_store_(password_store),
+ observing_(false),
+ expected_loop_(MessageLoop::current()) {
+ DCHECK(model_associator);
+ DCHECK(error_handler);
+#if defined(OS_MACOSX)
+ DCHECK(!ChromeThread::CurrentlyOn(ChromeThread::UI));
+#else
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB));
+#endif
+ StartObserving();
+}
+
+PasswordChangeProcessor::~PasswordChangeProcessor() {
+ DCHECK(expected_loop_ == MessageLoop::current());
+}
+
+void PasswordChangeProcessor::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ DCHECK(expected_loop_ == MessageLoop::current());
+ DCHECK(NotificationType::LOGINS_CHANGED == type);
+ if (!observing_)
+ return;
+
+ DCHECK(running());
+
+ sync_api::WriteTransaction trans(share_handle());
+
+ sync_api::ReadNode password_root(&trans);
+ if (!password_root.InitByTagLookup(kPasswordTag)) {
+ error_handler()->OnUnrecoverableError();
+ LOG(ERROR) << "Server did not create the top-level password node. "
+ << "We might be running against an out-of-date server.";
+ return;
+ }
+
+ PasswordStoreChangeList* changes =
+ Details<PasswordStoreChangeList>(details).ptr();
+ for (PasswordStoreChangeList::iterator change = changes->begin();
+ change != changes->end(); ++change) {
+ std::string tag = PasswordModelAssociator::MakeTag(change->form());
+ switch (change->type()) {
+ case PasswordStoreChange::ADD: {
+ sync_api::WriteNode sync_node(&trans);
+ if (!sync_node.InitUniqueByCreation(syncable::PASSWORD,
+ password_root, tag)) {
+ LOG(ERROR) << "Failed to create password sync node.";
+ error_handler()->OnUnrecoverableError();
+ return;
+ }
+
+ PasswordModelAssociator::WriteToSyncNode(change->form(), &sync_node);
+ model_associator_->Associate(&tag, sync_node.GetId());
+ break;
+ }
+ case PasswordStoreChange::UPDATE: {
+ sync_api::WriteNode sync_node(&trans);
+ int64 sync_id = model_associator_->GetSyncIdFromChromeId(tag);
+ if (sync_api::kInvalidId == sync_id) {
+ LOG(ERROR) << "Unexpected notification for: " << tag;
+ error_handler()->OnUnrecoverableError();
+ return;
+ } else {
+ if (!sync_node.InitByIdLookup(sync_id)) {
+ LOG(ERROR) << "Password node lookup failed.";
+ error_handler()->OnUnrecoverableError();
+ return;
+ }
+ }
+
+ PasswordModelAssociator::WriteToSyncNode(change->form(), &sync_node);
+ break;
+ }
+ case PasswordStoreChange::REMOVE: {
+ sync_api::WriteNode sync_node(&trans);
+ int64 sync_id = model_associator_->GetSyncIdFromChromeId(tag);
+ if (sync_api::kInvalidId == sync_id) {
+ LOG(ERROR) << "Unexpected notification";
+ error_handler()->OnUnrecoverableError();
+ return;
+ } else {
+ if (!sync_node.InitByIdLookup(sync_id)) {
+ LOG(ERROR) << "Password node lookup failed.";
+ error_handler()->OnUnrecoverableError();
+ return;
+ }
+ model_associator_->Disassociate(sync_node.GetId());
+ sync_node.Remove();
+ }
+ break;
+ }
+ }
+ }
+}
+
+void PasswordChangeProcessor::ApplyChangesFromSyncModel(
+ const sync_api::BaseTransaction* trans,
+ const sync_api::SyncManager::ChangeRecord* changes,
+ int change_count) {
+ DCHECK(expected_loop_ == MessageLoop::current());
+ if (!running())
+ return;
+ StopObserving();
+
+ sync_api::ReadNode password_root(trans);
+ if (!password_root.InitByTagLookup(kPasswordTag)) {
+ LOG(ERROR) << "Password root node lookup failed.";
+ error_handler()->OnUnrecoverableError();
+ return;
+ }
+
+ PasswordModelAssociator::PasswordVector new_passwords;
+ PasswordModelAssociator::PasswordVector updated_passwords;
+ PasswordModelAssociator::PasswordVector deleted_passwords;
+
+ for (int i = 0; i < change_count; ++i) {
+
+ sync_api::ReadNode sync_node(trans);
+ if (!sync_node.InitByIdLookup(changes[i].id)) {
+ LOG(ERROR) << "Password node lookup failed.";
+ error_handler()->OnUnrecoverableError();
+ return;
+ }
+
+ // Check that the changed node is a child of the passwords folder.
+ DCHECK(password_root.GetId() == sync_node.GetParentId());
+ DCHECK(syncable::PASSWORD == sync_node.GetModelType());
+
+ sync_pb::PasswordSpecificsData password_data;
+ if (!sync_node.GetPasswordSpecifics(&password_data)) {
+ LOG(ERROR) << "Could not read password specifics";
+ error_handler()->OnUnrecoverableError();
+ return;
+ }
+ webkit_glue::PasswordForm password;
+ PasswordModelAssociator::CopyPassword(password_data,
+ &password);
+
+ if (sync_api::SyncManager::ChangeRecord::ACTION_ADD == changes[i].action) {
+ new_passwords.push_back(password);
+ } else if (sync_api::SyncManager::ChangeRecord::ACTION_DELETE ==
+ changes[i].action) {
+ deleted_passwords.push_back(password);
+ } else {
+ DCHECK(sync_api::SyncManager::ChangeRecord::ACTION_UPDATE ==
+ changes[i].action);
+ updated_passwords.push_back(password);
+ }
+ }
+ if (!model_associator_->WriteToPasswordStore(&new_passwords,
+ &updated_passwords,
+ &deleted_passwords)) {
+ LOG(ERROR) << "Error writing passwords";
+ error_handler()->OnUnrecoverableError();
+ return;
+ }
+
+ StartObserving();
+}
+
+void PasswordChangeProcessor::StartImpl(Profile* profile) {
+ DCHECK(expected_loop_ == MessageLoop::current());
+ observing_ = true;
+}
+
+void PasswordChangeProcessor::StopImpl() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ observing_ = false;
+}
+
+
+void PasswordChangeProcessor::StartObserving() {
+ DCHECK(expected_loop_ == MessageLoop::current());
+ notification_registrar_.Add(this,
+ NotificationType::LOGINS_CHANGED,
+ NotificationService::AllSources());
+}
+
+void PasswordChangeProcessor::StopObserving() {
+ DCHECK(expected_loop_ == MessageLoop::current());
+ notification_registrar_.Remove(this,
+ NotificationType::LOGINS_CHANGED,
+ NotificationService::AllSources());
+}
+
+} // namespace browser_sync
« no previous file with comments | « chrome/browser/sync/glue/password_change_processor.h ('k') | chrome/browser/sync/glue/password_data_type_controller.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698