summaryrefslogtreecommitdiffstats
path: root/toolkit/components/passwordmgr/test/pwmgr_common.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/passwordmgr/test/pwmgr_common.js')
-rw-r--r--toolkit/components/passwordmgr/test/pwmgr_common.js509
1 files changed, 0 insertions, 509 deletions
diff --git a/toolkit/components/passwordmgr/test/pwmgr_common.js b/toolkit/components/passwordmgr/test/pwmgr_common.js
deleted file mode 100644
index fa7c4fd85..000000000
--- a/toolkit/components/passwordmgr/test/pwmgr_common.js
+++ /dev/null
@@ -1,509 +0,0 @@
-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) {
- 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;
-
- 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);
-
-
- 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);
- }
-}
-
-/**
- * Mochitest gives us a sendKey(), but it's targeted to a specific element.
- * This basically sends an untargeted key event, to whatever's focused.
- */
-function doKey(aKey, modifier) {
- var keyName = "DOM_VK_" + aKey.toUpperCase();
- var key = KeyEvent[keyName];
-
- // undefined --> null
- if (!modifier)
- modifier = null;
-
- // Window utils for sending fake sey events.
- var wutils = SpecialPowers.wrap(window).
- QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor).
- getInterface(SpecialPowers.Ci.nsIDOMWindowUtils);
-
- if (wutils.sendKeyEvent("keydown", key, 0, modifier)) {
- wutils.sendKeyEvent("keypress", key, 0, modifier);
- }
- wutils.sendKeyEvent("keyup", key, 0, modifier);
-}
-
-/**
- * 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) {
- 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');
- 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.QueryInterface(SpecialPowers.Ci.nsIDOMNode);
- 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", false);
-
- document.body.appendChild(form);
- });
- });
-}
-
-const masterPassword = "omgsecret!";
-
-function enableMasterPassword() {
- setMasterPassword(true);
-}
-
-function disableMasterPassword() {
- setMasterPassword(false);
-}
-
-function setMasterPassword(enable) {
- var oldPW, newPW;
- if (enable) {
- oldPW = "";
- newPW = masterPassword;
- } else {
- oldPW = masterPassword;
- newPW = "";
- }
- // Set master password. Note that this does not log you in, so the next
- // invocation of pwmgr can trigger a MP prompt.
-
- var pk11db = Cc["@mozilla.org/security/pk11tokendb;1"].getService(Ci.nsIPK11TokenDB);
- var token = pk11db.findTokenByName("");
- info("MP change from " + oldPW + " to " + newPW);
- token.changePassword(oldPW, newPW);
-}
-
-function logoutMasterPassword() {
- 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() {
- 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", false);
- });
-}
-
-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;
-}
-
-// Code to run when loaded as a chrome script in tests via loadChromeScript
-if (this.addMessageListener) {
- const { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
- 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 = () => {}; // eslint-disable-line no-native-reassign
-
- Cu.import("resource://gre/modules/LoginHelper.jsm");
- Cu.import("resource://gre/modules/LoginManagerParent.jsm");
- Cu.import("resource://gre/modules/Services.jsm");
- Cu.import("resource://gre/modules/Task.jsm");
-
- function onStorageChanged(subject, topic, data) {
- sendAsyncMessage("storageChanged", {
- topic,
- data,
- });
- }
- Services.obs.addObserver(onStorageChanged, "passwordmgr-storage-changed", false);
-
- function onPrompt(subject, topic, data) {
- sendAsyncMessage("promptShown", {
- topic,
- data,
- });
- }
- Services.obs.addObserver(onPrompt, "passwordmgr-prompt-change", false);
- Services.obs.addObserver(onPrompt, "passwordmgr-prompt-save", false);
-
- addMessageListener("setupParent", ({selfFilling = false} = {selfFilling: false}) => {
- // Force LoginManagerParent to init for the tests since it's normally delayed
- // by apps such as on Android.
- LoginManagerParent.init();
-
- commonInit(selfFilling);
- sendAsyncMessage("doneSetup");
- });
-
- addMessageListener("loadRecipes", Task.async(function*(recipes) {
- var recipeParent = yield LoginManagerParent.recipeParentPromise;
- yield recipeParent.load(recipes);
- sendAsyncMessage("loadedRecipes", recipes);
- }));
-
- addMessageListener("resetRecipes", Task.async(function*() {
- let recipeParent = yield LoginManagerParent.recipeParentPromise;
- yield 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);
- }
-
- return arg;
- });
-
- let rv = Services.logins[msg.methodName](...recreatedArgs);
- if (rv instanceof Ci.nsILoginInfo) {
- rv = LoginHelper.loginToVanillaObject(rv);
- }
- return rv;
- });
-
- var globalMM = Cc["@mozilla.org/globalmessagemanager;1"].getService(Ci.nsIMessageListenerManager);
- globalMM.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).
- SpecialPowers.pushPrefEnv({"set": [["signon.autofillForms.http", true],
- ["security.insecure_field_warning.contextual.enabled", false]]
- });
-
- SimpleTest.registerCleanupFunction(() => {
- SpecialPowers.popPrefEnv();
- runInParent(function cleanupParent() {
- const { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
- Cu.import("resource://gre/modules/Services.jsm");
- Cu.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");
- }
- for (let note of notes) {
- note.remove();
- }
- }
- });
- });
-
-
- 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 chromeScript.sendSyncMessage("proxyLoginManager", {
- args: cloneableArgs,
- loginInfoIndices,
- methodName: prop,
- })[0][0];
- };
- },
- });
-}