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

Side by Side Diff: chrome/browser/webdata/autofill_profile_syncable_service.cc

Issue 129463002: Move AutofillProfileSyncableService into the Autofill component. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Propagate define Created 6 years, 11 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) 2012 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/webdata/autofill_profile_syncable_service.h"
6
7 #include "base/guid.h"
8 #include "base/location.h"
9 #include "base/logging.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "components/autofill/core/browser/autofill_country.h"
12 #include "components/autofill/core/browser/autofill_profile.h"
13 #include "components/autofill/core/browser/form_group.h"
14 #include "components/autofill/core/browser/webdata/autofill_table.h"
15 #include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
16 #include "components/webdata/common/web_database.h"
17 #include "content/public/browser/browser_thread.h"
18 #include "sync/api/sync_error.h"
19 #include "sync/api/sync_error_factory.h"
20 #include "sync/protocol/sync.pb.h"
21
22 using base::ASCIIToUTF16;
23 using base::UTF8ToUTF16;
24 using base::UTF16ToUTF8;
25 using content::BrowserThread;
26
27 namespace autofill {
28
29 namespace {
30
31 std::string LimitData(const std::string& data) {
32 std::string sanitized_value(data);
33 if (sanitized_value.length() > AutofillTable::kMaxDataLength)
34 sanitized_value.resize(AutofillTable::kMaxDataLength);
35 return sanitized_value;
36 }
37
38 void* UserDataKey() {
39 // Use the address of a static that COMDAT folding won't ever fold
40 // with something else.
41 static int user_data_key = 0;
42 return reinterpret_cast<void*>(&user_data_key);
43 }
44
45 } // namespace
46
47 const char kAutofillProfileTag[] = "google_chrome_autofill_profiles";
48
49 AutofillProfileSyncableService::AutofillProfileSyncableService(
50 AutofillWebDataBackend* webdata_backend,
51 const std::string& app_locale)
52 : webdata_backend_(webdata_backend),
53 app_locale_(app_locale),
54 scoped_observer_(this) {
55 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
56 DCHECK(webdata_backend_);
57
58 scoped_observer_.Add(webdata_backend_);
59 }
60
61 AutofillProfileSyncableService::~AutofillProfileSyncableService() {
62 DCHECK(CalledOnValidThread());
63 }
64
65 // static
66 void AutofillProfileSyncableService::CreateForWebDataServiceAndBackend(
67 AutofillWebDataService* web_data_service,
68 AutofillWebDataBackend* webdata_backend,
69 const std::string& app_locale) {
70 web_data_service->GetDBUserData()->SetUserData(
71 UserDataKey(),
72 new AutofillProfileSyncableService(webdata_backend, app_locale));
73 }
74
75 // static
76 AutofillProfileSyncableService*
77 AutofillProfileSyncableService::FromWebDataService(
78 AutofillWebDataService* web_data_service) {
79 return static_cast<AutofillProfileSyncableService*>(
80 web_data_service->GetDBUserData()->GetUserData(UserDataKey()));
81 }
82
83 AutofillProfileSyncableService::AutofillProfileSyncableService()
84 : webdata_backend_(NULL),
85 scoped_observer_(this) {
86 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
87 }
88
89 syncer::SyncMergeResult
90 AutofillProfileSyncableService::MergeDataAndStartSyncing(
91 syncer::ModelType type,
92 const syncer::SyncDataList& initial_sync_data,
93 scoped_ptr<syncer::SyncChangeProcessor> sync_processor,
94 scoped_ptr<syncer::SyncErrorFactory> sync_error_factory) {
95 DCHECK(CalledOnValidThread());
96 DCHECK(!sync_processor_.get());
97 DCHECK(sync_processor.get());
98 DCHECK(sync_error_factory.get());
99 DVLOG(1) << "Associating Autofill: MergeDataAndStartSyncing";
100
101 syncer::SyncMergeResult merge_result(type);
102 sync_error_factory_ = sync_error_factory.Pass();
103 if (!LoadAutofillData(&profiles_.get())) {
104 merge_result.set_error(sync_error_factory_->CreateAndUploadError(
105 FROM_HERE, "Could not get the autofill data from WebDatabase."));
106 return merge_result;
107 }
108
109 if (DLOG_IS_ON(INFO)) {
110 DVLOG(2) << "[AUTOFILL MIGRATION]"
111 << "Printing profiles from web db";
112
113 for (ScopedVector<AutofillProfile>::const_iterator ix =
114 profiles_.begin(); ix != profiles_.end(); ++ix) {
115 AutofillProfile* p = *ix;
116 DVLOG(2) << "[AUTOFILL MIGRATION] "
117 << UTF16ToUTF8(p->GetRawInfo(NAME_FIRST))
118 << UTF16ToUTF8(p->GetRawInfo(NAME_LAST))
119 << p->guid();
120 }
121 }
122
123 sync_processor_ = sync_processor.Pass();
124
125 GUIDToProfileMap remaining_profiles;
126 CreateGUIDToProfileMap(profiles_.get(), &remaining_profiles);
127
128 DataBundle bundle;
129 // Go through and check for all the profiles that sync already knows about.
130 for (syncer::SyncDataList::const_iterator sync_iter =
131 initial_sync_data.begin();
132 sync_iter != initial_sync_data.end();
133 ++sync_iter) {
134 GUIDToProfileMap::iterator it =
135 CreateOrUpdateProfile(*sync_iter, &remaining_profiles, &bundle);
136 // |it| points to created/updated profile. Add it to the |profiles_map_| and
137 // then remove it from |remaining_profiles|. After this loop is completed
138 // |remaining_profiles| will have only those profiles that are not in the
139 // sync.
140 profiles_map_[it->first] = it->second;
141 remaining_profiles.erase(it);
142 }
143
144 // Check for similar unmatched profiles - they are created independently on
145 // two systems, so merge them.
146 for (GUIDToProfileMap::iterator it = bundle.candidates_to_merge.begin();
147 it != bundle.candidates_to_merge.end(); ++it) {
148 GUIDToProfileMap::iterator profile_to_merge =
149 remaining_profiles.find(it->first);
150 if (profile_to_merge != remaining_profiles.end()) {
151 bundle.profiles_to_delete.push_back(profile_to_merge->second->guid());
152 if (MergeProfile(*(profile_to_merge->second), it->second, app_locale_))
153 bundle.profiles_to_sync_back.push_back(it->second);
154 DVLOG(2) << "[AUTOFILL SYNC]"
155 << "Found similar profile in sync db but with a different guid: "
156 << UTF16ToUTF8(it->second->GetRawInfo(NAME_FIRST))
157 << UTF16ToUTF8(it->second->GetRawInfo(NAME_LAST))
158 << "New guid " << it->second->guid()
159 << ". Profile to be deleted "
160 << profile_to_merge->second->guid();
161 remaining_profiles.erase(profile_to_merge);
162 }
163 }
164
165 if (!SaveChangesToWebData(bundle)) {
166 merge_result.set_error(sync_error_factory_->CreateAndUploadError(
167 FROM_HERE,
168 "Failed to update webdata."));
169 return merge_result;
170 }
171
172 syncer::SyncChangeList new_changes;
173 for (GUIDToProfileMap::iterator i = remaining_profiles.begin();
174 i != remaining_profiles.end(); ++i) {
175 new_changes.push_back(
176 syncer::SyncChange(FROM_HERE,
177 syncer::SyncChange::ACTION_ADD,
178 CreateData(*(i->second))));
179 profiles_map_[i->first] = i->second;
180 }
181
182 for (size_t i = 0; i < bundle.profiles_to_sync_back.size(); ++i) {
183 new_changes.push_back(
184 syncer::SyncChange(FROM_HERE,
185 syncer::SyncChange::ACTION_UPDATE,
186 CreateData(*(bundle.profiles_to_sync_back[i]))));
187 }
188
189 if (!new_changes.empty()) {
190 merge_result.set_error(
191 sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes));
192 }
193
194 if (webdata_backend_)
195 webdata_backend_->NotifyOfMultipleAutofillChanges();
196
197 return merge_result;
198 }
199
200 void AutofillProfileSyncableService::StopSyncing(syncer::ModelType type) {
201 DCHECK(CalledOnValidThread());
202 DCHECK_EQ(type, syncer::AUTOFILL_PROFILE);
203
204 sync_processor_.reset();
205 sync_error_factory_.reset();
206 profiles_.clear();
207 profiles_map_.clear();
208 }
209
210 syncer::SyncDataList AutofillProfileSyncableService::GetAllSyncData(
211 syncer::ModelType type) const {
212 DCHECK(CalledOnValidThread());
213 DCHECK(sync_processor_.get());
214 DCHECK_EQ(type, syncer::AUTOFILL_PROFILE);
215
216 syncer::SyncDataList current_data;
217
218 for (GUIDToProfileMap::const_iterator i = profiles_map_.begin();
219 i != profiles_map_.end(); ++i) {
220 current_data.push_back(CreateData(*(i->second)));
221 }
222 return current_data;
223 }
224
225 syncer::SyncError AutofillProfileSyncableService::ProcessSyncChanges(
226 const tracked_objects::Location& from_here,
227 const syncer::SyncChangeList& change_list) {
228 DCHECK(CalledOnValidThread());
229 if (!sync_processor_.get()) {
230 syncer::SyncError error(FROM_HERE,
231 syncer::SyncError::DATATYPE_ERROR,
232 "Models not yet associated.",
233 syncer::AUTOFILL_PROFILE);
234 return error;
235 }
236
237 DataBundle bundle;
238
239 for (syncer::SyncChangeList::const_iterator i = change_list.begin();
240 i != change_list.end(); ++i) {
241 DCHECK(i->IsValid());
242 switch (i->change_type()) {
243 case syncer::SyncChange::ACTION_ADD:
244 case syncer::SyncChange::ACTION_UPDATE:
245 CreateOrUpdateProfile(i->sync_data(), &profiles_map_, &bundle);
246 break;
247 case syncer::SyncChange::ACTION_DELETE: {
248 std::string guid = i->sync_data().GetSpecifics().
249 autofill_profile().guid();
250 bundle.profiles_to_delete.push_back(guid);
251 profiles_map_.erase(guid);
252 } break;
253 default:
254 NOTREACHED() << "Unexpected sync change state.";
255 return sync_error_factory_->CreateAndUploadError(
256 FROM_HERE,
257 "ProcessSyncChanges failed on ChangeType " +
258 syncer::SyncChange::ChangeTypeToString(i->change_type()));
259 }
260 }
261
262 if (!SaveChangesToWebData(bundle)) {
263 return sync_error_factory_->CreateAndUploadError(
264 FROM_HERE,
265 "Failed to update webdata.");
266 }
267
268 if (webdata_backend_)
269 webdata_backend_->NotifyOfMultipleAutofillChanges();
270
271 return syncer::SyncError();
272 }
273
274 void AutofillProfileSyncableService::AutofillProfileChanged(
275 const AutofillProfileChange& change) {
276 // Check if sync is on. If we receive notification prior to the sync being set
277 // up we are going to process all when MergeData..() is called. If we receive
278 // notification after the sync exited, it will be sinced next time Chrome
279 // starts.
280 if (sync_processor_.get()) {
281 ActOnChange(change);
282 } else if (!flare_.is_null()) {
283 flare_.Run(syncer::AUTOFILL_PROFILE);
284 flare_.Reset();
285 }
286 }
287
288 bool AutofillProfileSyncableService::LoadAutofillData(
289 std::vector<AutofillProfile*>* profiles) {
290 return GetAutofillTable()->GetAutofillProfiles(profiles);
291 }
292
293 bool AutofillProfileSyncableService::SaveChangesToWebData(
294 const DataBundle& bundle) {
295 DCHECK(CalledOnValidThread());
296
297 AutofillTable* autofill_table = GetAutofillTable();
298
299 bool success = true;
300 for (size_t i = 0; i< bundle.profiles_to_delete.size(); ++i) {
301 if (!autofill_table->RemoveAutofillProfile(bundle.profiles_to_delete[i]))
302 success = false;
303 }
304
305 for (size_t i = 0; i < bundle.profiles_to_add.size(); i++) {
306 if (!autofill_table->AddAutofillProfile(*bundle.profiles_to_add[i]))
307 success = false;
308 }
309
310 for (size_t i = 0; i < bundle.profiles_to_update.size(); i++) {
311 if (!autofill_table->UpdateAutofillProfile(*bundle.profiles_to_update[i]))
312 success = false;
313 }
314 return success;
315 }
316
317 // static
318 bool AutofillProfileSyncableService::OverwriteProfileWithServerData(
319 const sync_pb::AutofillProfileSpecifics& specifics,
320 AutofillProfile* profile,
321 const std::string& app_locale) {
322 bool diff = false;
323 if (profile->origin() != specifics.origin()) {
324 bool was_verified = profile->IsVerified();
325 profile->set_origin(specifics.origin());
326 diff = true;
327
328 // Verified profiles should never be overwritten by unverified ones.
329 DCHECK(!was_verified || profile->IsVerified());
330 }
331
332 // Update all multivalued fields: names, emails, and phones.
333 diff = UpdateMultivaluedField(NAME_FIRST,
334 specifics.name_first(), profile) || diff;
335 diff = UpdateMultivaluedField(NAME_MIDDLE,
336 specifics.name_middle(), profile) || diff;
337 diff = UpdateMultivaluedField(NAME_LAST,
338 specifics.name_last(), profile) || diff;
339 diff = UpdateMultivaluedField(EMAIL_ADDRESS,
340 specifics.email_address(), profile) || diff;
341 diff = UpdateMultivaluedField(PHONE_HOME_WHOLE_NUMBER,
342 specifics.phone_home_whole_number(),
343 profile) || diff;
344
345 // Update all simple single-valued address fields.
346 diff = UpdateField(COMPANY_NAME, specifics.company_name(), profile) || diff;
347 diff = UpdateField(ADDRESS_HOME_CITY,
348 specifics.address_home_city(), profile) || diff;
349 diff = UpdateField(ADDRESS_HOME_STATE,
350 specifics.address_home_state(), profile) || diff;
351 diff = UpdateField(ADDRESS_HOME_ZIP,
352 specifics.address_home_zip(), profile) || diff;
353 diff = UpdateField(ADDRESS_HOME_SORTING_CODE,
354 specifics.address_home_sorting_code(), profile) || diff;
355 diff = UpdateField(ADDRESS_HOME_DEPENDENT_LOCALITY,
356 specifics.address_home_dependent_locality(),
357 profile) || diff;
358
359 // Update the country field, which can contain either a country code (if set
360 // by a newer version of Chrome), or a country name (if set by an older
361 // version of Chrome).
362 base::string16 country_name_or_code =
363 ASCIIToUTF16(specifics.address_home_country());
364 std::string country_code =
365 AutofillCountry::GetCountryCode(country_name_or_code, app_locale);
366 diff = UpdateField(ADDRESS_HOME_COUNTRY, country_code, profile) || diff;
367
368 // Update the street address. In newer versions of Chrome (M34+), this data
369 // is stored in the |address_home_street_address| field. In older versions,
370 // this data is stored separated out by address line.
371 if (specifics.has_address_home_street_address()) {
372 diff = UpdateField(ADDRESS_HOME_STREET_ADDRESS,
373 specifics.address_home_street_address(),
374 profile) || diff;
375 } else {
376 diff = UpdateField(ADDRESS_HOME_LINE1,
377 specifics.address_home_line1(), profile) || diff;
378 diff = UpdateField(ADDRESS_HOME_LINE2,
379 specifics.address_home_line2(), profile) || diff;
380 }
381 return diff;
382 }
383
384 // static
385 void AutofillProfileSyncableService::WriteAutofillProfile(
386 const AutofillProfile& profile,
387 sync_pb::EntitySpecifics* profile_specifics) {
388 sync_pb::AutofillProfileSpecifics* specifics =
389 profile_specifics->mutable_autofill_profile();
390
391 DCHECK(base::IsValidGUID(profile.guid()));
392
393 // Reset all multi-valued fields in the protobuf.
394 specifics->clear_name_first();
395 specifics->clear_name_middle();
396 specifics->clear_name_last();
397 specifics->clear_email_address();
398 specifics->clear_phone_home_whole_number();
399
400 specifics->set_guid(profile.guid());
401 specifics->set_origin(profile.origin());
402
403 std::vector<base::string16> values;
404 profile.GetRawMultiInfo(NAME_FIRST, &values);
405 for (size_t i = 0; i < values.size(); ++i) {
406 specifics->add_name_first(LimitData(UTF16ToUTF8(values[i])));
407 }
408
409 profile.GetRawMultiInfo(NAME_MIDDLE, &values);
410 for (size_t i = 0; i < values.size(); ++i) {
411 specifics->add_name_middle(LimitData(UTF16ToUTF8(values[i])));
412 }
413
414 profile.GetRawMultiInfo(NAME_LAST, &values);
415 for (size_t i = 0; i < values.size(); ++i) {
416 specifics->add_name_last(LimitData(UTF16ToUTF8(values[i])));
417 }
418
419 specifics->set_address_home_line1(
420 LimitData(UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_LINE1))));
421 specifics->set_address_home_line2(
422 LimitData(UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_LINE2))));
423 specifics->set_address_home_city(
424 LimitData(UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_CITY))));
425 specifics->set_address_home_state(
426 LimitData(UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_STATE))));
427 specifics->set_address_home_zip(
428 LimitData(UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_ZIP))));
429 specifics->set_address_home_country(
430 LimitData(UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_COUNTRY))));
431 specifics->set_address_home_street_address(
432 LimitData(UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS))));
433 specifics->set_address_home_sorting_code(
434 LimitData(UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_SORTING_CODE))));
435 specifics->set_address_home_dependent_locality(
436 LimitData(
437 UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY))));
438
439 profile.GetRawMultiInfo(EMAIL_ADDRESS, &values);
440 for (size_t i = 0; i < values.size(); ++i) {
441 specifics->add_email_address(LimitData(UTF16ToUTF8(values[i])));
442 }
443
444 specifics->set_company_name(
445 LimitData(UTF16ToUTF8(profile.GetRawInfo(COMPANY_NAME))));
446
447 profile.GetRawMultiInfo(PHONE_HOME_WHOLE_NUMBER, &values);
448 for (size_t i = 0; i < values.size(); ++i) {
449 specifics->add_phone_home_whole_number(LimitData(UTF16ToUTF8(values[i])));
450 }
451 }
452
453 void AutofillProfileSyncableService::CreateGUIDToProfileMap(
454 const std::vector<AutofillProfile*>& profiles,
455 GUIDToProfileMap* profile_map) {
456 DCHECK(profile_map);
457 profile_map->clear();
458 for (size_t i = 0; i < profiles.size(); ++i)
459 (*profile_map)[profiles[i]->guid()] = profiles[i];
460 }
461
462 AutofillProfileSyncableService::GUIDToProfileMap::iterator
463 AutofillProfileSyncableService::CreateOrUpdateProfile(
464 const syncer::SyncData& data,
465 GUIDToProfileMap* profile_map,
466 DataBundle* bundle) {
467 DCHECK(profile_map);
468 DCHECK(bundle);
469
470 DCHECK_EQ(syncer::AUTOFILL_PROFILE, data.GetDataType());
471
472 const sync_pb::EntitySpecifics& specifics = data.GetSpecifics();
473 const sync_pb::AutofillProfileSpecifics& autofill_specifics(
474 specifics.autofill_profile());
475
476 GUIDToProfileMap::iterator existing_profile = profile_map->find(
477 autofill_specifics.guid());
478 if (existing_profile != profile_map->end()) {
479 // The synced profile already exists locally. It might need to be updated.
480 if (OverwriteProfileWithServerData(
481 autofill_specifics, existing_profile->second, app_locale_)) {
482 bundle->profiles_to_update.push_back(existing_profile->second);
483 }
484 return existing_profile;
485 }
486
487
488 // New profile synced.
489 AutofillProfile* new_profile = new AutofillProfile(
490 autofill_specifics.guid(), autofill_specifics.origin());
491 OverwriteProfileWithServerData(autofill_specifics, new_profile, app_locale_);
492
493 // Check if profile appears under a different guid.
494 // Unverified profiles should never overwrite verified ones.
495 for (GUIDToProfileMap::iterator it = profile_map->begin();
496 it != profile_map->end(); ++it) {
497 AutofillProfile* local_profile = it->second;
498 if (local_profile->Compare(*new_profile) == 0) {
499 // Ensure that a verified profile can never revert back to an unverified
500 // one.
501 if (local_profile->IsVerified() && !new_profile->IsVerified()) {
502 new_profile->set_origin(local_profile->origin());
503 bundle->profiles_to_sync_back.push_back(new_profile);
504 }
505
506 bundle->profiles_to_delete.push_back(local_profile->guid());
507 DVLOG(2) << "[AUTOFILL SYNC]"
508 << "Found in sync db but with a different guid: "
509 << UTF16ToUTF8(local_profile->GetRawInfo(NAME_FIRST))
510 << UTF16ToUTF8(local_profile->GetRawInfo(NAME_LAST))
511 << "New guid " << new_profile->guid()
512 << ". Profile to be deleted " << local_profile->guid();
513 profile_map->erase(it);
514 break;
515 } else if (!local_profile->IsVerified() &&
516 !new_profile->IsVerified() &&
517 !local_profile->PrimaryValue().empty() &&
518 local_profile->PrimaryValue() == new_profile->PrimaryValue()) {
519 // Add it to candidates for merge - if there is no profile with this
520 // guid we will merge them.
521 bundle->candidates_to_merge.insert(
522 std::make_pair(local_profile->guid(), new_profile));
523 }
524 }
525 profiles_.push_back(new_profile);
526 bundle->profiles_to_add.push_back(new_profile);
527 return profile_map->insert(std::make_pair(new_profile->guid(),
528 new_profile)).first;
529 }
530
531 void AutofillProfileSyncableService::ActOnChange(
532 const AutofillProfileChange& change) {
533 DCHECK((change.type() == AutofillProfileChange::REMOVE &&
534 !change.profile()) ||
535 (change.type() != AutofillProfileChange::REMOVE && change.profile()));
536 DCHECK(sync_processor_.get());
537 syncer::SyncChangeList new_changes;
538 DataBundle bundle;
539 switch (change.type()) {
540 case AutofillProfileChange::ADD:
541 new_changes.push_back(
542 syncer::SyncChange(FROM_HERE,
543 syncer::SyncChange::ACTION_ADD,
544 CreateData(*(change.profile()))));
545 DCHECK(profiles_map_.find(change.profile()->guid()) ==
546 profiles_map_.end());
547 profiles_.push_back(new AutofillProfile(*(change.profile())));
548 profiles_map_[change.profile()->guid()] = profiles_.get().back();
549 break;
550 case AutofillProfileChange::UPDATE: {
551 GUIDToProfileMap::iterator it = profiles_map_.find(
552 change.profile()->guid());
553 DCHECK(it != profiles_map_.end());
554 *(it->second) = *(change.profile());
555 new_changes.push_back(
556 syncer::SyncChange(FROM_HERE,
557 syncer::SyncChange::ACTION_UPDATE,
558 CreateData(*(change.profile()))));
559 break;
560 }
561 case AutofillProfileChange::REMOVE: {
562 AutofillProfile empty_profile(change.key(), std::string());
563 new_changes.push_back(
564 syncer::SyncChange(FROM_HERE,
565 syncer::SyncChange::ACTION_DELETE,
566 CreateData(empty_profile)));
567 profiles_map_.erase(change.key());
568 break;
569 }
570 default:
571 NOTREACHED();
572 }
573 syncer::SyncError error =
574 sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes);
575 if (error.IsSet()) {
576 // TODO(isherman): Investigating http://crbug.com/121592
577 VLOG(1) << "[AUTOFILL SYNC] "
578 << "Failed processing change:\n"
579 << " Error: " << error.message() << "\n"
580 << " Guid: " << change.key();
581 }
582 }
583
584 syncer::SyncData AutofillProfileSyncableService::CreateData(
585 const AutofillProfile& profile) {
586 sync_pb::EntitySpecifics specifics;
587 WriteAutofillProfile(profile, &specifics);
588 return
589 syncer::SyncData::CreateLocalData(
590 profile.guid(), profile.guid(), specifics);
591 }
592
593 bool AutofillProfileSyncableService::UpdateField(
594 ServerFieldType field_type,
595 const std::string& new_value,
596 AutofillProfile* autofill_profile) {
597 if (UTF16ToUTF8(autofill_profile->GetRawInfo(field_type)) == new_value)
598 return false;
599 autofill_profile->SetRawInfo(field_type, UTF8ToUTF16(new_value));
600 return true;
601 }
602
603 bool AutofillProfileSyncableService::UpdateMultivaluedField(
604 ServerFieldType field_type,
605 const ::google::protobuf::RepeatedPtrField<std::string>& new_values,
606 AutofillProfile* autofill_profile) {
607 std::vector<base::string16> values;
608 autofill_profile->GetRawMultiInfo(field_type, &values);
609 bool changed = false;
610 if (static_cast<size_t>(new_values.size()) != values.size()) {
611 values.clear();
612 values.resize(static_cast<size_t>(new_values.size()));
613 changed = true;
614 }
615 for (size_t i = 0; i < values.size(); ++i) {
616 base::string16 synced_value(
617 UTF8ToUTF16(new_values.Get(static_cast<int>(i))));
618 if (values[i] != synced_value) {
619 values[i] = synced_value;
620 changed = true;
621 }
622 }
623 if (changed)
624 autofill_profile->SetRawMultiInfo(field_type, values);
625 return changed;
626 }
627
628 bool AutofillProfileSyncableService::MergeProfile(
629 const AutofillProfile& merge_from,
630 AutofillProfile* merge_into,
631 const std::string& app_locale) {
632 merge_into->OverwriteWithOrAddTo(merge_from, app_locale);
633 return (merge_into->Compare(merge_from) != 0 ||
634 merge_into->origin() != merge_from.origin());
635 }
636
637 AutofillTable* AutofillProfileSyncableService::GetAutofillTable() const {
638 return AutofillTable::FromWebDatabase(webdata_backend_->GetDatabase());
639 }
640
641 void AutofillProfileSyncableService::InjectStartSyncFlare(
642 const syncer::SyncableService::StartSyncFlare& flare) {
643 flare_ = flare;
644 }
645
646 AutofillProfileSyncableService::DataBundle::DataBundle() {}
647
648 AutofillProfileSyncableService::DataBundle::~DataBundle() {}
649
650 } // namespace autofill
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698