diff options
30 files changed, 701 insertions, 85 deletions
diff --git a/chrome/browser/sync/glue/autofill_wallet_data_type_controller.cc b/chrome/browser/sync/glue/autofill_wallet_data_type_controller.cc new file mode 100644 index 0000000..771a568 --- /dev/null +++ b/chrome/browser/sync/glue/autofill_wallet_data_type_controller.cc @@ -0,0 +1,90 @@ +// 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 "chrome/browser/sync/glue/autofill_wallet_data_type_controller.h" + +#include "base/bind.h" +#include "chrome/browser/autofill/personal_data_manager_factory.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/sync/glue/chrome_report_unrecoverable_error.h" +#include "chrome/browser/sync/profile_sync_components_factory.h" +#include "chrome/browser/webdata/web_data_service_factory.h" +#include "components/autofill/core/browser/personal_data_manager.h" +#include "components/autofill/core/browser/webdata/autofill_webdata_service.h" +#include "content/public/browser/browser_thread.h" +#include "sync/api/sync_error.h" +#include "sync/api/syncable_service.h" + +using content::BrowserThread; + +namespace browser_sync { + +AutofillWalletDataTypeController::AutofillWalletDataTypeController( + ProfileSyncComponentsFactory* profile_sync_factory, + Profile* profile) + : NonUIDataTypeController( + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), + base::Bind(&ChromeReportUnrecoverableError), + profile_sync_factory), + profile_(profile), + personal_data_(nullptr), + callback_registered_(false) { +} + +AutofillWalletDataTypeController::~AutofillWalletDataTypeController() { +} + +syncer::ModelType AutofillWalletDataTypeController::type() const { + return syncer::AUTOFILL_WALLET_DATA; +} + +syncer::ModelSafeGroup + AutofillWalletDataTypeController::model_safe_group() const { + return syncer::GROUP_DB; +} + +bool AutofillWalletDataTypeController::PostTaskOnBackendThread( + const tracked_objects::Location& from_here, + const base::Closure& task) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + return BrowserThread::PostTask(BrowserThread::DB, from_here, task); +} + +bool AutofillWalletDataTypeController::StartModels() { + DCHECK(content::BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_EQ(state(), MODEL_STARTING); + + personal_data_ = + autofill::PersonalDataManagerFactory::GetForProfile(profile_); + if (!personal_data_->IsDataLoaded()) + return false; + + autofill::AutofillWebDataService* web_data_service = + WebDataServiceFactory::GetAutofillWebDataForProfile( + profile_, ServiceAccessType::EXPLICIT_ACCESS).get(); + + if (!web_data_service) + return false; + + if (web_data_service->IsDatabaseLoaded()) + return true; + + if (!callback_registered_) { + web_data_service->RegisterDBLoadedCallback(base::Bind( + &AutofillWalletDataTypeController::WebDatabaseLoaded, this)); + callback_registered_ = true; + } + + return false; +} + +void AutofillWalletDataTypeController::StopModels() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); +} + +void AutofillWalletDataTypeController::WebDatabaseLoaded() { + OnModelLoaded(); +} + +} // namespace browser_sync diff --git a/chrome/browser/sync/glue/autofill_wallet_data_type_controller.h b/chrome/browser/sync/glue/autofill_wallet_data_type_controller.h new file mode 100644 index 0000000..408f595 --- /dev/null +++ b/chrome/browser/sync/glue/autofill_wallet_data_type_controller.h @@ -0,0 +1,52 @@ +// 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. + +#ifndef CHROME_BROWSER_SYNC_GLUE_AUTOFILL_WALLET_DATA_TYPE_CONTROLLER_H_ +#define CHROME_BROWSER_SYNC_GLUE_AUTOFILL_WALLET_DATA_TYPE_CONTROLLER_H_ + +#include "base/basictypes.h" +#include "components/sync_driver/non_ui_data_type_controller.h" + +class Profile; +class ProfileSyncComponentsFactory; + +namespace autofill { +class PersonalDataManager; +} + +namespace browser_sync { + +class AutofillWalletDataTypeController + : public sync_driver::NonUIDataTypeController { + public: + AutofillWalletDataTypeController( + ProfileSyncComponentsFactory* profile_sync_factory, + Profile* profile); + + // NonUIDataTypeController implementation. + syncer::ModelType type() const override; + syncer::ModelSafeGroup model_safe_group() const override; + + protected: + ~AutofillWalletDataTypeController() override; + + private: + // NonUIDataTypeController implementation. + bool PostTaskOnBackendThread(const tracked_objects::Location& from_here, + const base::Closure& task) override; + bool StartModels() override; + void StopModels() override; + + void WebDatabaseLoaded(); + + Profile* const profile_; + autofill::PersonalDataManager* personal_data_; + bool callback_registered_; + + DISALLOW_COPY_AND_ASSIGN(AutofillWalletDataTypeController); +}; + +} // namespace browser_sync + +#endif // CHROME_BROWSER_SYNC_GLUE_AUTOFILL_WALLET_DATA_TYPE_CONTROLLER_H_ diff --git a/chrome/browser/sync/profile_sync_components_factory_impl.cc b/chrome/browser/sync/profile_sync_components_factory_impl.cc index 2d0edd8..bffaf01 100644 --- a/chrome/browser/sync/profile_sync_components_factory_impl.cc +++ b/chrome/browser/sync/profile_sync_components_factory_impl.cc @@ -18,6 +18,7 @@ #include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/browser/sync/glue/autofill_data_type_controller.h" #include "chrome/browser/sync/glue/autofill_profile_data_type_controller.h" +#include "chrome/browser/sync/glue/autofill_wallet_data_type_controller.h" #include "chrome/browser/sync/glue/bookmark_change_processor.h" #include "chrome/browser/sync/glue/bookmark_data_type_controller.h" #include "chrome/browser/sync/glue/bookmark_model_associator.h" @@ -45,7 +46,10 @@ #include "chrome/common/pref_names.h" #include "components/autofill/core/browser/webdata/autocomplete_syncable_service.h" #include "components/autofill/core/browser/webdata/autofill_profile_syncable_service.h" +#include "components/autofill/core/browser/webdata/autofill_wallet_syncable_service.h" #include "components/autofill/core/browser/webdata/autofill_webdata_service.h" +#include "components/autofill/core/common/autofill_pref_names.h" +#include "components/autofill/core/common/autofill_switches.h" #include "components/dom_distiller/core/dom_distiller_service.h" #include "components/password_manager/core/browser/password_store.h" #include "components/search_engines/template_url_service.h" @@ -213,6 +217,17 @@ void ProfileSyncComponentsFactoryImpl::RegisterCommonDataTypes( new AutofillProfileDataTypeController(this, profile_)); } + if ((base::CommandLine::ForCurrentProcess()->HasSwitch( + autofill::switches::kEnableWalletCardImport) || + profile_->GetPrefs()->GetBoolean( + autofill::prefs::kAutofillWalletSyncExperimentEnabled)) && + !disabled_types.Has(syncer::AUTOFILL_WALLET_DATA)) { + // The feature can be enabled by sync experiment *or* command line flag, + // and additionally the sync type must be enabled. + pss->RegisterDataTypeController( + new browser_sync::AutofillWalletDataTypeController(this, profile_)); + } + // Bookmark sync is enabled by default. Register unless explicitly // disabled. if (!disabled_types.Has(syncer::BOOKMARKS)) { @@ -470,16 +485,19 @@ base::WeakPtr<syncer::SyncableService> ProfileSyncComponentsFactoryImpl:: return PrefServiceSyncable::FromProfile(profile_)->GetSyncableService( syncer::PRIORITY_PREFERENCES)->AsWeakPtr(); case syncer::AUTOFILL: - case syncer::AUTOFILL_PROFILE: { + case syncer::AUTOFILL_PROFILE: + case syncer::AUTOFILL_WALLET_DATA: { if (!web_data_service_.get()) return base::WeakPtr<syncer::SyncableService>(); if (type == syncer::AUTOFILL) { return autofill::AutocompleteSyncableService::FromWebDataService( web_data_service_.get())->AsWeakPtr(); - } else { + } else if (type == syncer::AUTOFILL_PROFILE) { return autofill::AutofillProfileSyncableService::FromWebDataService( web_data_service_.get())->AsWeakPtr(); } + return autofill::AutofillWalletSyncableService::FromWebDataService( + web_data_service_.get())->AsWeakPtr(); } case syncer::SEARCH_ENGINES: return TemplateURLServiceFactory::GetForProfile(profile_)->AsWeakPtr(); diff --git a/chrome/browser/sync/profile_sync_service.cc b/chrome/browser/sync/profile_sync_service.cc index acbfb7c..61ad4f3 100644 --- a/chrome/browser/sync/profile_sync_service.cc +++ b/chrome/browser/sync/profile_sync_service.cc @@ -1743,7 +1743,7 @@ void ProfileSyncService::UpdateSelectedTypesHistogram( sync_driver::user_selectable_type::PROXY_TABS, }; - static_assert(34 == syncer::MODEL_TYPE_COUNT, + static_assert(35 == syncer::MODEL_TYPE_COUNT, "custom config histogram must be updated"); if (!sync_everything) { diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index a0d1ce8..3a95fbd 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -2665,6 +2665,8 @@ 'browser/sync/glue/autofill_data_type_controller.h', 'browser/sync/glue/autofill_profile_data_type_controller.cc', 'browser/sync/glue/autofill_profile_data_type_controller.h', + 'browser/sync/glue/autofill_wallet_data_type_controller.cc', + 'browser/sync/glue/autofill_wallet_data_type_controller.h', 'browser/sync/glue/bookmark_change_processor.cc', 'browser/sync/glue/bookmark_change_processor.h', 'browser/sync/glue/bookmark_data_type_controller.cc', diff --git a/components/autofill.gypi b/components/autofill.gypi index a2f8015..b0d2c23 100644 --- a/components/autofill.gypi +++ b/components/autofill.gypi @@ -200,6 +200,8 @@ 'autofill/core/browser/webdata/autofill_profile_syncable_service.h', 'autofill/core/browser/webdata/autofill_table.cc', 'autofill/core/browser/webdata/autofill_table.h', + 'autofill/core/browser/webdata/autofill_wallet_syncable_service.cc', + 'autofill/core/browser/webdata/autofill_wallet_syncable_service.h', 'autofill/core/browser/webdata/autofill_webdata.h', 'autofill/core/browser/webdata/autofill_webdata_backend.h', 'autofill/core/browser/webdata/autofill_webdata_backend_impl.cc', @@ -240,6 +242,8 @@ 'autofill/core/browser/webdata/autocomplete_syncable_service.h', 'autofill/core/browser/webdata/autofill_profile_syncable_service.cc', 'autofill/core/browser/webdata/autofill_profile_syncable_service.h', + 'autofill/core/browser/webdata/autofill_wallet_syncable_service.cc', + 'autofill/core/browser/webdata/autofill_wallet_syncable_service.h', ], }], ], diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn index f66122c..b839082 100644 --- a/components/autofill/core/browser/BUILD.gn +++ b/components/autofill/core/browser/BUILD.gn @@ -133,6 +133,8 @@ static_library("browser") { "webdata/autofill_profile_syncable_service.h", "webdata/autofill_table.cc", "webdata/autofill_table.h", + "webdata/autofill_wallet_syncable_service.cc", + "webdata/autofill_wallet_syncable_service.h", "webdata/autofill_webdata.h", "webdata/autofill_webdata_backend.h", "webdata/autofill_webdata_backend_impl.cc", @@ -183,6 +185,8 @@ static_library("browser") { "webdata/autocomplete_syncable_service.h", "webdata/autofill_profile_syncable_service.cc", "webdata/autofill_profile_syncable_service.h", + "webdata/autofill_wallet_syncable_service.cc", + "webdata/autofill_wallet_syncable_service.h", ] } diff --git a/components/autofill/core/browser/autofill_metrics_unittest.cc b/components/autofill/core/browser/autofill_metrics_unittest.cc index 48c7847..a8672c4 100644 --- a/components/autofill/core/browser/autofill_metrics_unittest.cc +++ b/components/autofill/core/browser/autofill_metrics_unittest.cc @@ -1146,6 +1146,12 @@ TEST_F(AutofillMetricsTest, CreditCardFormEventsAreSegmented) { // Test that we log interacted form event for address only once. TEST_F(AutofillMetricsTest, AddressFormEventsAreSegmented) { + // Enabling server card. + base::CommandLine::ForCurrentProcess()->AppendSwitch( + ::autofill::switches::kEnableWalletCardImport); + autofill_client_.GetPrefs()->SetBoolean( + ::autofill::prefs::kAutofillWalletImportEnabled, true); + // Set up our form data. FormData form; form.name = ASCIIToUTF16("TestForm"); diff --git a/components/autofill/core/browser/credit_card.cc b/components/autofill/core/browser/credit_card.cc index cfae31b..45430d3 100644 --- a/components/autofill/core/browser/credit_card.cc +++ b/components/autofill/core/browser/credit_card.cc @@ -503,6 +503,19 @@ void CreditCard::SetInfoForMonthInputType(const base::string16& value) { SetExpirationMonth(num); } +void CreditCard::SetExpirationMonth(int expiration_month) { + if (expiration_month < 0 || expiration_month > 12) + return; + expiration_month_ = expiration_month; +} + +void CreditCard::SetExpirationYear(int expiration_year) { + if (expiration_year != 0 && + (expiration_year < 2006 || expiration_year > 10000)) + return; + expiration_year_ = expiration_year; +} + base::string16 CreditCard::LastFourDigits() const { static const size_t kNumLastDigits = 4; @@ -729,22 +742,6 @@ void CreditCard::SetNumber(const base::string16& number) { type_ = GetCreditCardType(StripSeparators(number_)); } -void CreditCard::SetExpirationMonth(int expiration_month) { - if (expiration_month < 0 || expiration_month > 12) - return; - - expiration_month_ = expiration_month; -} - -void CreditCard::SetExpirationYear(int expiration_year) { - if (expiration_year != 0 && - (expiration_year < 2006 || expiration_year > 10000)) { - return; - } - - expiration_year_ = expiration_year; -} - // So we can compare CreditCards with EXPECT_EQ(). std::ostream& operator<<(std::ostream& os, const CreditCard& credit_card) { return os diff --git a/components/autofill/core/browser/credit_card.h b/components/autofill/core/browser/credit_card.h index d8eda0a9..d8c7feb 100644 --- a/components/autofill/core/browser/credit_card.h +++ b/components/autofill/core/browser/credit_card.h @@ -115,6 +115,12 @@ class CreditCard : public AutofillDataModel { int expiration_month() const { return expiration_month_; } int expiration_year() const { return expiration_year_; } + // These setters verify that the month and year are within appropriate + // ranges, or 0. They take integers as an alternative to setting the inputs + // from strings via SetInfo(). + void SetExpirationMonth(int expiration_month); + void SetExpirationYear(int expiration_year); + const std::string& server_id() const { return server_id_; } // For use in STL containers. @@ -184,11 +190,6 @@ class CreditCard : public AutofillDataModel { // Sets |expiration_year_| to the integer conversion of |text|. void SetExpirationYearFromString(const base::string16& text); - // These setters verify that the month and year are within appropriate - // ranges. - void SetExpirationMonth(int expiration_month); - void SetExpirationYear(int expiration_year); - // See enum definition above. RecordType record_type_; diff --git a/components/autofill/core/browser/personal_data_manager.cc b/components/autofill/core/browser/personal_data_manager.cc index 131f3ae..f9afcf5 100644 --- a/components/autofill/core/browser/personal_data_manager.cc +++ b/components/autofill/core/browser/personal_data_manager.cc @@ -1211,20 +1211,19 @@ const std::vector<AutofillProfile*>& PersonalDataManager::GetProfiles( #endif // defined(OS_MACOSX) && !defined(OS_IOS) profiles_.clear(); - - // Populates |auxiliary_profiles_|. - if (use_auxiliary_profiles) - LoadAuxiliaryProfiles(record_metrics); - profiles_.insert(profiles_.end(), web_profiles().begin(), web_profiles().end()); if (use_auxiliary_profiles) { + LoadAuxiliaryProfiles(record_metrics); profiles_.insert( profiles_.end(), auxiliary_profiles_.begin(), auxiliary_profiles_.end()); } - profiles_.insert( - profiles_.end(), server_profiles_.begin(), server_profiles_.end()); + if (IsExperimentalWalletIntegrationEnabled() && + pref_service_->GetBoolean(prefs::kAutofillWalletImportEnabled)) { + profiles_.insert( + profiles_.end(), server_profiles_.begin(), server_profiles_.end()); + } return profiles_; } diff --git a/components/autofill/core/browser/webdata/autofill_table.cc b/components/autofill/core/browser/webdata/autofill_table.cc index 4f4c815..da4e3fe 100644 --- a/components/autofill/core/browser/webdata/autofill_table.cc +++ b/components/autofill/core/browser/webdata/autofill_table.cc @@ -1257,54 +1257,6 @@ bool AutofillTable::GetServerCreditCards( credit_cards->push_back(card); } - static bool do_once = true; - // Fake out some masked cards. TODO(estade): remove this block of code. - if (do_once && - base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableWalletCardImport)) { - do_once = false; - std::vector<CreditCard> fake_masked_cards; - fake_masked_cards.push_back( - CreditCard(CreditCard::MASKED_SERVER_CARD, "a123")); - fake_masked_cards.back().SetRawInfo(CREDIT_CARD_NAME, - ASCIIToUTF16("Edgar Salazar")); - fake_masked_cards.back().SetRawInfo(CREDIT_CARD_EXP_MONTH, - ASCIIToUTF16("03")); - fake_masked_cards.back().SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, - ASCIIToUTF16("2016")); - fake_masked_cards.back().SetRawInfo(CREDIT_CARD_NUMBER, - ASCIIToUTF16("8431")); - fake_masked_cards.back().SetTypeForMaskedCard(kAmericanExpressCard); - - fake_masked_cards.push_back( - CreditCard(CreditCard::MASKED_SERVER_CARD, "b456")); - fake_masked_cards.back().SetRawInfo(CREDIT_CARD_NAME, - ASCIIToUTF16("Elena Salazar")); - fake_masked_cards.back().SetRawInfo(CREDIT_CARD_EXP_MONTH, - ASCIIToUTF16("05")); - fake_masked_cards.back().SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, - ASCIIToUTF16("2017")); - fake_masked_cards.back().SetRawInfo(CREDIT_CARD_NUMBER, - ASCIIToUTF16("9424")); - fake_masked_cards.back().SetTypeForMaskedCard(kDiscoverCard); - - fake_masked_cards.push_back( - CreditCard(CreditCard::MASKED_SERVER_CARD, "c789")); - fake_masked_cards.back().SetRawInfo(CREDIT_CARD_NAME, - ASCIIToUTF16("Efren Salazar, Sr")); - fake_masked_cards.back().SetRawInfo(CREDIT_CARD_EXP_MONTH, - ASCIIToUTF16("12")); - fake_masked_cards.back().SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, - ASCIIToUTF16("2014")); - fake_masked_cards.back().SetRawInfo(CREDIT_CARD_NUMBER, - ASCIIToUTF16("1881")); - fake_masked_cards.back().SetTypeForMaskedCard(kVisaCard); - fake_masked_cards.back().SetServerStatus(CreditCard::EXPIRED); - - SetServerCreditCards(fake_masked_cards); - return GetServerCreditCards(credit_cards); - } - return s.Succeeded(); } diff --git a/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc b/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc new file mode 100644 index 0000000..2cd0909 --- /dev/null +++ b/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc @@ -0,0 +1,259 @@ +// 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_syncable_service.h" + +#include <set> + +#include "base/logging.h" +#include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" +#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_error_factory.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); +} + +const char* CardTypeFromWalletCardType( + sync_pb::WalletMaskedCreditCard::WalletCardType type) { + switch (type) { + case sync_pb::WalletMaskedCreditCard::AMEX: + return kAmericanExpressCard; + case sync_pb::WalletMaskedCreditCard::DISCOVER: + return kDiscoverCard; + case sync_pb::WalletMaskedCreditCard::JCB: + return kJCBCard; + case sync_pb::WalletMaskedCreditCard::MASTER_CARD: + return kMasterCard; + case sync_pb::WalletMaskedCreditCard::VISA: + return kVisaCard; + + // These aren't supported by the client, so just declare a generic card. + case sync_pb::WalletMaskedCreditCard::MAESTRO: + case sync_pb::WalletMaskedCreditCard::SOLO: + case sync_pb::WalletMaskedCreditCard::SWITCH: + default: + return kGenericCard; + } +} + +CreditCard::ServerStatus ServerToLocalStatus( + sync_pb::WalletMaskedCreditCard::WalletCardStatus status) { + switch (status) { + case sync_pb::WalletMaskedCreditCard::VALID: + return CreditCard::OK; + case sync_pb::WalletMaskedCreditCard::EXPIRED: + default: + DCHECK_EQ(sync_pb::WalletMaskedCreditCard::EXPIRED, status); + return CreditCard::EXPIRED; + } +} + +CreditCard CardFromSpecifics(const sync_pb::WalletMaskedCreditCard& card) { + CreditCard result(CreditCard::MASKED_SERVER_CARD, card.id()); + result.SetNumber(base::UTF8ToUTF16(card.last_four())); + result.SetServerStatus(ServerToLocalStatus(card.status())); + result.SetTypeForMaskedCard(CardTypeFromWalletCardType(card.type())); + result.SetRawInfo(CREDIT_CARD_NAME, base::UTF8ToUTF16(card.name_on_card())); + result.SetExpirationMonth(card.exp_month()); + result.SetExpirationYear(card.exp_year()); + return result; +} + +AutofillProfile ProfileFromSpecifics( + const sync_pb::WalletPostalAddress& address) { + AutofillProfile profile(AutofillProfile::SERVER_PROFILE, address.id()); + + // AutofillProfile stores multi-line addresses with newline separators. + std::vector<std::string> street_address(address.street_address().begin(), + address.street_address().end()); + profile.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, + base::UTF8ToUTF16(JoinString(street_address, '\n'))); + + profile.SetRawInfo(COMPANY_NAME, base::UTF8ToUTF16(address.company_name())); + profile.SetRawInfo(ADDRESS_HOME_STATE, + base::UTF8ToUTF16(address.address_1())); + profile.SetRawInfo(ADDRESS_HOME_CITY, + base::UTF8ToUTF16(address.address_2())); + profile.SetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY, + base::UTF8ToUTF16(address.address_3())); + // AutofillProfile doesn't support address_4 ("sub dependent locality"). + profile.SetRawInfo(ADDRESS_HOME_ZIP, + base::UTF8ToUTF16(address.postal_code())); + profile.SetRawInfo(ADDRESS_HOME_SORTING_CODE, + base::UTF8ToUTF16(address.sorting_code())); + profile.SetRawInfo(ADDRESS_HOME_COUNTRY, + base::UTF8ToUTF16(address.country_code())); + profile.set_language_code(address.language_code()); + + return profile; +} + +// Implements operator< for two objects given their pointers. +template<class Data> struct AutofillDataPtrLessThan { + bool operator()(const Data* a, const Data* b) const { + return a->Compare(*b) < 0; + } +}; + +// This function handles conditionally updating the AutofillTable with either +// a set of CreditCards or AutocompleteProfiles only when the existing data +// doesn't match. +// +// It's passed the getter and setter function on the AutofillTable for the +// corresponding data type, and expects the types to implement a server_id() +// and a Compare function. +// +// Returns the previous number of items in the table (for sync tracking). +template<class Data> +size_t SetDataIfChanged( + AutofillTable* table, + const std::vector<Data>& data, + bool (AutofillTable::*getter)(std::vector<Data*>*), + void (AutofillTable::*setter)(const std::vector<Data>&)) { + ScopedVector<Data> existing_data; + (table->*getter)(&existing_data.get()); + + bool difference_found = true; + if (existing_data.size() == data.size()) { + difference_found = false; + + // Implement this set with pointers using our custom operator that takes + // pointers which avoids any copies. + std::set<const Data*, AutofillDataPtrLessThan<Data>> existing_data_set; + for (const Data* cur : existing_data) + existing_data_set.insert(cur); + + for (const Data& new_data : data) { + if (existing_data_set.find(&new_data) == existing_data_set.end()) { + difference_found = true; + break; + } + } + } + + if (difference_found) + (table->*setter)(data); + + return existing_data.size(); +} + +} // namespace + +AutofillWalletSyncableService::AutofillWalletSyncableService( + AutofillWebDataBackend* webdata_backend, + const std::string& app_locale) + : webdata_backend_(webdata_backend) { +} + +AutofillWalletSyncableService::~AutofillWalletSyncableService() { +} + +syncer::SyncMergeResult +AutofillWalletSyncableService::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()); + + std::vector<CreditCard> wallet_cards; + std::vector<AutofillProfile> wallet_addresses; + + for (const syncer::SyncData& data : initial_sync_data) { + DCHECK_EQ(syncer::AUTOFILL_WALLET_DATA, data.GetDataType()); + const sync_pb::AutofillWalletSpecifics& autofill_specifics = + data.GetSpecifics().autofill_wallet(); + if (autofill_specifics.type() == + sync_pb::AutofillWalletSpecifics::MASKED_CREDIT_CARD) { + wallet_cards.push_back( + CardFromSpecifics(autofill_specifics.masked_card())); + } else { + DCHECK_EQ(sync_pb::AutofillWalletSpecifics::POSTAL_ADDRESS, + autofill_specifics.type()); + wallet_addresses.push_back( + ProfileFromSpecifics(autofill_specifics.address())); + } + } + + // In the common case, the database won't have changed. Committing an update + // to the database will require at least one DB page write and will schedule + // a fsync. To avoid this I/O, it should be more efficient to do a read and + // only do the writes if something changed. + AutofillTable* table = + AutofillTable::FromWebDatabase(webdata_backend_->GetDatabase()); + size_t prev_card_count = + SetDataIfChanged(table, wallet_cards, + &AutofillTable::GetServerCreditCards, + &AutofillTable::SetServerCreditCards); + size_t prev_address_count = + SetDataIfChanged(table, wallet_addresses, + &AutofillTable::GetAutofillServerProfiles, + &AutofillTable::SetAutofillServerProfiles); + + syncer::SyncMergeResult merge_result(type); + merge_result.set_num_items_before_association( + static_cast<int>(prev_card_count + prev_address_count)); + merge_result.set_num_items_after_association( + static_cast<int>(wallet_cards.size() + wallet_addresses.size())); + return merge_result; +} + +void AutofillWalletSyncableService::StopSyncing(syncer::ModelType type) { + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_EQ(type, syncer::AUTOFILL_WALLET_DATA); +} + +syncer::SyncDataList AutofillWalletSyncableService::GetAllSyncData( + syncer::ModelType type) const { + DCHECK(thread_checker_.CalledOnValidThread()); + syncer::SyncDataList current_data; + return current_data; +} + +syncer::SyncError AutofillWalletSyncableService::ProcessSyncChanges( + const tracked_objects::Location& from_here, + const syncer::SyncChangeList& change_list) { + DCHECK(thread_checker_.CalledOnValidThread()); + // TODO(brettw) handle incremental updates while Chrome is running. + return syncer::SyncError(); +} + +// static +void AutofillWalletSyncableService::CreateForWebDataServiceAndBackend( + AutofillWebDataService* web_data_service, + AutofillWebDataBackend* webdata_backend, + const std::string& app_locale) { + web_data_service->GetDBUserData()->SetUserData( + UserDataKey(), + new AutofillWalletSyncableService(webdata_backend, app_locale)); +} + +// static +AutofillWalletSyncableService* +AutofillWalletSyncableService::FromWebDataService( + AutofillWebDataService* web_data_service) { + return static_cast<AutofillWalletSyncableService*>( + web_data_service->GetDBUserData()->GetUserData(UserDataKey())); +} + +void AutofillWalletSyncableService::InjectStartSyncFlare( + const syncer::SyncableService::StartSyncFlare& flare) { + flare_ = flare; +} + +} // namespace autofill diff --git a/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.h b/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.h new file mode 100644 index 0000000..fd32bae --- /dev/null +++ b/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.h @@ -0,0 +1,72 @@ +// 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. + +#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOFILL_WALLET_SYNCABLE_SERVICE_H_ +#define COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOFILL_WALLET_SYNCABLE_SERVICE_H_ + +#include "base/basictypes.h" +#include "base/supports_user_data.h" +#include "base/threading/thread_checker.h" +#include "sync/api/syncable_service.h" + +namespace autofill { + +class AutofillWebDataBackend; +class AutofillWebDataService; + +// Syncs masked cards (last 4 digits only) and addresses from the sync user's +// Wallet account. +class AutofillWalletSyncableService + : public base::SupportsUserData::Data, + public syncer::SyncableService { + public: + ~AutofillWalletSyncableService() override; + + // syncer::SyncableService implementation. + syncer::SyncMergeResult MergeDataAndStartSyncing( + syncer::ModelType type, + const syncer::SyncDataList& initial_sync_data, + scoped_ptr<syncer::SyncChangeProcessor> sync_processor, + scoped_ptr<syncer::SyncErrorFactory> sync_error_factory) override; + void StopSyncing(syncer::ModelType type) override; + syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const override; + syncer::SyncError ProcessSyncChanges( + const tracked_objects::Location& from_here, + const syncer::SyncChangeList& change_list) override; + + // Creates a new AutofillWalletSyncableService and hangs it off of + // |web_data_service|, which takes ownership. This method should only be + // called on |web_data_service|'s DB thread. + static void CreateForWebDataServiceAndBackend( + AutofillWebDataService* web_data_service, + AutofillWebDataBackend* webdata_backend, + const std::string& app_locale); + + // Retrieves the AutofillWalletSyncableService stored on |web_data_service|. + static AutofillWalletSyncableService* FromWebDataService( + AutofillWebDataService* web_data_service); + + // Provides a StartSyncFlare to the SyncableService. See + // sync_start_util for more. + void InjectStartSyncFlare( + const syncer::SyncableService::StartSyncFlare& flare); + + protected: + AutofillWalletSyncableService( + AutofillWebDataBackend* webdata_backend, + const std::string& app_locale); + + private: + base::ThreadChecker thread_checker_; + + AutofillWebDataBackend* webdata_backend_; // Weak ref. + + syncer::SyncableService::StartSyncFlare flare_; + + DISALLOW_COPY_AND_ASSIGN(AutofillWalletSyncableService); +}; + +} // namespace autofill + +#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOFILL_WALLET_SYNCABLE_SERVICE_H_ diff --git a/components/sync_driver/model_association_manager.cc b/components/sync_driver/model_association_manager.cc index 5c2d223..71fbdd5 100644 --- a/components/sync_driver/model_association_manager.cc +++ b/components/sync_driver/model_association_manager.cc @@ -30,6 +30,7 @@ static const syncer::ModelType kStartOrder[] = { syncer::PASSWORDS, syncer::AUTOFILL, syncer::AUTOFILL_PROFILE, + syncer::AUTOFILL_WALLET_DATA, syncer::EXTENSION_SETTINGS, syncer::APP_SETTINGS, syncer::TYPED_URLS, diff --git a/components/sync_driver/pref_names.cc b/components/sync_driver/pref_names.cc index 6ad3763..d4f04d37 100644 --- a/components/sync_driver/pref_names.cc +++ b/components/sync_driver/pref_names.cc @@ -36,6 +36,7 @@ const char kSyncAppSettings[] = "sync.app_settings"; const char kSyncApps[] = "sync.apps"; const char kSyncArticles[] = "sync.articles"; const char kSyncAutofillProfile[] = "sync.autofill_profile"; +const char kSyncAutofillWallet[] = "sync.autofill_wallet"; const char kSyncAutofill[] = "sync.autofill"; const char kSyncBookmarks[] = "sync.bookmarks"; const char kSyncDeviceInfo[] = "sync.device_info"; diff --git a/components/sync_driver/pref_names.h b/components/sync_driver/pref_names.h index 6d77b98..31a605a 100644 --- a/components/sync_driver/pref_names.h +++ b/components/sync_driver/pref_names.h @@ -24,6 +24,7 @@ extern const char kSyncAppSettings[]; extern const char kSyncApps[]; extern const char kSyncArticles[]; extern const char kSyncAutofillProfile[]; +extern const char kSyncAutofillWallet[]; extern const char kSyncAutofill[]; extern const char kSyncBookmarks[]; extern const char kSyncDeviceInfo[]; diff --git a/components/sync_driver/sync_prefs.cc b/components/sync_driver/sync_prefs.cc index e8c3f19..23ccbbf 100644 --- a/components/sync_driver/sync_prefs.cc +++ b/components/sync_driver/sync_prefs.cc @@ -129,6 +129,7 @@ void SyncPrefs::RegisterProfilePrefs( model_set.Put(syncer::PREFERENCES); model_set.Put(syncer::PASSWORDS); model_set.Put(syncer::AUTOFILL_PROFILE); + model_set.Put(syncer::AUTOFILL_WALLET_DATA); model_set.Put(syncer::AUTOFILL); model_set.Put(syncer::THEMES); model_set.Put(syncer::EXTENSIONS); @@ -299,6 +300,8 @@ const char* SyncPrefs::GetPrefNameForDataType(syncer::ModelType data_type) { case syncer::AUTOFILL: return prefs::kSyncAutofill; case syncer::AUTOFILL_PROFILE: + return prefs::kSyncAutofillWallet; + case syncer::AUTOFILL_WALLET_DATA: return prefs::kSyncAutofillProfile; case syncer::THEMES: return prefs::kSyncThemes; @@ -415,6 +418,7 @@ void SyncPrefs::RegisterPrefGroups() { pref_groups_[syncer::APPS].Put(syncer::APP_LIST); pref_groups_[syncer::AUTOFILL].Put(syncer::AUTOFILL_PROFILE); + pref_groups_[syncer::AUTOFILL].Put(syncer::AUTOFILL_WALLET_DATA); pref_groups_[syncer::EXTENSIONS].Put(syncer::EXTENSION_SETTINGS); diff --git a/components/sync_driver/sync_prefs_unittest.cc b/components/sync_driver/sync_prefs_unittest.cc index 8380dba..b1f3423 100644 --- a/components/sync_driver/sync_prefs_unittest.cc +++ b/components/sync_driver/sync_prefs_unittest.cc @@ -140,6 +140,7 @@ TEST_F(SyncPrefsTest, PreferredTypesNotKeepEverythingSynced) { syncer::ModelTypeSet expected_preferred_types(preferred_types); if (it.Get() == syncer::AUTOFILL) { expected_preferred_types.Put(syncer::AUTOFILL_PROFILE); + expected_preferred_types.Put(syncer::AUTOFILL_WALLET_DATA); } if (it.Get() == syncer::PREFERENCES) { expected_preferred_types.Put(syncer::DICTIONARY); diff --git a/components/webdata_services/web_data_service_wrapper.cc b/components/webdata_services/web_data_service_wrapper.cc index 6253a17..c1c5deb 100644 --- a/components/webdata_services/web_data_service_wrapper.cc +++ b/components/webdata_services/web_data_service_wrapper.cc @@ -11,6 +11,7 @@ #include "components/autofill/core/browser/webdata/autocomplete_syncable_service.h" #include "components/autofill/core/browser/webdata/autofill_profile_syncable_service.h" #include "components/autofill/core/browser/webdata/autofill_table.h" +#include "components/autofill/core/browser/webdata/autofill_wallet_syncable_service.h" #include "components/autofill/core/browser/webdata/autofill_webdata_service.h" #include "components/password_manager/core/browser/webdata/logins_table.h" #include "components/search_engines/keyword_table.h" @@ -41,10 +42,16 @@ void InitSyncableServicesOnDBThread( autofill_web_data.get(), autofill_backend); autofill::AutocompleteSyncableService::FromWebDataService( autofill_web_data.get())->InjectStartSyncFlare(sync_flare); + autofill::AutofillProfileSyncableService::CreateForWebDataServiceAndBackend( autofill_web_data.get(), autofill_backend, app_locale); + autofill::AutofillWalletSyncableService::CreateForWebDataServiceAndBackend( + autofill_web_data.get(), autofill_backend, app_locale); + autofill::AutofillProfileSyncableService::FromWebDataService( autofill_web_data.get())->InjectStartSyncFlare(sync_flare); + autofill::AutofillWalletSyncableService::FromWebDataService( + autofill_web_data.get())->InjectStartSyncFlare(sync_flare); } } // namespace diff --git a/sync/internal_api/public/base/model_type.h b/sync/internal_api/public/base/model_type.h index e86814c..8695d8e 100644 --- a/sync/internal_api/public/base/model_type.h +++ b/sync/internal_api/public/base/model_type.h @@ -63,6 +63,9 @@ enum ModelType { AUTOFILL_PROFILE, // An autofill object. AUTOFILL, + // Credit cards and addresses synced from the user's account. These are + // read-only on the client. + AUTOFILL_WALLET_DATA, // A themes object. THEMES, // A typed_url object. diff --git a/sync/protocol/proto_enum_conversions.cc b/sync/protocol/proto_enum_conversions.cc index e531533..7be7453 100644 --- a/sync/protocol/proto_enum_conversions.cc +++ b/sync/protocol/proto_enum_conversions.cc @@ -200,6 +200,46 @@ const char* GetLaunchTypeString(sync_pb::AppSpecifics::LaunchType launch_type) { return ""; } +const char* GetWalletInfoTypeString( + sync_pb::AutofillWalletSpecifics::WalletInfoType wallet_info_type) { + ASSERT_ENUM_BOUNDS(sync_pb::AutofillWalletSpecifics, WalletInfoType, + UNKNOWN, POSTAL_ADDRESS); + switch (wallet_info_type) { + ENUM_CASE(sync_pb::AutofillWalletSpecifics, UNKNOWN); + ENUM_CASE(sync_pb::AutofillWalletSpecifics, MASKED_CREDIT_CARD); + ENUM_CASE(sync_pb::AutofillWalletSpecifics, POSTAL_ADDRESS); + } + NOTREACHED(); + return ""; +} + +const char* GetWalletCardStatusString( + sync_pb::WalletMaskedCreditCard::WalletCardStatus wallet_card_status) { + switch (wallet_card_status) { + ENUM_CASE(sync_pb::WalletMaskedCreditCard, VALID); + ENUM_CASE(sync_pb::WalletMaskedCreditCard, EXPIRED); + } + NOTREACHED(); + return ""; +} + +const char* GetWalletCardTypeString( + sync_pb::WalletMaskedCreditCard::WalletCardType wallet_card_type) { + switch (wallet_card_type) { + ENUM_CASE(sync_pb::WalletMaskedCreditCard, UNKNOWN); + ENUM_CASE(sync_pb::WalletMaskedCreditCard, AMEX); + ENUM_CASE(sync_pb::WalletMaskedCreditCard, DISCOVER); + ENUM_CASE(sync_pb::WalletMaskedCreditCard, JCB); + ENUM_CASE(sync_pb::WalletMaskedCreditCard, MAESTRO); + ENUM_CASE(sync_pb::WalletMaskedCreditCard, MASTER_CARD); + ENUM_CASE(sync_pb::WalletMaskedCreditCard, SOLO); + ENUM_CASE(sync_pb::WalletMaskedCreditCard, SWITCH); + ENUM_CASE(sync_pb::WalletMaskedCreditCard, VISA); + } + NOTREACHED(); + return ""; +} + const char* GetDeviceTypeString( sync_pb::SyncEnums::DeviceType device_type) { ASSERT_ENUM_BOUNDS(sync_pb::SyncEnums, DeviceType, TYPE_WIN, TYPE_TABLET); diff --git a/sync/protocol/proto_enum_conversions.h b/sync/protocol/proto_enum_conversions.h index 6a6bbdc..55d62a0 100644 --- a/sync/protocol/proto_enum_conversions.h +++ b/sync/protocol/proto_enum_conversions.h @@ -56,6 +56,14 @@ SYNC_EXPORT_PRIVATE const char* GetActionString( SYNC_EXPORT_PRIVATE const char* GetLaunchTypeString( sync_pb::AppSpecifics::LaunchType launch_type); +SYNC_EXPORT_PRIVATE const char* GetWalletInfoTypeString( + sync_pb::AutofillWalletSpecifics::WalletInfoType wallet_info_type); + +SYNC_EXPORT_PRIVATE const char* GetWalletCardStatusString( + sync_pb::WalletMaskedCreditCard::WalletCardStatus wallet_card_status); + +SYNC_EXPORT_PRIVATE const char* GetWalletCardTypeString( + sync_pb::WalletMaskedCreditCard::WalletCardType wallet_card_type); const char* GetDeviceTypeString(sync_pb::SyncEnums::DeviceType device_type); diff --git a/sync/protocol/proto_value_conversions.cc b/sync/protocol/proto_value_conversions.cc index d1786f8..54f0e03 100644 --- a/sync/protocol/proto_value_conversions.cc +++ b/sync/protocol/proto_value_conversions.cc @@ -351,6 +351,21 @@ base::DictionaryValue* AutofillProfileSpecificsToValue( return value; } +base::DictionaryValue* AutofillWalletSpecificsToValue( + const sync_pb::AutofillWalletSpecifics& proto) { + base::DictionaryValue* value = new base::DictionaryValue(); + + SET_ENUM(type, GetWalletInfoTypeString); + if (proto.type() == sync_pb::AutofillWalletSpecifics::MASKED_CREDIT_CARD) { + value->Set("masked_card", + WalletMaskedCreditCardToValue(proto.masked_card())); + } else if (proto.type() == sync_pb::AutofillWalletSpecifics::POSTAL_ADDRESS) { + value->Set("masked_card", + WalletPostalAddressToValue(proto.address())); + } + return value; +} + base::DictionaryValue* MetaInfoToValue( const sync_pb::MetaInfo& proto) { base::DictionaryValue* value = new base::DictionaryValue(); @@ -666,6 +681,35 @@ base::DictionaryValue* TypedUrlSpecificsToValue( return value; } +base::DictionaryValue* WalletMaskedCreditCardToValue( + const sync_pb::WalletMaskedCreditCard& proto) { + base::DictionaryValue* value = new base::DictionaryValue(); + SET_STR(id); + SET_ENUM(status, GetWalletCardStatusString); + SET_STR(name_on_card); + SET_ENUM(type, GetWalletCardTypeString); + SET_STR(last_four); + SET_INT32(exp_month); + SET_INT32(exp_year); + return value; +} + +base::DictionaryValue* WalletPostalAddressToValue( + const sync_pb::WalletPostalAddress& proto) { + base::DictionaryValue* value = new base::DictionaryValue(); + SET_STR(company_name); + SET_STR_REP(street_address); + SET_STR(address_1); + SET_STR(address_2); + SET_STR(address_3); + SET_STR(address_4); + SET_STR(postal_code); + SET_STR(sorting_code); + SET_STR(country_code); + SET_STR(language_code); + return value; +} + base::DictionaryValue* WifiCredentialSpecificsToValue( const sync_pb::WifiCredentialSpecifics& proto) { base::DictionaryValue* value = new base::DictionaryValue(); @@ -685,6 +729,7 @@ base::DictionaryValue* EntitySpecificsToValue( SET_FIELD(article, ArticleSpecificsToValue); SET_FIELD(autofill, AutofillSpecificsToValue); SET_FIELD(autofill_profile, AutofillProfileSpecificsToValue); + SET_FIELD(autofill_wallet, AutofillWalletSpecificsToValue); SET_FIELD(bookmark, BookmarkSpecificsToValue); SET_FIELD(device_info, DeviceInfoSpecificsToValue); SET_FIELD(dictionary, DictionarySpecificsToValue); diff --git a/sync/protocol/proto_value_conversions.h b/sync/protocol/proto_value_conversions.h index 960ee45..02d7314 100644 --- a/sync/protocol/proto_value_conversions.h +++ b/sync/protocol/proto_value_conversions.h @@ -23,6 +23,7 @@ class ArticleSpecifics; class AttachmentIdProto; class AutofillProfileSpecifics; class AutofillSpecifics; +class AutofillWalletSpecifics; class BookmarkSpecifics; class ClientConfigParams; class ClientToServerMessage; @@ -71,6 +72,8 @@ class Target; class ThemeSpecifics; class TimeRangeDirective; class TypedUrlSpecifics; +class WalletMaskedCreditCard; +class WalletPostalAddress; class WifiCredentialSpecifics; } // namespace sync_pb @@ -163,6 +166,9 @@ SYNC_EXPORT_PRIVATE base::DictionaryValue* AutofillSpecificsToValue( SYNC_EXPORT_PRIVATE base::DictionaryValue* AutofillProfileSpecificsToValue( const sync_pb::AutofillProfileSpecifics& autofill_profile_specifics); +SYNC_EXPORT_PRIVATE base::DictionaryValue* AutofillWalletSpecificsToValue( + const sync_pb::AutofillWalletSpecifics& autofill_wallet_specifics); + SYNC_EXPORT_PRIVATE base::DictionaryValue* BookmarkSpecificsToValue( const sync_pb::BookmarkSpecifics& bookmark_specifics); @@ -239,6 +245,12 @@ SYNC_EXPORT_PRIVATE base::DictionaryValue* ThemeSpecificsToValue( SYNC_EXPORT_PRIVATE base::DictionaryValue* TypedUrlSpecificsToValue( const sync_pb::TypedUrlSpecifics& typed_url_specifics); +SYNC_EXPORT_PRIVATE base::DictionaryValue* WalletMaskedCreditCardToValue( + const sync_pb::WalletMaskedCreditCard& wallet_masked_card); + +SYNC_EXPORT_PRIVATE base::DictionaryValue* WalletPostalAddressToValue( + const sync_pb::WalletPostalAddress& wallet_postal_address); + SYNC_EXPORT_PRIVATE base::DictionaryValue* WifiCredentialSpecificsToValue( const sync_pb::WifiCredentialSpecifics& wifi_credential_specifics); diff --git a/sync/protocol/proto_value_conversions_unittest.cc b/sync/protocol/proto_value_conversions_unittest.cc index 698da6b..d52223b 100644 --- a/sync/protocol/proto_value_conversions_unittest.cc +++ b/sync/protocol/proto_value_conversions_unittest.cc @@ -57,7 +57,7 @@ TEST_F(ProtoValueConversionsTest, ProtoChangeCheck) { // If this number changes, that means we added or removed a data // type. Don't forget to add a unit test for {New // type}SpecificsToValue below. - EXPECT_EQ(34, MODEL_TYPE_COUNT); + EXPECT_EQ(35, MODEL_TYPE_COUNT); // We'd also like to check if we changed any field in our messages. // However, that's hard to do: sizeof could work, but it's @@ -135,6 +135,10 @@ TEST_F(ProtoValueConversionsTest, AutofillProfileSpecificsToValue) { TestSpecificsToValue(AutofillProfileSpecificsToValue); } +TEST_F(ProtoValueConversionsTest, AutofillWalletSpecificsToValue) { + TestSpecificsToValue(AutofillWalletSpecificsToValue); +} + TEST_F(ProtoValueConversionsTest, BookmarkSpecificsToValue) { TestSpecificsToValue(BookmarkSpecificsToValue); } @@ -314,6 +318,8 @@ TEST_F(ProtoValueConversionsTest, EntitySpecificsToValue) { SET_FIELD(typed_url); SET_FIELD(wifi_credential); + SET_FIELD(autofill_wallet); + #undef SET_FIELD scoped_ptr<base::DictionaryValue> value(EntitySpecificsToValue(specifics)); diff --git a/sync/syncable/model_type.cc b/sync/syncable/model_type.cc index ced8c3a..bb1f4e5 100644 --- a/sync/syncable/model_type.cc +++ b/sync/syncable/model_type.cc @@ -44,7 +44,7 @@ const char* kUserSelectableDataTypeNames[] = { }; static_assert( - 34 == MODEL_TYPE_COUNT, + 35 == MODEL_TYPE_COUNT, "update kUserSelectableDataTypeName to match UserSelectableTypes"); void AddDefaultFieldValue(ModelType datatype, @@ -69,6 +69,9 @@ void AddDefaultFieldValue(ModelType datatype, case AUTOFILL_PROFILE: specifics->mutable_autofill_profile(); break; + case AUTOFILL_WALLET_DATA: + specifics->mutable_autofill_wallet(); + break; case THEMES: specifics->mutable_theme(); break; @@ -176,6 +179,8 @@ int GetSpecificsFieldNumberFromModelType(ModelType model_type) { return sync_pb::EntitySpecifics::kAutofillFieldNumber; case AUTOFILL_PROFILE: return sync_pb::EntitySpecifics::kAutofillProfileFieldNumber; + case AUTOFILL_WALLET_DATA: + return sync_pb::EntitySpecifics::kAutofillWalletFieldNumber; case THEMES: return sync_pb::EntitySpecifics::kThemeFieldNumber; case TYPED_URLS: @@ -284,6 +289,9 @@ ModelType GetModelTypeFromSpecifics(const sync_pb::EntitySpecifics& specifics) { if (specifics.has_autofill_profile()) return AUTOFILL_PROFILE; + if (specifics.has_autofill_wallet()) + return AUTOFILL_WALLET_DATA; + if (specifics.has_theme()) return THEMES; @@ -444,6 +452,8 @@ ModelTypeSet EncryptableUserTypes() { // Note however that proxy types map to one or more protocol types, which // may or may not be encrypted themselves. encryptable_user_types.RemoveAll(ProxyTypes()); + // Wallet data is not encrypted since it actually originates on the server. + encryptable_user_types.Remove(AUTOFILL_WALLET_DATA); return encryptable_user_types; } @@ -585,6 +595,8 @@ const char* ModelTypeToString(ModelType model_type) { return "WiFi Credentials"; case PROXY_TABS: return "Tabs"; + case AUTOFILL_WALLET_DATA: + return "Autofill Wallet"; default: break; } @@ -594,8 +606,10 @@ const char* ModelTypeToString(ModelType model_type) { // The normal rules about histograms apply here. Always append to the bottom of // the list, and be careful to not reuse integer values that have already been -// assigned. Don't forget to update histograms.xml when you make changes to -// this list. +// assigned. +// +// Don't forget to update the "SyncModelTypes" enum in histograms.xml when you +// make changes to this list. int ModelTypeToHistogramInt(ModelType model_type) { switch (model_type) { case UNSPECIFIED: @@ -666,6 +680,8 @@ int ModelTypeToHistogramInt(ModelType model_type) { return 32; case SUPERVISED_USER_WHITELISTS: return 33; + case AUTOFILL_WALLET_DATA: + return 34; // Silence a compiler warning. case MODEL_TYPE_COUNT: return 0; @@ -711,6 +727,8 @@ ModelType ModelTypeFromString(const std::string& model_type_string) { return AUTOFILL; else if (model_type_string == "Autofill Profiles") return AUTOFILL_PROFILE; + else if (model_type_string == "Autofill Wallet") + return AUTOFILL_WALLET_DATA; else if (model_type_string == "Themes") return THEMES; else if (model_type_string == "Typed URLs") @@ -855,6 +873,8 @@ std::string ModelTypeToRootTag(ModelType type) { return "google_chrome_app_list"; case AUTOFILL_PROFILE: return "google_chrome_autofill_profiles"; + case AUTOFILL_WALLET_DATA: + return "google_chrome_autofill_wallet"; case APP_SETTINGS: return "google_chrome_app_settings"; case EXTENSION_SETTINGS: @@ -919,6 +939,7 @@ const char kAppListNotificationType[] = "APP_LIST"; const char kSearchEngineNotificationType[] = "SEARCH_ENGINE"; const char kSessionNotificationType[] = "SESSION"; const char kAutofillProfileNotificationType[] = "AUTOFILL_PROFILE"; +const char kAutofillWalletNotificationType[] = "AUTOFILL_WALLET"; const char kAppNotificationNotificationType[] = "APP_NOTIFICATION"; const char kHistoryDeleteDirectiveNotificationType[] = "HISTORY_DELETE_DIRECTIVE"; @@ -985,6 +1006,9 @@ bool RealModelTypeToNotificationType(ModelType model_type, case AUTOFILL_PROFILE: *notification_type = kAutofillProfileNotificationType; return true; + case AUTOFILL_WALLET_DATA: + *notification_type = kAutofillWalletNotificationType; + return true; case EXTENSION_SETTINGS: *notification_type = kExtensionSettingNotificationType; return true; @@ -1084,6 +1108,9 @@ bool NotificationTypeToRealModelType(const std::string& notification_type, } else if (notification_type == kAutofillProfileNotificationType) { *model_type = AUTOFILL_PROFILE; return true; + } else if (notification_type == kAutofillWalletNotificationType) { + *model_type = AUTOFILL_WALLET_DATA; + return true; } else if (notification_type == kAppSettingNotificationType) { *model_type = APP_SETTINGS; return true; diff --git a/sync/syncable/nigori_util.cc b/sync/syncable/nigori_util.cc index 18b8fce..1eb9227 100644 --- a/sync/syncable/nigori_util.cc +++ b/sync/syncable/nigori_util.cc @@ -243,7 +243,7 @@ void UpdateNigoriFromEncryptedTypes(ModelTypeSet encrypted_types, bool encrypt_everything, sync_pb::NigoriSpecifics* nigori) { nigori->set_encrypt_everything(encrypt_everything); - static_assert(34 == MODEL_TYPE_COUNT, "update encrypted types"); + static_assert(35 == MODEL_TYPE_COUNT, "update encrypted types"); nigori->set_encrypt_bookmarks( encrypted_types.Has(BOOKMARKS)); nigori->set_encrypt_preferences( @@ -279,7 +279,7 @@ ModelTypeSet GetEncryptedTypesFromNigori( return ModelTypeSet::All(); ModelTypeSet encrypted_types; - static_assert(34 == MODEL_TYPE_COUNT, "update encrypted types"); + static_assert(35 == MODEL_TYPE_COUNT, "update encrypted types"); if (nigori.encrypt_bookmarks()) encrypted_types.Put(BOOKMARKS); if (nigori.encrypt_preferences()) diff --git a/sync/util/data_type_histogram.h b/sync/util/data_type_histogram.h index 49885a7..2c4ac8e 100644 --- a/sync/util/data_type_histogram.h +++ b/sync/util/data_type_histogram.h @@ -51,6 +51,9 @@ case ::syncer::AUTOFILL_PROFILE: \ PER_DATA_TYPE_MACRO("AutofillProfiles"); \ break; \ + case ::syncer::AUTOFILL_WALLET_DATA: \ + PER_DATA_TYPE_MACRO("AutofillWallet"); \ + break; \ case ::syncer::THEMES: \ PER_DATA_TYPE_MACRO("Themes"); \ break; \ diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 934a237..1ab21ad 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml @@ -58729,6 +58729,7 @@ To add a new entry, add it with any value and run test to compute valid value. <int value="31" label="Synced Notification App Info"/> <int value="32" label="Wifi Credentials"/> <int value="33" label="Managed User Whitelists"/> + <int value="34" label="Autofill Wallet"/> </enum> <enum name="SyncNigoriMigrationResult" type="int"> |