OLD | NEW |
---|---|
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 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
107 syncer::SyncMergeResult PasswordSyncableService::MergeDataAndStartSyncing( | 107 syncer::SyncMergeResult PasswordSyncableService::MergeDataAndStartSyncing( |
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 // We add all the db entries as |new_local_entries| initially. During model | |
118 // association entries that match a sync entry will be removed and this list | |
119 // will only contain entries that are not in sync. | |
117 ScopedVector<autofill::PasswordForm> password_entries; | 120 ScopedVector<autofill::PasswordForm> password_entries; |
118 if (!password_store_->FillAutofillableLogins(&password_entries.get())) { | 121 PasswordEntryMap new_local_entries; |
119 // Password store often fails to load passwords. Track failures with UMA. | 122 if (!ReadFromPasswordStore(&password_entries, &new_local_entries)) { |
120 // (http://crbug.com/249000) | 123 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( | 124 merge_result.set_error(sync_error_factory_->CreateAndUploadError( |
125 FROM_HERE, | 125 FROM_HERE, |
126 "Failed to get passwords from store.")); | 126 "Failed to get passwords from store.")); |
127 return merge_result; | 127 return merge_result; |
128 } | 128 } |
129 | 129 |
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. | |
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()); | 130 merge_result.set_num_items_before_association(new_local_entries.size()); |
142 | 131 |
143 // List that contains the entries that are known only to sync. | 132 // List that contains the entries that are known only to sync. |
144 ScopedVector<autofill::PasswordForm> new_sync_entries; | 133 ScopedVector<autofill::PasswordForm> new_sync_entries; |
145 | 134 |
146 // List that contains the entries that are known to both sync and db but | 135 // 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. | 136 // have updates in sync. They need to be updated in the passwords db. |
148 ScopedVector<autofill::PasswordForm> updated_sync_entries; | 137 ScopedVector<autofill::PasswordForm> updated_sync_entries; |
149 | 138 |
150 // Changes from password db that need to be propagated to sync. | 139 // Changes from password db that need to be propagated to sync. |
151 syncer::SyncChangeList updated_db_entries; | 140 syncer::SyncChangeList updated_db_entries; |
152 for (syncer::SyncDataList::const_iterator sync_iter = | 141 for (syncer::SyncDataList::const_iterator sync_iter = |
153 initial_sync_data.begin(); | 142 initial_sync_data.begin(); |
154 sync_iter != initial_sync_data.end(); ++sync_iter) { | 143 sync_iter != initial_sync_data.end(); ++sync_iter) { |
155 CreateOrUpdateEntry(*sync_iter, | 144 CreateOrUpdateEntry(*sync_iter, |
156 &new_local_entries, | 145 &new_local_entries, |
157 &new_sync_entries, | 146 &new_sync_entries, |
158 &updated_sync_entries, | 147 &updated_sync_entries, |
159 &updated_db_entries); | 148 &updated_db_entries); |
160 } | 149 } |
161 | 150 |
162 WriteToPasswordStore(new_sync_entries.get(), | 151 WriteToPasswordStore(new_sync_entries.get(), |
163 updated_sync_entries.get()); | 152 updated_sync_entries.get(), |
153 PasswordForms()); | |
164 | 154 |
165 merge_result.set_num_items_after_association( | 155 merge_result.set_num_items_after_association( |
166 merge_result.num_items_before_association() + new_sync_entries.size()); | 156 merge_result.num_items_before_association() + new_sync_entries.size()); |
167 | 157 |
168 merge_result.set_num_items_added(new_sync_entries.size()); | 158 merge_result.set_num_items_added(new_sync_entries.size()); |
169 | 159 |
170 merge_result.set_num_items_modified(updated_sync_entries.size()); | 160 merge_result.set_num_items_modified(updated_sync_entries.size()); |
171 | 161 |
172 for (PasswordEntryMap::iterator it = new_local_entries.begin(); | 162 for (PasswordEntryMap::iterator it = new_local_entries.begin(); |
173 it != new_local_entries.end(); | 163 it != new_local_entries.end(); |
174 ++it) { | 164 ++it) { |
175 updated_db_entries.push_back( | 165 updated_db_entries.push_back( |
176 syncer::SyncChange(FROM_HERE, | 166 syncer::SyncChange(FROM_HERE, |
177 syncer::SyncChange::ACTION_ADD, | 167 syncer::SyncChange::ACTION_ADD, |
178 SyncDataFromPassword(*it->second))); | 168 SyncDataFromPassword(*it->second))); |
179 } | 169 } |
180 | 170 |
181 merge_result.set_error( | 171 merge_result.set_error( |
182 sync_processor_->ProcessSyncChanges(FROM_HERE, updated_db_entries)); | 172 sync_processor_->ProcessSyncChanges(FROM_HERE, updated_db_entries)); |
183 return merge_result; | 173 return merge_result; |
184 } | 174 } |
185 | 175 |
186 void PasswordSyncableService::StopSyncing(syncer::ModelType type) { | 176 void PasswordSyncableService::StopSyncing(syncer::ModelType type) { |
187 sync_processor_.reset(); | 177 sync_processor_.reset(); |
188 sync_error_factory_.reset(); | 178 sync_error_factory_.reset(); |
189 } | 179 } |
190 | 180 |
191 syncer::SyncDataList PasswordSyncableService::GetAllSyncData( | 181 syncer::SyncDataList PasswordSyncableService::GetAllSyncData( |
192 syncer::ModelType type) const { | 182 syncer::ModelType type) const { |
183 DCHECK_EQ(syncer::PASSWORDS, type); | |
184 ScopedVector<autofill::PasswordForm> password_entries; | |
185 ReadFromPasswordStore(&password_entries, NULL); | |
186 | |
193 syncer::SyncDataList sync_data; | 187 syncer::SyncDataList sync_data; |
188 for (PasswordForms::iterator it = password_entries.begin(); | |
189 it != password_entries.end(); ++it) { | |
190 sync_data.push_back(SyncDataFromPassword(**it)); | |
191 } | |
194 return sync_data; | 192 return sync_data; |
195 } | 193 } |
196 | 194 |
197 syncer::SyncError PasswordSyncableService::ProcessSyncChanges( | 195 syncer::SyncError PasswordSyncableService::ProcessSyncChanges( |
198 const tracked_objects::Location& from_here, | 196 const tracked_objects::Location& from_here, |
199 const syncer::SyncChangeList& change_list) { | 197 const syncer::SyncChangeList& change_list) { |
200 syncer::SyncError error(FROM_HERE, | 198 // The |db_entries_map| and associated vectors are filled only in case of |
201 syncer::SyncError::UNRECOVERABLE_ERROR, | 199 // add/update change. |
Ilya Sherman
2014/02/11 07:59:46
nit: Now only on an update change, right?
vasilii
2014/02/11 12:23:33
Done.
| |
202 "Password Syncable Service Not Implemented.", | 200 PasswordEntryMap db_entries_map; |
203 syncer::PASSWORDS); | 201 ScopedVector<autofill::PasswordForm> password_db_entries; |
204 return error; | 202 ScopedVector<autofill::PasswordForm> new_sync_entries; |
203 ScopedVector<autofill::PasswordForm> updated_sync_entries; | |
204 ScopedVector<autofill::PasswordForm> deleted_entries; | |
205 bool has_read_passwords = false; | |
206 | |
207 for (syncer::SyncChangeList::const_iterator it = change_list.begin(); | |
208 it != change_list.end(); | |
209 ++it) { | |
210 switch (it->change_type()) { | |
211 case syncer::SyncChange::ACTION_ADD: { | |
212 const sync_pb::EntitySpecifics& specifics = | |
213 it->sync_data().GetSpecifics(); | |
214 new_sync_entries.push_back(new autofill::PasswordForm); | |
215 PasswordFromSpecifics(specifics.password().client_only_encrypted_data(), | |
216 new_sync_entries.back()); | |
217 break; | |
218 } | |
219 case syncer::SyncChange::ACTION_UPDATE: { | |
220 if (!has_read_passwords) { | |
221 if (ReadFromPasswordStore(&password_db_entries, | |
222 &db_entries_map)) { | |
223 has_read_passwords = true; | |
224 } else { | |
225 return sync_error_factory_->CreateAndUploadError( | |
226 FROM_HERE, | |
227 "Failed to get passwords from store."); | |
228 } | |
229 } | |
230 syncer::SyncChangeList sync_changes; | |
231 | |
232 CreateOrUpdateEntry(it->sync_data(), | |
233 &db_entries_map, | |
234 &new_sync_entries, | |
235 &updated_sync_entries, | |
236 &sync_changes); | |
Ilya Sherman
2014/02/11 07:59:46
Would be nice to DCHECK that sync_changes remains
vasilii
2014/02/11 12:23:33
CreateOrUpdateEntry() is written in the way that i
Ilya Sherman
2014/02/11 21:58:25
Ah. Yes, I do think it should be fixed -- it's un
vasilii
2014/02/12 13:27:12
Done.
Ilya Sherman
2014/02/12 22:58:50
Thanks! (Still LGTM, so the CQ doesn't freak out.
| |
237 break; | |
238 } | |
239 | |
240 case syncer::SyncChange::ACTION_DELETE: { | |
241 const sync_pb::EntitySpecifics& specifics = | |
242 it->sync_data().GetSpecifics(); | |
243 const sync_pb::PasswordSpecificsData& password_specifics( | |
244 specifics.password().client_only_encrypted_data()); | |
245 deleted_entries.push_back(new autofill::PasswordForm); | |
246 PasswordFromSpecifics(password_specifics, deleted_entries.back()); | |
247 break; | |
248 } | |
249 case syncer::SyncChange::ACTION_INVALID: | |
250 return sync_error_factory_->CreateAndUploadError( | |
251 FROM_HERE, | |
252 "Failed to process sync changes for passwords datatype."); | |
253 } | |
254 } | |
255 WriteToPasswordStore(new_sync_entries.get(), | |
256 updated_sync_entries.get(), | |
257 deleted_entries.get()); | |
258 return syncer::SyncError(); | |
205 } | 259 } |
206 | 260 |
207 void PasswordSyncableService::ActOnPasswordStoreChanges( | 261 void PasswordSyncableService::ActOnPasswordStoreChanges( |
208 const PasswordStoreChangeList& local_changes) { | 262 const PasswordStoreChangeList& local_changes) { |
209 if (!sync_processor_) | 263 if (!sync_processor_) |
210 return; | 264 return; |
211 syncer::SyncChangeList sync_changes; | 265 syncer::SyncChangeList sync_changes; |
212 for (PasswordStoreChangeList::const_iterator it = local_changes.begin(); | 266 for (PasswordStoreChangeList::const_iterator it = local_changes.begin(); |
213 it != local_changes.end(); | 267 it != local_changes.end(); |
214 ++it) { | 268 ++it) { |
215 sync_changes.push_back( | 269 sync_changes.push_back( |
216 syncer::SyncChange(FROM_HERE, | 270 syncer::SyncChange(FROM_HERE, |
217 GetSyncChangeType(it->type()), | 271 GetSyncChangeType(it->type()), |
218 SyncDataFromPassword(it->form()))); | 272 SyncDataFromPassword(it->form()))); |
219 } | 273 } |
220 sync_processor_->ProcessSyncChanges(FROM_HERE, sync_changes); | 274 sync_processor_->ProcessSyncChanges(FROM_HERE, sync_changes); |
221 } | 275 } |
222 | 276 |
277 bool PasswordSyncableService::ReadFromPasswordStore( | |
278 ScopedVector<autofill::PasswordForm>* password_entries, | |
279 PasswordEntryMap* passwords_entry_map) const { | |
280 DCHECK(password_entries); | |
281 if (!password_store_->FillAutofillableLogins(&password_entries->get()) || | |
282 !password_store_->FillBlacklistLogins(&password_entries->get())) { | |
283 // Password store often fails to load passwords. Track failures with UMA. | |
284 // (http://crbug.com/249000) | |
285 UMA_HISTOGRAM_ENUMERATION("Sync.LocalDataFailedToLoad", | |
286 ModelTypeToHistogramInt(syncer::PASSWORDS), | |
287 syncer::MODEL_TYPE_COUNT); | |
288 return false; | |
289 } | |
290 | |
291 if (!passwords_entry_map) | |
292 return true; | |
293 | |
294 for (PasswordForms::iterator it = password_entries->begin(); | |
295 it != password_entries->end(); ++it) { | |
296 autofill::PasswordForm* password_form = *it; | |
297 passwords_entry_map->insert( | |
298 std::make_pair(MakePasswordSyncTag(*password_form), password_form)); | |
299 } | |
300 | |
301 return true; | |
302 } | |
303 | |
223 void PasswordSyncableService::WriteToPasswordStore( | 304 void PasswordSyncableService::WriteToPasswordStore( |
224 const PasswordForms& new_entries, | 305 const PasswordForms& new_entries, |
225 const PasswordForms& updated_entries) { | 306 const PasswordForms& updated_entries, |
307 const PasswordForms& deleted_entries) { | |
226 PasswordStoreChangeList changes; | 308 PasswordStoreChangeList changes; |
227 for (std::vector<autofill::PasswordForm*>::const_iterator it = | 309 for (std::vector<autofill::PasswordForm*>::const_iterator it = |
228 new_entries.begin(); | 310 new_entries.begin(); |
229 it != new_entries.end(); | 311 it != new_entries.end(); |
230 ++it) { | 312 ++it) { |
231 AppendChanges(password_store_->AddLoginImpl(**it), &changes); | 313 AppendChanges(password_store_->AddLoginImpl(**it), &changes); |
232 } | 314 } |
233 | 315 |
234 for (std::vector<autofill::PasswordForm*>::const_iterator it = | 316 for (std::vector<autofill::PasswordForm*>::const_iterator it = |
235 updated_entries.begin(); | 317 updated_entries.begin(); |
236 it != updated_entries.end(); | 318 it != updated_entries.end(); |
237 ++it) { | 319 ++it) { |
238 AppendChanges(password_store_->UpdateLoginImpl(**it), &changes); | 320 AppendChanges(password_store_->UpdateLoginImpl(**it), &changes); |
239 } | 321 } |
240 | 322 |
323 for (std::vector<autofill::PasswordForm*>::const_iterator it = | |
324 deleted_entries.begin(); | |
325 it != deleted_entries.end(); | |
326 ++it) { | |
327 AppendChanges(password_store_->RemoveLoginImpl(**it), &changes); | |
328 } | |
329 | |
241 // We have to notify password store observers of the change by hand since | 330 // We have to notify password store observers of the change by hand since |
242 // we use internal password store interfaces to make changes synchronously. | 331 // we use internal password store interfaces to make changes synchronously. |
243 NotifyPasswordStoreOfLoginChanges(changes); | 332 NotifyPasswordStoreOfLoginChanges(changes); |
244 } | 333 } |
245 | 334 |
246 void PasswordSyncableService::NotifyPasswordStoreOfLoginChanges( | 335 void PasswordSyncableService::NotifyPasswordStoreOfLoginChanges( |
247 const PasswordStoreChangeList& changes) { | 336 const PasswordStoreChangeList& changes) { |
248 password_store_->NotifyLoginsChanged(changes); | 337 password_store_->NotifyLoginsChanged(changes); |
249 } | 338 } |
250 | 339 |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
340 } | 429 } |
341 | 430 |
342 std::string MakePasswordSyncTag( | 431 std::string MakePasswordSyncTag( |
343 const sync_pb::PasswordSpecificsData& password) { | 432 const sync_pb::PasswordSpecificsData& password) { |
344 return MakePasswordSyncTag(password.origin(), | 433 return MakePasswordSyncTag(password.origin(), |
345 password.username_element(), | 434 password.username_element(), |
346 password.username_value(), | 435 password.username_value(), |
347 password.password_element(), | 436 password.password_element(), |
348 password.signon_realm()); | 437 password.signon_realm()); |
349 } | 438 } |
OLD | NEW |