Bug 1304001 - Move LoginUtils._getPasswordOrigin to LoginHelper. r=sfoster
☠☠ backed out by c320a8b15dfc ☠ ☠
authorMatthew Noorenberghe <mozilla@noorenberghe.ca>
Thu, 21 Feb 2019 20:18:39 +0000
changeset 460444 7d8f97779a35029dcbc72430464e7254ef1d72ca
parent 460443 a5644de3c2f5a4dcb7e9bc4c6b0f822543d8736e
child 460445 c9628639b5e13d96e0c7260b5875d3987937d80c
push id35593
push userccoroiu@mozilla.com
push dateFri, 22 Feb 2019 16:25:14 +0000
treeherdermozilla-central@a1d118e856dd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssfoster
bugs1304001
milestone67.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1304001 - Move LoginUtils._getPasswordOrigin to LoginHelper. r=sfoster There were too many top-level objects in that large JSM and LoginHelper didn't exist when it was added. Differential Revision: https://phabricator.services.mozilla.com/D20393
toolkit/components/passwordmgr/LoginHelper.jsm
toolkit/components/passwordmgr/LoginManagerContent.jsm
toolkit/components/passwordmgr/test/unit/test_getPasswordOrigin.js
toolkit/components/passwordmgr/test/unit/test_getUserNameAndPasswordFields.js
--- a/toolkit/components/passwordmgr/LoginHelper.jsm
+++ b/toolkit/components/passwordmgr/LoginHelper.jsm
@@ -214,16 +214,41 @@ var LoginHelper = {
       return uri.hostPort;
     } catch (ex) {
       // No need to warn for javascript:/data:/about:/chrome:/etc.
     }
     return aURL;
   },
 
   /**
+   * Get the parts of the URL we want for identification.
+   * Strip out things like the userPass portion and handle javascript:.
+   */
+  getLoginOrigin(uriString, allowJS) {
+    let realm = "";
+    try {
+      let uri = Services.io.newURI(uriString);
+
+      if (allowJS && uri.scheme == "javascript") {
+        return "javascript:";
+      }
+
+      // Build this manually instead of using prePath to avoid including the userPass portion.
+      realm = uri.scheme + "://" + uri.displayHostPort;
+    } catch (e) {
+      // bug 159484 - disallow url types that don't support a hostPort.
+      // (although we handle "javascript:..." as a special case above.)
+      log.warn("Couldn't parse origin for", uriString, e);
+      realm = null;
+    }
+
+    return realm;
+  },
+
+  /**
    * @param {String} aLoginOrigin - An origin value from a stored login's
    *                                hostname or formSubmitURL properties.
    * @param {String} aSearchOrigin - The origin that was are looking to match
    *                                 with aLoginOrigin. This would normally come
    *                                 from a form or page that we are considering.
    * @param {nsILoginFindOptions} aOptions - Options to affect whether the origin
    *                                         from the login (aLoginOrigin) is a
    *                                         match for the origin we're looking
--- a/toolkit/components/passwordmgr/LoginManagerContent.jsm
+++ b/toolkit/components/passwordmgr/LoginManagerContent.jsm
@@ -276,17 +276,17 @@ var LoginManagerContent = {
    * @param {HTMLFormElement} form - form to get login data for
    * @param {Object} options
    * @param {boolean} options.showMasterPassword - whether to show a master password prompt
    */
   _getLoginDataFromParent(form, options) {
     let doc = form.ownerDocument;
     let win = doc.defaultView;
 
-    let formOrigin = LoginUtils._getPasswordOrigin(doc.documentURI);
+    let formOrigin = LoginHelper.getLoginOrigin(doc.documentURI);
     if (!formOrigin) {
       return Promise.reject("_getLoginDataFromParent: A form origin is required");
     }
     let actionOrigin = LoginUtils._getActionOrigin(form);
 
     let messageManager = win.docShell.messageManager;
 
     // XXX Weak??
@@ -301,17 +301,17 @@ var LoginManagerContent = {
   },
 
   _autoCompleteSearchAsync(aSearchString, aPreviousResult,
                            aElement, aRect) {
     let doc = aElement.ownerDocument;
     let form = LoginFormFactory.createFromField(aElement);
     let win = doc.defaultView;
 
-    let formOrigin = LoginUtils._getPasswordOrigin(doc.documentURI);
+    let formOrigin = LoginHelper.getLoginOrigin(doc.documentURI);
     let actionOrigin = LoginUtils._getActionOrigin(form);
 
     let messageManager = win.docShell.messageManager;
 
     let previousResult = aPreviousResult ?
                            { searchString: aPreviousResult.searchString,
                              logins: LoginHelper.loginsToVanillaObjects(aPreviousResult.logins) } :
                            null;
@@ -517,19 +517,19 @@ var LoginManagerContent = {
    *            Username or password input element from the form we want to fill.
    *        }
    */
   fillForm({ topDocument, loginFormOrigin, loginsFound, recipes, inputElement }) {
     if (!inputElement) {
       log("fillForm: No input element specified");
       return;
     }
-    if (LoginUtils._getPasswordOrigin(topDocument.documentURI) != loginFormOrigin) {
+    if (LoginHelper.getLoginOrigin(topDocument.documentURI) != loginFormOrigin) {
       if (!inputElement ||
-          LoginUtils._getPasswordOrigin(inputElement.ownerDocument.documentURI) != loginFormOrigin) {
+          LoginHelper.getLoginOrigin(inputElement.ownerDocument.documentURI) != loginFormOrigin) {
         log("fillForm: The requested origin doesn't match the one form the",
             "document. This may mean we navigated to a document from a different",
             "site before we had a chance to indicate this change in the user",
             "interface.");
         return;
       }
     }
 
@@ -547,17 +547,17 @@ var LoginManagerContent = {
       userTriggered: true,
     });
   },
 
   loginsFound({ form, loginsFound, recipes }) {
     let doc = form.ownerDocument;
     let autofillForm = LoginHelper.autofillForms && !PrivateBrowsingUtils.isContentWindowPrivate(doc.defaultView);
 
-    let formOrigin = LoginUtils._getPasswordOrigin(doc.documentURI);
+    let formOrigin = LoginHelper.getLoginOrigin(doc.documentURI);
     LoginRecipesContent.cacheRecipes(formOrigin, doc.defaultView, recipes);
 
     this._fillForm(form, loginsFound, recipes, {autofillForm});
   },
 
   /**
    * Focus event handler for username fields to decide whether to show autocomplete.
    * @param {FocusEvent} event
@@ -634,17 +634,17 @@ var LoginManagerContent = {
     if (!acInputField.value) {
       return;
     }
 
     log("onUsernameInput from", event.type);
 
     let acForm = LoginFormFactory.createFromField(acInputField);
     let doc = acForm.ownerDocument;
-    let formOrigin = LoginUtils._getPasswordOrigin(doc.documentURI);
+    let formOrigin = LoginHelper.getLoginOrigin(doc.documentURI);
     let recipes = LoginRecipesContent.getRecipes(formOrigin, doc.defaultView);
 
     // Make sure the username field fillForm will use is the
     // same field as the autocomplete was activated on.
     var [usernameField, passwordField, ignored] =
         this._getFormFields(acForm, false, recipes);
     if (usernameField == acInputField && passwordField) {
       this._getLoginDataFromParent(acForm, { showMasterPassword: false })
@@ -930,17 +930,17 @@ var LoginManagerContent = {
       return;
     }
 
     // If password saving is disabled globally, bail out now.
     if (!LoginHelper.enabled) {
       return;
     }
 
-    var hostname = LoginUtils._getPasswordOrigin(doc.documentURI);
+    var hostname = LoginHelper.getLoginOrigin(doc.documentURI);
     if (!hostname) {
       log("(form submission ignored -- invalid hostname)");
       return;
     }
 
     let formSubmitURL = LoginUtils._getActionOrigin(form);
     let messageManager = win.docShell.messageManager;
 
@@ -1391,17 +1391,17 @@ var LoginManagerContent = {
         (aField.type != "password" && !LoginHelper.isUsernameFieldType(aField)) ||
         aField.nodePrincipal.isNullPrincipal ||
         !aField.ownerDocument) {
       return [null, null, null];
     }
     let form = LoginFormFactory.createFromField(aField);
 
     let doc = aField.ownerDocument;
-    let formOrigin = LoginUtils._getPasswordOrigin(doc.documentURI);
+    let formOrigin = LoginHelper.getLoginOrigin(doc.documentURI);
     let recipes = LoginRecipesContent.getRecipes(formOrigin, doc.defaultView);
 
     return this._getFormFields(form, false, recipes);
   },
 
   /**
    * Verify if a field is a valid login form field and
    * returns some information about it's FormLike.
@@ -1440,50 +1440,25 @@ var LoginManagerContent = {
         found: !!newPasswordField,
         disabled: newPasswordField && (newPasswordField.disabled || newPasswordField.readOnly),
       },
     };
   },
 };
 
 var LoginUtils = {
-  /**
-   * Get the parts of the URL we want for identification.
-   * Strip out things like the userPass portion
-   */
-  _getPasswordOrigin(uriString, allowJS) {
-    var realm = "";
-    try {
-      var uri = Services.io.newURI(uriString);
-
-      if (allowJS && uri.scheme == "javascript") {
-        return "javascript:";
-      }
-
-      // Build this manually instead of using prePath to avoid including the userPass portion.
-      realm = uri.scheme + "://" + uri.displayHostPort;
-    } catch (e) {
-      // bug 159484 - disallow url types that don't support a hostPort.
-      // (although we handle "javascript:..." as a special case above.)
-      log("Couldn't parse origin for", uriString, e);
-      realm = null;
-    }
-
-    return realm;
-  },
-
   _getActionOrigin(form) {
     var uriString = form.action;
 
     // A blank or missing action submits to where it came from.
     if (uriString == "") {
       uriString = form.baseURI;
     } // ala bug 297761
 
-    return this._getPasswordOrigin(uriString, true);
+    return LoginHelper.getLoginOrigin(uriString, true);
   },
 };
 
 // nsIAutoCompleteResult implementation
 function UserAutoCompleteResult(aSearchString, matchingLogins, {isSecure, messageManager, isPasswordField}) {
   function loginSort(a, b) {
     var userA = a.username.toLowerCase();
     var userB = b.username.toLowerCase();
@@ -1694,17 +1669,17 @@ var LoginFormFactory = {
       throw new Error("createFromField requires a password or username field in a document");
     }
 
     if (aField.form) {
       return this.createFromForm(aField.form);
     }
 
     let formLike = FormLikeFactory.createFromField(aField);
-    formLike.action = LoginUtils._getPasswordOrigin(aField.ownerDocument.baseURI);
+    formLike.action = LoginHelper.getLoginOrigin(aField.ownerDocument.baseURI);
     log("Created non-form FormLike for rootElement:", aField.ownerDocument.documentElement);
 
     let state = LoginManagerContent.stateForDocument(formLike.ownerDocument);
     state.loginFormRootElements.add(formLike.rootElement);
     log("adding", formLike.rootElement, "to loginFormRootElements for", formLike.ownerDocument);
 
 
     LoginManagerContent._formLikeByRootElement.set(formLike.rootElement, formLike);
--- a/toolkit/components/passwordmgr/test/unit/test_getPasswordOrigin.js
+++ b/toolkit/components/passwordmgr/test/unit/test_getPasswordOrigin.js
@@ -1,15 +1,14 @@
-/*
- * Test for LoginUtils._getPasswordOrigin
+/**
+ * Test for LoginHelper.getLoginOrigin
  */
 
 "use strict";
 
-const LMCBackstagePass = ChromeUtils.import("resource://gre/modules/LoginManagerContent.jsm", null);
 const TESTCASES = [
   ["javascript:void(0);", null],
   ["javascript:void(0);", "javascript:", true],
   ["chrome://MyAccount", null],
   ["data:text/html,example", null],
   ["http://username:password@example.com:80/foo?bar=baz#fragment", "http://example.com", true],
   ["http://127.0.0.1:80/foo", "http://127.0.0.1"],
   ["http://[::1]:80/foo", "http://[::1]"],
@@ -18,11 +17,11 @@ const TESTCASES = [
   ["http://[::1]:8080/foo", "http://[::1]:8080"],
   ["https://example.com:443/foo", "https://example.com"],
   ["https://[::1]:443/foo", "https://[::1]"],
   ["https://[::1]:8443/foo", "https://[::1]:8443"],
   ["ftp://username:password@[::1]:2121/foo", "ftp://[::1]:2121"],
 ];
 
 for (let [input, expected, allowJS] of TESTCASES) {
-  let actual = LMCBackstagePass.LoginUtils._getPasswordOrigin(input, allowJS);
+  let actual = LoginHelper.getLoginOrigin(input, allowJS);
   Assert.strictEqual(actual, expected, "Checking: " + input);
 }
--- a/toolkit/components/passwordmgr/test/unit/test_getUserNameAndPasswordFields.js
+++ b/toolkit/components/passwordmgr/test/unit/test_getUserNameAndPasswordFields.js
@@ -1,16 +1,14 @@
-/*
+/**
  * Test for LoginManagerContent.getUserNameAndPasswordFields
  */
 
 "use strict";
 
-// Services.prefs.setBoolPref("signon.debug", true);
-
 XPCOMUtils.defineLazyGlobalGetters(this, ["URL"]);
 
 const LMCBackstagePass = ChromeUtils.import("resource://gre/modules/LoginManagerContent.jsm", null);
 const { LoginManagerContent, LoginFormFactory } = LMCBackstagePass;
 const TESTCASES = [
   {
     description: "1 password field outside of a <form>",
     document: `<input id="pw1" type=password>`,
@@ -90,17 +88,17 @@ for (let tc of TESTCASES) {
       MockDocument.mockOwnerDocumentProperty(input, document, "http://localhost:8080/test/");
       MockDocument.mockNodePrincipalProperty(input, "http://localhost:8080/test/");
 
       // Additional mock to cache recipes
       let win = {};
       Object.defineProperty(document, "defaultView", {
         value: win,
       });
-      let formOrigin = LMCBackstagePass.LoginUtils._getPasswordOrigin(document.documentURI);
+      let formOrigin = LoginHelper.getLoginOrigin(document.documentURI);
       LoginRecipesContent.cacheRecipes(formOrigin, win, new Set());
 
       let actual = LoginManagerContent.getUserNameAndPasswordFields(input);
 
       Assert.strictEqual(testcase.returnedFieldIDs.length, 3,
                          "getUserNameAndPasswordFields returns 3 elements");
 
       for (let i = 0; i < testcase.returnedFieldIDs.length; i++) {