/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ const HTTPS_ONLY_PERMISSION = "https-only-load-insecure"; const WEBSITE = scheme => `${scheme}://example.com`; add_task(async function () { info("Running regular tests"); await runTests(); info("Running tests with view-source: uri"); await runTests({ outerScheme: "view-source" }); }); async function runTests(options = {}) { const { outerScheme = "" } = options; const outerSchemePrefix = outerScheme ? outerScheme + ":" : ""; await SpecialPowers.pushPrefEnv({ set: [["dom.security.https_only_mode", true]], }); // Site is already HTTPS, so the UI should not be visible. await runTest({ name: "No HTTPS-Only UI", initialScheme: outerSchemePrefix + "https", initialPermission: 0, isUiVisible: false, }); // Site gets upgraded to HTTPS, so the UI should be visible. // Adding a HTTPS-Only exemption through the menulist should reload the page and // set the permission accordingly. await runTest({ name: "Add HTTPS-Only exemption", initialScheme: outerSchemePrefix + "http", initialPermission: 0, isUiVisible: true, selectPermission: 1, expectReload: true, finalScheme: outerScheme || "https", }); // HTTPS-Only Mode is disabled for this site, so the UI should be visible. // Switching HTTPS-Only exemption modes through the menulist should not reload the page // but set the permission accordingly. await runTest({ name: "Switch between HTTPS-Only exemption modes", initialScheme: outerSchemePrefix + "http", initialPermission: 1, isUiVisible: true, selectPermission: 2, expectReload: false, finalScheme: outerScheme || "http", }); // HTTPS-Only Mode is disabled for this site, so the UI should be visible. // Disabling HTTPS-Only exemptions through the menulist should reload and upgrade the // page and set the permission accordingly. await runTest({ name: "Remove HTTPS-Only exemption again", initialScheme: outerSchemePrefix + "http", initialPermission: 2, permissionScheme: "http", isUiVisible: true, selectPermission: 0, expectReload: true, finalScheme: outerScheme || "https", }); await SpecialPowers.flushPrefEnv(); await SpecialPowers.pushPrefEnv({ set: [["dom.security.https_first", true]], }); // Site is already HTTPS, so the UI should not be visible. await runTest({ name: "No HTTPS-Only UI", initialScheme: outerSchemePrefix + "https", initialPermission: 0, permissionScheme: "https", isUiVisible: false, }); // Site gets upgraded to HTTPS, so the UI should be visible. // Adding a HTTPS-Only exemption through the menulist should reload the page and // set the permission accordingly. await runTest({ name: "Add HTTPS-Only exemption", initialScheme: outerSchemePrefix + "http", initialPermission: 0, permissionScheme: "https", isUiVisible: true, selectPermission: 1, expectReload: true, finalScheme: outerScheme || "https", }); // HTTPS-First Mode is disabled for this site, so the UI should be visible. // Switching HTTPS-Only exemption modes through the menulist should not reload the page // but set the permission accordingly. await runTest({ name: "Switch between HTTPS-Only exemption modes", initialScheme: outerSchemePrefix + "http", initialPermission: 1, permissionScheme: "http", isUiVisible: true, selectPermission: 2, expectReload: false, finalScheme: outerScheme || "http", }); // HTTPS-First Mode is disabled for this site, so the UI should be visible. // Disabling HTTPS-Only exemptions through the menulist should reload and upgrade the // page and set the permission accordingly. await runTest({ name: "Remove HTTPS-Only exemption again", initialScheme: outerSchemePrefix + "http", initialPermission: 2, isUiVisible: true, selectPermission: 0, expectReload: true, finalScheme: outerScheme || "https", }); } async function runTest(options) { // Set the initial permission setPermission(WEBSITE("http"), options.initialPermission); await BrowserTestUtils.withNewTab( WEBSITE(options.initialScheme), async function (browser) { const name = options.name + " | "; // Open the identity popup. let { gIdentityHandler } = gBrowser.ownerGlobal; let promisePanelOpen = BrowserTestUtils.waitForEvent( gBrowser.ownerGlobal, "popupshown", true, event => event.target == gIdentityHandler._identityPopup ); gIdentityHandler._identityIconBox.click(); await promisePanelOpen; // Check if the HTTPS-Only UI is visible const httpsOnlyUI = document.getElementById( "identity-popup-security-httpsonlymode" ); is( gBrowser.ownerGlobal.getComputedStyle(httpsOnlyUI).display != "none", options.isUiVisible, options.isUiVisible ? name + "HTTPS-Only UI should be visible." : name + "HTTPS-Only UI shouldn't be visible." ); // If it's not visible we can't do much else :) if (!options.isUiVisible) { return; } // Check if the value of the menulist matches the initial permission const httpsOnlyMenulist = document.getElementById( "identity-popup-security-httpsonlymode-menulist" ); is( parseInt(httpsOnlyMenulist.value, 10), options.initialPermission, name + "Menulist value should match expected permission value." ); // Select another HTTPS-Only state and potentially wait for the page to reload if (options.expectReload) { const loaded = BrowserTestUtils.browserLoaded(browser); httpsOnlyMenulist.getItemAtIndex(options.selectPermission).doCommand(); await loaded; } else { httpsOnlyMenulist.getItemAtIndex(options.selectPermission).doCommand(); } // Check if the site has the expected scheme is( browser.currentURI.scheme, options.finalScheme, name + "Unexpected scheme after page reloaded." ); // Check if the permission was sucessfully changed is( getPermission(WEBSITE("http")), options.selectPermission, name + "Set permission should match the one selected from the menulist." ); } ); // Reset permission Services.perms.removeAll(); } function setPermission(url, newValue) { let uri = Services.io.newURI(url); let principal = Services.scriptSecurityManager.createContentPrincipal( uri, {} ); if (newValue === 0) { Services.perms.removeFromPrincipal(principal, HTTPS_ONLY_PERMISSION); } else if (newValue === 1) { Services.perms.addFromPrincipal( principal, HTTPS_ONLY_PERMISSION, Ci.nsIHttpsOnlyModePermission.LOAD_INSECURE_ALLOW, Ci.nsIPermissionManager.EXPIRE_NEVER ); } else { Services.perms.addFromPrincipal( principal, HTTPS_ONLY_PERMISSION, Ci.nsIHttpsOnlyModePermission.LOAD_INSECURE_ALLOW_SESSION, Ci.nsIPermissionManager.EXPIRE_SESSION ); } } function getPermission(url) { let uri = Services.io.newURI(url); let principal = Services.scriptSecurityManager.createContentPrincipal( uri, {} ); const state = Services.perms.testPermissionFromPrincipal( principal, HTTPS_ONLY_PERMISSION ); switch (state) { case Ci.nsIHttpsOnlyModePermission.LOAD_INSECURE_ALLOW_SESSION: return 2; // Off temporarily case Ci.nsIHttpsOnlyModePermission.LOAD_INSECURE_ALLOW: return 1; // Off default: return 0; // On } }