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

Side by Side Diff: chrome/browser/password_manager/password_syncable_service.cc

Issue 139443004: Password sync refactoring: implemented ProcessSyncChanges() and GetAllSyncData() (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 10 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/password_manager/password_syncable_service.h" 5 #include "chrome/browser/password_manager/password_syncable_service.h"
6 6
7 #include "base/location.h" 7 #include "base/location.h"
8 #include "base/memory/scoped_vector.h" 8 #include "base/memory/scoped_vector.h"
9 #include "base/metrics/histogram.h" 9 #include "base/metrics/histogram.h"
10 #include "base/strings/utf_string_conversions.h" 10 #include "base/strings/utf_string_conversions.h"
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 syncer::ModelType type, 108 syncer::ModelType type,
109 const syncer::SyncDataList& initial_sync_data, 109 const syncer::SyncDataList& initial_sync_data,
110 scoped_ptr<syncer::SyncChangeProcessor> sync_processor, 110 scoped_ptr<syncer::SyncChangeProcessor> sync_processor,
111 scoped_ptr<syncer::SyncErrorFactory> sync_error_factory) { 111 scoped_ptr<syncer::SyncErrorFactory> sync_error_factory) {
112 DCHECK_EQ(syncer::PASSWORDS, type); 112 DCHECK_EQ(syncer::PASSWORDS, type);
113 syncer::SyncMergeResult merge_result(type); 113 syncer::SyncMergeResult merge_result(type);
114 sync_error_factory_ = sync_error_factory.Pass(); 114 sync_error_factory_ = sync_error_factory.Pass();
115 sync_processor_ = sync_processor.Pass(); 115 sync_processor_ = sync_processor.Pass();
116 116
117 ScopedVector<autofill::PasswordForm> password_entries; 117 ScopedVector<autofill::PasswordForm> password_entries;
118 if (!password_store_->FillAutofillableLogins(&password_entries.get())) { 118 PasswordEntryMap new_local_entries;
119 // Password store often fails to load passwords. Track failures with UMA. 119 if (!ReadFromPasswordStore(&password_entries, &new_local_entries)) {
120 // (http://crbug.com/249000) 120 DCHECK(sync_error_factory_);
121 UMA_HISTOGRAM_ENUMERATION("Sync.LocalDataFailedToLoad",
122 syncer::PASSWORDS,
123 syncer::MODEL_TYPE_COUNT);
124 merge_result.set_error(sync_error_factory_->CreateAndUploadError( 121 merge_result.set_error(sync_error_factory_->CreateAndUploadError(
125 FROM_HERE, 122 FROM_HERE,
126 "Failed to get passwords from store.")); 123 "Failed to get passwords from store."));
127 return merge_result; 124 return merge_result;
128 } 125 }
129 126
130 PasswordEntryMap new_local_entries;
131 for (PasswordForms::iterator it = password_entries.begin();
132 it != password_entries.end(); ++it) {
133 autofill::PasswordForm* password_form = *it;
134 // We add all the db entries as |new_local_entries| initially. During
135 // model association entries that match a sync entry will be
136 // removed and this list will only contain entries that are not in sync.
Ilya Sherman 2014/02/07 22:56:35 This was a useful comment, IMO. It would be nice
vasilii 2014/02/10 19:06:50 Done.
137 new_local_entries.insert(
138 std::make_pair(MakePasswordSyncTag(*password_form), password_form));
139 }
140
141 merge_result.set_num_items_before_association(new_local_entries.size()); 127 merge_result.set_num_items_before_association(new_local_entries.size());
142 128
143 // List that contains the entries that are known only to sync. 129 // List that contains the entries that are known only to sync.
144 ScopedVector<autofill::PasswordForm> new_sync_entries; 130 ScopedVector<autofill::PasswordForm> new_sync_entries;
145 131
146 // List that contains the entries that are known to both sync and db but 132 // List that contains the entries that are known to both sync and db but
147 // have updates in sync. They need to be updated in the passwords db. 133 // have updates in sync. They need to be updated in the passwords db.
148 ScopedVector<autofill::PasswordForm> updated_sync_entries; 134 ScopedVector<autofill::PasswordForm> updated_sync_entries;
149 135
150 // Changes from password db that need to be propagated to sync. 136 // Changes from password db that need to be propagated to sync.
151 syncer::SyncChangeList updated_db_entries; 137 syncer::SyncChangeList updated_db_entries;
152 for (syncer::SyncDataList::const_iterator sync_iter = 138 for (syncer::SyncDataList::const_iterator sync_iter =
153 initial_sync_data.begin(); 139 initial_sync_data.begin();
154 sync_iter != initial_sync_data.end(); ++sync_iter) { 140 sync_iter != initial_sync_data.end(); ++sync_iter) {
155 CreateOrUpdateEntry(*sync_iter, 141 CreateOrUpdateEntry(*sync_iter,
156 &new_local_entries, 142 &new_local_entries,
157 &new_sync_entries, 143 &new_sync_entries,
158 &updated_sync_entries, 144 &updated_sync_entries,
159 &updated_db_entries); 145 &updated_db_entries);
160 } 146 }
161 147
162 WriteToPasswordStore(new_sync_entries.get(), 148 WriteToPasswordStore(new_sync_entries.get(),
163 updated_sync_entries.get()); 149 updated_sync_entries.get(),
150 PasswordForms());
164 151
165 merge_result.set_num_items_after_association( 152 merge_result.set_num_items_after_association(
166 merge_result.num_items_before_association() + new_sync_entries.size()); 153 merge_result.num_items_before_association() + new_sync_entries.size());
167 154
168 merge_result.set_num_items_added(new_sync_entries.size()); 155 merge_result.set_num_items_added(new_sync_entries.size());
169 156
170 merge_result.set_num_items_modified(updated_sync_entries.size()); 157 merge_result.set_num_items_modified(updated_sync_entries.size());
171 158
172 for (PasswordEntryMap::iterator it = new_local_entries.begin(); 159 for (PasswordEntryMap::iterator it = new_local_entries.begin();
173 it != new_local_entries.end(); 160 it != new_local_entries.end();
174 ++it) { 161 ++it) {
175 updated_db_entries.push_back( 162 updated_db_entries.push_back(
176 syncer::SyncChange(FROM_HERE, 163 syncer::SyncChange(FROM_HERE,
177 syncer::SyncChange::ACTION_ADD, 164 syncer::SyncChange::ACTION_ADD,
178 SyncDataFromPassword(*it->second))); 165 SyncDataFromPassword(*it->second)));
179 } 166 }
180 167
181 merge_result.set_error( 168 merge_result.set_error(
182 sync_processor_->ProcessSyncChanges(FROM_HERE, updated_db_entries)); 169 sync_processor_->ProcessSyncChanges(FROM_HERE, updated_db_entries));
183 return merge_result; 170 return merge_result;
184 } 171 }
185 172
186 void PasswordSyncableService::StopSyncing(syncer::ModelType type) { 173 void PasswordSyncableService::StopSyncing(syncer::ModelType type) {
187 sync_processor_.reset(); 174 sync_processor_.reset();
188 sync_error_factory_.reset(); 175 sync_error_factory_.reset();
189 } 176 }
190 177
191 syncer::SyncDataList PasswordSyncableService::GetAllSyncData( 178 syncer::SyncDataList PasswordSyncableService::GetAllSyncData(
192 syncer::ModelType type) const { 179 syncer::ModelType type) const {
180 DCHECK_EQ(syncer::PASSWORDS, type);
181 ScopedVector<autofill::PasswordForm> password_entries;
182 ReadFromPasswordStore(&password_entries, NULL);
183
193 syncer::SyncDataList sync_data; 184 syncer::SyncDataList sync_data;
185 for (PasswordForms::iterator i = password_entries.begin();
Ilya Sherman 2014/02/07 22:56:35 nit: i -> it
vasilii 2014/02/10 19:06:50 Done.
186 i != password_entries.end(); ++i) {
187 sync_data.push_back(SyncDataFromPassword(**i));
188 }
194 return sync_data; 189 return sync_data;
195 } 190 }
196 191
197 syncer::SyncError PasswordSyncableService::ProcessSyncChanges( 192 syncer::SyncError PasswordSyncableService::ProcessSyncChanges(
198 const tracked_objects::Location& from_here, 193 const tracked_objects::Location& from_here,
199 const syncer::SyncChangeList& change_list) { 194 const syncer::SyncChangeList& change_list) {
200 syncer::SyncError error(FROM_HERE, 195 // The |db_entries_map| and associated vectors are filled only in case of
201 syncer::SyncError::UNRECOVERABLE_ERROR, 196 // add/update change.
202 "Password Syncable Service Not Implemented.", 197 PasswordEntryMap db_entries_map;
203 syncer::PASSWORDS); 198 ScopedVector<autofill::PasswordForm> password_db_entries;
204 return error; 199 ScopedVector<autofill::PasswordForm> new_sync_entries;
200 ScopedVector<autofill::PasswordForm> updated_sync_entries;
201 ScopedVector<autofill::PasswordForm> deleted_entries;
202 bool has_read_passwords = false;
203
204 for (syncer::SyncChangeList::const_iterator it = change_list.begin();
205 it != change_list.end();
206 ++it) {
207 switch (it->change_type()) {
208 case syncer::SyncChange::ACTION_ADD:
209 case syncer::SyncChange::ACTION_UPDATE: {
210 if (!has_read_passwords) {
211 if (ReadFromPasswordStore(&password_db_entries,
Nicolas Zea 2014/02/07 21:16:47 It seems expensive to read all passwords from the
Ilya Sherman 2014/02/07 22:56:35 FWIW, my vote is against caching unless we really
vasilii 2014/02/10 19:06:50 This implementation isn't slower than the existing
212 &db_entries_map)) {
213 has_read_passwords = true;
214 } else {
215 return sync_error_factory_->CreateAndUploadError(
216 FROM_HERE,
217 "Failed to get passwords from store.");
218 }
219 }
220 syncer::SyncChangeList sync_changes;
221
222 // This item from sync will be compared to the data in passwords db and
223 // |new_sync_entries| or |updated_sync_entries| will be updated based on
224 // whether this sync item is an addition or update.
Ilya Sherman 2014/02/07 22:56:35 Hmm, why is this needed? That is, why is it not s
vasilii 2014/02/10 19:06:50 It's safe. I just reuse the existing method.
225 CreateOrUpdateEntry(it->sync_data(),
226 &db_entries_map,
227 &new_sync_entries,
228 &updated_sync_entries,
229 &sync_changes);
230 break;
231 }
Ilya Sherman 2014/02/07 22:56:35 nit: Leave a blank line between cases, IMO.
vasilii 2014/02/10 19:06:50 Done.
232 case syncer::SyncChange::ACTION_DELETE: {
233 const sync_pb::EntitySpecifics& specifics =
234 it->sync_data().GetSpecifics();
235 const sync_pb::PasswordSpecificsData& password_specifics(
236 specifics.password().client_only_encrypted_data());
237 autofill::PasswordForm* new_password = new autofill::PasswordForm;
Ilya Sherman 2014/02/07 22:56:35 nit: I prefer to immediately wrap all |new|s in sc
vasilii 2014/02/10 19:06:50 Done.
238 PasswordFromSpecifics(password_specifics, new_password);
239 deleted_entries.push_back(new_password);
240 break;
241 }
242 default: {
Ilya Sherman 2014/02/07 22:56:35 nit: Rather than a default case, please have an ex
vasilii 2014/02/10 19:06:50 Done.
243 return sync_error_factory_->CreateAndUploadError(
244 FROM_HERE,
245 "Failed to process sync changes for passwords datatype.");
246 }
Ilya Sherman 2014/02/07 22:56:35 nit: No need for curly braces.
vasilii 2014/02/10 19:06:50 Done.
247 }
248 }
249 WriteToPasswordStore(new_sync_entries.get(),
250 updated_sync_entries.get(),
251 deleted_entries.get());
252 return syncer::SyncError();
205 } 253 }
206 254
207 void PasswordSyncableService::ActOnPasswordStoreChanges( 255 void PasswordSyncableService::ActOnPasswordStoreChanges(
208 const PasswordStoreChangeList& local_changes) { 256 const PasswordStoreChangeList& local_changes) {
209 if (!sync_processor_) 257 if (!sync_processor_)
210 return; 258 return;
211 syncer::SyncChangeList sync_changes; 259 syncer::SyncChangeList sync_changes;
212 for (PasswordStoreChangeList::const_iterator it = local_changes.begin(); 260 for (PasswordStoreChangeList::const_iterator it = local_changes.begin();
213 it != local_changes.end(); 261 it != local_changes.end();
214 ++it) { 262 ++it) {
215 sync_changes.push_back( 263 sync_changes.push_back(
216 syncer::SyncChange(FROM_HERE, 264 syncer::SyncChange(FROM_HERE,
217 GetSyncChangeType(it->type()), 265 GetSyncChangeType(it->type()),
218 SyncDataFromPassword(it->form()))); 266 SyncDataFromPassword(it->form())));
219 } 267 }
220 sync_processor_->ProcessSyncChanges(FROM_HERE, sync_changes); 268 sync_processor_->ProcessSyncChanges(FROM_HERE, sync_changes);
221 } 269 }
222 270
271 bool PasswordSyncableService::ReadFromPasswordStore(
272 ScopedVector<autofill::PasswordForm>* password_entries,
273 PasswordEntryMap* passwords_entry_map) const {
274 DCHECK(password_entries);
Ilya Sherman 2014/02/07 22:56:35 nit: No need for this, IMO, since you dereference
vasilii 2014/02/10 19:06:50 For better log readability?
275 if (!password_store_->FillAutofillableLogins(&password_entries->get()) ||
276 !password_store_->FillBlacklistLogins(&password_entries->get())) {
Ilya Sherman 2014/02/07 22:56:35 Have you added test coverage for blacklisted login
vasilii 2014/02/10 19:06:50 I modified PasswordSyncableServiceTest.ProcessSync
Ilya Sherman 2014/02/11 07:59:45 Lovely, thanks :)
277 // Password store often fails to load passwords. Track failures with UMA.
278 // (http://crbug.com/249000)
279 UMA_HISTOGRAM_ENUMERATION("Sync.LocalDataFailedToLoad",
280 ModelTypeToHistogramInt(syncer::PASSWORDS),
281 syncer::MODEL_TYPE_COUNT);
282 return false;
283 }
284
285 if (!passwords_entry_map)
286 return true;
287
288 for (PasswordForms::iterator it = password_entries->begin();
289 it != password_entries->end(); ++it) {
290 autofill::PasswordForm* password_form = *it;
291 passwords_entry_map->insert(
292 std::make_pair(MakePasswordSyncTag(*password_form), password_form));
293 }
294
295 return true;
296 }
297
223 void PasswordSyncableService::WriteToPasswordStore( 298 void PasswordSyncableService::WriteToPasswordStore(
224 const PasswordForms& new_entries, 299 const PasswordForms& new_entries,
225 const PasswordForms& updated_entries) { 300 const PasswordForms& updated_entries,
301 const PasswordForms& deleted_entries) {
226 PasswordStoreChangeList changes; 302 PasswordStoreChangeList changes;
227 for (std::vector<autofill::PasswordForm*>::const_iterator it = 303 for (std::vector<autofill::PasswordForm*>::const_iterator it =
228 new_entries.begin(); 304 new_entries.begin();
229 it != new_entries.end(); 305 it != new_entries.end();
230 ++it) { 306 ++it) {
231 AppendChanges(password_store_->AddLoginImpl(**it), &changes); 307 AppendChanges(password_store_->AddLoginImpl(**it), &changes);
232 } 308 }
233 309
234 for (std::vector<autofill::PasswordForm*>::const_iterator it = 310 for (std::vector<autofill::PasswordForm*>::const_iterator it =
235 updated_entries.begin(); 311 updated_entries.begin();
236 it != updated_entries.end(); 312 it != updated_entries.end();
237 ++it) { 313 ++it) {
238 AppendChanges(password_store_->UpdateLoginImpl(**it), &changes); 314 AppendChanges(password_store_->UpdateLoginImpl(**it), &changes);
239 } 315 }
240 316
317 for (std::vector<autofill::PasswordForm*>::const_iterator it =
318 deleted_entries.begin();
319 it != deleted_entries.end();
320 ++it) {
321 AppendChanges(password_store_->RemoveLoginImpl(**it), &changes);
322 }
323
241 // We have to notify password store observers of the change by hand since 324 // We have to notify password store observers of the change by hand since
242 // we use internal password store interfaces to make changes synchronously. 325 // we use internal password store interfaces to make changes synchronously.
243 NotifyPasswordStoreOfLoginChanges(changes); 326 NotifyPasswordStoreOfLoginChanges(changes);
244 } 327 }
245 328
246 void PasswordSyncableService::NotifyPasswordStoreOfLoginChanges( 329 void PasswordSyncableService::NotifyPasswordStoreOfLoginChanges(
247 const PasswordStoreChangeList& changes) { 330 const PasswordStoreChangeList& changes) {
248 password_store_->NotifyLoginsChanged(changes); 331 password_store_->NotifyLoginsChanged(changes);
249 } 332 }
250 333
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
340 } 423 }
341 424
342 std::string MakePasswordSyncTag( 425 std::string MakePasswordSyncTag(
343 const sync_pb::PasswordSpecificsData& password) { 426 const sync_pb::PasswordSpecificsData& password) {
344 return MakePasswordSyncTag(password.origin(), 427 return MakePasswordSyncTag(password.origin(),
345 password.username_element(), 428 password.username_element(),
346 password.username_value(), 429 password.username_value(),
347 password.password_element(), 430 password.password_element(),
348 password.signon_realm()); 431 password.signon_realm());
349 } 432 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698