From f900222890dd7e4d6ca6ac872520b6ee9c518f04 Mon Sep 17 00:00:00 2001 From: hcarmona Date: Mon, 23 May 2016 16:29:21 -0700 Subject: [PATCH] Separate the listeners and getters for the Autofill Private API. OnAddressListChanged and OnCreditCardListChanged used to trigger an update when a listener was added. This is now de-coupled so that a list can be retrieved separately from listening for changes. BUG=607348,607347 CQ_INCLUDE_TRYBOTS=tryserver.chromium.linux:closure_compilation Review-Url: https://codereview.chromium.org/1957043002 Cr-Commit-Position: refs/heads/master@{#395462} --- .../autofill_private/autofill_private_api.cc | 50 +++ .../autofill_private/autofill_private_api.h | 37 ++ .../autofill_private_event_router.cc | 45 +-- .../autofill_private_event_router.h | 8 - .../passwords_and_forms_page.html | 3 +- .../passwords_and_forms_page.js | 277 +++++++++++-- chrome/chrome_tests.gypi | 2 + .../extensions/api/autofill_private.idl | 13 +- .../api_test/autofill_private/test.js | 3 + .../passwords_and_autofill_fake_data.js | 108 +++++ .../passwords_and_forms_browsertest.js | 378 ++++++++++++++++++ .../settings_autofill_section_browsertest.js | 95 +---- .../settings_passwords_section_browsertest.js | 107 ++--- .../extension_function_histogram_value.h | 2 + .../externs/autofill_private.js | 16 + tools/metrics/histograms/histograms.xml | 2 + 16 files changed, 909 insertions(+), 237 deletions(-) create mode 100644 chrome/test/data/webui/settings/passwords_and_autofill_fake_data.js create mode 100644 chrome/test/data/webui/settings/passwords_and_forms_browsertest.js diff --git a/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc b/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc index e3b92654f2a5d3..ce3ab6460e1c54 100644 --- a/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc +++ b/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc @@ -12,6 +12,7 @@ #include "base/values.h" #include "chrome/browser/autofill/personal_data_manager_factory.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/extensions/api/autofill_private/autofill_util.h" #include "chrome/common/extensions/api/autofill_private.h" #include "chrome/grit/generated_resources.h" #include "components/autofill/core/browser/autofill_profile.h" @@ -299,6 +300,29 @@ ExtensionFunction::ResponseAction return RespondNow(OneArgument(components.ToValue().release())); } +//////////////////////////////////////////////////////////////////////////////// +// AutofillPrivateGetAddressListFunction + +AutofillPrivateGetAddressListFunction::AutofillPrivateGetAddressListFunction() + : chrome_details_(this) {} + +AutofillPrivateGetAddressListFunction:: + ~AutofillPrivateGetAddressListFunction() {} + +ExtensionFunction::ResponseAction AutofillPrivateGetAddressListFunction::Run() { + autofill::PersonalDataManager* personal_data = + autofill::PersonalDataManagerFactory::GetForProfile( + chrome_details_.GetProfile()); + + DCHECK(personal_data && personal_data->IsDataLoaded()); + + autofill_util::AddressEntryList addressList = + extensions::autofill_util::GenerateAddressList(*personal_data); + + return RespondNow(ArgumentList( + api::autofill_private::GetAddressList::Results::Create(addressList))); +} + //////////////////////////////////////////////////////////////////////////////// // AutofillPrivateSaveCreditCardFunction @@ -437,4 +461,30 @@ ExtensionFunction::ResponseAction AutofillPrivateMaskCreditCardFunction::Run() { return RespondNow(NoArguments()); } +//////////////////////////////////////////////////////////////////////////////// +// AutofillPrivateGetCreditCardListFunction + +AutofillPrivateGetCreditCardListFunction:: + AutofillPrivateGetCreditCardListFunction() + : chrome_details_(this) {} + +AutofillPrivateGetCreditCardListFunction:: + ~AutofillPrivateGetCreditCardListFunction() {} + +ExtensionFunction::ResponseAction +AutofillPrivateGetCreditCardListFunction::Run() { + autofill::PersonalDataManager* personal_data = + autofill::PersonalDataManagerFactory::GetForProfile( + chrome_details_.GetProfile()); + + DCHECK(personal_data && personal_data->IsDataLoaded()); + + autofill_util::CreditCardEntryList creditCardList = + extensions::autofill_util::GenerateCreditCardList(*personal_data); + + return RespondNow( + ArgumentList(api::autofill_private::GetCreditCardList::Results::Create( + creditCardList))); +} + } // namespace extensions diff --git a/chrome/browser/extensions/api/autofill_private/autofill_private_api.h b/chrome/browser/extensions/api/autofill_private/autofill_private_api.h index 819881a2c3ab0a..9a34697c635f8f 100644 --- a/chrome/browser/extensions/api/autofill_private/autofill_private_api.h +++ b/chrome/browser/extensions/api/autofill_private/autofill_private_api.h @@ -48,6 +48,24 @@ class AutofillPrivateGetAddressComponentsFunction : DISALLOW_COPY_AND_ASSIGN(AutofillPrivateGetAddressComponentsFunction); }; +class AutofillPrivateGetAddressListFunction : public UIThreadExtensionFunction { + public: + AutofillPrivateGetAddressListFunction(); + DECLARE_EXTENSION_FUNCTION("autofillPrivate.getAddressList", + AUTOFILLPRIVATE_GETADDRESSLIST); + + protected: + ~AutofillPrivateGetAddressListFunction() override; + + // ExtensionFunction overrides. + ResponseAction Run() override; + + private: + ChromeExtensionFunctionDetails chrome_details_; + + DISALLOW_COPY_AND_ASSIGN(AutofillPrivateGetAddressListFunction); +}; + class AutofillPrivateSaveCreditCardFunction : public UIThreadExtensionFunction { public: AutofillPrivateSaveCreditCardFunction(); @@ -119,6 +137,25 @@ class AutofillPrivateMaskCreditCardFunction : public UIThreadExtensionFunction { DISALLOW_COPY_AND_ASSIGN(AutofillPrivateMaskCreditCardFunction); }; +class AutofillPrivateGetCreditCardListFunction + : public UIThreadExtensionFunction { + public: + AutofillPrivateGetCreditCardListFunction(); + DECLARE_EXTENSION_FUNCTION("autofillPrivate.getCreditCardList", + AUTOFILLPRIVATE_GETCREDITCARDLIST); + + protected: + ~AutofillPrivateGetCreditCardListFunction() override; + + // ExtensionFunction overrides. + ResponseAction Run() override; + + private: + ChromeExtensionFunctionDetails chrome_details_; + + DISALLOW_COPY_AND_ASSIGN(AutofillPrivateGetCreditCardListFunction); +}; + } // namespace extensions #endif // CHROME_BROWSER_EXTENSIONS_API_AUTOFILL_PRIVATE_AUTOFILL_PRIVATE_API_H_ diff --git a/chrome/browser/extensions/api/autofill_private/autofill_private_event_router.cc b/chrome/browser/extensions/api/autofill_private/autofill_private_event_router.cc index 5162c97f582b7c..f1fd03426cb934 100644 --- a/chrome/browser/extensions/api/autofill_private/autofill_private_event_router.cc +++ b/chrome/browser/extensions/api/autofill_private/autofill_private_event_router.cc @@ -40,35 +40,15 @@ AutofillPrivateEventRouter::AutofillPrivateEventRouter( if (!personal_data_) return; - event_router_->RegisterObserver( - this, - api::autofill_private::OnAddressListChanged::kEventName); - event_router_->RegisterObserver( - this, - api::autofill_private::OnCreditCardListChanged::kEventName); - StartOrStopListeningForChanges(); + personal_data_->AddObserver(this); } AutofillPrivateEventRouter::~AutofillPrivateEventRouter() { } void AutofillPrivateEventRouter::Shutdown() { - if (event_router_) - event_router_->UnregisterObserver(this); -} - -void AutofillPrivateEventRouter::OnListenerAdded( - const EventListenerInfo& details) { - // Start listening to change events and propagate the original lists to - // listeners. - StartOrStopListeningForChanges(); - OnPersonalDataChanged(); -} - -void AutofillPrivateEventRouter::OnListenerRemoved( - const EventListenerInfo& details) { - // Stop listening to events if there are no more listeners. - StartOrStopListeningForChanges(); + if (personal_data_) + personal_data_->RemoveObserver(this); } void AutofillPrivateEventRouter::OnPersonalDataChanged() { @@ -97,25 +77,6 @@ void AutofillPrivateEventRouter::OnPersonalDataChanged() { event_router_->BroadcastEvent(std::move(extension_event)); } -void AutofillPrivateEventRouter::StartOrStopListeningForChanges() { - if (!personal_data_ || !personal_data_->IsDataLoaded()) - return; - - bool should_listen_for_address_changes = event_router_->HasEventListener( - api::autofill_private::OnAddressListChanged::kEventName); - bool should_listen_for_credit_card_changes = event_router_->HasEventListener( - api::autofill_private::OnCreditCardListChanged::kEventName); - bool should_listen = should_listen_for_address_changes || - should_listen_for_credit_card_changes; - - if (should_listen && !listening_) - personal_data_->AddObserver(this); - else if (!should_listen && listening_) - personal_data_->RemoveObserver(this); - - listening_ = should_listen; -} - AutofillPrivateEventRouter* AutofillPrivateEventRouter::Create( content::BrowserContext* context) { return new AutofillPrivateEventRouter(context); diff --git a/chrome/browser/extensions/api/autofill_private/autofill_private_event_router.h b/chrome/browser/extensions/api/autofill_private/autofill_private_event_router.h index 2c435aed5ff9c5..ae00019a47bbba 100644 --- a/chrome/browser/extensions/api/autofill_private/autofill_private_event_router.h +++ b/chrome/browser/extensions/api/autofill_private/autofill_private_event_router.h @@ -38,18 +38,10 @@ class AutofillPrivateEventRouter : // KeyedService overrides: void Shutdown() override; - // EventRouter::Observer overrides: - void OnListenerAdded(const EventListenerInfo& details) override; - void OnListenerRemoved(const EventListenerInfo& details) override; - // PersonalDataManagerObserver implementation. void OnPersonalDataChanged() override; private: - // Either listens or unlistens for changes to |personal_data_|, depending on - // whether clients are listening to the autofillPrivate API events. - void StartOrStopListeningForChanges(); - content::BrowserContext* context_; EventRouter* event_router_; diff --git a/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.html b/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.html index 68b70b3836dfc7..364530c6677b6f 100644 --- a/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.html +++ b/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.html @@ -37,7 +37,8 @@ diff --git a/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.js b/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.js index f0c52b28b6993c..d38235f03cc5fe 100644 --- a/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.js +++ b/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.js @@ -27,10 +27,22 @@ PasswordManager.PlaintextPasswordEvent; PasswordManager.prototype = { /** - * Request the list of saved passwords and observe future changes. + * Add an observer to the list of saved passwords. + * @param {function(!Array):void} listener + */ + addSavedPasswordListChangedListener: assertNotReached, + + /** + * Remove an observer from the list of saved passwords. + * @param {function(!Array):void} listener + */ + removeSavedPasswordListChangedListener: assertNotReached, + + /** + * Request the list of saved passwords. * @param {function(!Array):void} callback */ - setSavedPasswordListChangedCallback: assertNotReached, + getSavedPasswordList: assertNotReached, /** * Should remove the saved password and notify that the list has changed. @@ -40,30 +52,87 @@ PasswordManager.prototype = { removeSavedPassword: assertNotReached, /** - * Request the list of password exceptions and observe future changes. + * Add an observer to the list of password exceptions. + * @param {function(!Array):void} listener + */ + addExceptionListChangedListener: assertNotReached, + + /** + * Remove an observer from the list of password exceptions. + * @param {function(!Array):void} listener + */ + removeExceptionListChangedListener: assertNotReached, + + /** + * Request the list of password exceptions. * @param {function(!Array):void} callback */ - setExceptionListChangedCallback: assertNotReached, + getExceptionList: assertNotReached, /** * Should remove the password exception and notify that the list has changed. * @param {!string} exception The exception that should be removed from the * list. No-op if |exception| is not in the list. */ - removePasswordException: assertNotReached, + removeException: assertNotReached, /** - * Register a callback for when a password is requested. - * @param {function(!Array):void} callback + * Gets the saved password for a given login pair. + * @param {!PasswordManager.LoginPair} loginPair The saved password that + * should be retrieved. + * @param {function(!PasswordManager.PlaintextPasswordEvent):void} callback */ - onPlaintextPasswordRequestedCallback: assertNotReached, + getPlaintextPassword: assertNotReached, +}; + +/** + * Interface for all callbacks to the autofill API. + * @interface + */ +function AutofillManager() {} + +/** @typedef {chrome.autofillPrivate.AddressEntry} */ +AutofillManager.AddressEntry; + +/** @typedef {chrome.autofillPrivate.CreditCardEntry} */ +AutofillManager.CreditCardEntry; +AutofillManager.prototype = { /** - * Should request the saved password for a given login pair. - * @param {!PasswordManager.LoginPair} loginPair The saved password that - * should be retrieved. + * Add an observer to the list of addresses. + * @param {function(!Array):void} listener + */ + addAddressListChangedListener: assertNotReached, + + /** + * Remove an observer from the list of addresses. + * @param {function(!Array):void} listener */ - requestPlaintextPassword: assertNotReached, + removeAddressListChangedListener: assertNotReached, + + /** + * Request the list of addresses. + * @param {function(!Array):void} callback + */ + getAddressList: assertNotReached, + + /** + * Add an observer to the list of credit cards. + * @param {function(!Array):void} listener + */ + addCreditCardListChangedListener: assertNotReached, + + /** + * Remove an observer from the list of credit cards. + * @param {function(!Array):void} listener + */ + removeCreditCardListChangedListener: assertNotReached, + + /** + * Request the list of credit cards. + * @param {function(!Array):void} callback + */ + getCreditCardList: assertNotReached, }; /** @@ -78,11 +147,19 @@ PasswordManagerImpl.prototype = { __proto__: PasswordManager, /** @override */ - setSavedPasswordListChangedCallback: function(callback) { - // Get the list of passwords... + addSavedPasswordListChangedListener: function(listener) { + chrome.passwordsPrivate.onSavedPasswordsListChanged.addListener(listener); + }, + + /** @override */ + removeSavedPasswordListChangedListener: function(listener) { + chrome.passwordsPrivate.onSavedPasswordsListChanged.removeListener( + listener); + }, + + /** @override */ + getSavedPasswordList: function(callback) { chrome.passwordsPrivate.getSavedPasswordList(callback); - // ...and listen for future changes. - chrome.passwordsPrivate.onSavedPasswordsListChanged.addListener(callback); }, /** @override */ @@ -91,30 +168,85 @@ PasswordManagerImpl.prototype = { }, /** @override */ - setExceptionListChangedCallback: function(callback) { - // Get the list of exceptions... - chrome.passwordsPrivate.getPasswordExceptionList(callback); - // ...and listen for future changes. + addExceptionListChangedListener: function(listener) { chrome.passwordsPrivate.onPasswordExceptionsListChanged.addListener( - callback); + listener); }, /** @override */ - removePasswordException: function(exception) { - chrome.passwordsPrivate.removePasswordException(exception); + removeExceptionListChangedListener: function(listener) { + chrome.passwordsPrivate.onPasswordExceptionsListChanged.removeListener( + listener); }, /** @override */ - onPlaintextPasswordRequestedCallback: function(callback) { - chrome.passwordsPrivate.onPlaintextPasswordRetrieved.addListener(callback); + getExceptionList: function(callback) { + chrome.passwordsPrivate.getPasswordExceptionList(callback); }, /** @override */ - requestPlaintextPassword: function(loginPair) { + removeException: function(exception) { + chrome.passwordsPrivate.removePasswordException(exception); + }, + + /** @override */ + getPlaintextPassword: function(loginPair, callback) { + var listener = function(reply) { + // Only handle the reply for our loginPair request. + if (reply.loginPair.originUrl == loginPair.originUrl && + reply.loginPair.username == loginPair.username) { + chrome.passwordsPrivate.onPlaintextPasswordRetrieved.removeListener( + listener); + callback(reply); + } + }; + chrome.passwordsPrivate.onPlaintextPasswordRetrieved.addListener(listener); chrome.passwordsPrivate.requestPlaintextPassword(loginPair); }, }; +/** + * Implementation that accesses the private API. + * @implements {AutofillManager} + * @constructor + */ +function AutofillManagerImpl() {} +cr.addSingletonGetter(AutofillManagerImpl); + +AutofillManagerImpl.prototype = { + __proto__: AutofillManager, + + /** @override */ + addAddressListChangedListener: function(listener) { + chrome.autofillPrivate.onAddressListChanged.addListener(listener); + }, + + /** @override */ + removeAddressListChangedListener: function(listener) { + chrome.autofillPrivate.onAddressListChanged.removeListener(listener); + }, + + /** @override */ + getAddressList: function(callback) { + chrome.autofillPrivate.getAddressList(callback); + }, + + /** @override */ + addCreditCardListChangedListener: function(listener) { + chrome.autofillPrivate.onCreditCardListChanged.addListener(listener); + }, + + /** @override */ + removeCreditCardListChangedListener: function(listener) { + chrome.autofillPrivate.onCreditCardListChanged.removeListener(listener); + }, + + /** @override */ + getCreditCardList: function(callback) { + chrome.autofillPrivate.getCreditCardList(callback); + }, +}; + (function() { 'use strict'; @@ -144,7 +276,6 @@ Polymer({ */ savedPasswords: { type: Array, - value: function() { return []; }, }, /** @@ -153,9 +284,24 @@ Polymer({ */ passwordExceptions: { type: Array, - value: function() { return []; }, }, - }, + + /** + * An array of saved addresses. + * @type {!Array} + */ + addresses: { + type: Array, + }, + + /** + * An array of saved addresses. + * @type {!Array} + */ + creditCards: { + type: Array, + }, + }, listeners: { 'remove-password-exception': 'removePasswordException_', @@ -163,19 +309,68 @@ Polymer({ 'show-password': 'showPassword_', }, + /** @type {?function(!Array):void} */ + setSavedPasswordsListener_: null, + + /** @type {?function(!Array):void} */ + setPasswordExceptionsListener_: null, + + /** @type {?function(!Array)} */ + setAddressesListener_: null, + + /** @type {?function(!Array)} */ + setCreditCardsListener_: null, + /** @override */ ready: function() { - this.passwordManager_ = PasswordManagerImpl.getInstance(); - - this.passwordManager_.setSavedPasswordListChangedCallback(function(list) { + // Create listener functions. + this.setSavedPasswordsListener_ = function(list) { this.savedPasswords = list; - }.bind(this)); - this.passwordManager_.setExceptionListChangedCallback(function(list) { + }.bind(this); + + this.setPasswordExceptionsListener_ = function(list) { this.passwordExceptions = list; - }.bind(this)); - this.passwordManager_.onPlaintextPasswordRequestedCallback(function(e) { - this.$$('#passwordSection').setPassword(e.loginPair, e.plaintextPassword); - }.bind(this)); + }.bind(this); + + this.setAddressesListener_ = function(list) { + this.addresses = list; + }.bind(this); + + this.setCreditCardsListener_ = function(list) { + this.creditCards = list; + }.bind(this); + + // Set the managers. These can be overridden by tests. + this.passwordManager_ = PasswordManagerImpl.getInstance(); + this.autofillManager_ = AutofillManagerImpl.getInstance(); + + // Request initial data. + this.passwordManager_.getSavedPasswordList(this.setSavedPasswordsListener_); + this.passwordManager_.getExceptionList(this.setPasswordExceptionsListener_); + this.autofillManager_.getAddressList(this.setAddressesListener_); + this.autofillManager_.getCreditCardList(this.setCreditCardsListener_); + + // Listen for changes. + this.passwordManager_.addSavedPasswordListChangedListener( + this.setSavedPasswordsListener_); + this.passwordManager_.addExceptionListChangedListener( + this.setPasswordExceptionsListener_); + this.autofillManager_.addAddressListChangedListener( + this.setAddressesListener_); + this.autofillManager_.addCreditCardListChangedListener( + this.setCreditCardsListener_); + }, + + /** @override */ + detached: function() { + this.passwordManager_.removeSavedPasswordListChangedListener( + this.setSavedPasswordsListener_); + this.passwordManager_.removeExceptionListChangedListener( + this.setPasswordExceptionsListener_); + this.autofillManager_.removeAddressListChangedListener( + this.setAddressesListener_); + this.autofillManager_.removeCreditCardListChangedListener( + this.setCreditCardsListener_); }, /** @@ -184,7 +379,7 @@ Polymer({ * @private */ removePasswordException_: function(event) { - this.passwordManager_.removePasswordException(event.detail); + this.passwordManager_.removeException(event.detail); }, /** @@ -229,7 +424,9 @@ Polymer({ * @private */ showPassword_: function(event) { - this.passwordManager_.requestPlaintextPassword(event.detail); + this.passwordManager_.getPlaintextPassword(event.detail, function(e) { + this.$$('#passwordSection').setPassword(e.loginPair, e.plaintextPassword); + }.bind(this)); }, }); })(); diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 57f46a2cb47ab9..c81bb925863965 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -1017,6 +1017,8 @@ 'test/data/webui/settings/easy_unlock_browsertest_chromeos.js', 'test/data/webui/settings/languages_page_browsertest.js', 'test/data/webui/settings/on_startup_browsertest.js', + 'test/data/webui/settings/passwords_and_autofill_fake_data.js', + 'test/data/webui/settings/passwords_and_forms_browsertest.js', 'test/data/webui/settings/settings_autofill_section_browsertest.js', 'test/data/webui/settings/settings_page_browsertest.js', 'test/data/webui/settings/settings_passwords_section_browsertest.js', diff --git a/chrome/common/extensions/api/autofill_private.idl b/chrome/common/extensions/api/autofill_private.idl index 43edb3d0d28b0d..b70b6496ca96e9 100644 --- a/chrome/common/extensions/api/autofill_private.idl +++ b/chrome/common/extensions/api/autofill_private.idl @@ -165,10 +165,11 @@ namespace autofillPrivate { DOMString countryCode; }; - callback GetAddressComponentsCallback = - void(AddressComponents components); + callback GetAddressComponentsCallback = void(AddressComponents components); + callback GetAddressListCallback = void(AddressEntry[] entries); callback ValidatePhoneNumbersCallback = void(DOMString[] validatedPhoneNumbers); + callback GetCreditCardListCallback = void(CreditCardEntry[] entries); interface Functions { // Saves the given address. If |address| has an empty string as its ID, it @@ -186,6 +187,10 @@ namespace autofillPrivate { static void getAddressComponents(DOMString countryCode, GetAddressComponentsCallback callback); + // Gets the list of addresses. + // |callback|: Callback which will be called with the list of addresses. + static void getAddressList(GetAddressListCallback callback); + // Saves the given credit card. If |card| has an empty string as its // ID, it will be assigned a new one and added as a new entry. // @@ -206,6 +211,10 @@ namespace autofillPrivate { static void validatePhoneNumbers(ValidatePhoneParams params, ValidatePhoneNumbersCallback callback); + // Gets the list of credit cards. + // |callback|: Callback which will be called with the list of credit cards. + static void getCreditCardList(GetCreditCardListCallback callback); + // Clears the data associated with a wallet card which was saved // locally so that the saved copy is masked (e.g., "Card ending // in 1234"). diff --git a/chrome/test/data/extensions/api_test/autofill_private/test.js b/chrome/test/data/extensions/api_test/autofill_private/test.js index 3097ba0790f4cc..bc4b9ee1394ae6 100644 --- a/chrome/test/data/extensions/api_test/autofill_private/test.js +++ b/chrome/test/data/extensions/api_test/autofill_private/test.js @@ -25,6 +25,7 @@ var availableTests = [ } chrome.autofillPrivate.onAddressListChanged.addListener(handler); + chrome.autofillPrivate.getAddressList(handler); chrome.autofillPrivate.saveAddress({fullNames: [NAME]}); }, @@ -63,6 +64,7 @@ var availableTests = [ } chrome.autofillPrivate.onCreditCardListChanged.addListener(handler); + chrome.autofillPrivate.getCreditCardList(handler); chrome.autofillPrivate.saveCreditCard({name: NAME}); }, @@ -90,6 +92,7 @@ var availableTests = [ } chrome.autofillPrivate.onCreditCardListChanged.addListener(handler); + chrome.autofillPrivate.getCreditCardList(handler); chrome.autofillPrivate.saveCreditCard({name: NAME}); }, diff --git a/chrome/test/data/webui/settings/passwords_and_autofill_fake_data.js b/chrome/test/data/webui/settings/passwords_and_autofill_fake_data.js new file mode 100644 index 00000000000000..5d4de53de7c9d0 --- /dev/null +++ b/chrome/test/data/webui/settings/passwords_and_autofill_fake_data.js @@ -0,0 +1,108 @@ +// Copyright 2016 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. + +/** + * Used to create fake data for both passwords and autofill. + * These sections are related, so it made sense to share this. + */ +function FakeDataMaker() {} +/** + * Creates a single item for the list of passwords. + * @param {string|undefined} url + * @param {string|undefined} username + * @param {number|undefined} passwordLength + * @return {chrome.passwordsPrivate.PasswordUiEntry} + */ +FakeDataMaker.passwordEntry = function(url, username, passwordLength) { + // Generate fake data if param is undefined. + url = url || FakeDataMaker.patternMaker_('www.xxxxxx.com', 16); + username = username || FakeDataMaker.patternMaker_('user_xxxxx', 16); + passwordLength = passwordLength || Math.floor(Math.random() * 15) + 3; + + return { + loginPair: { + originUrl: url, + username: username, + }, + linkUrl: 'http://' + url + '/login', + numCharactersInPassword: passwordLength, + }; +}; + +/** + * Creates a single item for the list of password exceptions. + * @param {string|undefined} url + * @return {chrome.passwordsPrivate.ExceptionPair} + */ +FakeDataMaker.exceptionEntry = function(url) { + url = url || FakeDataMaker.patternMaker_('www.xxxxxx.com', 16); + return { + exceptionUrl: url, + linkUrl: 'http://' + url + '/login', + }; +}; + +/** + * Creates a fake address entry for testing. + * @return {!chrome.autofillPrivate.AddressEntry} + */ +FakeDataMaker.addressEntry = function() { + var ret = {}; + ret.guid = FakeDataMaker.makeGuid_(); + ret.fullNames = ['John', 'Doe']; + ret.companyName = 'Google'; + ret.addressLines = FakeDataMaker.patternMaker_('xxxx Main St', 10); + ret.addressLevel1 = "CA"; + ret.addressLevel2 = "Venice"; + ret.postalCode = FakeDataMaker.patternMaker_('xxxxx', 10); + ret.countryCode = 'US'; + ret.phoneNumbers = [FakeDataMaker.patternMaker_('(xxx) xxx-xxxx', 10)]; + ret.emailAddresses = [FakeDataMaker.patternMaker_('userxxxx@gmail.com', 16)]; + ret.languageCode = 'EN-US'; + ret.metadata = {isLocal: true}; + ret.metadata.summaryLabel = ret.fullNames[0]; + ret.metadata.summarySublabel = ' ' + ret.addressLines; + return ret; +}; + +/** + * Creates a new random credit card entry for testing. + * @return {!chrome.autofillPrivate.CreditCardEntry} + */ +FakeDataMaker.creditCardEntry = function() { + var ret = {}; + ret.guid = FakeDataMaker.makeGuid_(); + ret.name = 'Jane Doe'; + ret.cardNumber = FakeDataMaker.patternMaker_('xxxx xxxx xxxx xxxx', 10); + ret.expirationMonth = Math.ceil(Math.random() * 11).toString(); + ret.expirationYear = (2016 + Math.floor(Math.random() * 5)).toString(); + ret.metadata = {isLocal: true}; + var cards = ['Visa', 'Mastercard', 'Discover', 'Card']; + var card = cards[Math.floor(Math.random() * cards.length)]; + ret.metadata.summaryLabel = card + ' ' + '****' + ret.cardNumber.substr(-4); + return ret; +}; + +/** + * Creates a new random GUID for testing. + * @return {!string} + * @private + */ +FakeDataMaker.makeGuid_ = function() { + return FakeDataMaker.patternMaker_( + 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', 16); +}; + +/** + * Replaces any 'x' in a string with a random number of the base. + * @param {!string} pattern The pattern that should be used as an input. + * @param {!number} base The number base. ie: 16 for hex or 10 for decimal. + * @return {!string} + * @private + */ +FakeDataMaker.patternMaker_ = function(pattern, base) { + return pattern.replace(/x/g, function() { + return Math.floor(Math.random() * base).toString(base); + }); +}; diff --git a/chrome/test/data/webui/settings/passwords_and_forms_browsertest.js b/chrome/test/data/webui/settings/passwords_and_forms_browsertest.js new file mode 100644 index 00000000000000..b983bc103f6ffa --- /dev/null +++ b/chrome/test/data/webui/settings/passwords_and_forms_browsertest.js @@ -0,0 +1,378 @@ +// Copyright 2016 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. + +/** @fileoverview Runs the Polymer Passwords and Forms tests. */ + +/** @const {string} Path to root from chrome/test/data/webui/settings/. */ +var ROOT_PATH = '../../../../../'; + +// Polymer BrowserTest fixture. +GEN_INCLUDE( + [ROOT_PATH + 'chrome/test/data/webui/polymer_browser_test_base.js']); + +// Fake data generator. +GEN_INCLUDE([ROOT_PATH + + 'chrome/test/data/webui/settings/passwords_and_autofill_fake_data.js']); + +function PasswordManagerExpectations() {}; +PasswordManagerExpectations.prototype = { + requested: { + passwords: 0, + exceptions: 0, + plaintextPassword: 0, + }, + + removed: { + passwords: 0, + exceptions: 0, + }, + + listening: { + passwords: 0, + exceptions: 0, + }, +}; + +/** + * Test implementation + * @implements {PasswordManager} + * @constructor + */ +function TestPasswordManager() { + this.actual_ = new PasswordManagerExpectations(); +}; +TestPasswordManager.prototype = { + /** @override */ + addSavedPasswordListChangedListener: function(listener) { + this.actual_.listening.passwords++; + this.lastCallback.addSavedPasswordListChangedListener = listener; + }, + + /** @override */ + removeSavedPasswordListChangedListener: function(listener) { + this.actual_.listening.passwords--; + }, + + /** @override */ + getSavedPasswordList: function(callback) { + this.actual_.requested.passwords++; + callback(this.data.passwords); + }, + + /** @override */ + removeSavedPassword: function(loginPair) { + this.actual_.removed.passwords++; + }, + + /** @override */ + addExceptionListChangedListener: function(listener) { + this.actual_.listening.exceptions++; + this.lastCallback.addExceptionListChangedListener = listener; + }, + + /** @override */ + removeExceptionListChangedListener: function(listener) { + this.actual_.listening.exceptions--; + }, + + /** @override */ + getExceptionList: function(callback) { + this.actual_.requested.exceptions++; + callback(this.data.exceptions); + }, + + /** @override */ + removeException: function(exception) { + this.actual_.removed.exceptions++; + }, + + /** @override */ + getPlaintextPassword: function(loginPair, callback) { + this.actual_.requested.plaintextPassword++; + this.lastCallback.getPlaintextPassword = callback; + }, + + /** + * Verifies expectations. + * @param {!PasswordManagerExpectations} expected + */ + assertExpectations: function(expected) { + var actual = this.actual_; + + assertEquals(expected.requested.passwords, actual.requested.passwords); + assertEquals(expected.requested.exceptions, actual.requested.exceptions); + assertEquals(expected.requested.plaintextPassword, + actual.requested.plaintextPassword); + + assertEquals(expected.removed.passwords, actual.removed.passwords); + assertEquals(expected.removed.exceptions, actual.removed.exceptions); + + assertEquals(expected.listening.passwords, actual.listening.passwords); + assertEquals(expected.listening.exceptions, actual.listening.exceptions); + }, + + // Set these to have non-empty data. + data: { + passwords: [], + exceptions: [], + }, + + // Holds the last callbacks so they can be called when needed/ + lastCallback: { + addSavedPasswordListChangedListener: null, + addExceptionListChangedListener: null, + getPlaintextPassword: null, + }, +}; + +function AutofillManagerExpectations() {}; +AutofillManagerExpectations.prototype = { + requested: { + addresses: 0, + creditCards: 0, + }, + + listening: { + addresses: 0, + creditCards: 0, + }, +}; + +/** + * Test implementation + * @implements {AutofillManager} + * @constructor + */ +function TestAutofillManager() { + this.actual_ = new AutofillManagerExpectations(); +}; +TestAutofillManager.prototype = { + /** @override */ + addAddressListChangedListener: function(listener) { + this.actual_.listening.addresses++; + this.lastCallback.addAddressListChangedListener = listener; + }, + + /** @override */ + removeAddressListChangedListener: function(listener) { + this.actual_.listening.addresses--; + }, + + /** @override */ + getAddressList: function(callback) { + this.actual_.requested.addresses++; + callback(this.data.addresses); + }, + + /** @override */ + addCreditCardListChangedListener: function(listener) { + this.actual_.listening.creditCards++; + this.lastCallback.addCreditCardListChangedListener = listener; + }, + + /** @override */ + removeCreditCardListChangedListener: function(listener) { + this.actual_.listening.creditCards--; + }, + + /** @override */ + getCreditCardList: function(callback) { + this.actual_.requested.creditCards++; + callback(this.data.creditCards); + }, + + /** + * Verifies expectations. + * @param {!AutofillManagerExpectations} expected + */ + assertExpectations: function(expected) { + var actual = this.actual_; + + assertEquals(expected.requested.addresses, actual.requested.addresses); + assertEquals(expected.requested.creditCards, actual.requested.creditCards); + + assertEquals(expected.listening.addresses, actual.listening.addresses); + assertEquals(expected.listening.creditCards, actual.listening.creditCards); + }, + + // Set these to have non-empty data. + data: { + addresses: [], + creditCards: [], + }, + + // Holds the last callbacks so they can be called when needed/ + lastCallback: { + addAddressListChangedListener: null, + addCreditCardListChangedListener: null, + }, +}; + +/** + * @constructor + * @extends {PolymerTest} + */ +function PasswordsAndFormsBrowserTest() {} + +PasswordsAndFormsBrowserTest.prototype = { + __proto__: PolymerTest.prototype, + + /** @override */ + browsePreload: 'chrome://md-settings/passwords_and_forms_page/' + + 'passwords_and_forms_page.html', + + /** @override */ + extraLibraries: PolymerTest.getLibraries(ROOT_PATH), + + /** @override */ + setUp: function() { + PolymerTest.prototype.setUp.call(this); + + // Test is run on an individual element that won't have a page language. + this.accessibilityAuditConfig.auditRulesToIgnore.push('humanLangMissing'); + + // Override the PasswordManagerImpl for testing. + this.passwordManager = new TestPasswordManager(); + PasswordManagerImpl.instance_ = this.passwordManager; + + // Override the AutofillManagerImpl for testing. + this.autofillManager = new TestAutofillManager(); + AutofillManagerImpl.instance_ = this.autofillManager; + }, + + /** + * Creates a new passwords and forms element. + * @return {!Object} + */ + createPasswordsAndFormsElement: function() { + var element = document.createElement('settings-passwords-and-forms-page'); + document.body.appendChild(element); + Polymer.dom.flush(); + return element; + }, + + /** + * Creates PasswordManagerExpectations with the values expected after first + * creating the element. + * @return {!PasswordManagerExpectations} + */ + basePasswordExpectations: function() { + var expected = new PasswordManagerExpectations(); + expected.requested.passwords = 1; + expected.requested.exceptions = 1; + expected.listening.passwords = 1; + expected.listening.exceptions = 1; + return expected; + }, + + /** + * Creates AutofillManagerExpectations with the values expected after first + * creating the element. + * @return {!AutofillManagerExpectations} + */ + baseAutofillExpectations: function() { + var expected = new AutofillManagerExpectations(); + expected.requested.addresses = 1; + expected.requested.creditCards = 1; + expected.listening.addresses = 1; + expected.listening.creditCards = 1; + return expected; + }, +}; + +/** + * This test will validate that the section is loaded with data. + */ +TEST_F('PasswordsAndFormsBrowserTest', 'uiTests', function() { + var self = this; + + suite('PasswordsAndForms', function() { + test('baseLoadAndRemove', function() { + var element = self.createPasswordsAndFormsElement(); + + var passwordsExpectations = self.basePasswordExpectations(); + self.passwordManager.assertExpectations(passwordsExpectations); + + var autofillExpectations = self.baseAutofillExpectations(); + self.autofillManager.assertExpectations(autofillExpectations); + + element.remove(); + Polymer.dom.flush(); + + passwordsExpectations.listening.passwords = 0; + passwordsExpectations.listening.exceptions = 0; + self.passwordManager.assertExpectations(passwordsExpectations); + + autofillExpectations.listening.addresses = 0; + autofillExpectations.listening.creditCards = 0; + self.autofillManager.assertExpectations(autofillExpectations); + }); + + test('loadPasswordsAsync', function() { + var element = self.createPasswordsAndFormsElement(); + + var list = [FakeDataMaker.passwordEntry(), FakeDataMaker.passwordEntry()]; + self.passwordManager.lastCallback.addSavedPasswordListChangedListener( + list); + Polymer.dom.flush(); + + assertEquals(list, element.savedPasswords); + + // The callback is coming from the manager, so the element shouldn't have + // additional calls to the manager after the base expectations. + self.passwordManager.assertExpectations(self.basePasswordExpectations()); + self.autofillManager.assertExpectations(self.baseAutofillExpectations()); + }); + + test('loadExceptionsAsync', function() { + var element = self.createPasswordsAndFormsElement(); + + var list = [FakeDataMaker.exceptionEntry(), + FakeDataMaker.exceptionEntry()]; + self.passwordManager.lastCallback.addExceptionListChangedListener( + list); + Polymer.dom.flush(); + + assertEquals(list, element.passwordExceptions); + + // The callback is coming from the manager, so the element shouldn't have + // additional calls to the manager after the base expectations. + self.passwordManager.assertExpectations(self.basePasswordExpectations()); + self.autofillManager.assertExpectations(self.baseAutofillExpectations()); + }); + + test('loadAddressesAsync', function() { + var element = self.createPasswordsAndFormsElement(); + + var list = [FakeDataMaker.addressEntry(), FakeDataMaker.addressEntry()]; + self.autofillManager.lastCallback.addAddressListChangedListener(list); + Polymer.dom.flush(); + + assertEquals(list, element.addresses); + + // The callback is coming from the manager, so the element shouldn't have + // additional calls to the manager after the base expectations. + self.passwordManager.assertExpectations(self.basePasswordExpectations()); + self.autofillManager.assertExpectations(self.baseAutofillExpectations()); + }); + + test('loadCreditCardsAsync', function() { + var element = self.createPasswordsAndFormsElement(); + + var list = [FakeDataMaker.creditCardEntry(), + FakeDataMaker.creditCardEntry()]; + self.autofillManager.lastCallback.addCreditCardListChangedListener(list); + Polymer.dom.flush(); + + assertEquals(list, element.creditCards); + + // The callback is coming from the manager, so the element shouldn't have + // additional calls to the manager after the base expectations. + self.passwordManager.assertExpectations(self.basePasswordExpectations()); + self.autofillManager.assertExpectations(self.baseAutofillExpectations()); + }); + }); + + mocha.run(); +}); diff --git a/chrome/test/data/webui/settings/settings_autofill_section_browsertest.js b/chrome/test/data/webui/settings/settings_autofill_section_browsertest.js index ac82b06575c34c..7876c3376c4335 100644 --- a/chrome/test/data/webui/settings/settings_autofill_section_browsertest.js +++ b/chrome/test/data/webui/settings/settings_autofill_section_browsertest.js @@ -11,6 +11,10 @@ var ROOT_PATH = '../../../../../'; GEN_INCLUDE( [ROOT_PATH + 'chrome/test/data/webui/polymer_browser_test_base.js']); +// Fake data generator. +GEN_INCLUDE([ROOT_PATH + + 'chrome/test/data/webui/settings/passwords_and_autofill_fake_data.js']); + /** * @constructor * @extends {PolymerTest} @@ -35,71 +39,6 @@ SettingsAutofillSectionBrowserTest.prototype = { this.accessibilityAuditConfig.auditRulesToIgnore.push('humanLangMissing'); }, - /** - * Replaces any 'x' in a string with a random number of the base. - * @param {!string} pattern The pattern that should be used as an input. - * @param {!number} base The number base. ie: 16 for hex or 10 for decimal. - * @return {!string} - * @private - */ - patternMaker_: function(pattern, base) { - return pattern.replace(/x/g, function() { - return Math.floor(Math.random() * base).toString(base); - }); - }, - - /** - * Creates a new random GUID for testing. - * @return {!string} - * @private - */ - makeGuid_: function() { - return this.patternMaker_('xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', 16); - }, - - /** - * Creates a fake address entry for testing. - * @return {!chrome.autofillPrivate.AddressEntry} - * @private - */ - createFakeAddressEntry_: function() { - var ret = {}; - ret.guid = this.makeGuid_(); - ret.fullNames = ['John', 'Doe']; - ret.companyName = 'Google'; - ret.addressLines = this.patternMaker_('xxxx Main St', 10); - ret.addressLevel1 = "CA"; - ret.addressLevel2 = "Venice"; - ret.postalCode = this.patternMaker_('xxxxx', 10); - ret.countryCode = 'US'; - ret.phoneNumbers = [this.patternMaker_('(xxx) xxx-xxxx', 10)]; - ret.emailAddresses = [this.patternMaker_('userxxxx@gmail.com', 16)]; - ret.languageCode = 'EN-US'; - ret.metadata = {isLocal: true}; - ret.metadata.summaryLabel = ret.fullNames[0]; - ret.metadata.summarySublabel = ' ' + ret.addressLines; - return ret; - }, - - /** - * Creates a new random credit card entry for testing. - * @return {!chrome.autofillPrivate.CreditCardEntry} - * @private - */ - createFakeCreditCardEntry_: function() { - var ret = {}; - ret.guid = this.makeGuid_(); - ret.name = 'Jane Doe'; - ret.cardNumber = this.patternMaker_('xxxx xxxx xxxx xxxx', 10); - ret.expirationMonth = Math.ceil(Math.random() * 11).toString(); - ret.expirationYear = (2016 + Math.floor(Math.random() * 5)).toString(); - ret.metadata = {isLocal: true}; - var cards = ['Visa', 'Mastercard', 'Discover', 'Card']; - var card = cards[Math.floor(Math.random() * cards.length)]; - ret.metadata.summaryLabel = card + ' ' + '****' + ret.cardNumber.substr(-4); - return ret; - }, - /** * Allow the iron-list to be sized properly. * @param {!Object} autofillSection @@ -137,12 +76,12 @@ TEST_F('SettingsAutofillSectionBrowserTest', 'uiTests', function() { suite('AutofillSection', function() { test('verifyCreditCardCount', function() { var creditCards = [ - self.createFakeCreditCardEntry_(), - self.createFakeCreditCardEntry_(), - self.createFakeCreditCardEntry_(), - self.createFakeCreditCardEntry_(), - self.createFakeCreditCardEntry_(), - self.createFakeCreditCardEntry_(), + FakeDataMaker.creditCardEntry(), + FakeDataMaker.creditCardEntry(), + FakeDataMaker.creditCardEntry(), + FakeDataMaker.creditCardEntry(), + FakeDataMaker.creditCardEntry(), + FakeDataMaker.creditCardEntry(), ]; var section = self.createAutofillSection_([], creditCards); @@ -156,7 +95,7 @@ TEST_F('SettingsAutofillSectionBrowserTest', 'uiTests', function() { }); test('verifyCreditCardFields', function() { - var creditCard = self.createFakeCreditCardEntry_(); + var creditCard = FakeDataMaker.creditCardEntry(); var section = self.createAutofillSection_([], [creditCard]); var creditCardList = section.$.creditCardList; var row = creditCardList.children[1]; // Skip over the template. @@ -170,11 +109,11 @@ TEST_F('SettingsAutofillSectionBrowserTest', 'uiTests', function() { test('verifyAddressCount', function() { var addresses = [ - self.createFakeAddressEntry_(), - self.createFakeAddressEntry_(), - self.createFakeAddressEntry_(), - self.createFakeAddressEntry_(), - self.createFakeAddressEntry_(), + FakeDataMaker.addressEntry(), + FakeDataMaker.addressEntry(), + FakeDataMaker.addressEntry(), + FakeDataMaker.addressEntry(), + FakeDataMaker.addressEntry(), ]; var section = self.createAutofillSection_(addresses, []); @@ -188,7 +127,7 @@ TEST_F('SettingsAutofillSectionBrowserTest', 'uiTests', function() { }); test('verifyAddressFields', function() { - var address = self.createFakeAddressEntry_(); + var address = FakeDataMaker.addressEntry(); var section = self.createAutofillSection_([address], []); var addressList = section.$.addressList; var row = addressList.children[1]; // Skip over the template. diff --git a/chrome/test/data/webui/settings/settings_passwords_section_browsertest.js b/chrome/test/data/webui/settings/settings_passwords_section_browsertest.js index 24dbfe6c4112b8..c74d561161d25c 100644 --- a/chrome/test/data/webui/settings/settings_passwords_section_browsertest.js +++ b/chrome/test/data/webui/settings/settings_passwords_section_browsertest.js @@ -11,6 +11,10 @@ var ROOT_PATH = '../../../../../'; GEN_INCLUDE( [ROOT_PATH + 'chrome/test/data/webui/polymer_browser_test_base.js']); +// Fake data generator. +GEN_INCLUDE([ROOT_PATH + + 'chrome/test/data/webui/settings/passwords_and_autofill_fake_data.js']); + /** * @constructor * @extends {PolymerTest} @@ -35,35 +39,6 @@ SettingsPasswordSectionBrowserTest.prototype = { this.accessibilityAuditConfig.auditRulesToIgnore.push('humanLangMissing'); }, - /** - * Creates a single item for the list of passwords. - * @param {string} url - * @param {string} username - * @param {number} passwordLength - * @return {chrome.passwordsPrivate.PasswordUiEntry} - * @private - */ - createPasswordItem_: function(url, username, passwordLength) { - return { - loginPair: {originUrl: url, username: username}, - linkUrl: 'http://' + url + '/login', - numCharactersInPassword: passwordLength - }; - }, - - /** - * Creates a single item for the list of password exceptions. - * @param {string} url - * @return {chrome.passwordsPrivate.ExceptionPair} - * @private - */ - createExceptionItem_: function(url) { - return { - exceptionUrl: url, - linkUrl: 'http://' + url + '/login', - }; - }, - /** * Helper method that validates a that elements in the password list match * the expected data. @@ -200,12 +175,12 @@ TEST_F('SettingsPasswordSectionBrowserTest', 'uiTests', function() { assertEquals(self.browsePreload, document.location.href); var passwordList = [ - self.createPasswordItem_('site1.com', 'luigi', 1), - self.createPasswordItem_('longwebsite.com', 'peach', 7), - self.createPasswordItem_('site2.com', 'mario', 70), - self.createPasswordItem_('site1.com', 'peach', 11), - self.createPasswordItem_('google.com', 'mario', 7), - self.createPasswordItem_('site2.com', 'luigi', 8), + FakeDataMaker.passwordEntry('site1.com', 'luigi', 1), + FakeDataMaker.passwordEntry('longwebsite.com', 'peach', 7), + FakeDataMaker.passwordEntry('site2.com', 'mario', 70), + FakeDataMaker.passwordEntry('site1.com', 'peach', 11), + FakeDataMaker.passwordEntry('google.com', 'mario', 7), + FakeDataMaker.passwordEntry('site2.com', 'luigi', 8), ]; var passwordsSection = self.createPasswordsSection_(passwordList, []); @@ -222,9 +197,9 @@ TEST_F('SettingsPasswordSectionBrowserTest', 'uiTests', function() { // Test verifies that removing a password will update the elements. test('verifyPasswordListRemove', function() { var passwordList = [ - self.createPasswordItem_('anotherwebsite.com', 'luigi', 1), - self.createPasswordItem_('longwebsite.com', 'peach', 7), - self.createPasswordItem_('website.com', 'mario', 70) + FakeDataMaker.passwordEntry('anotherwebsite.com', 'luigi', 1), + FakeDataMaker.passwordEntry('longwebsite.com', 'peach', 7), + FakeDataMaker.passwordEntry('website.com', 'mario', 70) ]; var passwordsSection = self.createPasswordsSection_(passwordList, []); @@ -249,12 +224,12 @@ TEST_F('SettingsPasswordSectionBrowserTest', 'uiTests', function() { // event. Does not actually remove any passwords. test('verifyPasswordItemRemoveButton', function(done) { var passwordList = [ - self.createPasswordItem_('one', 'six', 5), - self.createPasswordItem_('two', 'five', 3), - self.createPasswordItem_('three', 'four', 1), - self.createPasswordItem_('four', 'three', 2), - self.createPasswordItem_('five', 'two', 4), - self.createPasswordItem_('six', 'one', 6), + FakeDataMaker.passwordEntry('one', 'six', 5), + FakeDataMaker.passwordEntry('two', 'five', 3), + FakeDataMaker.passwordEntry('three', 'four', 1), + FakeDataMaker.passwordEntry('four', 'three', 2), + FakeDataMaker.passwordEntry('five', 'two', 4), + FakeDataMaker.passwordEntry('six', 'one', 6), ]; var passwordsSection = self.createPasswordsSection_(passwordList, []); @@ -295,12 +270,12 @@ TEST_F('SettingsPasswordSectionBrowserTest', 'uiTests', function() { test('verifyPasswordExceptions', function() { var exceptionList = [ - self.createExceptionItem_('docs.google.com'), - self.createExceptionItem_('mail.com'), - self.createExceptionItem_('google.com'), - self.createExceptionItem_('inbox.google.com'), - self.createExceptionItem_('maps.google.com'), - self.createExceptionItem_('plus.google.com'), + FakeDataMaker.exceptionEntry('docs.google.com'), + FakeDataMaker.exceptionEntry('mail.com'), + FakeDataMaker.exceptionEntry('google.com'), + FakeDataMaker.exceptionEntry('inbox.google.com'), + FakeDataMaker.exceptionEntry('maps.google.com'), + FakeDataMaker.exceptionEntry('plus.google.com'), ]; var passwordsSection = self.createPasswordsSection_([], exceptionList); @@ -318,12 +293,12 @@ TEST_F('SettingsPasswordSectionBrowserTest', 'uiTests', function() { // Test verifies that removing an exception will update the elements. test('verifyPasswordExceptionRemove', function() { var exceptionList = [ - self.createExceptionItem_('docs.google.com'), - self.createExceptionItem_('mail.com'), - self.createExceptionItem_('google.com'), - self.createExceptionItem_('inbox.google.com'), - self.createExceptionItem_('maps.google.com'), - self.createExceptionItem_('plus.google.com'), + FakeDataMaker.exceptionEntry('docs.google.com'), + FakeDataMaker.exceptionEntry('mail.com'), + FakeDataMaker.exceptionEntry('google.com'), + FakeDataMaker.exceptionEntry('inbox.google.com'), + FakeDataMaker.exceptionEntry('maps.google.com'), + FakeDataMaker.exceptionEntry('plus.google.com'), ]; var passwordsSection = self.createPasswordsSection_([], exceptionList); @@ -348,12 +323,12 @@ TEST_F('SettingsPasswordSectionBrowserTest', 'uiTests', function() { // event. Does not actually remove any exceptions. test('verifyPasswordExceptionRemoveButton', function(done) { var exceptionList = [ - self.createExceptionItem_('docs.google.com'), - self.createExceptionItem_('mail.com'), - self.createExceptionItem_('google.com'), - self.createExceptionItem_('inbox.google.com'), - self.createExceptionItem_('maps.google.com'), - self.createExceptionItem_('plus.google.com'), + FakeDataMaker.exceptionEntry('docs.google.com'), + FakeDataMaker.exceptionEntry('mail.com'), + FakeDataMaker.exceptionEntry('google.com'), + FakeDataMaker.exceptionEntry('inbox.google.com'), + FakeDataMaker.exceptionEntry('maps.google.com'), + FakeDataMaker.exceptionEntry('plus.google.com'), ]; var passwordsSection = self.createPasswordsSection_([], exceptionList); @@ -389,7 +364,7 @@ TEST_F('SettingsPasswordSectionBrowserTest', 'uiTests', function() { test('usePasswordDialogTwice', function() { var BLANK_PASSWORD = ' '; - var item = self.createPasswordItem_('google.com', 'homer', + var item = FakeDataMaker.passwordEntry('google.com', 'homer', BLANK_PASSWORD.length); var passwordDialog = self.createPasswordDialog_(item); @@ -410,7 +385,7 @@ TEST_F('SettingsPasswordSectionBrowserTest', 'uiTests', function() { Polymer.dom.flush(); var blankPassword2 = ' '.repeat(17); - var item2 = self.createPasswordItem_('drive.google.com', 'marge', + var item2 = FakeDataMaker.passwordEntry('drive.google.com', 'marge', blankPassword2.length); passwordDialog.item = item2; @@ -430,7 +405,7 @@ TEST_F('SettingsPasswordSectionBrowserTest', 'uiTests', function() { test('showSavedPassword', function() { var PASSWORD = 'bAn@n@5'; - var item = self.createPasswordItem_('goo.gl', 'bart', PASSWORD.length); + var item = FakeDataMaker.passwordEntry('goo.gl', 'bart', PASSWORD.length); var passwordDialog = self.createPasswordDialog_(item); passwordDialog.open(); @@ -450,7 +425,7 @@ TEST_F('SettingsPasswordSectionBrowserTest', 'uiTests', function() { // Test will timeout if event is not received. test('onShowSavedPassword', function(done) { - var item = self.createPasswordItem_('goo.gl', 'bart', 1); + var item = FakeDataMaker.passwordEntry('goo.gl', 'bart', 1); var passwordDialog = self.createPasswordDialog_(item); passwordDialog.open(); diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h index 1884272d3b4072..f65223b67449f9 100644 --- a/extensions/browser/extension_function_histogram_value.h +++ b/extensions/browser/extension_function_histogram_value.h @@ -1188,6 +1188,8 @@ enum HistogramValue { BLUETOOTHLOWENERGY_SENDREQUESTRESPONSE, BLUETOOTHLOWENERGY_NOTIFYCHARACTERISTICVALUECHANGED, BLUETOOTHLOWENERGY_REMOVESERVICE, + AUTOFILLPRIVATE_GETADDRESSLIST, + AUTOFILLPRIVATE_GETCREDITCARDLIST, // Last entry: Add new entries above, then run: // python tools/metrics/histograms/update_extension_histograms.py ENUM_BOUNDARY diff --git a/third_party/closure_compiler/externs/autofill_private.js b/third_party/closure_compiler/externs/autofill_private.js index dc2f693243f164..61498c832014d6 100644 --- a/third_party/closure_compiler/externs/autofill_private.js +++ b/third_party/closure_compiler/externs/autofill_private.js @@ -135,6 +135,14 @@ chrome.autofillPrivate.saveAddress = function(address) {}; */ chrome.autofillPrivate.getAddressComponents = function(countryCode, callback) {}; +/** + * Gets the list of addresses. + * @param {function(!Array):void} callback + * Callback which will be called with the list of addresses. + * @see https://developer.chrome.com/extensions/autofillPrivate#method-getAddressList + */ +chrome.autofillPrivate.getAddressList = function(callback) {}; + /** * Saves the given credit card. If |card| has an empty string as its ID, it will * be assigned a new one and added as a new entry. @@ -162,6 +170,14 @@ chrome.autofillPrivate.removeEntry = function(guid) {}; */ chrome.autofillPrivate.validatePhoneNumbers = function(params, callback) {}; +/** + * Gets the list of credit cards. + * @param {function(!Array):void} + * callback Callback which will be called with the list of credit cards. + * @see https://developer.chrome.com/extensions/autofillPrivate#method-getCreditCardList + */ +chrome.autofillPrivate.getCreditCardList = function(callback) {}; + /** * Clears the data associated with a wallet card which was saved locally so that * the saved copy is masked (e.g., "Card ending in 1234"). diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 117c618a518207..bc6a233fc9f653 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml @@ -71394,6 +71394,8 @@ http://cs/file:chrome/histograms.xml - but prefer this file for new entries. + +