Commit 4b02e3f5 authored by Jan Krcal's avatar Jan Krcal Committed by Commit Bot

[Autofill wallet] Implement local changes for metadata sync

This CL implements the following features in the wallet_metadata USS
sync bridge:
 - caching current sync data and filling the cache on start,
 - informing the processor the bridge is ready to sync,
 - reacting to local single modifications of server profiles and cards
   (i.e. to updating the use stats when the address/card is used).

Bug: 853688
Change-Id: I07405e02cdf9cd0eb814179d883594253859845c
Reviewed-on: https://chromium-review.googlesource.com/1151628
Commit-Queue: Jan Krcal <jkrcal@chromium.org>
Reviewed-by: default avatarSebastien Seguin-Gagnon <sebsg@chromium.org>
Cr-Commit-Position: refs/heads/master@{#581183}
parent 965888f3
...@@ -2393,7 +2393,8 @@ bool AutofillTable::AddFormFieldValueTime(const FormFieldData& element, ...@@ -2393,7 +2393,8 @@ bool AutofillTable::AddFormFieldValueTime(const FormFieldData& element,
bool AutofillTable::SupportsMetadataForModelType( bool AutofillTable::SupportsMetadataForModelType(
syncer::ModelType model_type) const { syncer::ModelType model_type) const {
return (model_type == syncer::AUTOFILL || return (model_type == syncer::AUTOFILL ||
model_type == syncer::AUTOFILL_PROFILE); model_type == syncer::AUTOFILL_PROFILE ||
model_type == syncer::AUTOFILL_WALLET_METADATA);
} }
int AutofillTable::GetKeyValueForModelType(syncer::ModelType model_type) const { int AutofillTable::GetKeyValueForModelType(syncer::ModelType model_type) const {
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "components/sync/model/entity_data.h" #include "components/sync/model/entity_data.h"
#include "components/sync/model/mutable_data_batch.h" #include "components/sync/model/mutable_data_batch.h"
#include "components/sync/model_impl/client_tag_based_model_type_processor.h" #include "components/sync/model_impl/client_tag_based_model_type_processor.h"
#include "components/sync/model_impl/sync_metadata_store_change_list.h"
namespace autofill { namespace autofill {
...@@ -26,6 +27,7 @@ namespace { ...@@ -26,6 +27,7 @@ namespace {
using sync_pb::WalletMetadataSpecifics; using sync_pb::WalletMetadataSpecifics;
using syncer::EntityData; using syncer::EntityData;
using syncer::MetadataChangeList;
// Address to this variable used as the user data key. // Address to this variable used as the user data key.
static int kAutofillWalletMetadataSyncBridgeUserDataKey = 0; static int kAutofillWalletMetadataSyncBridgeUserDataKey = 0;
...@@ -62,7 +64,7 @@ std::unique_ptr<EntityData> CreateEntityDataFromAutofillDataModel( ...@@ -62,7 +64,7 @@ std::unique_ptr<EntityData> CreateEntityDataFromAutofillDataModel(
} }
// Returns EntityData for wallet_metadata for |local_profile|. // Returns EntityData for wallet_metadata for |local_profile|.
std::unique_ptr<EntityData> CreateWalletMetadataEntityDataFromAutofillProfile( std::unique_ptr<EntityData> CreateMetadataEntityDataFromAutofillServerProfile(
const AutofillProfile& local_profile) { const AutofillProfile& local_profile) {
std::unique_ptr<EntityData> entity_data = std::unique_ptr<EntityData> entity_data =
CreateEntityDataFromAutofillDataModel( CreateEntityDataFromAutofillDataModel(
...@@ -76,7 +78,7 @@ std::unique_ptr<EntityData> CreateWalletMetadataEntityDataFromAutofillProfile( ...@@ -76,7 +78,7 @@ std::unique_ptr<EntityData> CreateWalletMetadataEntityDataFromAutofillProfile(
} }
// Returns EntityData for wallet_metadata for |local_card|. // Returns EntityData for wallet_metadata for |local_card|.
std::unique_ptr<EntityData> CreateEntityDataFromCreditCard( std::unique_ptr<EntityData> CreateMetadataEntityDataFromCard(
const CreditCard& local_card) { const CreditCard& local_card) {
std::unique_ptr<EntityData> entity_data = std::unique_ptr<EntityData> entity_data =
CreateEntityDataFromAutofillDataModel( CreateEntityDataFromAutofillDataModel(
...@@ -103,7 +105,7 @@ void AutofillWalletMetadataSyncBridge::CreateForWebDataServiceAndBackend( ...@@ -103,7 +105,7 @@ void AutofillWalletMetadataSyncBridge::CreateForWebDataServiceAndBackend(
&kAutofillWalletMetadataSyncBridgeUserDataKey, &kAutofillWalletMetadataSyncBridgeUserDataKey,
std::make_unique<AutofillWalletMetadataSyncBridge>( std::make_unique<AutofillWalletMetadataSyncBridge>(
std::make_unique<syncer::ClientTagBasedModelTypeProcessor>( std::make_unique<syncer::ClientTagBasedModelTypeProcessor>(
syncer::AUTOFILL_WALLET_DATA, syncer::AUTOFILL_WALLET_METADATA,
/*dump_stack=*/base::RepeatingClosure()), /*dump_stack=*/base::RepeatingClosure()),
web_data_backend)); web_data_backend));
} }
...@@ -121,14 +123,22 @@ AutofillWalletMetadataSyncBridge::AutofillWalletMetadataSyncBridge( ...@@ -121,14 +123,22 @@ AutofillWalletMetadataSyncBridge::AutofillWalletMetadataSyncBridge(
std::unique_ptr<syncer::ModelTypeChangeProcessor> change_processor, std::unique_ptr<syncer::ModelTypeChangeProcessor> change_processor,
AutofillWebDataBackend* web_data_backend) AutofillWebDataBackend* web_data_backend)
: ModelTypeSyncBridge(std::move(change_processor)), : ModelTypeSyncBridge(std::move(change_processor)),
web_data_backend_(web_data_backend) {} web_data_backend_(web_data_backend),
scoped_observer_(this) {
DCHECK(web_data_backend_);
scoped_observer_.Add(web_data_backend_);
LoadDataCacheAndMetadata();
}
AutofillWalletMetadataSyncBridge::~AutofillWalletMetadataSyncBridge() {} AutofillWalletMetadataSyncBridge::~AutofillWalletMetadataSyncBridge() {}
std::unique_ptr<syncer::MetadataChangeList> std::unique_ptr<syncer::MetadataChangeList>
AutofillWalletMetadataSyncBridge::CreateMetadataChangeList() { AutofillWalletMetadataSyncBridge::CreateMetadataChangeList() {
NOTIMPLEMENTED(); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return nullptr; return std::make_unique<syncer::SyncMetadataStoreChangeList>(
GetAutofillTable(), syncer::AUTOFILL_WALLET_METADATA);
} }
base::Optional<syncer::ModelError> base::Optional<syncer::ModelError>
...@@ -175,10 +185,111 @@ std::string AutofillWalletMetadataSyncBridge::GetStorageKey( ...@@ -175,10 +185,111 @@ std::string AutofillWalletMetadataSyncBridge::GetStorageKey(
entity_data.specifics.wallet_metadata().id()); entity_data.specifics.wallet_metadata().id());
} }
void AutofillWalletMetadataSyncBridge::AutofillProfileChanged(
const AutofillProfileChange& change) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
const AutofillProfile* changed = change.data_model();
if (!changed || changed->record_type() != AutofillProfile::SERVER_PROFILE) {
return;
}
// The only legal change on a server profile is that its use count or use date
// or has-converted status gets updated. Other changes (adding, deleting) are
// only done by the AutofillWalletSyncBridge and result only in the
// AutofillMultipleChanged() notification.
DCHECK(change.type() == AutofillProfileChange::UPDATE);
SyncUpUpdatedEntity(
CreateMetadataEntityDataFromAutofillServerProfile(*changed));
}
void AutofillWalletMetadataSyncBridge::CreditCardChanged(
const CreditCardChange& change) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
const CreditCard* changed = change.data_model();
if (!changed || changed->record_type() == CreditCard::LOCAL_CARD) {
return;
}
// The only legal change on a server card is that its use count or use date or
// billing address id gets updated. Other changes (adding, deleting) are only
// done by the AutofillWalletSyncBridge and result only in the
// AutofillMultipleChanged() notification.
DCHECK(change.type() == CreditCardChange::UPDATE);
SyncUpUpdatedEntity(CreateMetadataEntityDataFromCard(*changed));
}
void AutofillWalletMetadataSyncBridge::AutofillMultipleChanged() {
NOTIMPLEMENTED();
}
void AutofillWalletMetadataSyncBridge::SyncUpUpdatedEntity(
std::unique_ptr<EntityData> entity_after_change) {
std::string storage_key = GetStorageKey(*entity_after_change);
auto it = cache_.find(storage_key);
// This *changed* entity should already be in the cache, ignore otherwise.
if (it == cache_.end())
return;
const WalletMetadataSpecifics& specifics_before = it->second;
const WalletMetadataSpecifics& specifics_after =
entity_after_change->specifics.wallet_metadata();
if (specifics_before.use_count() < specifics_after.use_count() &&
specifics_before.use_date() < specifics_after.use_date()) {
std::unique_ptr<MetadataChangeList> metadata_change_list =
CreateMetadataChangeList();
cache_[storage_key] = specifics_after;
change_processor()->Put(storage_key, std::move(entity_after_change),
metadata_change_list.get());
}
}
AutofillTable* AutofillWalletMetadataSyncBridge::GetAutofillTable() { AutofillTable* AutofillWalletMetadataSyncBridge::GetAutofillTable() {
return AutofillTable::FromWebDatabase(web_data_backend_->GetDatabase()); return AutofillTable::FromWebDatabase(web_data_backend_->GetDatabase());
} }
void AutofillWalletMetadataSyncBridge::LoadDataCacheAndMetadata() {
if (!web_data_backend_ || !web_data_backend_->GetDatabase() ||
!GetAutofillTable()) {
change_processor()->ReportError(
{FROM_HERE, "Failed to load AutofillWebDatabase."});
return;
}
// Load the data cache.
std::vector<std::unique_ptr<AutofillProfile>> profiles;
std::vector<std::unique_ptr<CreditCard>> cards;
if (!GetAutofillTable()->GetServerProfiles(&profiles) ||
!GetAutofillTable()->GetServerCreditCards(&cards)) {
change_processor()->ReportError(
{FROM_HERE, "Failed reading autofill data from WebDatabase."});
return;
}
for (const std::unique_ptr<AutofillProfile>& entry : profiles) {
cache_[GetStorageKeyForEntryServerId(entry->server_id())] =
CreateMetadataEntityDataFromAutofillServerProfile(*entry)
->specifics.wallet_metadata();
}
for (const std::unique_ptr<CreditCard>& entry : cards) {
cache_[GetStorageKeyForEntryServerId(entry->server_id())] =
CreateMetadataEntityDataFromCard(*entry)->specifics.wallet_metadata();
}
// Load the metadata and send to the processor.
auto batch = std::make_unique<syncer::MetadataBatch>();
if (!GetAutofillTable()->GetAllSyncMetadata(syncer::AUTOFILL_WALLET_METADATA,
batch.get())) {
change_processor()->ReportError(
{FROM_HERE, "Failed reading autofill metadata from WebDatabase."});
return;
}
change_processor()->ModelReadyToSync(std::move(batch));
}
void AutofillWalletMetadataSyncBridge::GetDataImpl( void AutofillWalletMetadataSyncBridge::GetDataImpl(
base::Optional<std::unordered_set<std::string>> storage_keys_set, base::Optional<std::unordered_set<std::string>> storage_keys_set,
DataCallback callback) { DataCallback callback) {
...@@ -199,14 +310,14 @@ void AutofillWalletMetadataSyncBridge::GetDataImpl( ...@@ -199,14 +310,14 @@ void AutofillWalletMetadataSyncBridge::GetDataImpl(
std::string key = GetStorageKeyForEntryServerId(entry->server_id()); std::string key = GetStorageKeyForEntryServerId(entry->server_id());
if (!storage_keys_set || base::ContainsKey(*storage_keys_set, key)) { if (!storage_keys_set || base::ContainsKey(*storage_keys_set, key)) {
batch->Put(key, batch->Put(key,
CreateWalletMetadataEntityDataFromAutofillProfile(*entry)); CreateMetadataEntityDataFromAutofillServerProfile(*entry));
} }
} }
for (const std::unique_ptr<CreditCard>& entry : cards) { for (const std::unique_ptr<CreditCard>& entry : cards) {
std::string key = GetStorageKeyForEntryServerId(entry->server_id()); std::string key = GetStorageKeyForEntryServerId(entry->server_id());
if (!storage_keys_set || base::ContainsKey(*storage_keys_set, key)) { if (!storage_keys_set || base::ContainsKey(*storage_keys_set, key)) {
batch->Put(GetStorageKeyForEntryServerId(entry->server_id()), batch->Put(GetStorageKeyForEntryServerId(entry->server_id()),
CreateEntityDataFromCreditCard(*entry)); CreateMetadataEntityDataFromCard(*entry));
} }
} }
......
...@@ -10,13 +10,20 @@ ...@@ -10,13 +10,20 @@
#include <unordered_set> #include <unordered_set>
#include "base/macros.h" #include "base/macros.h"
#include "base/scoped_observer.h"
#include "base/sequence_checker.h" #include "base/sequence_checker.h"
#include "base/supports_user_data.h" #include "base/supports_user_data.h"
#include "components/autofill/core/browser/webdata/autofill_change.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_service_observer.h"
#include "components/sync/model/metadata_change_list.h" #include "components/sync/model/metadata_change_list.h"
#include "components/sync/model/model_error.h" #include "components/sync/model/model_error.h"
#include "components/sync/model/model_type_change_processor.h" #include "components/sync/model/model_type_change_processor.h"
#include "components/sync/model/model_type_sync_bridge.h" #include "components/sync/model/model_type_sync_bridge.h"
namespace syncer {
struct EntityData;
} // namespace syncer
namespace autofill { namespace autofill {
class AutofillTable; class AutofillTable;
...@@ -25,8 +32,10 @@ class AutofillWebDataService; ...@@ -25,8 +32,10 @@ class AutofillWebDataService;
// Sync bridge responsible for propagating local changes to the processor and // Sync bridge responsible for propagating local changes to the processor and
// applying remote changes to the local database. // applying remote changes to the local database.
class AutofillWalletMetadataSyncBridge : public base::SupportsUserData::Data, class AutofillWalletMetadataSyncBridge
public syncer::ModelTypeSyncBridge { : public base::SupportsUserData::Data,
public syncer::ModelTypeSyncBridge,
public AutofillWebDataServiceObserverOnDBSequence {
public: public:
// Factory method that hides dealing with change_processor and also stores the // Factory method that hides dealing with change_processor and also stores the
// created bridge within |web_data_service|. This method should only be // created bridge within |web_data_service|. This method should only be
...@@ -58,10 +67,23 @@ class AutofillWalletMetadataSyncBridge : public base::SupportsUserData::Data, ...@@ -58,10 +67,23 @@ class AutofillWalletMetadataSyncBridge : public base::SupportsUserData::Data,
std::string GetClientTag(const syncer::EntityData& entity_data) override; std::string GetClientTag(const syncer::EntityData& entity_data) override;
std::string GetStorageKey(const syncer::EntityData& entity_data) override; std::string GetStorageKey(const syncer::EntityData& entity_data) override;
// AutofillWebDataServiceObserverOnDBSequence implementation.
void AutofillProfileChanged(const AutofillProfileChange& change) override;
void CreditCardChanged(const CreditCardChange& change) override;
void AutofillMultipleChanged() override;
private: private:
// Syncs up an updated entity |entity_after_change| (if needed).
void SyncUpUpdatedEntity(
std::unique_ptr<syncer::EntityData> entity_after_change);
// Returns the table associated with the |web_data_backend_|. // Returns the table associated with the |web_data_backend_|.
AutofillTable* GetAutofillTable(); AutofillTable* GetAutofillTable();
// Synchronously load |cache_| and sync metadata from the autofill table
// and pass the latter to the processor so that it can start tracking changes.
void LoadDataCacheAndMetadata();
// Reads local wallet metadata from the database and passes them into // Reads local wallet metadata from the database and passes them into
// |callback|. If |storage_keys_set| is not set, it returns all data entries. // |callback|. If |storage_keys_set| is not set, it returns all data entries.
// Otherwise, it returns only entries with storage key in |storage_keys_set|. // Otherwise, it returns only entries with storage key in |storage_keys_set|.
...@@ -73,6 +95,14 @@ class AutofillWalletMetadataSyncBridge : public base::SupportsUserData::Data, ...@@ -73,6 +95,14 @@ class AutofillWalletMetadataSyncBridge : public base::SupportsUserData::Data,
// SupportsUserData, so it's guaranteed to outlive |this|. // SupportsUserData, so it's guaranteed to outlive |this|.
AutofillWebDataBackend* const web_data_backend_; AutofillWebDataBackend* const web_data_backend_;
ScopedObserver<AutofillWebDataBackend, AutofillWalletMetadataSyncBridge>
scoped_observer_;
// Cache of the data (local data + data that hasn't synced down yet); keyed by
// storage keys. Needed for figuring out what to sync up when larger changes
// happen in the local database.
std::unordered_map<std::string, sync_pb::WalletMetadataSpecifics> cache_;
// The bridge should be used on the same sequence where it is constructed. // The bridge should be used on the same sequence where it is constructed.
SEQUENCE_CHECKER(sequence_checker_); SEQUENCE_CHECKER(sequence_checker_);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment