Bug 1258912 - Split pwmgr_common.js into separate content and chrome scripts. r=jaws
authorMatthew Noorenberghe <mozilla@noorenberghe.ca>
Wed, 30 Jan 2019 16:27:36 -0800
changeset 456532 c7a12059919a8039a41eed2463867c46d1f88285
parent 456531 520b19bd2109e8ed4a7153cf918e08b4785c8ef9
child 456533 0fccec2f53f85b58695347e86d7da6801764eb63
push id35488
push userdvarga@mozilla.com
push dateSat, 02 Feb 2019 09:44:51 +0000
treeherdermozilla-central@d8cebb3b46cf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjaws
bugs1258912
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 1258912 - Split pwmgr_common.js into separate content and chrome scripts. r=jaws Differential Revision: https://phabricator.services.mozilla.com/D18164
toolkit/components/passwordmgr/test/LoginTestUtils.jsm
toolkit/components/passwordmgr/test/mochitest/mochitest.ini
toolkit/components/passwordmgr/test/mochitest/pwmgr_common.js
toolkit/components/passwordmgr/test/mochitest/pwmgr_common_parent.js
toolkit/components/passwordmgr/test/mochitest/test_autofill_password-only.html
toolkit/components/passwordmgr/test/mochitest/test_formless_autofill.html
toolkit/components/passwordmgr/test/mochitest/test_formless_submit.html
toolkit/components/passwordmgr/test/mochitest/test_formless_submit_navigation.html
toolkit/components/passwordmgr/test/mochitest/test_formless_submit_navigation_negative.html
toolkit/components/passwordmgr/test/mochitest/test_master_password.html
toolkit/components/passwordmgr/test/mochitest/test_prompt_http.html
toolkit/components/passwordmgr/test/mochitest/test_prompt_noWindow.html
toolkit/components/passwordmgr/test/mochitest/test_prompt_promptAuth.html
toolkit/components/passwordmgr/test/mochitest/test_username_focus.html
toolkit/components/passwordmgr/test/pwmgr_common.js
--- a/toolkit/components/passwordmgr/test/LoginTestUtils.jsm
+++ b/toolkit/components/passwordmgr/test/LoginTestUtils.jsm
@@ -1,12 +1,12 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
-/*
+/**
  * Shared functions generally available for testing login components.
  */
 
 "use strict";
 
 var EXPORTED_SYMBOLS = [
   "LoginTestUtils",
 ];
--- a/toolkit/components/passwordmgr/test/mochitest/mochitest.ini
+++ b/toolkit/components/passwordmgr/test/mochitest/mochitest.ini
@@ -10,18 +10,19 @@ support-files =
   ../../../prompts/test/prompt_common.js
   ../../../satchel/test/parent_utils.js
   ../../../satchel/test/satchel_common.js
   ../blank.html
   ../browser/form_autofocus_js.html
   ../browser/form_basic.html
   ../browser/formless_basic.html
   ../browser/form_cross_origin_secure_action.html
-  ../pwmgr_common.js
   auth2/authenticate.sjs
+  pwmgr_common.js
+  pwmgr_common_parent.js
   ../authenticate.sjs
 skip-if = toolkit == 'android' && !isFennec # Don't run on GeckoView
 
 [test_autocomplete_https_upgrade.html]
 skip-if = toolkit == 'android' # autocomplete
 [test_autocomplete_sandboxed.html]
 scheme = https
 skip-if = toolkit == 'android' # autocomplete
rename from toolkit/components/passwordmgr/test/pwmgr_common.js
rename to toolkit/components/passwordmgr/test/mochitest/pwmgr_common.js
--- a/toolkit/components/passwordmgr/test/pwmgr_common.js
+++ b/toolkit/components/passwordmgr/test/mochitest/pwmgr_common.js
@@ -1,8 +1,14 @@
+/**
+ * Helpers for password manager mochitest-plain tests.
+ */
+
+// Copied from LoginTestUtils.masterPassword.masterPassword to use from the content process.
+const MASTER_PASSWORD = "omgsecret!";
 const TESTS_DIR = "/tests/toolkit/components/passwordmgr/test/";
 
 /**
  * Returns the element with the specified |name| attribute.
  */
 function $_(formNum, name) {
   var form = document.getElementById("form" + formNum);
   if (!form) {
@@ -100,63 +106,16 @@ function checkUnmodifiedForm(formNum) {
       continue;
     }
 
     is(ele.value, ele.defaultValue, "Test to default value of field " +
        ele.name + " in form " + formNum);
   }
 }
 
-/**
- * Init with a common login
- * If selfFilling is true or non-undefined, fires an event at the page so that
- * the test can start checking filled-in values. Tests that check observer
- * notifications might be confused by this.
- */
-function commonInit(selfFilling) {
-  // eslint-disable-next-line mozilla/use-services
-  var pwmgr = SpecialPowers.Cc["@mozilla.org/login-manager;1"].
-              getService(SpecialPowers.Ci.nsILoginManager);
-  ok(pwmgr != null, "Access LoginManager");
-
-  // Check that initial state has no logins
-  var logins = pwmgr.getAllLogins();
-  is(logins.length, 0, "Not expecting logins to be present");
-  var disabledHosts = pwmgr.getAllDisabledHosts();
-  if (disabledHosts.length) {
-    ok(false, "Warning: wasn't expecting disabled hosts to be present.");
-    for (var host of disabledHosts) {
-      pwmgr.setLoginSavingEnabled(host, true);
-    }
-  }
-
-  // Add a login that's used in multiple tests
-  var login = SpecialPowers.Cc["@mozilla.org/login-manager/loginInfo;1"].
-              createInstance(SpecialPowers.Ci.nsILoginInfo);
-  login.init("http://mochi.test:8888", "http://mochi.test:8888", null,
-             "testuser", "testpass", "uname", "pword");
-  pwmgr.addLogin(login);
-
-  // Last sanity check
-  logins = pwmgr.getAllLogins();
-  is(logins.length, 1, "Checking for successful init login");
-  disabledHosts = pwmgr.getAllDisabledHosts();
-  is(disabledHosts.length, 0, "Checking for no disabled hosts");
-
-  if (selfFilling) {
-    return;
-  }
-
-  if (this.sendAsyncMessage) {
-    sendAsyncMessage("registerRunTests");
-  } else {
-    registerRunTests();
-  }
-}
-
 function registerRunTests() {
   return new Promise(resolve => {
     // We provide a general mechanism for our tests to know when they can
     // safely run: we add a final form that we know will be filled in, wait
     // for the login manager to tell us that it's filled in and then continue
     // with the rest of the tests.
     window.addEventListener("DOMContentLoaded", (event) => {
       var form = document.createElement("form");
@@ -184,80 +143,40 @@ function registerRunTests() {
       });
       SpecialPowers.addObserver(observer, "passwordmgr-processed-form");
 
       document.body.appendChild(form);
     });
   });
 }
 
-const masterPassword = "omgsecret!";
-
 function enableMasterPassword() {
   setMasterPassword(true);
 }
 
 function disableMasterPassword() {
   setMasterPassword(false);
 }
 
 function setMasterPassword(enable) {
-  chromeScript.sendSyncMessage("setMasterPassword", { enable });
+  PWMGR_COMMON_PARENT.sendSyncMessage("setMasterPassword", { enable });
 }
 
 function isLoggedIn() {
-  return chromeScript.sendSyncMessage("isLoggedIn")[0][0];
+  return PWMGR_COMMON_PARENT.sendSyncMessage("isLoggedIn")[0][0];
 }
 
 function logoutMasterPassword() {
   runInParent(function parent_logoutMasterPassword() {
     const { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
     var sdr = Cc["@mozilla.org/security/sdr;1"].getService(Ci.nsISecretDecoderRing);
     sdr.logoutAndTeardown();
   });
 }
 
-function dumpLogins(pwmgr) {
-  var logins = pwmgr.getAllLogins();
-  ok(true, "----- dumpLogins: have " + logins.length + " logins. -----");
-  for (var i = 0; i < logins.length; i++) {
-    dumpLogin("login #" + i + " --- ", logins[i]);
-  }
-}
-
-function dumpLogin(label, login) {
-  var loginText = "";
-  loginText += "host: ";
-  loginText += login.hostname;
-  loginText += " / formURL: ";
-  loginText += login.formSubmitURL;
-  loginText += " / realm: ";
-  loginText += login.httpRealm;
-  loginText += " / user: ";
-  loginText += login.username;
-  loginText += " / pass: ";
-  loginText += login.password;
-  loginText += " / ufield: ";
-  loginText += login.usernameField;
-  loginText += " / pfield: ";
-  loginText += login.passwordField;
-  ok(true, label + loginText);
-}
-
-function getRecipeParent() {
-  // eslint-disable-next-line no-shadow
-  var { LoginManagerParent } = SpecialPowers.Cu.import("resource://gre/modules/LoginManagerParent.jsm", {});
-  if (!LoginManagerParent.recipeParentPromise) {
-    return null;
-  }
-  return LoginManagerParent.recipeParentPromise.then((recipeParent) => {
-    return SpecialPowers.wrap(recipeParent);
-  });
-}
-
 /**
  * Resolves when a specified number of forms have been processed.
  */
 function promiseFormsProcessed(expectedCount = 1) {
   var processedCount = 0;
   return new Promise((resolve, reject) => {
     function onProcessedForm(subject, topic, data) {
       processedCount++;
@@ -268,57 +187,57 @@ function promiseFormsProcessed(expectedC
     }
     SpecialPowers.addObserver(onProcessedForm, "passwordmgr-processed-form");
   });
 }
 
 function loadRecipes(recipes) {
   info("Loading recipes");
   return new Promise(resolve => {
-    chromeScript.addMessageListener("loadedRecipes", function loaded() {
-      chromeScript.removeMessageListener("loadedRecipes", loaded);
+    PWMGR_COMMON_PARENT.addMessageListener("loadedRecipes", function loaded() {
+      PWMGR_COMMON_PARENT.removeMessageListener("loadedRecipes", loaded);
       resolve(recipes);
     });
-    chromeScript.sendAsyncMessage("loadRecipes", recipes);
+    PWMGR_COMMON_PARENT.sendAsyncMessage("loadRecipes", recipes);
   });
 }
 
 function resetRecipes() {
   info("Resetting recipes");
   return new Promise(resolve => {
-    chromeScript.addMessageListener("recipesReset", function reset() {
-      chromeScript.removeMessageListener("recipesReset", reset);
+    PWMGR_COMMON_PARENT.addMessageListener("recipesReset", function reset() {
+      PWMGR_COMMON_PARENT.removeMessageListener("recipesReset", reset);
       resolve();
     });
-    chromeScript.sendAsyncMessage("resetRecipes");
+    PWMGR_COMMON_PARENT.sendAsyncMessage("resetRecipes");
   });
 }
 
 function promiseStorageChanged(expectedChangeTypes) {
   return new Promise((resolve, reject) => {
     function onStorageChanged({ topic, data }) {
       let changeType = expectedChangeTypes.shift();
       is(data, changeType, "Check expected passwordmgr-storage-changed type");
       if (expectedChangeTypes.length === 0) {
-        chromeScript.removeMessageListener("storageChanged", onStorageChanged);
+        PWMGR_COMMON_PARENT.removeMessageListener("storageChanged", onStorageChanged);
         resolve();
       }
     }
-    chromeScript.addMessageListener("storageChanged", onStorageChanged);
+    PWMGR_COMMON_PARENT.addMessageListener("storageChanged", onStorageChanged);
   });
 }
 
 function promisePromptShown(expectedTopic) {
   return new Promise((resolve, reject) => {
     function onPromptShown({ topic, data }) {
       is(topic, expectedTopic, "Check expected prompt topic");
-      chromeScript.removeMessageListener("promptShown", onPromptShown);
+      PWMGR_COMMON_PARENT.removeMessageListener("promptShown", onPromptShown);
       resolve();
     }
-    chromeScript.addMessageListener("promptShown", onPromptShown);
+    PWMGR_COMMON_PARENT.addMessageListener("promptShown", onPromptShown);
   });
 }
 
 /**
  * Run a function synchronously in the parent process and destroy it in the test cleanup function.
  * @param {Function|String} aFunctionOrURL - either a function that will be stringified and run
  *                                           or the URL to a JS file.
  * @return {Object} - the return value of loadChromeScript providing message-related methods.
@@ -334,182 +253,83 @@ function runInParent(aFunctionOrURL) {
 
 /**
  * Run commonInit synchronously in the parent then run the test function after the runTests event.
  *
  * @param {Function} aFunction The test function to run
  */
 function runChecksAfterCommonInit(aFunction = null) {
   SimpleTest.waitForExplicitFinish();
-  let pwmgrCommonScript = runInParent(SimpleTest.getTestFileURL("pwmgr_common.js"));
   if (aFunction) {
     window.addEventListener("runTests", aFunction);
-    pwmgrCommonScript.addMessageListener("registerRunTests", () => registerRunTests());
+    PWMGR_COMMON_PARENT.addMessageListener("registerRunTests", () => registerRunTests());
   }
-  pwmgrCommonScript.sendSyncMessage("setupParent");
-  return pwmgrCommonScript;
+  PWMGR_COMMON_PARENT.sendSyncMessage("setupParent");
+  return PWMGR_COMMON_PARENT;
 }
 
-// Code to run when loaded as a chrome script in tests via loadChromeScript
-if (this.addMessageListener) {
-  var SpecialPowers = { Cc, Ci, Cr, Cu };
-  var ok, is;
-  // Ignore ok/is in commonInit since they aren't defined in a chrome script.
-  ok = is = () => {};
+// Begin code that runs immediately for all tests that include this file.
 
-  ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
-  var {LoginHelper} = ChromeUtils.import("resource://gre/modules/LoginHelper.jsm");
-  var {LoginManagerParent} = ChromeUtils.import("resource://gre/modules/LoginManagerParent.jsm");
-  var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
+const PWMGR_COMMON_PARENT = runInParent(SimpleTest.getTestFileURL("pwmgr_common_parent.js"));
 
-  function onStorageChanged(subject, topic, data) {
-    sendAsyncMessage("storageChanged", {
-      topic,
-      data,
-    });
-  }
-  Services.obs.addObserver(onStorageChanged, "passwordmgr-storage-changed");
-
-  function onPrompt(subject, topic, data) {
-    sendAsyncMessage("promptShown", {
-      topic,
-      data,
-    });
-  }
-  Services.obs.addObserver(onPrompt, "passwordmgr-prompt-change");
-  Services.obs.addObserver(onPrompt, "passwordmgr-prompt-save");
-
-  addMessageListener("setupParent", ({selfFilling = false} = {selfFilling: false}) => {
-    commonInit(selfFilling);
-    sendAsyncMessage("doneSetup");
-  });
+SimpleTest.registerCleanupFunction(() => {
+  SpecialPowers.popPrefEnv();
+  runInParent(function cleanupParent() {
+    // eslint-disable-next-line no-shadow
+    const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
+    // eslint-disable-next-line no-shadow
+    const {LoginManagerParent} = ChromeUtils.import("resource://gre/modules/LoginManagerParent.jsm");
 
-  addMessageListener("loadRecipes", function(recipes) {
-    (async function() {
-      var recipeParent = await LoginManagerParent.recipeParentPromise;
-      await recipeParent.load(recipes);
-      sendAsyncMessage("loadedRecipes", recipes);
-    })();
-  });
+    // Remove all logins and disabled hosts
+    Services.logins.removeAllLogins();
 
-  addMessageListener("resetRecipes", function() {
-    (async function() {
-      let recipeParent = await LoginManagerParent.recipeParentPromise;
-      await recipeParent.reset();
-      sendAsyncMessage("recipesReset");
-    })();
-  });
-
-  addMessageListener("proxyLoginManager", msg => {
-    // Recreate nsILoginInfo objects from vanilla JS objects.
-    let recreatedArgs = msg.args.map((arg, index) => {
-      if (msg.loginInfoIndices.includes(index)) {
-        return LoginHelper.vanillaObjectToLogin(arg);
-      }
+    let disabledHosts = Services.logins.getAllDisabledHosts();
+    disabledHosts.forEach(host => Services.logins.setLoginSavingEnabled(host, true));
 
-      return arg;
-    });
-
-    let rv = Services.logins[msg.methodName](...recreatedArgs);
-    if (rv instanceof Ci.nsILoginInfo) {
-      rv = LoginHelper.loginToVanillaObject(rv);
-    } else if (Array.isArray(rv) && rv.length > 0 && rv[0] instanceof Ci.nsILoginInfo) {
-      rv = rv.map(login => LoginHelper.loginToVanillaObject(login));
-    }
-    return rv;
-  });
+    let authMgr = Cc["@mozilla.org/network/http-auth-manager;1"].
+                  getService(Ci.nsIHttpAuthManager);
+    authMgr.clearAll();
 
-  addMessageListener("isLoggedIn", () => {
-    // This can't use the LoginManager proxy below since it's not a method.
-    return Services.logins.isLoggedIn;
-  });
-
-  addMessageListener("setMasterPassword", ({ enable }) => {
-    let oldPW, newPW;
-    if (enable) {
-      oldPW = "";
-      newPW = masterPassword;
-    } else {
-      oldPW = masterPassword;
-      newPW = "";
+    if (LoginManagerParent._recipeManager) {
+      LoginManagerParent._recipeManager.reset();
     }
-    // Set master password. Note that this logs in the user if no password was
-    // set before. But after logging out the next invocation of pwmgr can
-    // trigger a MP prompt.
 
-    var pk11db = Cc["@mozilla.org/security/pk11tokendb;1"].getService(Ci.nsIPK11TokenDB);
-    var token = pk11db.getInternalKeyToken();
-    dump("MP change from " + oldPW + " to " + newPW + "\n");
-    token.changePassword(oldPW, newPW);
-    token.logoutSimple();
-  });
-
-  Services.mm.addMessageListener("RemoteLogins:onFormSubmit", function onFormSubmit(message) {
-    sendAsyncMessage("formSubmissionProcessed", message.data, message.objects);
+    // Cleanup PopupNotifications (if on a relevant platform)
+    let chromeWin = Services.wm.getMostRecentWindow("navigator:browser");
+    if (chromeWin && chromeWin.PopupNotifications) {
+      let notes = chromeWin.PopupNotifications._currentNotifications;
+      if (notes.length > 0) {
+        dump("Removing " + notes.length + " popup notifications.\n");
+      }
+      for (let note of notes) {
+        note.remove();
+      }
+    }
   });
-} else {
-  // Code to only run in the mochitest pages (not in the chrome script).
-  SimpleTest.registerCleanupFunction(() => {
-    SpecialPowers.popPrefEnv();
-    runInParent(function cleanupParent() {
-      // eslint-disable-next-line no-shadow
-      const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
-      // eslint-disable-next-line no-shadow
-      const {LoginManagerParent} = ChromeUtils.import("resource://gre/modules/LoginManagerParent.jsm");
-
-      // Remove all logins and disabled hosts
-      Services.logins.removeAllLogins();
-
-      let disabledHosts = Services.logins.getAllDisabledHosts();
-      disabledHosts.forEach(host => Services.logins.setLoginSavingEnabled(host, true));
-
-      let authMgr = Cc["@mozilla.org/network/http-auth-manager;1"].
-                    getService(Ci.nsIHttpAuthManager);
-      authMgr.clearAll();
-
-      if (LoginManagerParent._recipeManager) {
-        LoginManagerParent._recipeManager.reset();
-      }
+});
 
-      // Cleanup PopupNotifications (if on a relevant platform)
-      let chromeWin = Services.wm.getMostRecentWindow("navigator:browser");
-      if (chromeWin && chromeWin.PopupNotifications) {
-        let notes = chromeWin.PopupNotifications._currentNotifications;
-        if (notes.length > 0) {
-          dump("Removing " + notes.length + " popup notifications.\n");
+let { LoginHelper } = SpecialPowers.Cu.import("resource://gre/modules/LoginHelper.jsm", {});
+/**
+ * Proxy for Services.logins (nsILoginManager).
+ * Only supports arguments which support structured clone plus {nsILoginInfo}
+ * Assumes properties are methods.
+ */
+this.LoginManager = new Proxy({}, {
+  get(target, prop, receiver) {
+    return (...args) => {
+      let loginInfoIndices = [];
+      let cloneableArgs = args.map((val, index) => {
+        if (SpecialPowers.call_Instanceof(val, SpecialPowers.Ci.nsILoginInfo)) {
+          loginInfoIndices.push(index);
+          return LoginHelper.loginToVanillaObject(val);
         }
-        for (let note of notes) {
-          note.remove();
-        }
-      }
-    });
-  });
-
 
-  // eslint-disable-next-line no-shadow
-  let { LoginHelper } = SpecialPowers.Cu.import("resource://gre/modules/LoginHelper.jsm", {});
-  /**
-   * Proxy for Services.logins (nsILoginManager).
-   * Only supports arguments which support structured clone plus {nsILoginInfo}
-   * Assumes properties are methods.
-   */
-  this.LoginManager = new Proxy({}, {
-    get(target, prop, receiver) {
-      return (...args) => {
-        let loginInfoIndices = [];
-        let cloneableArgs = args.map((val, index) => {
-          if (SpecialPowers.call_Instanceof(val, SpecialPowers.Ci.nsILoginInfo)) {
-            loginInfoIndices.push(index);
-            return LoginHelper.loginToVanillaObject(val);
-          }
+        return val;
+      });
 
-          return val;
-        });
-
-        return chromeScript.sendSyncMessage("proxyLoginManager", {
-          args: cloneableArgs,
-          loginInfoIndices,
-          methodName: prop,
-        })[0][0];
-      };
-    },
-  });
-}
+      return PWMGR_COMMON_PARENT.sendSyncMessage("proxyLoginManager", {
+        args: cloneableArgs,
+        loginInfoIndices,
+        methodName: prop,
+      })[0][0];
+    };
+  },
+});
copy from toolkit/components/passwordmgr/test/pwmgr_common.js
copy to toolkit/components/passwordmgr/test/mochitest/pwmgr_common_parent.js
--- a/toolkit/components/passwordmgr/test/pwmgr_common.js
+++ b/toolkit/components/passwordmgr/test/mochitest/pwmgr_common_parent.js
@@ -1,228 +1,70 @@
-const TESTS_DIR = "/tests/toolkit/components/passwordmgr/test/";
-
 /**
- * Returns the element with the specified |name| attribute.
+ * Loaded as a frame script to do privileged things in mochitest-plain tests.
+ * See pwmgr_common.js for the content process companion.
  */
-function $_(formNum, name) {
-  var form = document.getElementById("form" + formNum);
-  if (!form) {
-    logWarning("$_ couldn't find requested form " + formNum);
-    return null;
-  }
-
-  var element = form.children.namedItem(name);
-  if (!element) {
-    logWarning("$_ couldn't find requested element " + name);
-    return null;
-  }
 
-  // Note that namedItem is a bit stupid, and will prefer an
-  // |id| attribute over a |name| attribute when looking for
-  // the element. Login Mananger happens to use .namedItem
-  // anyway, but let's rigorously check it here anyway so
-  // that we don't end up with tests that mistakenly pass.
-
-  if (element.getAttribute("name") != name) {
-    logWarning("$_ got confused.");
-    return null;
-  }
-
-  return element;
-}
-
-/**
- * Check a form for expected values. If an argument is null, a field's
- * expected value will be the default value.
- *
- * <form id="form#">
- * checkForm(#, "foo");
- */
-function checkForm(formNum, val1, val2, val3) {
-  var e, form = document.getElementById("form" + formNum);
-  ok(form, "Locating form " + formNum);
-
-  var numToCheck = arguments.length - 1;
+"use strict";
 
-  if (!numToCheck--) {
-    return;
-  }
-  e = form.elements[0];
-  if (val1 == null) {
-    is(e.value, e.defaultValue, "Test default value of field " + e.name +
-       " in form " + formNum);
-  } else {
-    is(e.value, val1, "Test value of field " + e.name +
-       " in form " + formNum);
-  }
-
-
-  if (!numToCheck--) {
-    return;
-  }
-  e = form.elements[1];
-  if (val2 == null) {
-    is(e.value, e.defaultValue, "Test default value of field " + e.name +
-       " in form " + formNum);
-  } else {
-    is(e.value, val2, "Test value of field " + e.name +
-       " in form " + formNum);
-  }
-
+// assert is available to chrome scripts loaded via SpecialPowers.loadChromeScript.
+/* global assert */
+/* eslint-env mozilla/frame-script */
 
-  if (!numToCheck--) {
-    return;
-  }
-  e = form.elements[2];
-  if (val3 == null) {
-    is(e.value, e.defaultValue, "Test default value of field " + e.name +
-       " in form " + formNum);
-  } else {
-    is(e.value, val3, "Test value of field " + e.name +
-       " in form " + formNum);
-  }
-}
-
-/**
- * Check a form for unmodified values from when page was loaded.
- *
- * <form id="form#">
- * checkUnmodifiedForm(#);
- */
-function checkUnmodifiedForm(formNum) {
-  var form = document.getElementById("form" + formNum);
-  ok(form, "Locating form " + formNum);
-
-  for (var i = 0; i < form.elements.length; i++) {
-    var ele = form.elements[i];
-
-    // No point in checking form submit/reset buttons.
-    if (ele.type == "submit" || ele.type == "reset") {
-      continue;
-    }
-
-    is(ele.value, ele.defaultValue, "Test to default value of field " +
-       ele.name + " in form " + formNum);
-  }
-}
+var {AppConstants} = ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
+var {LoginHelper} = ChromeUtils.import("resource://gre/modules/LoginHelper.jsm");
+var {LoginManagerParent} = ChromeUtils.import("resource://gre/modules/LoginManagerParent.jsm");
+const {LoginTestUtils} = ChromeUtils.import("resource://testing-common/LoginTestUtils.jsm");
+var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
 
 /**
  * Init with a common login
  * If selfFilling is true or non-undefined, fires an event at the page so that
  * the test can start checking filled-in values. Tests that check observer
  * notifications might be confused by this.
  */
 function commonInit(selfFilling) {
-  // eslint-disable-next-line mozilla/use-services
-  var pwmgr = SpecialPowers.Cc["@mozilla.org/login-manager;1"].
-              getService(SpecialPowers.Ci.nsILoginManager);
-  ok(pwmgr != null, "Access LoginManager");
+  var pwmgr = Services.logins;
+  assert.ok(pwmgr != null, "Access LoginManager");
 
   // Check that initial state has no logins
   var logins = pwmgr.getAllLogins();
-  is(logins.length, 0, "Not expecting logins to be present");
+  assert.equal(logins.length, 0, "Not expecting logins to be present");
   var disabledHosts = pwmgr.getAllDisabledHosts();
   if (disabledHosts.length) {
-    ok(false, "Warning: wasn't expecting disabled hosts to be present.");
+    assert.ok(false, "Warning: wasn't expecting disabled hosts to be present.");
     for (var host of disabledHosts) {
       pwmgr.setLoginSavingEnabled(host, true);
     }
   }
 
   // Add a login that's used in multiple tests
-  var login = SpecialPowers.Cc["@mozilla.org/login-manager/loginInfo;1"].
-              createInstance(SpecialPowers.Ci.nsILoginInfo);
+  var login = Cc["@mozilla.org/login-manager/loginInfo;1"].
+              createInstance(Ci.nsILoginInfo);
   login.init("http://mochi.test:8888", "http://mochi.test:8888", null,
              "testuser", "testpass", "uname", "pword");
   pwmgr.addLogin(login);
 
   // Last sanity check
   logins = pwmgr.getAllLogins();
-  is(logins.length, 1, "Checking for successful init login");
+  assert.equal(logins.length, 1, "Checking for successful init login");
   disabledHosts = pwmgr.getAllDisabledHosts();
-  is(disabledHosts.length, 0, "Checking for no disabled hosts");
+  assert.equal(disabledHosts.length, 0, "Checking for no disabled hosts");
 
   if (selfFilling) {
     return;
   }
 
-  if (this.sendAsyncMessage) {
-    sendAsyncMessage("registerRunTests");
-  } else {
-    registerRunTests();
-  }
+  // Notify the content side that initialization is done and tests can start.
+  sendAsyncMessage("registerRunTests");
 }
 
-function registerRunTests() {
-  return new Promise(resolve => {
-    // We provide a general mechanism for our tests to know when they can
-    // safely run: we add a final form that we know will be filled in, wait
-    // for the login manager to tell us that it's filled in and then continue
-    // with the rest of the tests.
-    window.addEventListener("DOMContentLoaded", (event) => {
-      var form = document.createElement("form");
-      form.id = "observerforcer";
-      var username = document.createElement("input");
-      username.name = "testuser";
-      form.appendChild(username);
-      var password = document.createElement("input");
-      password.name = "testpass";
-      password.type = "password";
-      form.appendChild(password);
-
-      var observer = SpecialPowers.wrapCallback(function(subject, topic, data) {
-        var formLikeRoot = subject;
-        if (formLikeRoot.id !== "observerforcer") {
-          return;
-        }
-        SpecialPowers.removeObserver(observer, "passwordmgr-processed-form");
-        formLikeRoot.remove();
-        SimpleTest.executeSoon(() => {
-          var runTestEvent = new Event("runTests");
-          window.dispatchEvent(runTestEvent);
-          resolve();
-        });
-      });
-      SpecialPowers.addObserver(observer, "passwordmgr-processed-form");
-
-      document.body.appendChild(form);
-    });
-  });
-}
-
-const masterPassword = "omgsecret!";
-
-function enableMasterPassword() {
-  setMasterPassword(true);
-}
-
-function disableMasterPassword() {
-  setMasterPassword(false);
-}
-
-function setMasterPassword(enable) {
-  chromeScript.sendSyncMessage("setMasterPassword", { enable });
-}
-
-function isLoggedIn() {
-  return chromeScript.sendSyncMessage("isLoggedIn")[0][0];
-}
-
-function logoutMasterPassword() {
-  runInParent(function parent_logoutMasterPassword() {
-    const { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
-    var sdr = Cc["@mozilla.org/security/sdr;1"].getService(Ci.nsISecretDecoderRing);
-    sdr.logoutAndTeardown();
-  });
-}
-
-function dumpLogins(pwmgr) {
-  var logins = pwmgr.getAllLogins();
-  ok(true, "----- dumpLogins: have " + logins.length + " logins. -----");
+function dumpLogins() {
+  let logins = Services.logins.getAllLogins();
+  assert.ok(true, "----- dumpLogins: have " + logins.length + " logins. -----");
   for (var i = 0; i < logins.length; i++) {
     dumpLogin("login #" + i + " --- ", logins[i]);
   }
 }
 
 function dumpLogin(label, login) {
   var loginText = "";
   loginText += "host: ";
@@ -234,282 +76,83 @@ function dumpLogin(label, login) {
   loginText += " / user: ";
   loginText += login.username;
   loginText += " / pass: ";
   loginText += login.password;
   loginText += " / ufield: ";
   loginText += login.usernameField;
   loginText += " / pfield: ";
   loginText += login.passwordField;
-  ok(true, label + loginText);
-}
-
-function getRecipeParent() {
-  // eslint-disable-next-line no-shadow
-  var { LoginManagerParent } = SpecialPowers.Cu.import("resource://gre/modules/LoginManagerParent.jsm", {});
-  if (!LoginManagerParent.recipeParentPromise) {
-    return null;
-  }
-  return LoginManagerParent.recipeParentPromise.then((recipeParent) => {
-    return SpecialPowers.wrap(recipeParent);
-  });
-}
-
-/**
- * Resolves when a specified number of forms have been processed.
- */
-function promiseFormsProcessed(expectedCount = 1) {
-  var processedCount = 0;
-  return new Promise((resolve, reject) => {
-    function onProcessedForm(subject, topic, data) {
-      processedCount++;
-      if (processedCount == expectedCount) {
-        SpecialPowers.removeObserver(onProcessedForm, "passwordmgr-processed-form");
-        resolve(SpecialPowers.Cu.waiveXrays(subject), data);
-      }
-    }
-    SpecialPowers.addObserver(onProcessedForm, "passwordmgr-processed-form");
-  });
-}
-
-function loadRecipes(recipes) {
-  info("Loading recipes");
-  return new Promise(resolve => {
-    chromeScript.addMessageListener("loadedRecipes", function loaded() {
-      chromeScript.removeMessageListener("loadedRecipes", loaded);
-      resolve(recipes);
-    });
-    chromeScript.sendAsyncMessage("loadRecipes", recipes);
-  });
-}
-
-function resetRecipes() {
-  info("Resetting recipes");
-  return new Promise(resolve => {
-    chromeScript.addMessageListener("recipesReset", function reset() {
-      chromeScript.removeMessageListener("recipesReset", reset);
-      resolve();
-    });
-    chromeScript.sendAsyncMessage("resetRecipes");
-  });
-}
-
-function promiseStorageChanged(expectedChangeTypes) {
-  return new Promise((resolve, reject) => {
-    function onStorageChanged({ topic, data }) {
-      let changeType = expectedChangeTypes.shift();
-      is(data, changeType, "Check expected passwordmgr-storage-changed type");
-      if (expectedChangeTypes.length === 0) {
-        chromeScript.removeMessageListener("storageChanged", onStorageChanged);
-        resolve();
-      }
-    }
-    chromeScript.addMessageListener("storageChanged", onStorageChanged);
-  });
-}
-
-function promisePromptShown(expectedTopic) {
-  return new Promise((resolve, reject) => {
-    function onPromptShown({ topic, data }) {
-      is(topic, expectedTopic, "Check expected prompt topic");
-      chromeScript.removeMessageListener("promptShown", onPromptShown);
-      resolve();
-    }
-    chromeScript.addMessageListener("promptShown", onPromptShown);
-  });
-}
-
-/**
- * Run a function synchronously in the parent process and destroy it in the test cleanup function.
- * @param {Function|String} aFunctionOrURL - either a function that will be stringified and run
- *                                           or the URL to a JS file.
- * @return {Object} - the return value of loadChromeScript providing message-related methods.
- *                    @see loadChromeScript in specialpowersAPI.js
- */
-function runInParent(aFunctionOrURL) {
-  let chromeScript = SpecialPowers.loadChromeScript(aFunctionOrURL);
-  SimpleTest.registerCleanupFunction(() => {
-    chromeScript.destroy();
-  });
-  return chromeScript;
-}
-
-/**
- * Run commonInit synchronously in the parent then run the test function after the runTests event.
- *
- * @param {Function} aFunction The test function to run
- */
-function runChecksAfterCommonInit(aFunction = null) {
-  SimpleTest.waitForExplicitFinish();
-  let pwmgrCommonScript = runInParent(SimpleTest.getTestFileURL("pwmgr_common.js"));
-  if (aFunction) {
-    window.addEventListener("runTests", aFunction);
-    pwmgrCommonScript.addMessageListener("registerRunTests", () => registerRunTests());
-  }
-  pwmgrCommonScript.sendSyncMessage("setupParent");
-  return pwmgrCommonScript;
+  assert.ok(true, label + loginText);
 }
 
-// Code to run when loaded as a chrome script in tests via loadChromeScript
-if (this.addMessageListener) {
-  var SpecialPowers = { Cc, Ci, Cr, Cu };
-  var ok, is;
-  // Ignore ok/is in commonInit since they aren't defined in a chrome script.
-  ok = is = () => {};
-
-  ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
-  var {LoginHelper} = ChromeUtils.import("resource://gre/modules/LoginHelper.jsm");
-  var {LoginManagerParent} = ChromeUtils.import("resource://gre/modules/LoginManagerParent.jsm");
-  var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
+function onStorageChanged(subject, topic, data) {
+  sendAsyncMessage("storageChanged", {
+    topic,
+    data,
+  });
+}
+Services.obs.addObserver(onStorageChanged, "passwordmgr-storage-changed");
 
-  function onStorageChanged(subject, topic, data) {
-    sendAsyncMessage("storageChanged", {
-      topic,
-      data,
-    });
-  }
-  Services.obs.addObserver(onStorageChanged, "passwordmgr-storage-changed");
+function onPrompt(subject, topic, data) {
+  sendAsyncMessage("promptShown", {
+    topic,
+    data,
+  });
+}
+Services.obs.addObserver(onPrompt, "passwordmgr-prompt-change");
+Services.obs.addObserver(onPrompt, "passwordmgr-prompt-save");
 
-  function onPrompt(subject, topic, data) {
-    sendAsyncMessage("promptShown", {
-      topic,
-      data,
-    });
-  }
-  Services.obs.addObserver(onPrompt, "passwordmgr-prompt-change");
-  Services.obs.addObserver(onPrompt, "passwordmgr-prompt-save");
 
-  addMessageListener("setupParent", ({selfFilling = false} = {selfFilling: false}) => {
-    commonInit(selfFilling);
-    sendAsyncMessage("doneSetup");
-  });
+// Begin message listeners
 
-  addMessageListener("loadRecipes", function(recipes) {
-    (async function() {
-      var recipeParent = await LoginManagerParent.recipeParentPromise;
-      await recipeParent.load(recipes);
-      sendAsyncMessage("loadedRecipes", recipes);
-    })();
-  });
+addMessageListener("setupParent", ({selfFilling = false} = {selfFilling: false}) => {
+  commonInit(selfFilling);
+  sendAsyncMessage("doneSetup");
+});
 
-  addMessageListener("resetRecipes", function() {
-    (async function() {
-      let recipeParent = await LoginManagerParent.recipeParentPromise;
-      await recipeParent.reset();
-      sendAsyncMessage("recipesReset");
-    })();
-  });
+addMessageListener("loadRecipes", async function(recipes) {
+  var recipeParent = await LoginManagerParent.recipeParentPromise;
+  await recipeParent.load(recipes);
+  sendAsyncMessage("loadedRecipes", recipes);
+});
 
-  addMessageListener("proxyLoginManager", msg => {
-    // Recreate nsILoginInfo objects from vanilla JS objects.
-    let recreatedArgs = msg.args.map((arg, index) => {
-      if (msg.loginInfoIndices.includes(index)) {
-        return LoginHelper.vanillaObjectToLogin(arg);
-      }
-
-      return arg;
-    });
+addMessageListener("resetRecipes", async function() {
+  let recipeParent = await LoginManagerParent.recipeParentPromise;
+  await recipeParent.reset();
+  sendAsyncMessage("recipesReset");
+});
 
-    let rv = Services.logins[msg.methodName](...recreatedArgs);
-    if (rv instanceof Ci.nsILoginInfo) {
-      rv = LoginHelper.loginToVanillaObject(rv);
-    } else if (Array.isArray(rv) && rv.length > 0 && rv[0] instanceof Ci.nsILoginInfo) {
-      rv = rv.map(login => LoginHelper.loginToVanillaObject(login));
+addMessageListener("proxyLoginManager", msg => {
+  // Recreate nsILoginInfo objects from vanilla JS objects.
+  let recreatedArgs = msg.args.map((arg, index) => {
+    if (msg.loginInfoIndices.includes(index)) {
+      return LoginHelper.vanillaObjectToLogin(arg);
     }
-    return rv;
-  });
 
-  addMessageListener("isLoggedIn", () => {
-    // This can't use the LoginManager proxy below since it's not a method.
-    return Services.logins.isLoggedIn;
+    return arg;
   });
 
-  addMessageListener("setMasterPassword", ({ enable }) => {
-    let oldPW, newPW;
-    if (enable) {
-      oldPW = "";
-      newPW = masterPassword;
-    } else {
-      oldPW = masterPassword;
-      newPW = "";
-    }
-    // Set master password. Note that this logs in the user if no password was
-    // set before. But after logging out the next invocation of pwmgr can
-    // trigger a MP prompt.
-
-    var pk11db = Cc["@mozilla.org/security/pk11tokendb;1"].getService(Ci.nsIPK11TokenDB);
-    var token = pk11db.getInternalKeyToken();
-    dump("MP change from " + oldPW + " to " + newPW + "\n");
-    token.changePassword(oldPW, newPW);
-    token.logoutSimple();
-  });
-
-  Services.mm.addMessageListener("RemoteLogins:onFormSubmit", function onFormSubmit(message) {
-    sendAsyncMessage("formSubmissionProcessed", message.data, message.objects);
-  });
-} else {
-  // Code to only run in the mochitest pages (not in the chrome script).
-  SimpleTest.registerCleanupFunction(() => {
-    SpecialPowers.popPrefEnv();
-    runInParent(function cleanupParent() {
-      // eslint-disable-next-line no-shadow
-      const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
-      // eslint-disable-next-line no-shadow
-      const {LoginManagerParent} = ChromeUtils.import("resource://gre/modules/LoginManagerParent.jsm");
-
-      // Remove all logins and disabled hosts
-      Services.logins.removeAllLogins();
-
-      let disabledHosts = Services.logins.getAllDisabledHosts();
-      disabledHosts.forEach(host => Services.logins.setLoginSavingEnabled(host, true));
-
-      let authMgr = Cc["@mozilla.org/network/http-auth-manager;1"].
-                    getService(Ci.nsIHttpAuthManager);
-      authMgr.clearAll();
+  let rv = Services.logins[msg.methodName](...recreatedArgs);
+  if (rv instanceof Ci.nsILoginInfo) {
+    rv = LoginHelper.loginToVanillaObject(rv);
+  } else if (Array.isArray(rv) && rv.length > 0 && rv[0] instanceof Ci.nsILoginInfo) {
+    rv = rv.map(login => LoginHelper.loginToVanillaObject(login));
+  }
+  return rv;
+});
 
-      if (LoginManagerParent._recipeManager) {
-        LoginManagerParent._recipeManager.reset();
-      }
-
-      // Cleanup PopupNotifications (if on a relevant platform)
-      let chromeWin = Services.wm.getMostRecentWindow("navigator:browser");
-      if (chromeWin && chromeWin.PopupNotifications) {
-        let notes = chromeWin.PopupNotifications._currentNotifications;
-        if (notes.length > 0) {
-          dump("Removing " + notes.length + " popup notifications.\n");
-        }
-        for (let note of notes) {
-          note.remove();
-        }
-      }
-    });
-  });
-
+addMessageListener("isLoggedIn", () => {
+  // This can't use the LoginManager proxy in pwmgr_common.js since it's not a method.
+  return Services.logins.isLoggedIn;
+});
 
-  // eslint-disable-next-line no-shadow
-  let { LoginHelper } = SpecialPowers.Cu.import("resource://gre/modules/LoginHelper.jsm", {});
-  /**
-   * Proxy for Services.logins (nsILoginManager).
-   * Only supports arguments which support structured clone plus {nsILoginInfo}
-   * Assumes properties are methods.
-   */
-  this.LoginManager = new Proxy({}, {
-    get(target, prop, receiver) {
-      return (...args) => {
-        let loginInfoIndices = [];
-        let cloneableArgs = args.map((val, index) => {
-          if (SpecialPowers.call_Instanceof(val, SpecialPowers.Ci.nsILoginInfo)) {
-            loginInfoIndices.push(index);
-            return LoginHelper.loginToVanillaObject(val);
-          }
+addMessageListener("setMasterPassword", ({ enable }) => {
+  if (enable) {
+    LoginTestUtils.masterPassword.enable();
+  } else {
+    LoginTestUtils.masterPassword.disable();
+  }
+});
 
-          return val;
-        });
-
-        return chromeScript.sendSyncMessage("proxyLoginManager", {
-          args: cloneableArgs,
-          loginInfoIndices,
-          methodName: prop,
-        })[0][0];
-      };
-    },
-  });
-}
+Services.mm.addMessageListener("RemoteLogins:onFormSubmit", function onFormSubmit(message) {
+  sendAsyncMessage("formSubmissionProcessed", message.data, message.objects);
+});
--- a/toolkit/components/passwordmgr/test/mochitest/test_autofill_password-only.html
+++ b/toolkit/components/passwordmgr/test/mochitest/test_autofill_password-only.html
@@ -5,18 +5,17 @@
   <title>Test password-only forms should prefer a password-only login when present</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="pwmgr_common.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 Login Manager test: Bug 444968
 <script>
-let pwmgrCommonScript = runInParent(SimpleTest.getTestFileURL("pwmgr_common.js"));
-pwmgrCommonScript.sendSyncMessage("setupParent", { selfFilling: true });
+PWMGR_COMMON_PARENT.sendSyncMessage("setupParent", { selfFilling: true });
 
 SimpleTest.waitForExplicitFinish();
 
 let chromeScript = runInParent(function chromeSetup() {
   const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 
   let login1A  = Cc["@mozilla.org/login-manager/loginInfo;1"].
                  createInstance(Ci.nsILoginInfo);
--- a/toolkit/components/passwordmgr/test/mochitest/test_formless_autofill.html
+++ b/toolkit/components/passwordmgr/test/mochitest/test_formless_autofill.html
@@ -5,28 +5,26 @@
   <title>Test autofilling of fields outside of a form</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/AddTask.js"></script>
   <script src="pwmgr_common.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <script type="application/javascript">
-let chromeScript = runInParent(SimpleTest.getTestFileURL("pwmgr_common.js"));
-
 document.addEventListener("DOMContentLoaded", () => {
   document.getElementById("loginFrame").addEventListener("load", (evt) => {
     // Tell the parent to setup test logins.
-    chromeScript.sendAsyncMessage("setupParent", { selfFilling: true });
+    PWMGR_COMMON_PARENT.sendAsyncMessage("setupParent", { selfFilling: true });
   });
 });
 
 let doneSetupPromise = new Promise(resolve => {
   // When the setup is done, load a recipe for this test.
-  chromeScript.addMessageListener("doneSetup", function doneSetup() {
+  PWMGR_COMMON_PARENT.addMessageListener("doneSetup", function doneSetup() {
     resolve();
   });
 });
 
 add_task(async function setup() {
   info("Waiting for loads and setup");
   await doneSetupPromise;
 
--- a/toolkit/components/passwordmgr/test/mochitest/test_formless_submit.html
+++ b/toolkit/components/passwordmgr/test/mochitest/test_formless_submit.html
@@ -8,18 +8,16 @@
   <script src="pwmgr_common.js"></script>
   <link rel="stylesheet" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <script type="application/javascript">
 const LMCBackstagePass = SpecialPowers.Cu.import("resource://gre/modules/LoginManagerContent.jsm");
 const { LoginManagerContent, LoginFormFactory } = LMCBackstagePass;
 
-let chromeScript = runInParent(SimpleTest.getTestFileURL("pwmgr_common.js"));
-
 let loadPromise = new Promise(resolve => {
   document.addEventListener("DOMContentLoaded", () => {
     document.getElementById("loginFrame").addEventListener("load", (evt) => {
       resolve();
     });
   });
 });
 
@@ -121,19 +119,19 @@ const TESTCASES = [
     newPasswordFieldValue: "pass2",
     oldPasswordFieldValue: null,
   },
 ];
 
 function getSubmitMessage() {
   info("getSubmitMessage");
   return new Promise((resolve, reject) => {
-    chromeScript.addMessageListener("formSubmissionProcessed", function processed(...args) {
+    PWMGR_COMMON_PARENT.addMessageListener("formSubmissionProcessed", function processed(...args) {
       info("got formSubmissionProcessed");
-      chromeScript.removeMessageListener("formSubmissionProcessed", processed);
+      PWMGR_COMMON_PARENT.removeMessageListener("formSubmissionProcessed", processed);
       resolve(...args);
     });
   });
 }
 
 add_task(async function test() {
   let loginFrame = document.getElementById("loginFrame");
   let frameDoc = loginFrame.contentWindow.document;
--- a/toolkit/components/passwordmgr/test/mochitest/test_formless_submit_navigation.html
+++ b/toolkit/components/passwordmgr/test/mochitest/test_formless_submit_navigation.html
@@ -8,18 +8,16 @@
   <script src="pwmgr_common.js"></script>
   <link rel="stylesheet" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <script type="application/javascript">
 const LMCBackstagePass = SpecialPowers.Cu.import("resource://gre/modules/LoginManagerContent.jsm");
 const { LoginManagerContent, LoginFormFactory } = LMCBackstagePass;
 
-let chromeScript = runInParent(SimpleTest.getTestFileURL("pwmgr_common.js"));
-
 let loadPromise = new Promise(resolve => {
   document.addEventListener("DOMContentLoaded", () => {
     document.getElementById("loginFrame").addEventListener("load", (evt) => {
       resolve();
     });
   });
 });
 
@@ -120,19 +118,19 @@ const TESTCASES = [
     newPasswordFieldValue: "pass2",
     oldPasswordFieldValue: null,
   },
 ];
 
 function getSubmitMessage() {
   info("getSubmitMessage");
   return new Promise((resolve, reject) => {
-    chromeScript.addMessageListener("formSubmissionProcessed", function processed(...args) {
+    PWMGR_COMMON_PARENT.addMessageListener("formSubmissionProcessed", function processed(...args) {
       info("got formSubmissionProcessed");
-      chromeScript.removeMessageListener("formSubmissionProcessed", processed);
+      PWMGR_COMMON_PARENT.removeMessageListener("formSubmissionProcessed", processed);
       resolve(...args);
     });
   });
 }
 
 add_task(async function test() {
   let loginFrame = document.getElementById("loginFrame");
 
--- a/toolkit/components/passwordmgr/test/mochitest/test_formless_submit_navigation_negative.html
+++ b/toolkit/components/passwordmgr/test/mochitest/test_formless_submit_navigation_negative.html
@@ -10,18 +10,16 @@
 </head>
 <body>
 <script type="application/javascript">
 const LMCBackstagePass = SpecialPowers.Cu.import("resource://gre/modules/LoginManagerContent.jsm");
 const { LoginManagerContent, LoginFormFactory } = LMCBackstagePass;
 
 SimpleTest.requestFlakyTimeout("Testing that a message doesn't arrive");
 
-let chromeScript = runInParent(SimpleTest.getTestFileURL("pwmgr_common.js"));
-
 let loadPromise = new Promise(resolve => {
   document.addEventListener("DOMContentLoaded", () => {
     document.getElementById("loginFrame").addEventListener("load", (evt) => {
       resolve();
     });
   });
 });
 
@@ -35,20 +33,20 @@ add_task(async function setup() {
     set: [
       ["signon.formlessCapture.enabled", true],
     ],
   });
 
   info("Waiting for page and frame loads");
   await loadPromise;
 
-  chromeScript.addMessageListener("formSubmissionProcessed", submissionProcessed);
+  PWMGR_COMMON_PARENT.addMessageListener("formSubmissionProcessed", submissionProcessed);
 
   SimpleTest.registerCleanupFunction(() => {
-    chromeScript.removeMessageListener("formSubmissionProcessed", submissionProcessed);
+    PWMGR_COMMON_PARENT.removeMessageListener("formSubmissionProcessed", submissionProcessed);
   });
 });
 
 const DEFAULT_ORIGIN = "http://test1.mochi.test:8888";
 const SCRIPTS = {
   PUSHSTATE: `history.pushState({}, "Pushed state", "?pushed");`,
   WINDOW_LOCATION: `window.location = "data:text/html;charset=utf-8,window.location";`,
   WINDOW_LOCATION_RELOAD: `window.location.reload();`,
--- a/toolkit/components/passwordmgr/test/mochitest/test_master_password.html
+++ b/toolkit/components/passwordmgr/test/mochitest/test_master_password.html
@@ -70,17 +70,17 @@ add_task(async function test_1() {
     checkHidden: true,
     checkMsg: "",
     checked: false,
     focused: "passField",
     defButton: "button0",
   };
   var action = {
     buttonClick: "ok",
-    passField: masterPassword,
+    passField: MASTER_PASSWORD,
   };
   var promptDone = handlePrompt(state, action);
 
   var logins = LoginManager.getAllLogins();
 
   await promptDone;
   is(logins.length, 3, "expected number of logins");
 
@@ -137,17 +137,17 @@ add_task(async function test_3() {
     checkHidden: true,
     checkMsg: "",
     checked: false,
     focused: "passField",
     defButton: "button0",
   };
   var action = {
     buttonClick: "ok",
-    passField: masterPassword,
+    passField: MASTER_PASSWORD,
   };
   var promptDone = handlePrompt(state, action);
 
   var fillPromise = promiseFormsProcessed();
 
   info("Load a single iframe to trigger a MP");
   iframe1.src = exampleCom + "subtst_master_pass.html";
 
@@ -242,17 +242,17 @@ add_task(async function test_4() {
 
   // Ok, now enter the MP. The MP prompt is already up.
 
   var fillPromise = promiseFormsProcessed(2);
 
   // fill existing MP dialog with MP.
   action = {
     buttonClick: "ok",
-    passField: masterPassword,
+    passField: MASTER_PASSWORD,
   };
   await handlePrompt(state, action);
   await fillPromise;
 
   // We shouldn't have to worry about iframe1's load event racing with
   // filling of iframe2's data. We notify observers synchronously, so
   // iframe2's observer will process iframe2 before iframe1 even finishes
   // processing the form.
--- a/toolkit/components/passwordmgr/test/mochitest/test_prompt_http.html
+++ b/toolkit/components/passwordmgr/test/mochitest/test_prompt_http.html
@@ -20,20 +20,17 @@
 <script class="testbody" type="text/javascript">
 var iframe = document.getElementById("iframe");
 
 // Force parent to not look for tab-modal prompts, as they're not used for auth prompts.
 isTabModal = false;
 
 const AUTHENTICATE_PATH = new URL("authenticate.sjs", window.location.href).pathname;
 
-let chromeScript = runInParent(SimpleTest.getTestFileURL("pwmgr_common.js"));
-
 runInParent(() => {
-  // eslint-disable-next-line no-shadow
   const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 
   let login3A, login3B, login4;
   login3A = Cc["@mozilla.org/login-manager/loginInfo;1"].
             createInstance(Ci.nsILoginInfo);
   login3B = Cc["@mozilla.org/login-manager/loginInfo;1"].
             createInstance(Ci.nsILoginInfo);
   login4  = Cc["@mozilla.org/login-manager/loginInfo;1"].
--- a/toolkit/components/passwordmgr/test/mochitest/test_prompt_noWindow.html
+++ b/toolkit/components/passwordmgr/test/mochitest/test_prompt_noWindow.html
@@ -16,18 +16,16 @@
 </div>
 
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 // Force parent to not look for tab-modal prompts, as they're not used for auth prompts.
 isTabModal = false;
 
-let chromeScript = runInParent(SimpleTest.getTestFileURL("pwmgr_common.js"));
-
 runInParent(() => {
   const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
 
   let login = Cc["@mozilla.org/login-manager/loginInfo;1"].
               createInstance(Ci.nsILoginInfo);
   login.init("http://mochi.test:8888", null, "mochitest",
              "mochiuser1", "mochipass1", "", "");
   Services.logins.addLogin(login);
--- a/toolkit/components/passwordmgr/test/mochitest/test_prompt_promptAuth.html
+++ b/toolkit/components/passwordmgr/test/mochitest/test_prompt_promptAuth.html
@@ -29,18 +29,16 @@ var authinfo = {
   flags: Ci.nsIAuthInformation.AUTH_HOST,
   authenticationScheme: "basic",
   realm: "",
 };
 
 // Force parent to not look for tab-modal prompts, as they're not used for auth prompts.
 isTabModal = false;
 
-let chromeScript = runInParent(SimpleTest.getTestFileURL("pwmgr_common.js"));
-
 let prompterParent = runInParent(() => {
   const promptFac = Cc["@mozilla.org/passwordmanager/authpromptfactory;1"].
                     getService(Ci.nsIPromptFactory);
 
   const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
   let chromeWin = Services.wm.getMostRecentWindow("navigator:browser");
   let prompter2 = promptFac.getPrompt(chromeWin, Ci.nsIAuthPrompt2);
 
--- a/toolkit/components/passwordmgr/test/mochitest/test_username_focus.html
+++ b/toolkit/components/passwordmgr/test/mochitest/test_username_focus.html
@@ -8,18 +8,16 @@
   <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/AddTask.js"></script>
   <script type="text/javascript" src="satchel_common.js"></script>
   <script type="text/javascript" src="pwmgr_common.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <script>
-let pwmgrCommonScript = runInParent(SimpleTest.getTestFileURL("pwmgr_common.js"));
-
 let readyPromise = registerRunTests();
 let chromeScript = runInParent(function chromeSetup() {
   const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
   let login1A  = Cc["@mozilla.org/login-manager/loginInfo;1"].
                  createInstance(Ci.nsILoginInfo);
   let login1B  = Cc["@mozilla.org/login-manager/loginInfo;1"].
                  createInstance(Ci.nsILoginInfo);
   let login2A  = Cc["@mozilla.org/login-manager/loginInfo;1"].