572 lines
15 KiB
JavaScript
572 lines
15 KiB
JavaScript
/* Any copyright is dedicated to the Public Domain.
|
|
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
|
|
"use strict";
|
|
|
|
// We explicitly need HTTP URLs in this test
|
|
/* eslint-disable @microsoft/sdl/no-insecure-url */
|
|
|
|
requestLongerTimeout(3);
|
|
|
|
ChromeUtils.defineLazyGetter(this, "UrlbarTestUtils", () => {
|
|
const { UrlbarTestUtils: module } = ChromeUtils.importESModule(
|
|
"resource://testing-common/UrlbarTestUtils.sys.mjs"
|
|
);
|
|
module.init(this);
|
|
return module;
|
|
});
|
|
|
|
const TEST_PATH_HTTP = getRootDirectory(gTestPath).replace(
|
|
"chrome://mochitests/content",
|
|
"http://example.com"
|
|
);
|
|
const TEST_PATH_HTTPS = getRootDirectory(gTestPath).replace(
|
|
"chrome://mochitests/content",
|
|
"https://example.com"
|
|
);
|
|
const TEST_PATH_SCHEMELESS = getRootDirectory(gTestPath).replace(
|
|
"chrome://mochitests/content",
|
|
"example.com"
|
|
);
|
|
|
|
const HSTS_SITE = TEST_PATH_HTTPS + "file_https_telemetry_hsts.sjs";
|
|
|
|
const NO_HTTPS_SUPPORT_SITE = TEST_PATH_HTTP + "file_no_https_support.sjs";
|
|
const NO_HTTPS_SUPPORT_SITE_SCHEMELESS =
|
|
TEST_PATH_SCHEMELESS + "file_no_https_support.sjs";
|
|
|
|
async function setPrefsAndResetFog(
|
|
aHTTPSOnlyPref,
|
|
aHTTPSFirstPref,
|
|
aSchemeLessPref
|
|
) {
|
|
Services.fog.testResetFOG();
|
|
|
|
await SpecialPowers.pushPrefEnv({
|
|
set: [
|
|
["dom.security.https_only_mode", aHTTPSOnlyPref],
|
|
["dom.security.https_first", aHTTPSFirstPref],
|
|
["dom.security.https_first_schemeless", aSchemeLessPref],
|
|
],
|
|
});
|
|
}
|
|
|
|
function verifyGleanValues(aDescription, aExpected) {
|
|
info(aDescription);
|
|
|
|
let notInitialized = aExpected.notInitialized || null;
|
|
let noUpgrade = aExpected.noUpgrade || null;
|
|
let alreadyHTTPS = aExpected.alreadyHTTPS || null;
|
|
let hsts = aExpected.hsts || null;
|
|
let httpsOnlyUpgrade = aExpected.httpsOnlyUpgrade || null;
|
|
let httpsOnlyUpgradeDowngrade = aExpected.httpsOnlyUpgradeDowngrade || null;
|
|
let httpsFirstUpgrade = aExpected.httpsFirstUpgrade || null;
|
|
let httpsFirstUpgradeDowngrade = aExpected.httpsFirstUpgradeDowngrade || null;
|
|
let httpsFirstSchemelessUpgrade =
|
|
aExpected.httpsFirstSchemelessUpgrade || null;
|
|
let httpsFirstSchemelessUpgradeDowngrade =
|
|
aExpected.httpsFirstSchemelessUpgradeDowngrade || null;
|
|
let cspUpgradeInsecureRequests = aExpected.cspUpgradeInsecureRequests || null;
|
|
let httpsRR = aExpected.httpsRR || null;
|
|
let webExtensionUpgrade = aExpected.webExtensionUpgrade || null;
|
|
let upgradeException = aExpected.upgradeException || null;
|
|
|
|
let glean = Glean.networking.httpToHttpsUpgradeReason;
|
|
is(
|
|
glean.not_initialized.testGetValue(),
|
|
notInitialized,
|
|
"verify not_initialized"
|
|
);
|
|
is(glean.no_upgrade.testGetValue(), noUpgrade, "verify no_upgrade");
|
|
is(glean.already_https.testGetValue(), alreadyHTTPS, "verify already_https");
|
|
is(glean.hsts.testGetValue(), hsts, "verify hsts");
|
|
is(
|
|
glean.https_only_upgrade.testGetValue(),
|
|
httpsOnlyUpgrade,
|
|
"verify https_only_upgrade"
|
|
);
|
|
is(
|
|
glean.https_only_upgrade_downgrade.testGetValue(),
|
|
httpsOnlyUpgradeDowngrade,
|
|
"verify https_only_upgrade_downgrade"
|
|
);
|
|
is(
|
|
glean.https_first_upgrade.testGetValue(),
|
|
httpsFirstUpgrade,
|
|
"verify https_first_upgrade"
|
|
);
|
|
is(
|
|
glean.https_first_upgrade_downgrade.testGetValue(),
|
|
httpsFirstUpgradeDowngrade,
|
|
"verify https_first_upgrade_downgrade"
|
|
);
|
|
is(
|
|
glean.https_first_schemeless_upgrade.testGetValue(),
|
|
httpsFirstSchemelessUpgrade,
|
|
"verify https_first_schemeless_upgrade"
|
|
);
|
|
is(
|
|
glean.https_first_schemeless_upgrade_downgrade.testGetValue(),
|
|
httpsFirstSchemelessUpgradeDowngrade,
|
|
"verify https_first_schemeless_upgrade_downgrade"
|
|
);
|
|
is(
|
|
glean.csp_uir.testGetValue(),
|
|
cspUpgradeInsecureRequests,
|
|
"verify csp_uir"
|
|
);
|
|
is(glean.https_rr.testGetValue(), httpsRR, "verify https_rr");
|
|
is(
|
|
glean.web_extension_upgrade.testGetValue(),
|
|
webExtensionUpgrade,
|
|
"verify web_extension_upgrade"
|
|
);
|
|
is(
|
|
glean.upgrade_exception.testGetValue(),
|
|
upgradeException,
|
|
"verify upgrade_exception"
|
|
);
|
|
}
|
|
|
|
async function runUpgradeTest(aURI, aDesc, aAssertURLStartsWith) {
|
|
await BrowserTestUtils.withNewTab("about:blank", async function (browser) {
|
|
const loaded = BrowserTestUtils.browserLoaded(browser, false, null, true);
|
|
BrowserTestUtils.startLoadingURIString(browser, aURI);
|
|
await loaded;
|
|
|
|
await SpecialPowers.spawn(
|
|
browser,
|
|
[aDesc, aAssertURLStartsWith],
|
|
async function (aDesc, aAssertURLStartsWith) {
|
|
ok(
|
|
content.document.location.href.startsWith(aAssertURLStartsWith),
|
|
aDesc
|
|
);
|
|
}
|
|
);
|
|
await SpecialPowers.removePermission("https-only-load-insecure", aURI);
|
|
});
|
|
}
|
|
|
|
async function runSchemelessTest(aURI, aDesc, aAssertURLStartsWith) {
|
|
await BrowserTestUtils.withNewTab("about:blank", async function (browser) {
|
|
const loaded = BrowserTestUtils.browserLoaded(browser, false, null, true);
|
|
await UrlbarTestUtils.promiseAutocompleteResultPopup({
|
|
window,
|
|
value: aURI,
|
|
});
|
|
EventUtils.synthesizeKey("KEY_Enter", { ctrlKey: true });
|
|
await loaded;
|
|
await SpecialPowers.spawn(
|
|
browser,
|
|
[aDesc, aAssertURLStartsWith],
|
|
async function (aDesc, aAssertURLStartsWith) {
|
|
ok(
|
|
content.document.location.href.startsWith(aAssertURLStartsWith),
|
|
aDesc
|
|
);
|
|
}
|
|
);
|
|
// we can't pass a schemeless uri to removePermission
|
|
let uri = "https://" + aURI;
|
|
await SpecialPowers.removePermission("https-only-load-insecure", uri);
|
|
});
|
|
}
|
|
|
|
add_task(async function () {
|
|
info("(0) exempt loopback addresses");
|
|
|
|
await setPrefsAndResetFog(
|
|
false /* aHTTPSOnlyPref */,
|
|
false /* aHTTPSFirstPref */,
|
|
false /* aSchemeLessPref */
|
|
);
|
|
|
|
// the request to localhost will actually fail in our test infra,
|
|
// though the telemetry would be recorded.
|
|
await runUpgradeTest(
|
|
"https://localhost",
|
|
"(0) exempt loopback addresses",
|
|
"https://"
|
|
);
|
|
verifyGleanValues("(0) exempt loopback addresses", {});
|
|
});
|
|
|
|
add_task(async function () {
|
|
info("(1) no upgrade test");
|
|
|
|
await setPrefsAndResetFog(
|
|
false /* aHTTPSOnlyPref */,
|
|
false /* aHTTPSFirstPref */,
|
|
false /* aSchemeLessPref */
|
|
);
|
|
|
|
await runUpgradeTest(
|
|
"http://example.com?test1",
|
|
"(1) no upgrade test",
|
|
"http://"
|
|
);
|
|
verifyGleanValues("(1) no upgrade test", { noUpgrade: 1 });
|
|
});
|
|
|
|
add_task(async function () {
|
|
info("(2) already https test");
|
|
|
|
await setPrefsAndResetFog(
|
|
false /* aHTTPSOnlyPref */,
|
|
false /* aHTTPSFirstPref */,
|
|
false /* aSchemeLessPref */
|
|
);
|
|
|
|
await runUpgradeTest(
|
|
"https://example.com?test2",
|
|
"(2) already https test",
|
|
"https://"
|
|
);
|
|
|
|
verifyGleanValues("(2) already https test", { alreadyHTTPS: 1 });
|
|
});
|
|
|
|
add_task(async function () {
|
|
info("(2b) already https test all prefs true");
|
|
|
|
await setPrefsAndResetFog(
|
|
true /* aHTTPSOnlyPref */,
|
|
true /* aHTTPSFirstPref */,
|
|
true /* aSchemeLessPref */
|
|
);
|
|
|
|
await runUpgradeTest(
|
|
"https://example.com?test2b",
|
|
"(2b) already https test all prefs true",
|
|
"https://"
|
|
);
|
|
|
|
verifyGleanValues("(2b) already https test all prefs true", {
|
|
alreadyHTTPS: 1,
|
|
});
|
|
});
|
|
|
|
add_task(async function () {
|
|
info("(3) hsts");
|
|
|
|
await setPrefsAndResetFog(
|
|
false /* aHTTPSOnlyPref */,
|
|
false /* aHTTPSFirstPref */,
|
|
false /* aSchemeLessPref */
|
|
);
|
|
|
|
// we need to setup hsts first
|
|
await BrowserTestUtils.withNewTab("about:blank", async function (browser) {
|
|
const loaded = BrowserTestUtils.browserLoaded(browser, false, null, true);
|
|
BrowserTestUtils.startLoadingURIString(browser, HSTS_SITE);
|
|
await loaded;
|
|
});
|
|
|
|
// now we reset glean again
|
|
Services.fog.testResetFOG();
|
|
|
|
await runUpgradeTest("http://example.com?test3", "(3) hsts", "https://");
|
|
|
|
verifyGleanValues("(3) hsts", { hsts: 1 });
|
|
|
|
// finally we need to reset hsts
|
|
await BrowserTestUtils.withNewTab("about:blank", async function (browser) {
|
|
const loaded = BrowserTestUtils.browserLoaded(browser, false, null, true);
|
|
BrowserTestUtils.startLoadingURIString(browser, HSTS_SITE + "?reset");
|
|
await loaded;
|
|
});
|
|
|
|
info("(3b) hsts with all prefs true");
|
|
|
|
await setPrefsAndResetFog(
|
|
true /* aHTTPSOnlyPref */,
|
|
true /* aHTTPSFirstPref */,
|
|
true /* aSchemeLessPref */
|
|
);
|
|
|
|
// we need to setup hsts first
|
|
await BrowserTestUtils.withNewTab("about:blank", async function (browser) {
|
|
const loaded = BrowserTestUtils.browserLoaded(browser, false, null, true);
|
|
BrowserTestUtils.startLoadingURIString(browser, HSTS_SITE);
|
|
await loaded;
|
|
});
|
|
|
|
// now we reset glean again
|
|
Services.fog.testResetFOG();
|
|
|
|
await runUpgradeTest(
|
|
"http://example.com?test3b",
|
|
"(3b) hsts with all prefs true",
|
|
"https://"
|
|
);
|
|
|
|
verifyGleanValues("(3b) hsts with all prefs true", { hsts: 1 });
|
|
|
|
// finally we need to reset the hsts host
|
|
await BrowserTestUtils.withNewTab("about:blank", async function (browser) {
|
|
const loaded = BrowserTestUtils.browserLoaded(browser, false, null, true);
|
|
BrowserTestUtils.startLoadingURIString(browser, HSTS_SITE + "?reset");
|
|
await loaded;
|
|
});
|
|
});
|
|
|
|
add_task(async function () {
|
|
info("(4) https-only upgrade");
|
|
|
|
await setPrefsAndResetFog(
|
|
true /* aHTTPSOnlyPref */,
|
|
false /* aHTTPSFirstPref */,
|
|
false /* aSchemeLessPref */
|
|
);
|
|
|
|
await runUpgradeTest(
|
|
"http://example.com?test4",
|
|
"(4) https-only upgrade",
|
|
"https://"
|
|
);
|
|
|
|
verifyGleanValues("(4) https-only upgrade", { httpsOnlyUpgrade: 1 });
|
|
|
|
info("(4b) https-only upgrade downgrade");
|
|
|
|
await setPrefsAndResetFog(
|
|
true /* aHTTPSOnlyPref */,
|
|
false /* aHTTPSFirstPref */,
|
|
false /* aSchemeLessPref */
|
|
);
|
|
|
|
// We specifically want a insecure url here that will fail to upgrade
|
|
let uri = "http://untrusted.example.com:80";
|
|
let desc = "(4b) https-only upgrade downgrade";
|
|
let assertErrorPageStartsWith = "https://";
|
|
let assertDowngradedURLStartsWith = "http://";
|
|
|
|
await BrowserTestUtils.withNewTab("about:blank", async function (browser) {
|
|
const loaded = BrowserTestUtils.waitForErrorPage(browser);
|
|
BrowserTestUtils.startLoadingURIString(browser, uri);
|
|
await loaded;
|
|
|
|
await SpecialPowers.spawn(
|
|
browser,
|
|
[desc, assertErrorPageStartsWith],
|
|
async function (desc, assertErrorPageStartsWith) {
|
|
ok(
|
|
content.document.location.href.startsWith(assertErrorPageStartsWith),
|
|
desc
|
|
);
|
|
}
|
|
);
|
|
|
|
const downGradeLoaded = BrowserTestUtils.browserLoaded(
|
|
browser,
|
|
false,
|
|
null,
|
|
true
|
|
);
|
|
|
|
// click the 'continue to insecure page' button
|
|
await SpecialPowers.spawn(browser, [], async function () {
|
|
let openInsecureButton = content.document.getElementById("openInsecure");
|
|
Assert.notEqual(
|
|
openInsecureButton,
|
|
null,
|
|
"openInsecureButton should exist."
|
|
);
|
|
info("Waiting for openInsecureButton to be enabled.");
|
|
function callback() {
|
|
if (!openInsecureButton.classList.contains("disabled")) {
|
|
observer.disconnect();
|
|
content.requestAnimationFrame(() => {
|
|
content.requestAnimationFrame(() => {
|
|
openInsecureButton.click();
|
|
});
|
|
});
|
|
}
|
|
}
|
|
const observer = new content.MutationObserver(callback);
|
|
observer.observe(openInsecureButton, { attributeFilter: ["class"] });
|
|
callback();
|
|
});
|
|
|
|
await downGradeLoaded;
|
|
|
|
await SpecialPowers.spawn(
|
|
browser,
|
|
[desc, assertDowngradedURLStartsWith],
|
|
async function (desc, assertDowngradedURLStartsWith) {
|
|
ok(
|
|
content.document.location.href.startsWith(
|
|
assertDowngradedURLStartsWith
|
|
),
|
|
desc
|
|
);
|
|
}
|
|
);
|
|
await SpecialPowers.removePermission("https-only-load-insecure", uri);
|
|
});
|
|
|
|
verifyGleanValues("(4b) https-only upgrade downgrade", {
|
|
httpsOnlyUpgrade: 1,
|
|
httpsOnlyUpgradeDowngrade: 1,
|
|
});
|
|
});
|
|
|
|
add_task(async function () {
|
|
info("(5) https-first upgrade");
|
|
|
|
await setPrefsAndResetFog(
|
|
false /* aHTTPSOnlyPref */,
|
|
true /* aHTTPSFirstPref */,
|
|
false /* aSchemeLessPref */
|
|
);
|
|
|
|
await runUpgradeTest(
|
|
"http://example.com?test5",
|
|
"(5) https-first upgrade",
|
|
"https://"
|
|
);
|
|
|
|
verifyGleanValues("(5) https-first upgrade", { httpsFirstUpgrade: 1 });
|
|
|
|
info("(5b) https-first upgrade downgrade");
|
|
|
|
await setPrefsAndResetFog(
|
|
false /* aHTTPSOnlyPref */,
|
|
true /* aHTTPSFirstPref */,
|
|
false /* aSchemeLessPref */
|
|
);
|
|
|
|
await runUpgradeTest(
|
|
NO_HTTPS_SUPPORT_SITE + "?test5b",
|
|
"(5b) https-first upgrade downgrade",
|
|
"http://"
|
|
);
|
|
|
|
verifyGleanValues("(5) https-first upgrade", {
|
|
httpsFirstUpgrade: 1,
|
|
httpsFirstUpgradeDowngrade: 1,
|
|
});
|
|
});
|
|
|
|
add_task(async function () {
|
|
info("(6) schemeless https-first upgrade");
|
|
|
|
await setPrefsAndResetFog(
|
|
false /* aHTTPSOnlyPref */,
|
|
false /* aHTTPSFirstPref */,
|
|
true /* aSchemeLessPref */
|
|
);
|
|
|
|
await runSchemelessTest(
|
|
"example.com?test6",
|
|
"(6) schemeless https-first upgrade",
|
|
"https://"
|
|
);
|
|
|
|
verifyGleanValues("(6) schemeless https-first upgrade", {
|
|
httpsFirstSchemelessUpgrade: 1,
|
|
});
|
|
|
|
info("(6b) schemeless https-first upgrade downgrade");
|
|
|
|
await setPrefsAndResetFog(
|
|
false /* aHTTPSOnlyPref */,
|
|
false /* aHTTPSFirstPref */,
|
|
true /* aSchemeLessPref */
|
|
);
|
|
|
|
await runSchemelessTest(
|
|
NO_HTTPS_SUPPORT_SITE_SCHEMELESS + "?test6b",
|
|
"(6) schemeless https-first upgrade downgrade",
|
|
"http://"
|
|
);
|
|
|
|
verifyGleanValues("(6b) schemeless https-first upgrade downgrade", {
|
|
httpsFirstSchemelessUpgrade: 1,
|
|
httpsFirstSchemelessUpgradeDowngrade: 1,
|
|
});
|
|
});
|
|
|
|
add_task(async function () {
|
|
info("(7) https-rr upgrade");
|
|
|
|
Services.fog.testResetFOG();
|
|
|
|
await SpecialPowers.pushPrefEnv({
|
|
set: [
|
|
["dom.security.https_only_mode", false],
|
|
["dom.security.https_first", false],
|
|
["dom.security.https_first_schemeless", false],
|
|
["network.dns.force_use_https_rr", true],
|
|
["network.dns.mock_HTTPS_RR_domain", "example.org"],
|
|
],
|
|
});
|
|
|
|
await runUpgradeTest(
|
|
"http://example.org",
|
|
"(7) https-rr upgrade",
|
|
"https://"
|
|
);
|
|
|
|
verifyGleanValues("(7) https-rr upgrade", { httpsRR: 1 });
|
|
});
|
|
|
|
add_task(async function () {
|
|
info("(8) upgrade/downgrade/reload");
|
|
// This test performs an upgrade-downgrade and then reloads
|
|
// the document which then triggers an upgrade_exception.
|
|
|
|
await setPrefsAndResetFog(
|
|
false /* aHTTPSOnlyPref */,
|
|
true /* aHTTPSFirstPref */,
|
|
false /* aSchemeLessPref */
|
|
);
|
|
|
|
await BrowserTestUtils.withNewTab("about:blank", async function (browser) {
|
|
// First, perform the upgrade/downgrade
|
|
const upgradeDowngradeLoaded = BrowserTestUtils.browserLoaded(
|
|
browser,
|
|
false,
|
|
null,
|
|
true
|
|
);
|
|
BrowserTestUtils.startLoadingURIString(
|
|
browser,
|
|
NO_HTTPS_SUPPORT_SITE + "?test8"
|
|
);
|
|
await upgradeDowngradeLoaded;
|
|
|
|
await SpecialPowers.spawn(browser, [], async function () {
|
|
ok(
|
|
content.document.location.href.startsWith("http://"),
|
|
"(8) upgrade/downgrade/reload"
|
|
);
|
|
});
|
|
|
|
// Before reloading the doc we have to reset the fog
|
|
Services.fog.testResetFOG();
|
|
|
|
const reloadLoaded = BrowserTestUtils.browserLoaded(
|
|
browser,
|
|
false,
|
|
null,
|
|
true
|
|
);
|
|
|
|
await SpecialPowers.spawn(browser, [], async function () {
|
|
content.location.reload();
|
|
});
|
|
|
|
await reloadLoaded;
|
|
|
|
await SpecialPowers.spawn(browser, [], async function () {
|
|
ok(
|
|
content.document.location.href.startsWith("http://"),
|
|
"(8) upgrade/downgrade/reload"
|
|
);
|
|
});
|
|
});
|
|
|
|
verifyGleanValues("(8) upgrade/downgrade/reload", { upgradeException: 1 });
|
|
});
|