summaryrefslogtreecommitdiffstats
path: root/toolkit/components/passwordmgr/test/browser/browser_context_menu.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/passwordmgr/test/browser/browser_context_menu.js')
-rw-r--r--toolkit/components/passwordmgr/test/browser/browser_context_menu.js432
1 files changed, 0 insertions, 432 deletions
diff --git a/toolkit/components/passwordmgr/test/browser/browser_context_menu.js b/toolkit/components/passwordmgr/test/browser/browser_context_menu.js
deleted file mode 100644
index 6cfcaa7c2..000000000
--- a/toolkit/components/passwordmgr/test/browser/browser_context_menu.js
+++ /dev/null
@@ -1,432 +0,0 @@
-/*
- * Test the password manager context menu.
- */
-
-/* eslint no-shadow:"off" */
-
-"use strict";
-
-// The hostname for the test URIs.
-const TEST_HOSTNAME = "https://example.com";
-const MULTIPLE_FORMS_PAGE_PATH = "/browser/toolkit/components/passwordmgr/test/browser/multiple_forms.html";
-
-const CONTEXT_MENU = document.getElementById("contentAreaContextMenu");
-const POPUP_HEADER = document.getElementById("fill-login");
-
-/**
- * Initialize logins needed for the tests and disable autofill
- * for login forms for easier testing of manual fill.
- */
-add_task(function* test_initialize() {
- Services.prefs.setBoolPref("signon.autofillForms", false);
- registerCleanupFunction(() => {
- Services.prefs.clearUserPref("signon.autofillForms");
- Services.prefs.clearUserPref("signon.schemeUpgrades");
- });
- for (let login of loginList()) {
- Services.logins.addLogin(login);
- }
-});
-
-/**
- * Check if the context menu is populated with the right
- * menuitems for the target password input field.
- */
-add_task(function* test_context_menu_populate_password_noSchemeUpgrades() {
- Services.prefs.setBoolPref("signon.schemeUpgrades", false);
- yield BrowserTestUtils.withNewTab({
- gBrowser,
- url: TEST_HOSTNAME + MULTIPLE_FORMS_PAGE_PATH,
- }, function* (browser) {
- yield openPasswordContextMenu(browser, "#test-password-1");
-
- // Check the content of the password manager popup
- let popupMenu = document.getElementById("fill-login-popup");
- checkMenu(popupMenu, 2);
-
- CONTEXT_MENU.hidePopup();
- });
-});
-
-/**
- * Check if the context menu is populated with the right
- * menuitems for the target password input field.
- */
-add_task(function* test_context_menu_populate_password_schemeUpgrades() {
- Services.prefs.setBoolPref("signon.schemeUpgrades", true);
- yield BrowserTestUtils.withNewTab({
- gBrowser,
- url: TEST_HOSTNAME + MULTIPLE_FORMS_PAGE_PATH,
- }, function* (browser) {
- yield openPasswordContextMenu(browser, "#test-password-1");
-
- // Check the content of the password manager popup
- let popupMenu = document.getElementById("fill-login-popup");
- checkMenu(popupMenu, 3);
-
- CONTEXT_MENU.hidePopup();
- });
-});
-
-/**
- * Check if the context menu is populated with the right menuitems
- * for the target username field with a password field present.
- */
-add_task(function* test_context_menu_populate_username_with_password_noSchemeUpgrades() {
- Services.prefs.setBoolPref("signon.schemeUpgrades", false);
- yield BrowserTestUtils.withNewTab({
- gBrowser,
- url: TEST_HOSTNAME + "/browser/toolkit/components/" +
- "passwordmgr/test/browser/multiple_forms.html",
- }, function* (browser) {
- yield openPasswordContextMenu(browser, "#test-username-2");
-
- // Check the content of the password manager popup
- let popupMenu = document.getElementById("fill-login-popup");
- checkMenu(popupMenu, 2);
-
- CONTEXT_MENU.hidePopup();
- });
-});
-/**
- * Check if the context menu is populated with the right menuitems
- * for the target username field with a password field present.
- */
-add_task(function* test_context_menu_populate_username_with_password_schemeUpgrades() {
- Services.prefs.setBoolPref("signon.schemeUpgrades", true);
- yield BrowserTestUtils.withNewTab({
- gBrowser,
- url: TEST_HOSTNAME + "/browser/toolkit/components/" +
- "passwordmgr/test/browser/multiple_forms.html",
- }, function* (browser) {
- yield openPasswordContextMenu(browser, "#test-username-2");
-
- // Check the content of the password manager popup
- let popupMenu = document.getElementById("fill-login-popup");
- checkMenu(popupMenu, 3);
-
- CONTEXT_MENU.hidePopup();
- });
-});
-
-/**
- * Check if the password field is correctly filled when one
- * login menuitem is clicked.
- */
-add_task(function* test_context_menu_password_fill() {
- Services.prefs.setBoolPref("signon.schemeUpgrades", true);
- yield BrowserTestUtils.withNewTab({
- gBrowser,
- url: TEST_HOSTNAME + MULTIPLE_FORMS_PAGE_PATH,
- }, function* (browser) {
- let formDescriptions = yield ContentTask.spawn(browser, {}, function*() {
- let forms = Array.from(content.document.getElementsByClassName("test-form"));
- return forms.map((f) => f.getAttribute("description"));
- });
-
- for (let description of formDescriptions) {
- info("Testing form: " + description);
-
- let passwordInputIds = yield ContentTask.spawn(browser, {description}, function*({description}) {
- let formElement = content.document.querySelector(`[description="${description}"]`);
- let passwords = Array.from(formElement.querySelectorAll("input[type='password']"));
- return passwords.map((p) => p.id);
- });
-
- for (let inputId of passwordInputIds) {
- info("Testing password field: " + inputId);
-
- // Synthesize a right mouse click over the username input element.
- yield openPasswordContextMenu(browser, "#" + inputId, function*() {
- let inputDisabled = yield ContentTask
- .spawn(browser, {inputId}, function*({inputId}) {
- let input = content.document.getElementById(inputId);
- return input.disabled || input.readOnly;
- });
-
- // If the password field is disabled or read-only, we want to see
- // the disabled Fill Password popup header.
- if (inputDisabled) {
- Assert.ok(!POPUP_HEADER.hidden, "Popup menu is not hidden.");
- Assert.ok(POPUP_HEADER.disabled, "Popup menu is disabled.");
- CONTEXT_MENU.hidePopup();
- }
-
- return !inputDisabled;
- });
-
- if (CONTEXT_MENU.state != "open") {
- continue;
- }
-
- // The only field affected by the password fill
- // should be the target password field itself.
- yield assertContextMenuFill(browser, description, null, inputId, 1);
- yield ContentTask.spawn(browser, {inputId}, function*({inputId}) {
- let passwordField = content.document.getElementById(inputId);
- Assert.equal(passwordField.value, "password1", "Check upgraded login was actually used");
- });
-
- CONTEXT_MENU.hidePopup();
- }
- }
- });
-});
-
-/**
- * Check if the form is correctly filled when one
- * username context menu login menuitem is clicked.
- */
-add_task(function* test_context_menu_username_login_fill() {
- Services.prefs.setBoolPref("signon.schemeUpgrades", true);
- yield BrowserTestUtils.withNewTab({
- gBrowser,
- url: TEST_HOSTNAME + MULTIPLE_FORMS_PAGE_PATH,
- }, function* (browser) {
-
- let formDescriptions = yield ContentTask.spawn(browser, {}, function*() {
- let forms = Array.from(content.document.getElementsByClassName("test-form"));
- return forms.map((f) => f.getAttribute("description"));
- });
-
- for (let description of formDescriptions) {
- info("Testing form: " + description);
- let usernameInputIds = yield ContentTask
- .spawn(browser, {description}, function*({description}) {
- let formElement = content.document.querySelector(`[description="${description}"]`);
- let inputs = Array.from(formElement.querySelectorAll("input[type='text']"));
- return inputs.map((p) => p.id);
- });
-
- for (let inputId of usernameInputIds) {
- info("Testing username field: " + inputId);
-
- // Synthesize a right mouse click over the username input element.
- yield openPasswordContextMenu(browser, "#" + inputId, function*() {
- let headerHidden = POPUP_HEADER.hidden;
- let headerDisabled = POPUP_HEADER.disabled;
-
- let data = {description, inputId, headerHidden, headerDisabled};
- let shouldContinue = yield ContentTask.spawn(browser, data, function*(data) {
- let {description, inputId, headerHidden, headerDisabled} = data;
- let formElement = content.document.querySelector(`[description="${description}"]`);
- let usernameField = content.document.getElementById(inputId);
- // We always want to check if the first password field is filled,
- // since this is the current behavior from the _fillForm function.
- let passwordField = formElement.querySelector("input[type='password']");
-
- // If we don't want to see the actual popup menu,
- // check if the popup is hidden or disabled.
- if (!passwordField || usernameField.disabled || usernameField.readOnly ||
- passwordField.disabled || passwordField.readOnly) {
- if (!passwordField) {
- Assert.ok(headerHidden, "Popup menu is hidden.");
- } else {
- Assert.ok(!headerHidden, "Popup menu is not hidden.");
- Assert.ok(headerDisabled, "Popup menu is disabled.");
- }
- return false;
- }
- return true;
- });
-
- if (!shouldContinue) {
- CONTEXT_MENU.hidePopup();
- }
-
- return shouldContinue;
- });
-
- if (CONTEXT_MENU.state != "open") {
- continue;
- }
-
- let passwordFieldId = yield ContentTask
- .spawn(browser, {description}, function*({description}) {
- let formElement = content.document.querySelector(`[description="${description}"]`);
- return formElement.querySelector("input[type='password']").id;
- });
-
- // We shouldn't change any field that's not the target username field or the first password field
- yield assertContextMenuFill(browser, description, inputId, passwordFieldId, 1);
-
- yield ContentTask.spawn(browser, {passwordFieldId}, function*({passwordFieldId}) {
- let passwordField = content.document.getElementById(passwordFieldId);
- if (!passwordField.hasAttribute("expectedFail")) {
- Assert.equal(passwordField.value, "password1", "Check upgraded login was actually used");
- }
- });
-
- CONTEXT_MENU.hidePopup();
- }
- }
- });
-});
-
-/**
- * Synthesize mouse clicks to open the password manager context menu popup
- * for a target password input element.
- *
- * assertCallback should return true if we should continue or else false.
- */
-function* openPasswordContextMenu(browser, passwordInput, assertCallback = null) {
- // Synthesize a right mouse click over the password input element.
- let contextMenuShownPromise = BrowserTestUtils.waitForEvent(CONTEXT_MENU, "popupshown");
- let eventDetails = {type: "contextmenu", button: 2};
- BrowserTestUtils.synthesizeMouseAtCenter(passwordInput, eventDetails, browser);
- yield contextMenuShownPromise;
-
- if (assertCallback) {
- let shouldContinue = yield assertCallback();
- if (!shouldContinue) {
- return;
- }
- }
-
- // Synthesize a mouse click over the fill login menu header.
- let popupShownPromise = BrowserTestUtils.waitForEvent(POPUP_HEADER, "popupshown");
- EventUtils.synthesizeMouseAtCenter(POPUP_HEADER, {});
- yield popupShownPromise;
-}
-
-/**
- * Verify that only the expected form fields are filled.
- */
-function* assertContextMenuFill(browser, formId, usernameFieldId, passwordFieldId, loginIndex) {
- let popupMenu = document.getElementById("fill-login-popup");
- let unchangedSelector = `[description="${formId}"] input:not(#${passwordFieldId})`;
-
- if (usernameFieldId) {
- unchangedSelector += `:not(#${usernameFieldId})`;
- }
-
- yield ContentTask.spawn(browser, {unchangedSelector}, function*({unchangedSelector}) {
- let unchangedFields = content.document.querySelectorAll(unchangedSelector);
-
- // Store the value of fields that should remain unchanged.
- if (unchangedFields.length) {
- for (let field of unchangedFields) {
- field.setAttribute("original-value", field.value);
- }
- }
- });
-
- // Execute the default command of the specified login menuitem found in the context menu.
- let loginItem = popupMenu.getElementsByClassName("context-login-item")[loginIndex];
-
- // Find the used login by it's username (Use only unique usernames in this test).
- let {username, password} = getLoginFromUsername(loginItem.label);
-
- let data = {username, password, usernameFieldId, passwordFieldId, formId, unchangedSelector};
- let continuePromise = ContentTask.spawn(browser, data, function*(data) {
- let {username, password, usernameFieldId, passwordFieldId, formId, unchangedSelector} = data;
- let form = content.document.querySelector(`[description="${formId}"]`);
- yield ContentTaskUtils.waitForEvent(form, "input", "Username input value changed");
-
- if (usernameFieldId) {
- let usernameField = content.document.getElementById(usernameFieldId);
-
- // If we have an username field, check if it's correctly filled
- if (usernameField.getAttribute("expectedFail") == null) {
- Assert.equal(username, usernameField.value, "Username filled and correct.");
- }
- }
-
- if (passwordFieldId) {
- let passwordField = content.document.getElementById(passwordFieldId);
-
- // If we have a password field, check if it's correctly filled
- if (passwordField && passwordField.getAttribute("expectedFail") == null) {
- Assert.equal(password, passwordField.value, "Password filled and correct.");
- }
- }
-
- let unchangedFields = content.document.querySelectorAll(unchangedSelector);
-
- // Check that all fields that should not change have the same value as before.
- if (unchangedFields.length) {
- Assert.ok(() => {
- for (let field of unchangedFields) {
- if (field.value != field.getAttribute("original-value")) {
- return false;
- }
- }
- return true;
- }, "Other fields were not changed.");
- }
- });
-
- loginItem.doCommand();
-
- return continuePromise;
-}
-
-/**
- * Check if every login that matches the page hostname are available at the context menu.
- * @param {Element} contextMenu
- * @param {Number} expectedCount - Number of logins expected in the context menu. Used to ensure
-* we continue testing something useful.
- */
-function checkMenu(contextMenu, expectedCount) {
- let logins = loginList().filter(login => {
- return LoginHelper.isOriginMatching(login.hostname, TEST_HOSTNAME, {
- schemeUpgrades: Services.prefs.getBoolPref("signon.schemeUpgrades"),
- });
- });
- // Make an array of menuitems for easier comparison.
- let menuitems = [...CONTEXT_MENU.getElementsByClassName("context-login-item")];
- Assert.equal(menuitems.length, expectedCount, "Expected number of menu items");
- Assert.ok(logins.every(l => menuitems.some(m => l.username == m.label)), "Every login have an item at the menu.");
-}
-
-/**
- * Search for a login by it's username.
- *
- * Only unique login/hostname combinations should be used at this test.
- */
-function getLoginFromUsername(username) {
- return loginList().find(login => login.username == username);
-}
-
-/**
- * List of logins used for the test.
- *
- * We should only use unique usernames in this test,
- * because we need to search logins by username. There is one duplicate u+p combo
- * in order to test de-duping in the menu.
- */
-function loginList() {
- return [
- LoginTestUtils.testData.formLogin({
- hostname: "https://example.com",
- formSubmitURL: "https://example.com",
- username: "username",
- password: "password",
- }),
- // Same as above but HTTP in order to test de-duping.
- LoginTestUtils.testData.formLogin({
- hostname: "http://example.com",
- formSubmitURL: "http://example.com",
- username: "username",
- password: "password",
- }),
- LoginTestUtils.testData.formLogin({
- hostname: "http://example.com",
- formSubmitURL: "http://example.com",
- username: "username1",
- password: "password1",
- }),
- LoginTestUtils.testData.formLogin({
- hostname: "https://example.com",
- formSubmitURL: "https://example.com",
- username: "username2",
- password: "password2",
- }),
- LoginTestUtils.testData.formLogin({
- hostname: "http://example.org",
- formSubmitURL: "http://example.org",
- username: "username-cross-origin",
- password: "password-cross-origin",
- }),
- ];
-}