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

Unified Diff: components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc

Issue 1110833002: [autofill] Sync server card and address metadata. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Ditch ternary operator Created 5 years, 7 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 side-by-side diff with in-line comments
Download patch
Index: components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc b/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc
new file mode 100644
index 0000000000000000000000000000000000000000..49f1bec32f2565d002cb6621e08ec48a27d08d15
--- /dev/null
+++ b/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc
@@ -0,0 +1,410 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.h"
+
+#include <utility>
+
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/credit_card.h"
+#include "components/autofill/core/browser/webdata/autofill_table.h"
+#include "components/autofill/core/browser/webdata/autofill_webdata_backend.h"
+#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
+#include "sync/api/sync_change.h"
+#include "sync/api/sync_error_factory.h"
+#include "sync/protocol/autofill_specifics.pb.h"
+#include "sync/protocol/sync.pb.h"
+
+namespace autofill {
+
+namespace {
+
+void* UserDataKey() {
+ // Use the address of a static so that COMDAT folding won't ever fold
+ // with something else.
+ static int user_data_key = 0;
+ return reinterpret_cast<void*>(&user_data_key);
+}
+
+// Returns syncable metadata for the |local| profile or credit card.
+syncer::SyncData CreateSyncData(const AutofillDataModel& local,
+ const std::string& server_id,
+ sync_pb::WalletMetadataSpecifics::Type type) {
+ sync_pb::EntitySpecifics entity;
+ sync_pb::WalletMetadataSpecifics* metadata = entity.mutable_wallet_metadata();
+ metadata->set_type(type);
+ metadata->set_id(server_id);
+ metadata->set_use_count(local.use_count());
+ metadata->set_use_date(local.use_date().ToInternalValue());
+
+ std::string sync_tag;
+ switch (type) {
+ case sync_pb::WalletMetadataSpecifics::ADDRESS:
+ sync_tag = "address-" + server_id;
+ break;
+ case sync_pb::WalletMetadataSpecifics::CARD:
+ sync_tag = "card-" + server_id;
+ break;
+ case sync_pb::WalletMetadataSpecifics::UNKNOWN:
+ NOTREACHED();
+ break;
+ }
+
+ return syncer::SyncData::CreateLocalData(sync_tag, sync_tag, entity);
+}
+
+// Updates |local| usage stats from |remote_use_count| and |remote_use_date| if
+// necessary. Returns true if |local| is modified.
+bool UpdateLocalStats(size_t remote_use_count,
+ const base::Time& remote_use_date,
+ AutofillDataModel* local) {
+ bool modified = false;
+ if (local->use_count() < remote_use_count) {
+ local->set_use_count(remote_use_count);
+ modified = true;
+ }
+
+ if (local->use_date() < remote_use_date) {
+ local->set_use_date(remote_use_date);
+ modified = true;
+ }
+
+ return modified;
+}
+
+} // namespace
+
+AutofillWalletMetadataSyncableService::
+ ~AutofillWalletMetadataSyncableService() {
+}
+
+syncer::SyncMergeResult
+AutofillWalletMetadataSyncableService::MergeDataAndStartSyncing(
+ syncer::ModelType type,
+ const syncer::SyncDataList& initial_sync_data,
+ scoped_ptr<syncer::SyncChangeProcessor> sync_processor,
+ scoped_ptr<syncer::SyncErrorFactory> sync_error_factory) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(!sync_processor_);
+ DCHECK(!sync_error_factory_);
+ DCHECK_EQ(syncer::AUTOFILL_WALLET_METADATA, type);
+
+ sync_processor_ = sync_processor.Pass();
+ sync_error_factory_ = sync_error_factory.Pass();
+
+ syncer::SyncMergeResult result(syncer::AUTOFILL_WALLET_METADATA);
+ result.set_error(Reconcile(initial_sync_data));
+
+ return result;
+}
+
+void AutofillWalletMetadataSyncableService::StopSyncing(
+ syncer::ModelType type) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK_EQ(syncer::AUTOFILL_WALLET_METADATA, type);
+ sync_processor_.reset();
+ sync_error_factory_.reset();
+}
+
+syncer::SyncDataList AutofillWalletMetadataSyncableService::GetAllSyncData(
+ syncer::ModelType type) const {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK_EQ(syncer::AUTOFILL_WALLET_METADATA, type);
+
+ syncer::SyncDataList data_list;
+ std::vector<AutofillProfile*> profiles;
+ if (GetServerProfiles(&profiles)) {
+ for (const AutofillProfile* profile : profiles) {
+ data_list.push_back(
+ CreateSyncData(*profile, profile->server_id(),
+ sync_pb::WalletMetadataSpecifics::ADDRESS));
+ }
+ }
+
+ std::vector<CreditCard*> credit_cards;
+ if (GetServerCreditCards(&credit_cards)) {
+ for (const CreditCard* credit_card : credit_cards) {
+ data_list.push_back(
+ CreateSyncData(*credit_card, credit_card->server_id(),
+ sync_pb::WalletMetadataSpecifics::CARD));
+ }
+ }
+
+ return data_list;
+}
+
+syncer::SyncError AutofillWalletMetadataSyncableService::ProcessSyncChanges(
+ const tracked_objects::Location& from_here,
+ const syncer::SyncChangeList& change_list) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ std::map<std::string, AutofillProfile*> profiles;
+ std::map<std::string, CreditCard*> cards;
+ GetServerData(&profiles, &cards);
+
+ for (const syncer::SyncChange& change : change_list) {
+ // Add and update behave the same. Delete is ignored, because metadata is
+ // deleted along with the corresponding Wallet data.
+ if (change.change_type() == syncer::SyncChange::ACTION_ADD ||
+ change.change_type() == syncer::SyncChange::ACTION_UPDATE) {
+ const sync_pb::WalletMetadataSpecifics& metadata =
+ change.sync_data().GetSpecifics().wallet_metadata();
+
+ switch (metadata.type()) {
+ case sync_pb::WalletMetadataSpecifics::ADDRESS: {
+ if (profiles.find(metadata.id()) == profiles.end())
+ break;
+
+ AutofillProfile profile(AutofillProfile::SERVER_PROFILE,
+ metadata.id());
+ profile.set_use_count(metadata.use_count());
+ profile.set_use_date(
+ base::Time::FromInternalValue(metadata.use_date()));
+ UpdateServerAddressUsageStats(profile);
+ break;
+ }
+
+ case sync_pb::WalletMetadataSpecifics::CARD: {
+ if (cards.find(metadata.id()) == cards.end())
+ break;
+
+ // Does not matter whether MASKED_SERVER_CARD or FULL_SERVER_CARD is
+ // specified, because UpdateServerCardUsageStats does not use this
+ // value.
+ CreditCard card(CreditCard::MASKED_SERVER_CARD, metadata.id());
+ card.set_use_count(metadata.use_count());
+ card.set_use_date(base::Time::FromInternalValue(metadata.use_date()));
+ UpdateServerCardUsageStats(card);
+ break;
+ }
+
+ case sync_pb::WalletMetadataSpecifics::UNKNOWN:
+ NOTREACHED();
+ break;
+ }
+ }
+ }
+
+ return syncer::SyncError();
+}
+
+void AutofillWalletMetadataSyncableService::AutofillProfileChanged(
+ const AutofillProfileChange& change) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ // Handle only metadata updates while syncing. Addition and deletion are
+ // handled in AutofillMultipleChanged.
+ if (!sync_processor_ || change.type() != AutofillProfileChange::UPDATE ||
+ change.profile()->record_type() != AutofillProfile::SERVER_PROFILE) {
+ return;
+ }
+
+ syncer::SyncError error = sync_processor_->ProcessSyncChanges(
+ FROM_HERE,
+ syncer::SyncChangeList(
+ 1,
+ syncer::SyncChange(
+ FROM_HERE, syncer::SyncChange::ACTION_UPDATE,
+ CreateSyncData(*change.profile(), change.profile()->server_id(),
+ sync_pb::WalletMetadataSpecifics::ADDRESS))));
+ if (error.IsSet())
+ sync_error_factory_->CreateAndUploadError(FROM_HERE, error.ToString());
+}
+
+void AutofillWalletMetadataSyncableService::CreditCardChanged(
+ const CreditCardChange& change) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ // Handle only metadata updates while syncing. Addition and deletion are
+ // handled in AutofillMultipleChanged.
+ if (!sync_processor_ || change.type() != CreditCardChange::UPDATE ||
+ change.card()->record_type() == CreditCard::LOCAL_CARD) {
+ return;
+ }
+
+ syncer::SyncError error = sync_processor_->ProcessSyncChanges(
+ FROM_HERE,
+ syncer::SyncChangeList(
+ 1, syncer::SyncChange(
+ FROM_HERE, syncer::SyncChange::ACTION_UPDATE,
+ CreateSyncData(*change.card(), change.card()->server_id(),
+ sync_pb::WalletMetadataSpecifics::CARD))));
+ if (error.IsSet())
+ sync_error_factory_->CreateAndUploadError(FROM_HERE, error.ToString());
+}
+
+void AutofillWalletMetadataSyncableService::AutofillMultipleChanged() {
+ if (!sync_processor_)
+ return;
+
+ syncer::SyncError error = Reconcile(
+ sync_processor_->GetAllSyncData(syncer::AUTOFILL_WALLET_METADATA));
+ if (error.IsSet())
+ sync_error_factory_->CreateAndUploadError(FROM_HERE, error.ToString());
+}
+
+// static
+void AutofillWalletMetadataSyncableService::CreateForWebDataServiceAndBackend(
+ AutofillWebDataService* web_data_service,
+ AutofillWebDataBackend* webdata_backend,
+ const std::string& app_locale) {
+ web_data_service->GetDBUserData()->SetUserData(
+ UserDataKey(),
+ new AutofillWalletMetadataSyncableService(webdata_backend, app_locale));
+}
+
+// static
+AutofillWalletMetadataSyncableService*
+AutofillWalletMetadataSyncableService::FromWebDataService(
+ AutofillWebDataService* web_data_service) {
+ return static_cast<AutofillWalletMetadataSyncableService*>(
+ web_data_service->GetDBUserData()->GetUserData(UserDataKey()));
+}
+
+AutofillWalletMetadataSyncableService::AutofillWalletMetadataSyncableService(
+ AutofillWebDataBackend* webdata_backend,
+ const std::string& app_locale)
+ : webdata_backend_(webdata_backend), scoped_observer_(this) {
+ // No webdata in tests.
+ if (webdata_backend_)
+ scoped_observer_.Add(webdata_backend_);
+}
+
+bool AutofillWalletMetadataSyncableService::GetServerProfiles(
+ std::vector<AutofillProfile*>* profiles) const {
+ return AutofillTable::FromWebDatabase(webdata_backend_->GetDatabase())
+ ->GetServerProfiles(profiles);
+}
+
+bool AutofillWalletMetadataSyncableService::GetServerCreditCards(
+ std::vector<CreditCard*>* credit_cards) const {
+ return AutofillTable::FromWebDatabase(webdata_backend_->GetDatabase())
+ ->GetServerCreditCards(credit_cards);
+}
+
+bool AutofillWalletMetadataSyncableService::UpdateServerAddressUsageStats(
+ const AutofillProfile& profile) {
+ return AutofillTable::FromWebDatabase(webdata_backend_->GetDatabase())
+ ->UpdateServerAddressUsageStats(profile);
+}
+
+bool AutofillWalletMetadataSyncableService::UpdateServerCardUsageStats(
+ const CreditCard& credit_card) {
+ return AutofillTable::FromWebDatabase(webdata_backend_->GetDatabase())
+ ->UpdateServerCardUsageStats(credit_card);
+}
+
+syncer::SyncError AutofillWalletMetadataSyncableService::Reconcile(
+ const syncer::SyncDataList& sync_data) {
+ DCHECK(sync_processor_);
+
+ std::map<std::string, AutofillProfile*> profiles;
+ std::map<std::string, CreditCard*> cards;
+ GetServerData(&profiles, &cards);
+
+ syncer::SyncChangeList remote_changes;
+ for (const syncer::SyncData& datum : sync_data) {
+ const sync_pb::WalletMetadataSpecifics& remote =
+ datum.GetSpecifics().wallet_metadata();
+ size_t remote_use_count = static_cast<size_t>(remote.use_count());
+ base::Time remote_use_date =
+ base::Time::FromInternalValue(remote.use_date());
+
+ switch (remote.type()) {
+ case sync_pb::WalletMetadataSpecifics::ADDRESS: {
+ auto it = profiles.find(remote.id());
+ if (it == profiles.end()) {
+ remote_changes.push_back(syncer::SyncChange(
+ FROM_HERE, syncer::SyncChange::ACTION_DELETE, datum));
+ break;
+ }
+
+ AutofillProfile* local = it->second;
+ profiles.erase(it);
+ bool local_modified =
+ UpdateLocalStats(remote_use_count, remote_use_date, local);
+
+ if (local->use_count() > remote_use_count ||
+ local->use_date() > remote_use_date) {
+ remote_changes.push_back(syncer::SyncChange(
+ FROM_HERE, syncer::SyncChange::ACTION_UPDATE,
+ CreateSyncData(*local, local->server_id(),
+ sync_pb::WalletMetadataSpecifics::ADDRESS)));
+ }
+
+ // Save the stats last, because this clears values in |local|.
+ if (local_modified)
+ UpdateServerAddressUsageStats(*local);
+
+ break;
+ }
+
+ case sync_pb::WalletMetadataSpecifics::CARD: {
+ auto it = cards.find(remote.id());
+ if (it == cards.end()) {
+ remote_changes.push_back(syncer::SyncChange(
+ FROM_HERE, syncer::SyncChange::ACTION_DELETE, datum));
+ break;
+ }
+
+ CreditCard* local = it->second;
+ cards.erase(it);
+ bool local_modified =
+ UpdateLocalStats(remote_use_count, remote_use_date, local);
+
+ if (local->use_count() > remote_use_count ||
+ local->use_date() > remote_use_date) {
+ remote_changes.push_back(syncer::SyncChange(
+ FROM_HERE, syncer::SyncChange::ACTION_UPDATE,
+ CreateSyncData(*local, local->server_id(),
+ sync_pb::WalletMetadataSpecifics::CARD)));
+ }
+
+ // Save the stats last, because this clears values in |local|.
+ if (local_modified)
+ UpdateServerCardUsageStats(*local);
+
+ break;
+ }
+
+ case sync_pb::WalletMetadataSpecifics::UNKNOWN:
+ NOTREACHED();
+ break;
+ }
+ }
+
+ for (const auto& id_profile_pair : profiles) {
+ remote_changes.push_back(syncer::SyncChange(
+ FROM_HERE, syncer::SyncChange::ACTION_ADD,
+ CreateSyncData(*id_profile_pair.second, id_profile_pair.first,
+ sync_pb::WalletMetadataSpecifics::ADDRESS)));
+ }
+
+ for (const auto& id_card_pair : cards) {
+ remote_changes.push_back(syncer::SyncChange(
+ FROM_HERE, syncer::SyncChange::ACTION_ADD,
+ CreateSyncData(*id_card_pair.second, id_card_pair.first,
+ sync_pb::WalletMetadataSpecifics::CARD)));
+ }
+
+ return sync_processor_->ProcessSyncChanges(FROM_HERE, remote_changes);
+}
+
+bool AutofillWalletMetadataSyncableService::GetServerData(
+ std::map<std::string, AutofillProfile*>* profiles,
+ std::map<std::string, CreditCard*>* cards) {
+ std::vector<AutofillProfile*> profile_list;
+ bool success = GetServerProfiles(&profile_list);
+ for (AutofillProfile* profile : profile_list)
+ profiles->insert(std::make_pair(profile->server_id(), profile));
+
+ std::vector<CreditCard*> card_list;
+ success &= GetServerCreditCards(&card_list);
+ for (CreditCard* card : card_list)
+ cards->insert(std::make_pair(card->server_id(), card));
+
+ return success;
+}
+
+} // namespace autofill

Powered by Google App Engine
This is Rietveld 408576698