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" |
11 #include "components/autofill/core/common/password_form.h" | 11 #include "components/autofill/core/common/password_form.h" |
12 #include "components/password_manager/core/browser/password_store.h" | 12 #include "components/password_manager/core/browser/password_store.h" |
13 #include "net/base/escape.h" | 13 #include "net/base/escape.h" |
14 #include "sync/api/sync_error_factory.h" | 14 #include "sync/api/sync_error_factory.h" |
15 | 15 |
16 namespace { | 16 namespace { |
17 | 17 |
| 18 // Describes the result of merging sync and local passwords. |
| 19 enum MergeResult { |
| 20 IDENTICAL, |
| 21 SYNC, |
| 22 LOCAL, |
| 23 }; |
| 24 |
18 // Merges the local and sync passwords and outputs the entry into | 25 // Merges the local and sync passwords and outputs the entry into |
19 // |new_password_form|. Returns true if the local and the sync passwords differ. | 26 // |new_password_form|. Returns MergeResult value describing the content of |
20 // Returns false if they are identical. | 27 // |new_password_form|. |
21 bool MergeLocalAndSyncPasswords( | 28 MergeResult MergeLocalAndSyncPasswords( |
22 const sync_pb::PasswordSpecificsData& password_specifics, | 29 const sync_pb::PasswordSpecificsData& password_specifics, |
23 const autofill::PasswordForm& password_form, | 30 const autofill::PasswordForm& password_form, |
24 autofill::PasswordForm* new_password_form) { | 31 autofill::PasswordForm* new_password_form) { |
25 DCHECK(new_password_form); | 32 DCHECK(new_password_form); |
26 if (password_form.scheme == password_specifics.scheme() && | 33 if (password_form.scheme == password_specifics.scheme() && |
27 password_form.signon_realm == password_specifics.signon_realm() && | 34 password_form.signon_realm == password_specifics.signon_realm() && |
28 password_form.origin.spec() == password_specifics.origin() && | 35 password_form.origin.spec() == password_specifics.origin() && |
29 password_form.action.spec() == password_specifics.action() && | 36 password_form.action.spec() == password_specifics.action() && |
30 base::UTF16ToUTF8(password_form.username_element) == | 37 base::UTF16ToUTF8(password_form.username_element) == |
31 password_specifics.username_element() && | 38 password_specifics.username_element() && |
32 base::UTF16ToUTF8(password_form.password_element) == | 39 base::UTF16ToUTF8(password_form.password_element) == |
33 password_specifics.password_element() && | 40 password_specifics.password_element() && |
34 base::UTF16ToUTF8(password_form.username_value) == | 41 base::UTF16ToUTF8(password_form.username_value) == |
35 password_specifics.username_value() && | 42 password_specifics.username_value() && |
36 base::UTF16ToUTF8(password_form.password_value) == | 43 base::UTF16ToUTF8(password_form.password_value) == |
37 password_specifics.password_value() && | 44 password_specifics.password_value() && |
38 password_form.ssl_valid == password_specifics.ssl_valid() && | 45 password_form.ssl_valid == password_specifics.ssl_valid() && |
39 password_form.preferred == password_specifics.preferred() && | 46 password_form.preferred == password_specifics.preferred() && |
40 password_form.date_created.ToInternalValue() == | 47 password_form.date_created.ToInternalValue() == |
41 password_specifics.date_created() && | 48 password_specifics.date_created() && |
42 password_form.blacklisted_by_user == password_specifics.blacklisted()) { | 49 password_form.blacklisted_by_user == password_specifics.blacklisted()) { |
43 return false; | 50 return IDENTICAL; |
44 } | 51 } |
45 | 52 |
46 // If the passwords differ, take the one that was created more recently. | 53 // If the passwords differ, take the one that was created more recently. |
47 if (base::Time::FromInternalValue(password_specifics.date_created()) <= | 54 if (base::Time::FromInternalValue(password_specifics.date_created()) <= |
48 password_form.date_created) { | 55 password_form.date_created) { |
49 *new_password_form = password_form; | 56 *new_password_form = password_form; |
50 } else { | 57 return LOCAL; |
51 PasswordFromSpecifics(password_specifics, new_password_form); | |
52 } | 58 } |
53 | 59 |
54 return true; | 60 PasswordFromSpecifics(password_specifics, new_password_form); |
| 61 return SYNC; |
55 } | 62 } |
56 | 63 |
57 std::string MakePasswordSyncTag(const std::string& origin_url, | 64 std::string MakePasswordSyncTag(const std::string& origin_url, |
58 const std::string& username_element, | 65 const std::string& username_element, |
59 const std::string& username_value, | 66 const std::string& username_value, |
60 const std::string& password_element, | 67 const std::string& password_element, |
61 const std::string& signon_realm) { | 68 const std::string& signon_realm) { |
62 return net::EscapePath(origin_url) + "|" + | 69 return net::EscapePath(origin_url) + "|" + |
63 net::EscapePath(username_element) + "|" + | 70 net::EscapePath(username_element) + "|" + |
64 net::EscapePath(username_value) + "|" + | 71 net::EscapePath(username_value) + "|" + |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
107 syncer::SyncMergeResult PasswordSyncableService::MergeDataAndStartSyncing( | 114 syncer::SyncMergeResult PasswordSyncableService::MergeDataAndStartSyncing( |
108 syncer::ModelType type, | 115 syncer::ModelType type, |
109 const syncer::SyncDataList& initial_sync_data, | 116 const syncer::SyncDataList& initial_sync_data, |
110 scoped_ptr<syncer::SyncChangeProcessor> sync_processor, | 117 scoped_ptr<syncer::SyncChangeProcessor> sync_processor, |
111 scoped_ptr<syncer::SyncErrorFactory> sync_error_factory) { | 118 scoped_ptr<syncer::SyncErrorFactory> sync_error_factory) { |
112 DCHECK_EQ(syncer::PASSWORDS, type); | 119 DCHECK_EQ(syncer::PASSWORDS, type); |
113 syncer::SyncMergeResult merge_result(type); | 120 syncer::SyncMergeResult merge_result(type); |
114 sync_error_factory_ = sync_error_factory.Pass(); | 121 sync_error_factory_ = sync_error_factory.Pass(); |
115 sync_processor_ = sync_processor.Pass(); | 122 sync_processor_ = sync_processor.Pass(); |
116 | 123 |
| 124 // We add all the db entries as |new_local_entries| initially. During model |
| 125 // association entries that match a sync entry will be removed and this list |
| 126 // will only contain entries that are not in sync. |
117 ScopedVector<autofill::PasswordForm> password_entries; | 127 ScopedVector<autofill::PasswordForm> password_entries; |
118 if (!password_store_->FillAutofillableLogins(&password_entries.get())) { | 128 PasswordEntryMap new_local_entries; |
119 // Password store often fails to load passwords. Track failures with UMA. | 129 if (!ReadFromPasswordStore(&password_entries, &new_local_entries)) { |
120 // (http://crbug.com/249000) | 130 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( | 131 merge_result.set_error(sync_error_factory_->CreateAndUploadError( |
125 FROM_HERE, | 132 FROM_HERE, |
126 "Failed to get passwords from store.")); | 133 "Failed to get passwords from store.")); |
127 return merge_result; | 134 return merge_result; |
128 } | 135 } |
129 | 136 |
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()); | 137 merge_result.set_num_items_before_association(new_local_entries.size()); |
142 | 138 |
143 // List that contains the entries that are known only to sync. | 139 // List that contains the entries that are known only to sync. |
144 ScopedVector<autofill::PasswordForm> new_sync_entries; | 140 ScopedVector<autofill::PasswordForm> new_sync_entries; |
145 | 141 |
146 // List that contains the entries that are known to both sync and db but | 142 // 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. | 143 // have updates in sync. They need to be updated in the passwords db. |
148 ScopedVector<autofill::PasswordForm> updated_sync_entries; | 144 ScopedVector<autofill::PasswordForm> updated_sync_entries; |
149 | 145 |
150 // Changes from password db that need to be propagated to sync. | 146 // Changes from password db that need to be propagated to sync. |
151 syncer::SyncChangeList updated_db_entries; | 147 syncer::SyncChangeList updated_db_entries; |
152 for (syncer::SyncDataList::const_iterator sync_iter = | 148 for (syncer::SyncDataList::const_iterator sync_iter = |
153 initial_sync_data.begin(); | 149 initial_sync_data.begin(); |
154 sync_iter != initial_sync_data.end(); ++sync_iter) { | 150 sync_iter != initial_sync_data.end(); ++sync_iter) { |
155 CreateOrUpdateEntry(*sync_iter, | 151 CreateOrUpdateEntry(*sync_iter, |
156 &new_local_entries, | 152 &new_local_entries, |
157 &new_sync_entries, | 153 &new_sync_entries, |
158 &updated_sync_entries, | 154 &updated_sync_entries, |
159 &updated_db_entries); | 155 &updated_db_entries); |
160 } | 156 } |
161 | 157 |
162 WriteToPasswordStore(new_sync_entries.get(), | 158 WriteToPasswordStore(new_sync_entries.get(), |
163 updated_sync_entries.get()); | 159 updated_sync_entries.get(), |
| 160 PasswordForms()); |
164 | 161 |
165 merge_result.set_num_items_after_association( | 162 merge_result.set_num_items_after_association( |
166 merge_result.num_items_before_association() + new_sync_entries.size()); | 163 merge_result.num_items_before_association() + new_sync_entries.size()); |
167 | 164 |
168 merge_result.set_num_items_added(new_sync_entries.size()); | 165 merge_result.set_num_items_added(new_sync_entries.size()); |
169 | 166 |
170 merge_result.set_num_items_modified(updated_sync_entries.size()); | 167 merge_result.set_num_items_modified(updated_sync_entries.size()); |
171 | 168 |
172 for (PasswordEntryMap::iterator it = new_local_entries.begin(); | 169 for (PasswordEntryMap::iterator it = new_local_entries.begin(); |
173 it != new_local_entries.end(); | 170 it != new_local_entries.end(); |
174 ++it) { | 171 ++it) { |
175 updated_db_entries.push_back( | 172 updated_db_entries.push_back( |
176 syncer::SyncChange(FROM_HERE, | 173 syncer::SyncChange(FROM_HERE, |
177 syncer::SyncChange::ACTION_ADD, | 174 syncer::SyncChange::ACTION_ADD, |
178 SyncDataFromPassword(*it->second))); | 175 SyncDataFromPassword(*it->second))); |
179 } | 176 } |
180 | 177 |
181 merge_result.set_error( | 178 merge_result.set_error( |
182 sync_processor_->ProcessSyncChanges(FROM_HERE, updated_db_entries)); | 179 sync_processor_->ProcessSyncChanges(FROM_HERE, updated_db_entries)); |
183 return merge_result; | 180 return merge_result; |
184 } | 181 } |
185 | 182 |
186 void PasswordSyncableService::StopSyncing(syncer::ModelType type) { | 183 void PasswordSyncableService::StopSyncing(syncer::ModelType type) { |
187 sync_processor_.reset(); | 184 sync_processor_.reset(); |
188 sync_error_factory_.reset(); | 185 sync_error_factory_.reset(); |
189 } | 186 } |
190 | 187 |
191 syncer::SyncDataList PasswordSyncableService::GetAllSyncData( | 188 syncer::SyncDataList PasswordSyncableService::GetAllSyncData( |
192 syncer::ModelType type) const { | 189 syncer::ModelType type) const { |
| 190 DCHECK_EQ(syncer::PASSWORDS, type); |
| 191 ScopedVector<autofill::PasswordForm> password_entries; |
| 192 ReadFromPasswordStore(&password_entries, NULL); |
| 193 |
193 syncer::SyncDataList sync_data; | 194 syncer::SyncDataList sync_data; |
| 195 for (PasswordForms::iterator it = password_entries.begin(); |
| 196 it != password_entries.end(); ++it) { |
| 197 sync_data.push_back(SyncDataFromPassword(**it)); |
| 198 } |
194 return sync_data; | 199 return sync_data; |
195 } | 200 } |
196 | 201 |
197 syncer::SyncError PasswordSyncableService::ProcessSyncChanges( | 202 syncer::SyncError PasswordSyncableService::ProcessSyncChanges( |
198 const tracked_objects::Location& from_here, | 203 const tracked_objects::Location& from_here, |
199 const syncer::SyncChangeList& change_list) { | 204 const syncer::SyncChangeList& change_list) { |
200 syncer::SyncError error(FROM_HERE, | 205 // The |db_entries_map| and associated vectors are filled only in case of |
201 syncer::SyncError::UNRECOVERABLE_ERROR, | 206 // update change. |
202 "Password Syncable Service Not Implemented.", | 207 PasswordEntryMap db_entries_map; |
203 syncer::PASSWORDS); | 208 ScopedVector<autofill::PasswordForm> password_db_entries; |
204 return error; | 209 ScopedVector<autofill::PasswordForm> new_sync_entries; |
| 210 ScopedVector<autofill::PasswordForm> updated_sync_entries; |
| 211 ScopedVector<autofill::PasswordForm> deleted_entries; |
| 212 bool has_read_passwords = false; |
| 213 |
| 214 for (syncer::SyncChangeList::const_iterator it = change_list.begin(); |
| 215 it != change_list.end(); |
| 216 ++it) { |
| 217 switch (it->change_type()) { |
| 218 case syncer::SyncChange::ACTION_ADD: { |
| 219 const sync_pb::EntitySpecifics& specifics = |
| 220 it->sync_data().GetSpecifics(); |
| 221 new_sync_entries.push_back(new autofill::PasswordForm); |
| 222 PasswordFromSpecifics(specifics.password().client_only_encrypted_data(), |
| 223 new_sync_entries.back()); |
| 224 break; |
| 225 } |
| 226 case syncer::SyncChange::ACTION_UPDATE: { |
| 227 if (!has_read_passwords) { |
| 228 if (ReadFromPasswordStore(&password_db_entries, |
| 229 &db_entries_map)) { |
| 230 has_read_passwords = true; |
| 231 } else { |
| 232 return sync_error_factory_->CreateAndUploadError( |
| 233 FROM_HERE, |
| 234 "Failed to get passwords from store."); |
| 235 } |
| 236 } |
| 237 syncer::SyncChangeList sync_changes; |
| 238 |
| 239 CreateOrUpdateEntry(it->sync_data(), |
| 240 &db_entries_map, |
| 241 &new_sync_entries, |
| 242 &updated_sync_entries, |
| 243 &sync_changes); |
| 244 DCHECK(sync_changes.empty()); |
| 245 break; |
| 246 } |
| 247 |
| 248 case syncer::SyncChange::ACTION_DELETE: { |
| 249 const sync_pb::EntitySpecifics& specifics = |
| 250 it->sync_data().GetSpecifics(); |
| 251 const sync_pb::PasswordSpecificsData& password_specifics( |
| 252 specifics.password().client_only_encrypted_data()); |
| 253 deleted_entries.push_back(new autofill::PasswordForm); |
| 254 PasswordFromSpecifics(password_specifics, deleted_entries.back()); |
| 255 break; |
| 256 } |
| 257 case syncer::SyncChange::ACTION_INVALID: |
| 258 return sync_error_factory_->CreateAndUploadError( |
| 259 FROM_HERE, |
| 260 "Failed to process sync changes for passwords datatype."); |
| 261 } |
| 262 } |
| 263 WriteToPasswordStore(new_sync_entries.get(), |
| 264 updated_sync_entries.get(), |
| 265 deleted_entries.get()); |
| 266 return syncer::SyncError(); |
205 } | 267 } |
206 | 268 |
207 void PasswordSyncableService::ActOnPasswordStoreChanges( | 269 void PasswordSyncableService::ActOnPasswordStoreChanges( |
208 const PasswordStoreChangeList& local_changes) { | 270 const PasswordStoreChangeList& local_changes) { |
209 if (!sync_processor_) | 271 if (!sync_processor_) |
210 return; | 272 return; |
211 syncer::SyncChangeList sync_changes; | 273 syncer::SyncChangeList sync_changes; |
212 for (PasswordStoreChangeList::const_iterator it = local_changes.begin(); | 274 for (PasswordStoreChangeList::const_iterator it = local_changes.begin(); |
213 it != local_changes.end(); | 275 it != local_changes.end(); |
214 ++it) { | 276 ++it) { |
215 sync_changes.push_back( | 277 sync_changes.push_back( |
216 syncer::SyncChange(FROM_HERE, | 278 syncer::SyncChange(FROM_HERE, |
217 GetSyncChangeType(it->type()), | 279 GetSyncChangeType(it->type()), |
218 SyncDataFromPassword(it->form()))); | 280 SyncDataFromPassword(it->form()))); |
219 } | 281 } |
220 sync_processor_->ProcessSyncChanges(FROM_HERE, sync_changes); | 282 sync_processor_->ProcessSyncChanges(FROM_HERE, sync_changes); |
221 } | 283 } |
222 | 284 |
| 285 bool PasswordSyncableService::ReadFromPasswordStore( |
| 286 ScopedVector<autofill::PasswordForm>* password_entries, |
| 287 PasswordEntryMap* passwords_entry_map) const { |
| 288 DCHECK(password_entries); |
| 289 if (!password_store_->FillAutofillableLogins(&password_entries->get()) || |
| 290 !password_store_->FillBlacklistLogins(&password_entries->get())) { |
| 291 // Password store often fails to load passwords. Track failures with UMA. |
| 292 // (http://crbug.com/249000) |
| 293 UMA_HISTOGRAM_ENUMERATION("Sync.LocalDataFailedToLoad", |
| 294 ModelTypeToHistogramInt(syncer::PASSWORDS), |
| 295 syncer::MODEL_TYPE_COUNT); |
| 296 return false; |
| 297 } |
| 298 |
| 299 if (!passwords_entry_map) |
| 300 return true; |
| 301 |
| 302 for (PasswordForms::iterator it = password_entries->begin(); |
| 303 it != password_entries->end(); ++it) { |
| 304 autofill::PasswordForm* password_form = *it; |
| 305 passwords_entry_map->insert( |
| 306 std::make_pair(MakePasswordSyncTag(*password_form), password_form)); |
| 307 } |
| 308 |
| 309 return true; |
| 310 } |
| 311 |
223 void PasswordSyncableService::WriteToPasswordStore( | 312 void PasswordSyncableService::WriteToPasswordStore( |
224 const PasswordForms& new_entries, | 313 const PasswordForms& new_entries, |
225 const PasswordForms& updated_entries) { | 314 const PasswordForms& updated_entries, |
| 315 const PasswordForms& deleted_entries) { |
226 PasswordStoreChangeList changes; | 316 PasswordStoreChangeList changes; |
227 for (std::vector<autofill::PasswordForm*>::const_iterator it = | 317 for (std::vector<autofill::PasswordForm*>::const_iterator it = |
228 new_entries.begin(); | 318 new_entries.begin(); |
229 it != new_entries.end(); | 319 it != new_entries.end(); |
230 ++it) { | 320 ++it) { |
231 AppendChanges(password_store_->AddLoginImpl(**it), &changes); | 321 AppendChanges(password_store_->AddLoginImpl(**it), &changes); |
232 } | 322 } |
233 | 323 |
234 for (std::vector<autofill::PasswordForm*>::const_iterator it = | 324 for (std::vector<autofill::PasswordForm*>::const_iterator it = |
235 updated_entries.begin(); | 325 updated_entries.begin(); |
236 it != updated_entries.end(); | 326 it != updated_entries.end(); |
237 ++it) { | 327 ++it) { |
238 AppendChanges(password_store_->UpdateLoginImpl(**it), &changes); | 328 AppendChanges(password_store_->UpdateLoginImpl(**it), &changes); |
239 } | 329 } |
240 | 330 |
| 331 for (std::vector<autofill::PasswordForm*>::const_iterator it = |
| 332 deleted_entries.begin(); |
| 333 it != deleted_entries.end(); |
| 334 ++it) { |
| 335 AppendChanges(password_store_->RemoveLoginImpl(**it), &changes); |
| 336 } |
| 337 |
241 // We have to notify password store observers of the change by hand since | 338 // We have to notify password store observers of the change by hand since |
242 // we use internal password store interfaces to make changes synchronously. | 339 // we use internal password store interfaces to make changes synchronously. |
243 NotifyPasswordStoreOfLoginChanges(changes); | 340 NotifyPasswordStoreOfLoginChanges(changes); |
244 } | 341 } |
245 | 342 |
246 void PasswordSyncableService::NotifyPasswordStoreOfLoginChanges( | 343 void PasswordSyncableService::NotifyPasswordStoreOfLoginChanges( |
247 const PasswordStoreChangeList& changes) { | 344 const PasswordStoreChangeList& changes) { |
248 password_store_->NotifyLoginsChanged(changes); | 345 password_store_->NotifyLoginsChanged(changes); |
249 } | 346 } |
250 | 347 |
(...skipping 14 matching lines...) Expand all Loading... |
265 if (existing_local_entry_iter == umatched_data_from_password_db->end()) { | 362 if (existing_local_entry_iter == umatched_data_from_password_db->end()) { |
266 // The sync data is not in the password store, so we need to create it in | 363 // The sync data is not in the password store, so we need to create it in |
267 // the password store. Add the entry to the new_entries list. | 364 // the password store. Add the entry to the new_entries list. |
268 scoped_ptr<autofill::PasswordForm> new_password(new autofill::PasswordForm); | 365 scoped_ptr<autofill::PasswordForm> new_password(new autofill::PasswordForm); |
269 PasswordFromSpecifics(password_specifics, new_password.get()); | 366 PasswordFromSpecifics(password_specifics, new_password.get()); |
270 new_sync_entries->push_back(new_password.release()); | 367 new_sync_entries->push_back(new_password.release()); |
271 } else { | 368 } else { |
272 // The entry is in password store. If the entries are not identical, then | 369 // The entry is in password store. If the entries are not identical, then |
273 // the entries need to be merged. | 370 // the entries need to be merged. |
274 scoped_ptr<autofill::PasswordForm> new_password(new autofill::PasswordForm); | 371 scoped_ptr<autofill::PasswordForm> new_password(new autofill::PasswordForm); |
275 if (MergeLocalAndSyncPasswords(password_specifics, | 372 switch (MergeLocalAndSyncPasswords(password_specifics, |
276 *existing_local_entry_iter->second, | 373 *existing_local_entry_iter->second, |
277 new_password.get())) { | 374 new_password.get())) { |
278 // Rather than checking which database -- sync or local -- needs updating, | 375 case IDENTICAL: |
279 // simply push an update to both. This will end up being a noop for the | 376 break; |
280 // database that didn't need an update. | 377 case SYNC: |
281 updated_db_entries->push_back( | 378 updated_sync_entries->push_back(new_password.release()); |
282 syncer::SyncChange(FROM_HERE, | 379 break; |
283 syncer::SyncChange::ACTION_UPDATE, | 380 case LOCAL: |
284 SyncDataFromPassword(*new_password))); | 381 updated_db_entries->push_back( |
285 | 382 syncer::SyncChange(FROM_HERE, |
286 updated_sync_entries->push_back(new_password.release()); | 383 syncer::SyncChange::ACTION_UPDATE, |
| 384 SyncDataFromPassword(*new_password))); |
| 385 break; |
287 } | 386 } |
288 // Remove the entry from the entry map to indicate a match has been found. | 387 // Remove the entry from the entry map to indicate a match has been found. |
289 // Entries that remain in the map at the end of associating all sync entries | 388 // Entries that remain in the map at the end of associating all sync entries |
290 // will be treated as additions that need to be propagated to sync. | 389 // will be treated as additions that need to be propagated to sync. |
291 umatched_data_from_password_db->erase(existing_local_entry_iter); | 390 umatched_data_from_password_db->erase(existing_local_entry_iter); |
292 } | 391 } |
293 } | 392 } |
294 | 393 |
295 syncer::SyncData SyncDataFromPassword( | 394 syncer::SyncData SyncDataFromPassword( |
296 const autofill::PasswordForm& password_form) { | 395 const autofill::PasswordForm& password_form) { |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
340 } | 439 } |
341 | 440 |
342 std::string MakePasswordSyncTag( | 441 std::string MakePasswordSyncTag( |
343 const sync_pb::PasswordSpecificsData& password) { | 442 const sync_pb::PasswordSpecificsData& password) { |
344 return MakePasswordSyncTag(password.origin(), | 443 return MakePasswordSyncTag(password.origin(), |
345 password.username_element(), | 444 password.username_element(), |
346 password.username_value(), | 445 password.username_value(), |
347 password.password_element(), | 446 password.password_element(), |
348 password.signon_realm()); | 447 password.signon_realm()); |
349 } | 448 } |
OLD | NEW |