Loading mobile/android/geckoview/src/androidTest/assets/www/address_form.html 0 → 100644 +21 −0 Original line number Diff line number Diff line <html> <head> <meta charset="utf-8"> <title>Address form</title> </head> <body> <form> <input autocomplete="name" id="name"> <input autocomplete="given-name" id="givenName"> <input autocomplete="additional-name" id="additionalName"> <input autocomplete="family-name" id="familyName"> <input autocomplete="street-address" id="streetAddress"> <input autocomplete="country" id="country"> <input autocomplete="postal-code" id="postalCode"> <input autocomplete="organization" id="organization"> <input autocomplete="email" id="email"> <input autocomplete="tel" id="tel"> <input type="submit" value="Submit"> </form> </body> </html> mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/AutocompleteTest.kt +218 −4 Original line number Diff line number Diff line Loading @@ -20,7 +20,8 @@ import org.mozilla.geckoview.GeckoResult import org.mozilla.geckoview.GeckoSession import org.mozilla.geckoview.GeckoSession.PromptDelegate import org.mozilla.geckoview.GeckoSession.PromptDelegate.AutocompleteRequest import org.mozilla.geckoview.Autocomplete import org.mozilla.geckoview.Autocomplete.Address import org.mozilla.geckoview.Autocomplete.AddressSelectOption import org.mozilla.geckoview.Autocomplete.CreditCard import org.mozilla.geckoview.Autocomplete.CreditCardSelectOption import org.mozilla.geckoview.Autocomplete.LoginEntry Loading @@ -28,6 +29,7 @@ import org.mozilla.geckoview.Autocomplete.LoginSaveOption import org.mozilla.geckoview.Autocomplete.LoginSelectOption import org.mozilla.geckoview.Autocomplete.SelectOption import org.mozilla.geckoview.Autocomplete.StorageDelegate import org.mozilla.geckoview.Autocomplete.UsedField import org.mozilla.geckoview.test.rule.GeckoSessionTestRule import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.AssertCalled import org.mozilla.geckoview.test.util.Callbacks Loading Loading @@ -172,7 +174,7 @@ class AutocompleteTest : BaseSessionTest() { assertThat("Session should not be null", session, notNullValue()) assertThat( "There should be one option", "There should be two options", prompt.options.size, equalTo(2)) Loading Loading @@ -219,6 +221,218 @@ class AutocompleteTest : BaseSessionTest() { equalTo(expYear[0])) } @Test fun fetchAddresses() { val runtime = sessionRule.runtime val register = { delegate: StorageDelegate -> runtime.autocompleteStorageDelegate = delegate } val unregister = { _: StorageDelegate -> runtime.autocompleteStorageDelegate = null } val fetchHandled = GeckoResult<Void>() sessionRule.addExternalDelegateUntilTestEnd( StorageDelegate::class, register, unregister, object : StorageDelegate { @AssertCalled(count = 1) override fun onAddressFetch() : GeckoResult<Array<Address>>? { Handler(Looper.getMainLooper()).postDelayed({ fetchHandled.complete(null) }, acceptDelay) return null } }) mainSession.loadTestPath(ADDRESS_FORM_HTML_PATH) mainSession.waitForPageStop() mainSession.evaluateJS("document.querySelector('#name').focus()") sessionRule.waitForResult(fetchHandled) } fun checkAddressesForCorrectness(savedAddresses: Array<Address>, selectedAddress: Address) { // Test: // 1. Load an address form page. // 2. Focus on the given name input field. // a. Ensure onAddressFetch is called. // b. Return the saved entries. // c. Ensure onAddressSelect is called. // d. Select and return one of the options. // e. Ensure the form is filled accordingly. val runtime = sessionRule.runtime val register = { delegate: StorageDelegate -> runtime.autocompleteStorageDelegate = delegate } val unregister = { _: StorageDelegate -> runtime.autocompleteStorageDelegate = null } val selectHandled = GeckoResult<Void>() sessionRule.addExternalDelegateUntilTestEnd( StorageDelegate::class, register, unregister, object : StorageDelegate { @AssertCalled override fun onAddressFetch() : GeckoResult<Array<Address>>? { return GeckoResult.fromValue(savedAddresses) } @AssertCalled(false) override fun onAddressSave(address: Address) {} }) mainSession.delegateUntilTestEnd(object : Callbacks.PromptDelegate { @AssertCalled(count = 1) override fun onAddressSelect( session: GeckoSession, prompt: AutocompleteRequest<AddressSelectOption>) : GeckoResult<PromptDelegate.PromptResponse>? { assertThat("Session should not be null", session, notNullValue()) assertThat( "There should be one option", prompt.options.size, equalTo(savedAddresses.size)) val addressOption = prompt.options.find { it.value.familyName == selectedAddress.familyName } val address = addressOption?.value assertThat("Address should not be null", address, notNullValue()) assertThat( "Given name should match", address?.givenName, equalTo(selectedAddress.givenName)) assertThat( "Family name should match", address?.familyName, equalTo(selectedAddress.familyName)) assertThat( "Street address should match", address?.streetAddress, equalTo(selectedAddress.streetAddress)) Handler(Looper.getMainLooper()).postDelayed({ selectHandled.complete(null) }, acceptDelay) return GeckoResult.fromValue(prompt.confirm(addressOption!!)) } }) mainSession.loadTestPath(ADDRESS_FORM_HTML_PATH) mainSession.waitForPageStop() // Focus on the given name input field. mainSession.evaluateJS("document.querySelector('#givenName').focus()") sessionRule.waitForResult(selectHandled) assertThat( "Filled given name should match", mainSession.evaluateJS("document.querySelector('#givenName').value") as String, equalTo(selectedAddress.givenName)) assertThat( "Filled family name should match", mainSession.evaluateJS("document.querySelector('#familyName').value") as String, equalTo(selectedAddress.familyName)) assertThat( "Filled street address should match", mainSession.evaluateJS("document.querySelector('#streetAddress').value") as String, equalTo(selectedAddress.streetAddress)) assertThat( "Filled country should match", mainSession.evaluateJS("document.querySelector('#country').value") as String, equalTo(selectedAddress.country)) assertThat( "Filled postal code should match", mainSession.evaluateJS("document.querySelector('#postalCode').value") as String, equalTo(selectedAddress.postalCode)) assertThat( "Filled email should match", mainSession.evaluateJS("document.querySelector('#email').value") as String, equalTo(selectedAddress.email)) assertThat( "Filled telephone number should match", mainSession.evaluateJS("document.querySelector('#tel').value") as String, equalTo(selectedAddress.tel)) assertThat( "Filled organization should match", mainSession.evaluateJS("document.querySelector('#organization').value") as String, equalTo(selectedAddress.organization)) } @Test fun addressSelectAndFill() { val givenName = "Peter" val familyName = "Parker" val streetAddress = "20 Ingram Street, Forest Hills Gardens, Queens" val postalCode = "11375" val country = "US" val email = "spiderman@newyork.com" val tel = "+1 180090021" val organization = "" val guid = "test-guid" val savedAddress = Address.Builder() .guid(guid) .givenName(givenName) .familyName(familyName) .streetAddress(streetAddress) .postalCode(postalCode) .country(country) .email(email) .tel(tel) .organization(organization) .build() val savedAddresses = mutableListOf<Address>(savedAddress) checkAddressesForCorrectness(savedAddresses.toTypedArray(), savedAddress) } @Test fun addressSelectAndFillMultipleAddresses() { val givenNames = arrayOf("Peter", "Wade") val familyNames = arrayOf("Parker", "Wilson") val streetAddresses = arrayOf("20 Ingram Street, Forest Hills Gardens, Queens", "890 Fifth Avenue, Manhattan") val postalCodes = arrayOf("11375", "10110") val countries = arrayOf("US", "US") val emails = arrayOf("spiderman@newyork.com", "deadpool@newyork.com") val tels = arrayOf("+1 180090021", "+1 180055555") val organizations = arrayOf("", "") val guids = arrayOf("test-guid-1", "test-guid-2") val selectedAddress = Address.Builder() .guid(guids[1]) .givenName(givenNames[1]) .familyName(familyNames[1]) .streetAddress(streetAddresses[1]) .postalCode(postalCodes[1]) .country(countries[1]) .email(emails[1]) .tel(tels[1]) .organization(organizations[1]) .build() val savedAddresses = mutableListOf<Address>( Address.Builder() .guid(guids[0]) .givenName(givenNames[0]) .familyName(familyNames[0]) .streetAddress(streetAddresses[0]) .postalCode(postalCodes[0]) .country(countries[0]) .email(emails[0]) .tel(tels[0]) .organization(organizations[0]) .build(), selectedAddress ) checkAddressesForCorrectness(savedAddresses.toTypedArray(), selectedAddress) } @Test fun loginSaveDismiss() { sessionRule.setPrefsUntilTestEnd(mapOf( Loading Loading @@ -616,7 +830,7 @@ class AutocompleteTest : BaseSessionTest() { assertThat( "Used fields should match", usedFields, equalTo(Autocomplete.UsedField.PASSWORD)) equalTo(UsedField.PASSWORD)) assertThat( "Username should match", Loading Loading @@ -883,7 +1097,7 @@ class AutocompleteTest : BaseSessionTest() { assertThat( "Used fields should match", usedFields, equalTo(Autocomplete.UsedField.PASSWORD)) equalTo(UsedField.PASSWORD)) assertThat( "Username should match", Loading mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/BaseSessionTest.kt +1 −0 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ open class BaseSessionTest(noErrorCollector: Boolean = false) { const val FORMS3_HTML_PATH = "/assets/www/forms3.html" const val FORMS4_HTML_PATH = "/assets/www/forms4.html" const val FORMS5_HTML_PATH = "/assets/www/forms5.html" const val ADDRESS_FORM_HTML_PATH = "/assets/www/address_form.html" const val FORMS_AUTOCOMPLETE_HTML_PATH = "/assets/www/forms_autocomplete.html" const val FORMS_ID_VALUE_HTML_PATH = "/assets/www/forms_id_value.html" const val CC_FORM_HTML_PATH = "/assets/www/cc_form.html" Loading toolkit/components/formautofill/FormAutofillContent.jsm +8 −3 Original line number Diff line number Diff line Loading @@ -18,6 +18,9 @@ const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm"); const { XPCOMUtils } = ChromeUtils.import( "resource://gre/modules/XPCOMUtils.jsm" ); const { AppConstants } = ChromeUtils.import( "resource://gre/modules/AppConstants.jsm" ); ChromeUtils.defineModuleGetter( this, Loading Loading @@ -696,9 +699,11 @@ var FormAutofillContent = { "updateActiveElement: checking if empty field is cc-*: ", this.activeFieldDetail?.fieldName ); // This restricts popups to credit card fields and may need adjustment // when enabling address support for the GeckoView backend. if (this.activeFieldDetail?.fieldName?.startsWith("cc-")) { if ( this.activeFieldDetail?.fieldName?.startsWith("cc-") || AppConstants.platform === "android" ) { if (Services.cpmm.sharedData.get("FormAutofill:enabled")) { this.debug("updateActiveElement: opening pop up"); formFillController.showPopup(); Loading Loading
mobile/android/geckoview/src/androidTest/assets/www/address_form.html 0 → 100644 +21 −0 Original line number Diff line number Diff line <html> <head> <meta charset="utf-8"> <title>Address form</title> </head> <body> <form> <input autocomplete="name" id="name"> <input autocomplete="given-name" id="givenName"> <input autocomplete="additional-name" id="additionalName"> <input autocomplete="family-name" id="familyName"> <input autocomplete="street-address" id="streetAddress"> <input autocomplete="country" id="country"> <input autocomplete="postal-code" id="postalCode"> <input autocomplete="organization" id="organization"> <input autocomplete="email" id="email"> <input autocomplete="tel" id="tel"> <input type="submit" value="Submit"> </form> </body> </html>
mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/AutocompleteTest.kt +218 −4 Original line number Diff line number Diff line Loading @@ -20,7 +20,8 @@ import org.mozilla.geckoview.GeckoResult import org.mozilla.geckoview.GeckoSession import org.mozilla.geckoview.GeckoSession.PromptDelegate import org.mozilla.geckoview.GeckoSession.PromptDelegate.AutocompleteRequest import org.mozilla.geckoview.Autocomplete import org.mozilla.geckoview.Autocomplete.Address import org.mozilla.geckoview.Autocomplete.AddressSelectOption import org.mozilla.geckoview.Autocomplete.CreditCard import org.mozilla.geckoview.Autocomplete.CreditCardSelectOption import org.mozilla.geckoview.Autocomplete.LoginEntry Loading @@ -28,6 +29,7 @@ import org.mozilla.geckoview.Autocomplete.LoginSaveOption import org.mozilla.geckoview.Autocomplete.LoginSelectOption import org.mozilla.geckoview.Autocomplete.SelectOption import org.mozilla.geckoview.Autocomplete.StorageDelegate import org.mozilla.geckoview.Autocomplete.UsedField import org.mozilla.geckoview.test.rule.GeckoSessionTestRule import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.AssertCalled import org.mozilla.geckoview.test.util.Callbacks Loading Loading @@ -172,7 +174,7 @@ class AutocompleteTest : BaseSessionTest() { assertThat("Session should not be null", session, notNullValue()) assertThat( "There should be one option", "There should be two options", prompt.options.size, equalTo(2)) Loading Loading @@ -219,6 +221,218 @@ class AutocompleteTest : BaseSessionTest() { equalTo(expYear[0])) } @Test fun fetchAddresses() { val runtime = sessionRule.runtime val register = { delegate: StorageDelegate -> runtime.autocompleteStorageDelegate = delegate } val unregister = { _: StorageDelegate -> runtime.autocompleteStorageDelegate = null } val fetchHandled = GeckoResult<Void>() sessionRule.addExternalDelegateUntilTestEnd( StorageDelegate::class, register, unregister, object : StorageDelegate { @AssertCalled(count = 1) override fun onAddressFetch() : GeckoResult<Array<Address>>? { Handler(Looper.getMainLooper()).postDelayed({ fetchHandled.complete(null) }, acceptDelay) return null } }) mainSession.loadTestPath(ADDRESS_FORM_HTML_PATH) mainSession.waitForPageStop() mainSession.evaluateJS("document.querySelector('#name').focus()") sessionRule.waitForResult(fetchHandled) } fun checkAddressesForCorrectness(savedAddresses: Array<Address>, selectedAddress: Address) { // Test: // 1. Load an address form page. // 2. Focus on the given name input field. // a. Ensure onAddressFetch is called. // b. Return the saved entries. // c. Ensure onAddressSelect is called. // d. Select and return one of the options. // e. Ensure the form is filled accordingly. val runtime = sessionRule.runtime val register = { delegate: StorageDelegate -> runtime.autocompleteStorageDelegate = delegate } val unregister = { _: StorageDelegate -> runtime.autocompleteStorageDelegate = null } val selectHandled = GeckoResult<Void>() sessionRule.addExternalDelegateUntilTestEnd( StorageDelegate::class, register, unregister, object : StorageDelegate { @AssertCalled override fun onAddressFetch() : GeckoResult<Array<Address>>? { return GeckoResult.fromValue(savedAddresses) } @AssertCalled(false) override fun onAddressSave(address: Address) {} }) mainSession.delegateUntilTestEnd(object : Callbacks.PromptDelegate { @AssertCalled(count = 1) override fun onAddressSelect( session: GeckoSession, prompt: AutocompleteRequest<AddressSelectOption>) : GeckoResult<PromptDelegate.PromptResponse>? { assertThat("Session should not be null", session, notNullValue()) assertThat( "There should be one option", prompt.options.size, equalTo(savedAddresses.size)) val addressOption = prompt.options.find { it.value.familyName == selectedAddress.familyName } val address = addressOption?.value assertThat("Address should not be null", address, notNullValue()) assertThat( "Given name should match", address?.givenName, equalTo(selectedAddress.givenName)) assertThat( "Family name should match", address?.familyName, equalTo(selectedAddress.familyName)) assertThat( "Street address should match", address?.streetAddress, equalTo(selectedAddress.streetAddress)) Handler(Looper.getMainLooper()).postDelayed({ selectHandled.complete(null) }, acceptDelay) return GeckoResult.fromValue(prompt.confirm(addressOption!!)) } }) mainSession.loadTestPath(ADDRESS_FORM_HTML_PATH) mainSession.waitForPageStop() // Focus on the given name input field. mainSession.evaluateJS("document.querySelector('#givenName').focus()") sessionRule.waitForResult(selectHandled) assertThat( "Filled given name should match", mainSession.evaluateJS("document.querySelector('#givenName').value") as String, equalTo(selectedAddress.givenName)) assertThat( "Filled family name should match", mainSession.evaluateJS("document.querySelector('#familyName').value") as String, equalTo(selectedAddress.familyName)) assertThat( "Filled street address should match", mainSession.evaluateJS("document.querySelector('#streetAddress').value") as String, equalTo(selectedAddress.streetAddress)) assertThat( "Filled country should match", mainSession.evaluateJS("document.querySelector('#country').value") as String, equalTo(selectedAddress.country)) assertThat( "Filled postal code should match", mainSession.evaluateJS("document.querySelector('#postalCode').value") as String, equalTo(selectedAddress.postalCode)) assertThat( "Filled email should match", mainSession.evaluateJS("document.querySelector('#email').value") as String, equalTo(selectedAddress.email)) assertThat( "Filled telephone number should match", mainSession.evaluateJS("document.querySelector('#tel').value") as String, equalTo(selectedAddress.tel)) assertThat( "Filled organization should match", mainSession.evaluateJS("document.querySelector('#organization').value") as String, equalTo(selectedAddress.organization)) } @Test fun addressSelectAndFill() { val givenName = "Peter" val familyName = "Parker" val streetAddress = "20 Ingram Street, Forest Hills Gardens, Queens" val postalCode = "11375" val country = "US" val email = "spiderman@newyork.com" val tel = "+1 180090021" val organization = "" val guid = "test-guid" val savedAddress = Address.Builder() .guid(guid) .givenName(givenName) .familyName(familyName) .streetAddress(streetAddress) .postalCode(postalCode) .country(country) .email(email) .tel(tel) .organization(organization) .build() val savedAddresses = mutableListOf<Address>(savedAddress) checkAddressesForCorrectness(savedAddresses.toTypedArray(), savedAddress) } @Test fun addressSelectAndFillMultipleAddresses() { val givenNames = arrayOf("Peter", "Wade") val familyNames = arrayOf("Parker", "Wilson") val streetAddresses = arrayOf("20 Ingram Street, Forest Hills Gardens, Queens", "890 Fifth Avenue, Manhattan") val postalCodes = arrayOf("11375", "10110") val countries = arrayOf("US", "US") val emails = arrayOf("spiderman@newyork.com", "deadpool@newyork.com") val tels = arrayOf("+1 180090021", "+1 180055555") val organizations = arrayOf("", "") val guids = arrayOf("test-guid-1", "test-guid-2") val selectedAddress = Address.Builder() .guid(guids[1]) .givenName(givenNames[1]) .familyName(familyNames[1]) .streetAddress(streetAddresses[1]) .postalCode(postalCodes[1]) .country(countries[1]) .email(emails[1]) .tel(tels[1]) .organization(organizations[1]) .build() val savedAddresses = mutableListOf<Address>( Address.Builder() .guid(guids[0]) .givenName(givenNames[0]) .familyName(familyNames[0]) .streetAddress(streetAddresses[0]) .postalCode(postalCodes[0]) .country(countries[0]) .email(emails[0]) .tel(tels[0]) .organization(organizations[0]) .build(), selectedAddress ) checkAddressesForCorrectness(savedAddresses.toTypedArray(), selectedAddress) } @Test fun loginSaveDismiss() { sessionRule.setPrefsUntilTestEnd(mapOf( Loading Loading @@ -616,7 +830,7 @@ class AutocompleteTest : BaseSessionTest() { assertThat( "Used fields should match", usedFields, equalTo(Autocomplete.UsedField.PASSWORD)) equalTo(UsedField.PASSWORD)) assertThat( "Username should match", Loading Loading @@ -883,7 +1097,7 @@ class AutocompleteTest : BaseSessionTest() { assertThat( "Used fields should match", usedFields, equalTo(Autocomplete.UsedField.PASSWORD)) equalTo(UsedField.PASSWORD)) assertThat( "Username should match", Loading
mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/BaseSessionTest.kt +1 −0 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ open class BaseSessionTest(noErrorCollector: Boolean = false) { const val FORMS3_HTML_PATH = "/assets/www/forms3.html" const val FORMS4_HTML_PATH = "/assets/www/forms4.html" const val FORMS5_HTML_PATH = "/assets/www/forms5.html" const val ADDRESS_FORM_HTML_PATH = "/assets/www/address_form.html" const val FORMS_AUTOCOMPLETE_HTML_PATH = "/assets/www/forms_autocomplete.html" const val FORMS_ID_VALUE_HTML_PATH = "/assets/www/forms_id_value.html" const val CC_FORM_HTML_PATH = "/assets/www/cc_form.html" Loading
toolkit/components/formautofill/FormAutofillContent.jsm +8 −3 Original line number Diff line number Diff line Loading @@ -18,6 +18,9 @@ const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm"); const { XPCOMUtils } = ChromeUtils.import( "resource://gre/modules/XPCOMUtils.jsm" ); const { AppConstants } = ChromeUtils.import( "resource://gre/modules/AppConstants.jsm" ); ChromeUtils.defineModuleGetter( this, Loading Loading @@ -696,9 +699,11 @@ var FormAutofillContent = { "updateActiveElement: checking if empty field is cc-*: ", this.activeFieldDetail?.fieldName ); // This restricts popups to credit card fields and may need adjustment // when enabling address support for the GeckoView backend. if (this.activeFieldDetail?.fieldName?.startsWith("cc-")) { if ( this.activeFieldDetail?.fieldName?.startsWith("cc-") || AppConstants.platform === "android" ) { if (Services.cpmm.sharedData.get("FormAutofill:enabled")) { this.debug("updateActiveElement: opening pop up"); formFillController.showPopup(); Loading