OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/webdata/autofill_profile_syncable_service.h" | 5 #include "chrome/browser/webdata/autofill_profile_syncable_service.h" |
6 | 6 |
7 #include "base/guid.h" | 7 #include "base/guid.h" |
8 #include "base/location.h" | 8 #include "base/location.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/strings/utf_string_conversions.h" | 10 #include "base/strings/utf_string_conversions.h" |
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
312 } | 312 } |
313 return success; | 313 return success; |
314 } | 314 } |
315 | 315 |
316 // static | 316 // static |
317 bool AutofillProfileSyncableService::OverwriteProfileWithServerData( | 317 bool AutofillProfileSyncableService::OverwriteProfileWithServerData( |
318 const sync_pb::AutofillProfileSpecifics& specifics, | 318 const sync_pb::AutofillProfileSpecifics& specifics, |
319 AutofillProfile* profile, | 319 AutofillProfile* profile, |
320 const std::string& app_locale) { | 320 const std::string& app_locale) { |
321 bool diff = false; | 321 bool diff = false; |
| 322 if (profile->origin() != specifics.origin()) { |
| 323 bool was_verified = profile->IsVerified(); |
| 324 profile->set_origin(specifics.origin()); |
| 325 diff = true; |
| 326 |
| 327 // Verified profiles should never be overwritten by unverified ones. |
| 328 DCHECK(!was_verified || profile->IsVerified()); |
| 329 } |
| 330 |
322 diff = UpdateMultivaluedField(autofill::NAME_FIRST, | 331 diff = UpdateMultivaluedField(autofill::NAME_FIRST, |
323 specifics.name_first(), profile) || diff; | 332 specifics.name_first(), profile) || diff; |
324 diff = UpdateMultivaluedField(autofill::NAME_MIDDLE, | 333 diff = UpdateMultivaluedField(autofill::NAME_MIDDLE, |
325 specifics.name_middle(), profile) || diff; | 334 specifics.name_middle(), profile) || diff; |
326 diff = UpdateMultivaluedField(autofill::NAME_LAST, | 335 diff = UpdateMultivaluedField(autofill::NAME_LAST, |
327 specifics.name_last(), profile) || diff; | 336 specifics.name_last(), profile) || diff; |
328 diff = UpdateField(autofill::ADDRESS_HOME_LINE1, | 337 diff = UpdateField(autofill::ADDRESS_HOME_LINE1, |
329 specifics.address_home_line1(), profile) || diff; | 338 specifics.address_home_line1(), profile) || diff; |
330 diff = UpdateField(autofill::ADDRESS_HOME_LINE2, | 339 diff = UpdateField(autofill::ADDRESS_HOME_LINE2, |
331 specifics.address_home_line2(), profile) || diff; | 340 specifics.address_home_line2(), profile) || diff; |
(...skipping 29 matching lines...) Expand all Loading... |
361 DCHECK(base::IsValidGUID(profile.guid())); | 370 DCHECK(base::IsValidGUID(profile.guid())); |
362 | 371 |
363 // Reset all multi-valued fields in the protobuf. | 372 // Reset all multi-valued fields in the protobuf. |
364 specifics->clear_name_first(); | 373 specifics->clear_name_first(); |
365 specifics->clear_name_middle(); | 374 specifics->clear_name_middle(); |
366 specifics->clear_name_last(); | 375 specifics->clear_name_last(); |
367 specifics->clear_email_address(); | 376 specifics->clear_email_address(); |
368 specifics->clear_phone_home_whole_number(); | 377 specifics->clear_phone_home_whole_number(); |
369 | 378 |
370 specifics->set_guid(profile.guid()); | 379 specifics->set_guid(profile.guid()); |
| 380 specifics->set_origin(profile.origin()); |
| 381 |
371 std::vector<string16> values; | 382 std::vector<string16> values; |
372 profile.GetRawMultiInfo(autofill::NAME_FIRST, &values); | 383 profile.GetRawMultiInfo(autofill::NAME_FIRST, &values); |
373 for (size_t i = 0; i < values.size(); ++i) { | 384 for (size_t i = 0; i < values.size(); ++i) { |
374 specifics->add_name_first(LimitData(UTF16ToUTF8(values[i]))); | 385 specifics->add_name_first(LimitData(UTF16ToUTF8(values[i]))); |
375 } | 386 } |
376 | 387 |
377 profile.GetRawMultiInfo(autofill::NAME_MIDDLE, &values); | 388 profile.GetRawMultiInfo(autofill::NAME_MIDDLE, &values); |
378 for (size_t i = 0; i < values.size(); ++i) { | 389 for (size_t i = 0; i < values.size(); ++i) { |
379 specifics->add_name_middle(LimitData(UTF16ToUTF8(values[i]))); | 390 specifics->add_name_middle(LimitData(UTF16ToUTF8(values[i]))); |
380 } | 391 } |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
428 DataBundle* bundle) { | 439 DataBundle* bundle) { |
429 DCHECK(profile_map); | 440 DCHECK(profile_map); |
430 DCHECK(bundle); | 441 DCHECK(bundle); |
431 | 442 |
432 DCHECK_EQ(syncer::AUTOFILL_PROFILE, data.GetDataType()); | 443 DCHECK_EQ(syncer::AUTOFILL_PROFILE, data.GetDataType()); |
433 | 444 |
434 const sync_pb::EntitySpecifics& specifics = data.GetSpecifics(); | 445 const sync_pb::EntitySpecifics& specifics = data.GetSpecifics(); |
435 const sync_pb::AutofillProfileSpecifics& autofill_specifics( | 446 const sync_pb::AutofillProfileSpecifics& autofill_specifics( |
436 specifics.autofill_profile()); | 447 specifics.autofill_profile()); |
437 | 448 |
438 GUIDToProfileMap::iterator it = profile_map->find( | 449 GUIDToProfileMap::iterator existing_profile = profile_map->find( |
439 autofill_specifics.guid()); | 450 autofill_specifics.guid()); |
440 if (it != profile_map->end()) { | 451 if (existing_profile != profile_map->end()) { |
441 // Some profile that already present is synced. | 452 // The synced profile already exists locally. It might need to be updated. |
442 if (OverwriteProfileWithServerData( | 453 if (OverwriteProfileWithServerData( |
443 autofill_specifics, it->second, app_locale_)) { | 454 autofill_specifics, existing_profile->second, app_locale_)) { |
444 bundle->profiles_to_update.push_back(it->second); | 455 bundle->profiles_to_update.push_back(existing_profile->second); |
445 } | 456 } |
446 } else { | 457 return existing_profile; |
447 // New profile synced. | 458 } |
448 // TODO(isherman): Read the origin from |autofill_specifics|. | |
449 AutofillProfile* new_profile( | |
450 new AutofillProfile(autofill_specifics.guid(), std::string())); | |
451 OverwriteProfileWithServerData( | |
452 autofill_specifics, new_profile, app_locale_); | |
453 | 459 |
454 // Check if profile appears under a different guid. | 460 |
455 for (GUIDToProfileMap::iterator i = profile_map->begin(); | 461 // New profile synced. |
456 i != profile_map->end(); ++i) { | 462 AutofillProfile* new_profile = new AutofillProfile( |
457 if (i->second->Compare(*new_profile) == 0) { | 463 autofill_specifics.guid(), autofill_specifics.origin()); |
458 bundle->profiles_to_delete.push_back(i->second->guid()); | 464 OverwriteProfileWithServerData(autofill_specifics, new_profile, app_locale_); |
459 DVLOG(2) << "[AUTOFILL SYNC]" | 465 |
460 << "Found in sync db but with a different guid: " | 466 // Check if profile appears under a different guid. |
461 << UTF16ToUTF8(i->second->GetRawInfo(autofill::NAME_FIRST)) | 467 // Unverified profiles should never overwrite verified ones. |
462 << UTF16ToUTF8(i->second->GetRawInfo(autofill::NAME_LAST)) | 468 for (GUIDToProfileMap::iterator it = profile_map->begin(); |
463 << "New guid " << new_profile->guid() | 469 it != profile_map->end(); ++it) { |
464 << ". Profile to be deleted " << i->second->guid(); | 470 AutofillProfile* local_profile = it->second; |
465 profile_map->erase(i); | 471 if (local_profile->Compare(*new_profile) == 0) { |
466 break; | 472 // Ensure that a verified profile can never revert back to an unverified |
467 } else if (!i->second->PrimaryValue().empty() && | 473 // one. |
468 i->second->PrimaryValue() == new_profile->PrimaryValue()) { | 474 if (local_profile->IsVerified() && !new_profile->IsVerified()) { |
469 // Add it to candidates for merge - if there is no profile with this | 475 new_profile->set_origin(local_profile->origin()); |
470 // guid we will merge them. | 476 bundle->profiles_to_sync_back.push_back(new_profile); |
471 bundle->candidates_to_merge.insert(std::make_pair(i->second->guid(), | |
472 new_profile)); | |
473 } | 477 } |
| 478 |
| 479 bundle->profiles_to_delete.push_back(local_profile->guid()); |
| 480 DVLOG(2) << "[AUTOFILL SYNC]" |
| 481 << "Found in sync db but with a different guid: " |
| 482 << UTF16ToUTF8(local_profile->GetRawInfo(autofill::NAME_FIRST)) |
| 483 << UTF16ToUTF8(local_profile->GetRawInfo(autofill::NAME_LAST)) |
| 484 << "New guid " << new_profile->guid() |
| 485 << ". Profile to be deleted " << local_profile->guid(); |
| 486 profile_map->erase(it); |
| 487 break; |
| 488 } else if (!local_profile->IsVerified() && |
| 489 !new_profile->IsVerified() && |
| 490 !local_profile->PrimaryValue().empty() && |
| 491 local_profile->PrimaryValue() == new_profile->PrimaryValue()) { |
| 492 // Add it to candidates for merge - if there is no profile with this |
| 493 // guid we will merge them. |
| 494 bundle->candidates_to_merge.insert( |
| 495 std::make_pair(local_profile->guid(), new_profile)); |
474 } | 496 } |
475 profiles_.push_back(new_profile); | 497 } |
476 it = profile_map->insert(std::make_pair(new_profile->guid(), | 498 profiles_.push_back(new_profile); |
| 499 bundle->profiles_to_add.push_back(new_profile); |
| 500 return profile_map->insert(std::make_pair(new_profile->guid(), |
477 new_profile)).first; | 501 new_profile)).first; |
478 bundle->profiles_to_add.push_back(new_profile); | |
479 } | |
480 return it; | |
481 } | 502 } |
482 | 503 |
483 void AutofillProfileSyncableService::ActOnChange( | 504 void AutofillProfileSyncableService::ActOnChange( |
484 const AutofillProfileChange& change) { | 505 const AutofillProfileChange& change) { |
485 DCHECK((change.type() == AutofillProfileChange::REMOVE && | 506 DCHECK((change.type() == AutofillProfileChange::REMOVE && |
486 !change.profile()) || | 507 !change.profile()) || |
487 (change.type() != AutofillProfileChange::REMOVE && change.profile())); | 508 (change.type() != AutofillProfileChange::REMOVE && change.profile())); |
488 DCHECK(sync_processor_.get()); | 509 DCHECK(sync_processor_.get()); |
489 syncer::SyncChangeList new_changes; | 510 syncer::SyncChangeList new_changes; |
490 DataBundle bundle; | 511 DataBundle bundle; |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
575 if (changed) | 596 if (changed) |
576 autofill_profile->SetRawMultiInfo(field_type, values); | 597 autofill_profile->SetRawMultiInfo(field_type, values); |
577 return changed; | 598 return changed; |
578 } | 599 } |
579 | 600 |
580 bool AutofillProfileSyncableService::MergeProfile( | 601 bool AutofillProfileSyncableService::MergeProfile( |
581 const AutofillProfile& merge_from, | 602 const AutofillProfile& merge_from, |
582 AutofillProfile* merge_into, | 603 AutofillProfile* merge_into, |
583 const std::string& app_locale) { | 604 const std::string& app_locale) { |
584 merge_into->OverwriteWithOrAddTo(merge_from, app_locale); | 605 merge_into->OverwriteWithOrAddTo(merge_from, app_locale); |
585 return (merge_into->Compare(merge_from) != 0); | 606 return (merge_into->Compare(merge_from) != 0 || |
| 607 merge_into->origin() != merge_from.origin()); |
586 } | 608 } |
587 | 609 |
588 AutofillTable* AutofillProfileSyncableService::GetAutofillTable() const { | 610 AutofillTable* AutofillProfileSyncableService::GetAutofillTable() const { |
589 return AutofillTable::FromWebDatabase(webdata_backend_->GetDatabase()); | 611 return AutofillTable::FromWebDatabase(webdata_backend_->GetDatabase()); |
590 } | 612 } |
591 | 613 |
592 void AutofillProfileSyncableService::InjectStartSyncFlare( | 614 void AutofillProfileSyncableService::InjectStartSyncFlare( |
593 const syncer::SyncableService::StartSyncFlare& flare) { | 615 const syncer::SyncableService::StartSyncFlare& flare) { |
594 flare_ = flare; | 616 flare_ = flare; |
595 } | 617 } |
596 | 618 |
597 AutofillProfileSyncableService::DataBundle::DataBundle() {} | 619 AutofillProfileSyncableService::DataBundle::DataBundle() {} |
598 | 620 |
599 AutofillProfileSyncableService::DataBundle::~DataBundle() {} | 621 AutofillProfileSyncableService::DataBundle::~DataBundle() {} |
OLD | NEW |