Bug 1435274 - Stop form autofilling if the master password prompt is cancelled. r=johannh draft
authorMatthew Noorenberghe <mozilla@noorenberghe.ca>
Fri, 02 Feb 2018 21:42:31 -0800
changeset 750908 4c8491c460d7fc0a9dc606f4c624d4e35e881586
parent 750839 fea9e610ec9d550f2aad41d0d83cf02f485460c4
push id97784
push usermozilla@noorenberghe.ca
push dateSat, 03 Feb 2018 05:44:04 +0000
reviewersjohannh
bugs1435274
milestone60.0a1
Bug 1435274 - Stop form autofilling if the master password prompt is cancelled. r=johannh MozReview-Commit-ID: HnFbcWYX6QL
browser/extensions/formautofill/FormAutofillHandler.jsm
browser/extensions/formautofill/test/browser/browser.ini
browser/extensions/formautofill/test/browser/browser_creditCard_fill_master_password.js
--- a/browser/extensions/formautofill/FormAutofillHandler.jsm
+++ b/browser/extensions/formautofill/FormAutofillHandler.jsm
@@ -110,18 +110,21 @@ class FormAutofillSection {
   preparePreviewProfile(profile) {}
 
   /**
    * Override this method if the profile is needed to be customized for filling
    * values.
    *
    * @param {Object} profile
    *        A profile for pre-processing before filling values.
+   * @returns {boolean} Whether the profile should be filled.
    */
-  async prepareFillingProfile(profile) {}
+  async prepareFillingProfile(profile) {
+    return true;
+  }
 
   /*
    * Override this methid if any data for `createRecord` is needed to be
    * normailized before submitting the record.
    *
    * @param {Object} profile
    *        A record for normalization.
    */
@@ -243,17 +246,20 @@ class FormAutofillSection {
    *        A profile to be filled in.
    */
   async autofillFields(profile) {
     let focusedDetail = this._focusedDetail;
     if (!focusedDetail) {
       throw new Error("No fieldDetail for the focused input.");
     }
 
-    await this.prepareFillingProfile(profile);
+    if (!await this.prepareFillingProfile(profile)) {
+      log.debug("profile cannot be filled", profile);
+      return;
+    }
     log.debug("profile in autofillFields:", profile);
 
     this.filledRecordGUID = profile.guid;
     for (let fieldDetail of this.fieldDetails) {
       // Avoid filling field value in the following cases:
       // 1. a non-empty input field for an unfocused input
       // 2. the invalid value set
       // 3. value already chosen in select element
@@ -848,33 +854,35 @@ class FormAutofillCreditCardSection exte
     }
   }
 
   /**
    * Customize for filling prorifle.
    *
    * @param {Object} profile
    *        A profile for pre-processing before filling values.
+   * @returns {boolean} Whether the profile should be filled.
    * @override
    */
   async prepareFillingProfile(profile) {
     // When Master Password is enabled by users, the decryption process
     // should prompt Master Password dialog to get the decrypted credit
     // card number. Otherwise, the number can be decrypted with the default
     // password.
     if (profile["cc-number-encrypted"]) {
       let decrypted = await this._decrypt(profile["cc-number-encrypted"], true);
 
       if (!decrypted) {
         // Early return if the decrypted is empty or undefined
-        return;
+        return false;
       }
 
       profile["cc-number"] = decrypted;
     }
+    return true;
   }
 }
 
 /**
  * Handles profile autofill for a DOM Form element.
  */
 class FormAutofillHandler {
   /**
--- a/browser/extensions/formautofill/test/browser/browser.ini
+++ b/browser/extensions/formautofill/test/browser/browser.ini
@@ -7,16 +7,17 @@ support-files =
   ../fixtures/autocomplete_simple_basic.html
   ../fixtures/autocomplete_creditcard_basic.html
 
 [browser_autocomplete_footer.js]
 [browser_autocomplete_marked_back_forward.js]
 [browser_autocomplete_marked_detached_tab.js]
 [browser_check_installed.js]
 [browser_creditCard_doorhanger.js]
+[browser_creditCard_fill_master_password.js]
 [browser_dropdown_layout.js]
 [browser_editAddressDialog.js]
 [browser_editCreditCardDialog.js]
 [browser_first_time_use_doorhanger.js]
 [browser_insecure_form.js]
 [browser_manageAddressesDialog.js]
 [browser_manageCreditCardsDialog.js]
 [browser_privacyPreferences.js]
new file mode 100644
--- /dev/null
+++ b/browser/extensions/formautofill/test/browser/browser_creditCard_fill_master_password.js
@@ -0,0 +1,25 @@
+"use strict";
+
+add_task(async function test_fill_creditCard_with_mp_enabled_but_canceled() {
+  await saveCreditCard(TEST_CREDIT_CARD_2);
+
+  LoginTestUtils.masterPassword.enable();
+  registerCleanupFunction(() => {
+    LoginTestUtils.masterPassword.disable();
+  });
+
+  let masterPasswordDialogShown = waitForMasterPasswordDialog(false); // cancel
+  await BrowserTestUtils.withNewTab({gBrowser, url: CREDITCARD_FORM_URL},
+    async function(browser) {
+      await openPopupOn(browser, "#cc-name");
+      const ccItem = getDisplayedPopupItems(browser)[0];
+      await EventUtils.synthesizeMouseAtCenter(ccItem, {});
+      await Promise.all([masterPasswordDialogShown, expectPopupClose(browser)]);
+
+      await ContentTask.spawn(browser, {}, async function() {
+        is(content.document.querySelector("#cc-name").value, "", "Check name");
+        is(content.document.querySelector("#cc-number").value, "", "Check number");
+      });
+    }
+  );
+});