Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

/* Any copyright is dedicated to the Public Domain.
*/
var unsecureEmptyURL =
var secureEmptyURL =
var secureAnotherEmptyURL =
var secureURL =
var unsecureURL =
var secureImgURL =
var unsecureImgURL =
var secureIncludeSubURL =
var unsecureSubEmptyURL =
var secureSubEmptyURL =
var unsecureNoCertSubEmptyURL =
function cleanupHSTS(aPartitionEnabled, aUseSite) {
// Ensure to remove example.com from the HSTS list.
let sss = Cc["@mozilla.org/ssservice;1"].getService(
Ci.nsISiteSecurityService
);
for (let origin of ["example.com", "example.org"]) {
let originAttributes = {};
if (aPartitionEnabled) {
if (aUseSite) {
originAttributes = { partitionKey: `(http,${origin})` };
} else {
originAttributes = { partitionKey: origin };
}
}
sss.resetState(NetUtil.newURI("http://example.com/"), originAttributes);
}
}
function promiseTabLoadEvent(aTab, aURL, aFinalURL) {
info("Wait for load tab event");
BrowserTestUtils.startLoadingURIString(aTab.linkedBrowser, aURL);
return BrowserTestUtils.browserLoaded(aTab.linkedBrowser, false, aFinalURL);
}
function waitFor(host, type) {
return new Promise(resolve => {
const observer = channel => {
if (
channel instanceof Ci.nsIHttpChannel &&
channel.URI.host === host &&
channel.loadInfo.internalContentPolicyType === type
) {
Services.obs.removeObserver(observer, "http-on-stop-request");
resolve(channel.URI.spec);
}
};
Services.obs.addObserver(observer, "http-on-stop-request");
});
}
add_task(async function () {
for (let networkIsolation of [true, false]) {
for (let partitionPerSite of [true, false]) {
await SpecialPowers.pushPrefEnv({
set: [
["privacy.partition.network_state", networkIsolation],
["privacy.dynamic_firstparty.use_site", partitionPerSite],
["security.mixed_content.upgrade_display_content", false],
],
});
let tab = (gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser));
// Let's load the secureURL as first-party in order to activate HSTS.
await promiseTabLoadEvent(tab, secureURL, secureURL);
// Let's test HSTS: unsecure -> secure.
await promiseTabLoadEvent(tab, unsecureURL, secureURL);
ok(true, "unsecure -> secure, first-party works!");
// Let's load a first-party.
await promiseTabLoadEvent(tab, unsecureEmptyURL, unsecureEmptyURL);
let finalURL = waitFor(
"example.com",
Ci.nsIContentPolicy.TYPE_INTERNAL_IFRAME
);
await SpecialPowers.spawn(tab.linkedBrowser, [unsecureURL], async url => {
let ifr = content.document.createElement("iframe");
content.document.body.appendChild(ifr);
ifr.src = url;
});
if (networkIsolation) {
is(await finalURL, unsecureURL, "HSTS doesn't work for 3rd parties");
} else {
is(await finalURL, secureURL, "HSTS works for 3rd parties");
}
gBrowser.removeCurrentTab();
cleanupHSTS(networkIsolation, partitionPerSite);
}
}
});
add_task(async function test_subresource() {
for (let networkIsolation of [true, false]) {
for (let partitionPerSite of [true, false]) {
await SpecialPowers.pushPrefEnv({
set: [
["privacy.partition.network_state", networkIsolation],
["privacy.dynamic_firstparty.use_site", partitionPerSite],
["security.mixed_content.upgrade_display_content", false],
],
});
let tab = (gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser));
// Load a secure page as first party.
await promiseTabLoadEvent(tab, secureEmptyURL, secureEmptyURL);
let loadPromise = waitFor(
"example.com",
Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE
);
// Load a secure subresource. HSTS won't be activated, since third
// parties can't set HSTS.
await SpecialPowers.spawn(
tab.linkedBrowser,
[secureImgURL],
async url => {
let ifr = content.document.createElement("img");
content.document.body.appendChild(ifr);
ifr.src = url;
}
);
// Ensure the subresource is loaded.
await loadPromise;
// Reload the secure page as first party.
await promiseTabLoadEvent(tab, secureEmptyURL, secureEmptyURL);
let finalURL = waitFor(
"example.com",
Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE
);
// Load an unsecure subresource. It should not be upgraded to https.
await SpecialPowers.spawn(
tab.linkedBrowser,
[unsecureImgURL],
async url => {
let ifr = content.document.createElement("img");
content.document.body.appendChild(ifr);
ifr.src = url;
}
);
is(await finalURL, unsecureImgURL, "HSTS isn't set for 3rd parties");
// Load the secure page with a different origin as first party.
await promiseTabLoadEvent(
tab,
secureAnotherEmptyURL,
secureAnotherEmptyURL
);
finalURL = waitFor(
"example.com",
Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE
);
// Load a unsecure subresource
await SpecialPowers.spawn(
tab.linkedBrowser,
[unsecureImgURL],
async url => {
let ifr = content.document.createElement("img");
content.document.body.appendChild(ifr);
ifr.src = url;
}
);
is(await finalURL, unsecureImgURL, "HSTS isn't set for 3rd parties");
gBrowser.removeCurrentTab();
cleanupHSTS(networkIsolation, partitionPerSite);
}
}
});
add_task(async function test_includeSubDomains() {
for (let networkIsolation of [true, false]) {
for (let partitionPerSite of [true, false]) {
await SpecialPowers.pushPrefEnv({
set: [
["privacy.partition.network_state", networkIsolation],
["privacy.dynamic_firstparty.use_site", partitionPerSite],
["security.mixed_content.upgrade_display_content", false],
],
});
let tab = (gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser));
// Load a secure page as first party to activate HSTS.
await promiseTabLoadEvent(tab, secureIncludeSubURL, secureIncludeSubURL);
// Load a unsecure sub-domain page as first party to see if it's upgraded.
await promiseTabLoadEvent(tab, unsecureSubEmptyURL, secureSubEmptyURL);
// Load a sub domain page which will trigger the cert error page.
let certErrorLoaded = BrowserTestUtils.waitForErrorPage(
tab.linkedBrowser
);
BrowserTestUtils.startLoadingURIString(
tab.linkedBrowser,
unsecureNoCertSubEmptyURL
);
await certErrorLoaded;
// Verify the error page has the 'badStsCert' in its query string
await SpecialPowers.spawn(tab.linkedBrowser, [], () => {
let searchParams = new content.URLSearchParams(
content.document.documentURI
);
is(
searchParams.get("s"),
"badStsCert",
"The cert error page has 'badStsCert' set"
);
});
gBrowser.removeCurrentTab();
cleanupHSTS(networkIsolation, partitionPerSite);
}
}
});