/* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ var unsecureEmptyURL = "http://example.org/browser/toolkit/components/antitracking/test/browser/empty.html"; var secureEmptyURL = "https://example.org/browser/toolkit/components/antitracking/test/browser/empty.html"; var secureAnotherEmptyURL = "https://example.com/browser/toolkit/components/antitracking/test/browser/empty.html"; var secureURL = "https://example.com/browser/toolkit/components/antitracking/test/browser/browser_staticPartition_HSTS.sjs"; var unsecureURL = "http://example.com/browser/toolkit/components/antitracking/test/browser/browser_staticPartition_HSTS.sjs"; var secureImgURL = "https://example.com/browser/toolkit/components/antitracking/test/browser/browser_staticPartition_HSTS.sjs?image"; var unsecureImgURL = "http://example.com/browser/toolkit/components/antitracking/test/browser/browser_staticPartition_HSTS.sjs?image"; 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( Ci.nsISiteSecurityService.HEADER_HSTS, NetUtil.newURI("http://example.com/"), 0, originAttributes ); } } function promiseTabLoadEvent(aTab, aURL, aFinalURL) { info("Wait for load tab event"); BrowserTestUtils.loadURI(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 to activate 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 a unsecure subresource, this should 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, secureImgURL, "HSTS works 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; } ); if (networkIsolation) { is(await finalURL, unsecureImgURL, "HSTS doesn't work for 3rd parties"); } else { is(await finalURL, secureImgURL, "HSTS works for 3rd parties"); } gBrowser.removeCurrentTab(); cleanupHSTS(networkIsolation, partitionPerSite); } } });