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

Side by Side 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/sync/glue/password_change_processor.h"
6
7 #include "base/string_util.h"
8 #include "base/utf_string_conversions.h"
9 #include "chrome/browser/password_manager/password_store.h"
10 #include "chrome/browser/password_manager/password_store_change.h"
11 #include "chrome/browser/profile.h"
12 #include "chrome/browser/sync/glue/password_model_associator.h"
13 #include "chrome/browser/sync/profile_sync_service.h"
14 #include "chrome/browser/sync/protocol/password_specifics.pb.h"
15 #include "chrome/common/notification_service.h"
16 #include "chrome/common/notification_type.h"
17 #include "webkit/glue/password_form.h"
18
19 namespace browser_sync {
20
21 PasswordChangeProcessor::PasswordChangeProcessor(
22 PasswordModelAssociator* model_associator,
23 PasswordStore* password_store,
24 UnrecoverableErrorHandler* error_handler)
25 : ChangeProcessor(error_handler),
26 model_associator_(model_associator),
27 password_store_(password_store),
28 observing_(false),
29 expected_loop_(MessageLoop::current()) {
30 DCHECK(model_associator);
31 DCHECK(error_handler);
32 #if defined(OS_MACOSX)
33 DCHECK(!ChromeThread::CurrentlyOn(ChromeThread::UI));
34 #else
35 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB));
36 #endif
37 StartObserving();
38 }
39
40 PasswordChangeProcessor::~PasswordChangeProcessor() {
41 DCHECK(expected_loop_ == MessageLoop::current());
42 }
43
44 void PasswordChangeProcessor::Observe(NotificationType type,
45 const NotificationSource& source,
46 const NotificationDetails& details) {
47 DCHECK(expected_loop_ == MessageLoop::current());
48 DCHECK(NotificationType::LOGINS_CHANGED == type);
49 if (!observing_)
50 return;
51
52 DCHECK(running());
53
54 sync_api::WriteTransaction trans(share_handle());
55
56 sync_api::ReadNode password_root(&trans);
57 if (!password_root.InitByTagLookup(kPasswordTag)) {
58 error_handler()->OnUnrecoverableError();
59 LOG(ERROR) << "Server did not create the top-level password node. "
60 << "We might be running against an out-of-date server.";
61 return;
62 }
63
64 PasswordStoreChangeList* changes =
65 Details<PasswordStoreChangeList>(details).ptr();
66 for (PasswordStoreChangeList::iterator change = changes->begin();
67 change != changes->end(); ++change) {
68 std::string tag = PasswordModelAssociator::MakeTag(change->form());
69 switch (change->type()) {
70 case PasswordStoreChange::ADD: {
71 sync_api::WriteNode sync_node(&trans);
72 if (!sync_node.InitUniqueByCreation(syncable::PASSWORD,
73 password_root, tag)) {
74 LOG(ERROR) << "Failed to create password sync node.";
75 error_handler()->OnUnrecoverableError();
76 return;
77 }
78
79 PasswordModelAssociator::WriteToSyncNode(change->form(), &sync_node);
80 model_associator_->Associate(&tag, sync_node.GetId());
81 break;
82 }
83 case PasswordStoreChange::UPDATE: {
84 sync_api::WriteNode sync_node(&trans);
85 int64 sync_id = model_associator_->GetSyncIdFromChromeId(tag);
86 if (sync_api::kInvalidId == sync_id) {
87 LOG(ERROR) << "Unexpected notification for: " << tag;
88 error_handler()->OnUnrecoverableError();
89 return;
90 } else {
91 if (!sync_node.InitByIdLookup(sync_id)) {
92 LOG(ERROR) << "Password node lookup failed.";
93 error_handler()->OnUnrecoverableError();
94 return;
95 }
96 }
97
98 PasswordModelAssociator::WriteToSyncNode(change->form(), &sync_node);
99 break;
100 }
101 case PasswordStoreChange::REMOVE: {
102 sync_api::WriteNode sync_node(&trans);
103 int64 sync_id = model_associator_->GetSyncIdFromChromeId(tag);
104 if (sync_api::kInvalidId == sync_id) {
105 LOG(ERROR) << "Unexpected notification";
106 error_handler()->OnUnrecoverableError();
107 return;
108 } else {
109 if (!sync_node.InitByIdLookup(sync_id)) {
110 LOG(ERROR) << "Password node lookup failed.";
111 error_handler()->OnUnrecoverableError();
112 return;
113 }
114 model_associator_->Disassociate(sync_node.GetId());
115 sync_node.Remove();
116 }
117 break;
118 }
119 }
120 }
121 }
122
123 void PasswordChangeProcessor::ApplyChangesFromSyncModel(
124 const sync_api::BaseTransaction* trans,
125 const sync_api::SyncManager::ChangeRecord* changes,
126 int change_count) {
127 DCHECK(expected_loop_ == MessageLoop::current());
128 if (!running())
129 return;
130 StopObserving();
131
132 sync_api::ReadNode password_root(trans);
133 if (!password_root.InitByTagLookup(kPasswordTag)) {
134 LOG(ERROR) << "Password root node lookup failed.";
135 error_handler()->OnUnrecoverableError();
136 return;
137 }
138
139 PasswordModelAssociator::PasswordVector new_passwords;
140 PasswordModelAssociator::PasswordVector updated_passwords;
141 PasswordModelAssociator::PasswordVector deleted_passwords;
142
143 for (int i = 0; i < change_count; ++i) {
144
145 sync_api::ReadNode sync_node(trans);
146 if (!sync_node.InitByIdLookup(changes[i].id)) {
147 LOG(ERROR) << "Password node lookup failed.";
148 error_handler()->OnUnrecoverableError();
149 return;
150 }
151
152 // Check that the changed node is a child of the passwords folder.
153 DCHECK(password_root.GetId() == sync_node.GetParentId());
154 DCHECK(syncable::PASSWORD == sync_node.GetModelType());
155
156 sync_pb::PasswordSpecificsData password_data;
157 if (!sync_node.GetPasswordSpecifics(&password_data)) {
158 LOG(ERROR) << "Could not read password specifics";
159 error_handler()->OnUnrecoverableError();
160 return;
161 }
162 webkit_glue::PasswordForm password;
163 PasswordModelAssociator::CopyPassword(password_data,
164 &password);
165
166 if (sync_api::SyncManager::ChangeRecord::ACTION_ADD == changes[i].action) {
167 new_passwords.push_back(password);
168 } else if (sync_api::SyncManager::ChangeRecord::ACTION_DELETE ==
169 changes[i].action) {
170 deleted_passwords.push_back(password);
171 } else {
172 DCHECK(sync_api::SyncManager::ChangeRecord::ACTION_UPDATE ==
173 changes[i].action);
174 updated_passwords.push_back(password);
175 }
176 }
177 if (!model_associator_->WriteToPasswordStore(&new_passwords,
178 &updated_passwords,
179 &deleted_passwords)) {
180 LOG(ERROR) << "Error writing passwords";
181 error_handler()->OnUnrecoverableError();
182 return;
183 }
184
185 StartObserving();
186 }
187
188 void PasswordChangeProcessor::StartImpl(Profile* profile) {
189 DCHECK(expected_loop_ == MessageLoop::current());
190 observing_ = true;
191 }
192
193 void PasswordChangeProcessor::StopImpl() {
194 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
195 observing_ = false;
196 }
197
198
199 void PasswordChangeProcessor::StartObserving() {
200 DCHECK(expected_loop_ == MessageLoop::current());
201 notification_registrar_.Add(this,
202 NotificationType::LOGINS_CHANGED,
203 NotificationService::AllSources());
204 }
205
206 void PasswordChangeProcessor::StopObserving() {
207 DCHECK(expected_loop_ == MessageLoop::current());
208 notification_registrar_.Remove(this,
209 NotificationType::LOGINS_CHANGED,
210 NotificationService::AllSources());
211 }
212
213 } // namespace browser_sync
OLDNEW
« 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