/* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ /** * First Test * Checks if buttons are disabled/enabled and visible/hidden correctly. */ add_task(async function testButtons() { // Let's make sure HTTPS-Only Mode is off. await setHttpsOnlyPref("off"); // Open the privacy-pane in about:preferences await openPreferencesViaOpenPreferencesAPI("panePrivacy", { leaveOpen: true, }); // Get button-element to open the exceptions-dialog const exceptionButton = gBrowser.contentDocument.getElementById( "httpsOnlyExceptionButton" ); is( exceptionButton.disabled, true, "HTTPS-Only exception button should be disabled when HTTPS-Only Mode is disabled." ); await setHttpsOnlyPref("private"); is( exceptionButton.disabled, true, "HTTPS-Only exception button should be disabled when HTTPS-Only Mode is only enabled in private browsing." ); await setHttpsOnlyPref("everywhere"); is( exceptionButton.disabled, false, "HTTPS-Only exception button should be enabled when HTTPS-Only Mode enabled everywhere." ); // Now that the button is clickable, we open the dialog // to check if the correct buttons are visible let promiseSubDialogLoaded = promiseLoadSubDialog( "chrome://browser/content/preferences/dialogs/permissions.xhtml" ); exceptionButton.doCommand(); let win = await promiseSubDialogLoaded; const dialogDoc = win.document; is( dialogDoc.getElementById("btnBlock").hidden, true, "Block button should not be visible in HTTPS-Only Dialog." ); is( dialogDoc.getElementById("btnCookieSession").hidden, true, "Cookie specific allow button should not be visible in HTTPS-Only Dialog." ); is( dialogDoc.getElementById("btnAllow").hidden, true, "Allow button should not be visible in HTTPS-Only Dialog." ); is( dialogDoc.getElementById("btnHttpsOnlyOff").hidden, false, "HTTPS-Only off button should be visible in HTTPS-Only Dialog." ); is( dialogDoc.getElementById("btnHttpsOnlyOffTmp").hidden, false, "HTTPS-Only temporary off button should be visible in HTTPS-Only Dialog." ); // Reset prefs and close the tab await SpecialPowers.flushPrefEnv(); BrowserTestUtils.removeTab(gBrowser.selectedTab); }); /** * Second Test * Checks permissions are added and removed correctly. * * Each test opens a new dialog, performs an action (second argument), * then closes the dialog and checks if the changes were made (third argument). */ add_task(async function checkDialogFunctionality() { // Enable HTTPS-Only Mode for every window, so the exceptions dialog is accessible. await setHttpsOnlyPref("everywhere"); // Open the privacy-pane in about:preferences await openPreferencesViaOpenPreferencesAPI("panePrivacy", { leaveOpen: true, }); const preferencesDoc = gBrowser.contentDocument; // Test if we can add permanent exceptions await runTest( preferencesDoc, elements => { assertListContents(elements, []); elements.url.value = "test.com"; elements.btnAllow.doCommand(); assertListContents(elements, [ ["http://test.com", elements.allowL10nId], ["https://test.com", elements.allowL10nId], ]); }, () => [ { type: "https-only-load-insecure", origin: "http://test.com", data: "added", capability: Ci.nsIPermissionManager.ALLOW_ACTION, expireType: Ci.nsIPermissionManager.EXPIRE_NEVER, }, { type: "https-only-load-insecure", origin: "https://test.com", data: "added", capability: Ci.nsIPermissionManager.ALLOW_ACTION, expireType: Ci.nsIPermissionManager.EXPIRE_NEVER, }, ] ); // Test if items are retained, and if temporary exceptions are added correctly await runTest( preferencesDoc, elements => { assertListContents(elements, [ ["http://test.com", elements.allowL10nId], ["https://test.com", elements.allowL10nId], ]); elements.url.value = "1.1.1.1:8080"; elements.btnAllowSession.doCommand(); assertListContents(elements, [ ["http://test.com", elements.allowL10nId], ["https://test.com", elements.allowL10nId], ["http://1.1.1.1:8080", elements.allowSessionL10nId], ["https://1.1.1.1:8080", elements.allowSessionL10nId], ]); }, () => [ { type: "https-only-load-insecure", origin: "http://1.1.1.1:8080", data: "added", capability: Ci.nsIHttpsOnlyModePermission.LOAD_INSECURE_ALLOW_SESSION, expireType: Ci.nsIPermissionManager.EXPIRE_SESSION, }, { type: "https-only-load-insecure", origin: "https://1.1.1.1:8080", data: "added", capability: Ci.nsIHttpsOnlyModePermission.LOAD_INSECURE_ALLOW_SESSION, expireType: Ci.nsIPermissionManager.EXPIRE_SESSION, }, ] ); await runTest( preferencesDoc, elements => { while (elements.richlistbox.itemCount) { elements.richlistbox.selectedIndex = 0; elements.btnRemove.doCommand(); } assertListContents(elements, []); }, elements => { let richlistItems = elements.richlistbox.getElementsByAttribute( "origin", "*" ); let observances = []; for (let item of richlistItems) { observances.push({ type: "https-only-load-insecure", origin: item.getAttribute("origin"), data: "deleted", }); } return observances; } ); BrowserTestUtils.removeTab(gBrowser.selectedTab); }); /** * Changes HTTPS-Only Mode pref * @param {string} state "everywhere", "private", "off" */ async function setHttpsOnlyPref(state) { await SpecialPowers.pushPrefEnv({ set: [ ["dom.security.https_only_mode", state === "everywhere"], ["dom.security.https_only_mode_pbm", state === "private"], ], }); } /** * Opens new exceptions dialog, runs test function * @param {HTMLElement} preferencesDoc document of about:preferences tab * @param {function} test function to call when dialog is open * @param {Array} observances permission changes to observe (order is important) */ async function runTest(preferencesDoc, test, observancesFn) { // Click on exception-button and wait for dialog to open let promiseSubDialogLoaded = promiseLoadSubDialog( "chrome://browser/content/preferences/dialogs/permissions.xhtml" ); preferencesDoc.getElementById("httpsOnlyExceptionButton").doCommand(); let win = await promiseSubDialogLoaded; // Create a bunch of references to UI-elements for the test-function const doc = win.document; let elements = { richlistbox: doc.getElementById("permissionsBox"), url: doc.getElementById("url"), btnAllow: doc.getElementById("btnHttpsOnlyOff"), btnAllowSession: doc.getElementById("btnHttpsOnlyOffTmp"), btnRemove: doc.getElementById("removePermission"), allowL10nId: win.gPermissionManager._getCapabilityL10nId( Ci.nsIPermissionManager.ALLOW_ACTION ), allowSessionL10nId: win.gPermissionManager._getCapabilityL10nId( Ci.nsIHttpsOnlyModePermission.LOAD_INSECURE_ALLOW_SESSION ), }; // Some observances need to be computed based on the current state. const observances = observancesFn(elements); // Run test function await test(elements); // Click on "Save changes" and wait for permission changes. let btnApplyChanges = doc.querySelector("dialog").getButton("accept"); let observeAllPromise = createObserveAllPromise(observances); btnApplyChanges.doCommand(); await observeAllPromise; } function assertListContents(elements, expected) { is( elements.richlistbox.itemCount, expected.length, "Richlistbox should match the expected amount of exceptions." ); for (let i = 0; i < expected.length; i++) { let website = expected[i][0]; let listItem = elements.richlistbox.getElementsByAttribute( "origin", website ); is(listItem.length, 1, "Each origin should be unique"); is( listItem[0] .querySelector(".website-capability-value") .getAttribute("data-l10n-id"), expected[i][1], "List item capability should match expected l10n-id" ); } }