зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset 54267d9f3d78 (bug 1701192) for causing mochitest failures on test_hsts_upgrade_intercept.html. CLOSED TREE DONTBUILD
This commit is contained in:
Родитель
0c2f477cee
Коммит
38414bfb41
|
@ -1740,43 +1740,59 @@ static void GetSTSConsoleErrorTag(uint32_t failureResult,
|
|||
}
|
||||
|
||||
/**
|
||||
* Process an HTTP Strict Transport Security (HSTS) header.
|
||||
* Process a single security header. Only one type is supported: HSTS
|
||||
*/
|
||||
nsresult nsHttpChannel::ProcessHSTSHeader(nsITransportSecurityInfo* aSecInfo,
|
||||
uint32_t aFlags) {
|
||||
nsHttpAtom atom(nsHttp::ResolveAtom("Strict-Transport-Security"));
|
||||
nsresult nsHttpChannel::ProcessSingleSecurityHeader(
|
||||
uint32_t aType, nsITransportSecurityInfo* aSecInfo, uint32_t aFlags) {
|
||||
nsHttpAtom atom;
|
||||
switch (aType) {
|
||||
case nsISiteSecurityService::HEADER_HSTS:
|
||||
atom = nsHttp::ResolveAtom("Strict-Transport-Security");
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Invalid security header type");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsAutoCString securityHeader;
|
||||
nsresult rv = mResponseHead->GetHeader(atom, securityHeader);
|
||||
if (rv == NS_ERROR_NOT_AVAILABLE) {
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsISiteSecurityService* sss = gHttpHandler->GetSSService();
|
||||
NS_ENSURE_TRUE(sss, NS_ERROR_OUT_OF_MEMORY);
|
||||
// Process header will now discard the headers itself if the channel
|
||||
// wasn't secure (whereas before it had to be checked manually)
|
||||
OriginAttributes originAttributes;
|
||||
if (NS_WARN_IF(!StoragePrincipalHelper::GetOriginAttributesForHSTS(
|
||||
this, originAttributes))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
uint32_t failureResult;
|
||||
uint32_t headerSource = nsISiteSecurityService::SOURCE_ORGANIC_REQUEST;
|
||||
rv = sss->ProcessHeader(aType, mURI, securityHeader, aSecInfo, aFlags,
|
||||
headerSource, originAttributes, nullptr, nullptr,
|
||||
&failureResult);
|
||||
if (NS_FAILED(rv)) {
|
||||
nsAutoString consoleErrorCategory;
|
||||
nsAutoString consoleErrorTag;
|
||||
switch (aType) {
|
||||
case nsISiteSecurityService::HEADER_HSTS:
|
||||
GetSTSConsoleErrorTag(failureResult, consoleErrorTag);
|
||||
consoleErrorCategory = u"Invalid HSTS Headers"_ns;
|
||||
break;
|
||||
default:
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
Unused << AddSecurityMessage(consoleErrorTag, consoleErrorCategory);
|
||||
LOG(("nsHttpChannel: Failed to parse %s header, continuing load.\n",
|
||||
atom.get()));
|
||||
}
|
||||
} else {
|
||||
if (rv != NS_ERROR_NOT_AVAILABLE) {
|
||||
// All other errors are fatal
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
LOG(("nsHttpChannel: No %s header, continuing load.\n", atom.get()));
|
||||
return NS_OK;
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsISiteSecurityService* sss = gHttpHandler->GetSSService();
|
||||
NS_ENSURE_TRUE(sss, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
OriginAttributes originAttributes;
|
||||
if (NS_WARN_IF(!StoragePrincipalHelper::GetOriginAttributesForHSTS(
|
||||
this, originAttributes))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
uint32_t failureResult;
|
||||
uint32_t headerSource = nsISiteSecurityService::SOURCE_ORGANIC_REQUEST;
|
||||
rv = sss->ProcessHeader(nsISiteSecurityService::HEADER_HSTS, mURI,
|
||||
securityHeader, aSecInfo, aFlags, headerSource,
|
||||
originAttributes, nullptr, nullptr, &failureResult);
|
||||
if (NS_FAILED(rv)) {
|
||||
nsAutoString consoleErrorCategory(u"Invalid HSTS Headers"_ns);
|
||||
nsAutoString consoleErrorTag;
|
||||
GetSTSConsoleErrorTag(failureResult, consoleErrorTag);
|
||||
Unused << AddSecurityMessage(consoleErrorTag, consoleErrorCategory);
|
||||
LOG(("nsHttpChannel: Failed to parse %s header, continuing load.\n",
|
||||
atom.get()));
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1823,12 +1839,9 @@ nsresult nsHttpChannel::ProcessSecurityHeaders() {
|
|||
do_QueryInterface(mSecurityInfo);
|
||||
NS_ENSURE_TRUE(transSecInfo, NS_ERROR_FAILURE);
|
||||
|
||||
// Only process HSTS headers for first-party loads. This prevents a
|
||||
// proliferation of useless HSTS state for partitioned third parties.
|
||||
if (!mLoadInfo->GetIsThirdPartyContextToTopWindow()) {
|
||||
rv = ProcessHSTSHeader(transSecInfo, flags);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
rv = ProcessSingleSecurityHeader(nsISiteSecurityService::HEADER_HSTS,
|
||||
transSecInfo, flags);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -447,12 +447,12 @@ class nsHttpChannel final : public HttpBaseChannel,
|
|||
nsHttpResponseHead* aResponseHead);
|
||||
|
||||
/**
|
||||
* A function to process HTTP Strict Transport Security (HSTS) headers.
|
||||
* Some basic consistency checks have been applied to the channel. Called
|
||||
* A function to process a single security header (STS or PKP), assumes
|
||||
* some basic sanity checks have been applied to the channel. Called
|
||||
* from ProcessSecurityHeaders.
|
||||
*/
|
||||
[[nodiscard]] nsresult ProcessHSTSHeader(nsITransportSecurityInfo* aSecInfo,
|
||||
uint32_t aFlags);
|
||||
[[nodiscard]] nsresult ProcessSingleSecurityHeader(
|
||||
uint32_t aType, nsITransportSecurityInfo* aSecInfo, uint32_t aFlags);
|
||||
|
||||
void InvalidateCacheEntryForLocation(const char* location);
|
||||
void AssembleCacheKey(const char* spec, uint32_t postID, nsACString& key);
|
||||
|
|
|
@ -1,14 +1,9 @@
|
|||
[DEFAULT]
|
||||
tags = psm
|
||||
support-files =
|
||||
*.pem
|
||||
head.js
|
||||
hsts_headers.sjs
|
||||
hsts_headers_framed.html
|
||||
some_content.html
|
||||
some_content_framed.html
|
||||
*.pem
|
||||
|
||||
[browser_HSTS.js]
|
||||
[browser_bug627234_perwindowpb.js]
|
||||
[browser_certificateManager.js]
|
||||
[browser_certViewer.js]
|
||||
|
|
|
@ -1,271 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Tests that HTTP Strict Transport Security (HSTS) headers are noted as appropriate.
|
||||
|
||||
// Register a cleanup function to clear all accumulated HSTS state when this
|
||||
// test is done.
|
||||
add_task(async function register_cleanup() {
|
||||
registerCleanupFunction(() => {
|
||||
let sss = Cc["@mozilla.org/ssservice;1"].getService(
|
||||
Ci.nsISiteSecurityService
|
||||
);
|
||||
sss.clearAll();
|
||||
});
|
||||
});
|
||||
|
||||
// In the absense of HSTS information, no upgrade should happen.
|
||||
add_task(async function test_no_hsts_information_no_upgrade() {
|
||||
let httpUrl =
|
||||
getRootDirectory(gTestPath).replace(
|
||||
"chrome://mochitests/content",
|
||||
"http://example.com"
|
||||
) + "some_content.html";
|
||||
await BrowserTestUtils.openNewForegroundTab(gBrowser, httpUrl);
|
||||
Assert.equal(gBrowser.selectedBrowser.currentURI.scheme, "http");
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
// Visit a secure site that sends an HSTS header to set up the rest of the
|
||||
// test.
|
||||
add_task(async function see_hsts_header() {
|
||||
let setHstsUrl =
|
||||
getRootDirectory(gTestPath).replace(
|
||||
"chrome://mochitests/content",
|
||||
"https://example.com"
|
||||
) + "hsts_headers.sjs";
|
||||
await BrowserTestUtils.openNewForegroundTab(gBrowser, setHstsUrl);
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
// Given a known HSTS host, future http navigations to that domain will be
|
||||
// upgraded.
|
||||
add_task(async function test_http_upgrade() {
|
||||
let httpUrl =
|
||||
getRootDirectory(gTestPath).replace(
|
||||
"chrome://mochitests/content",
|
||||
"http://example.com"
|
||||
) + "some_content.html";
|
||||
await BrowserTestUtils.openNewForegroundTab(gBrowser, httpUrl);
|
||||
Assert.equal(gBrowser.selectedBrowser.currentURI.scheme, "https");
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
// http navigations to unrelated hosts should not be upgraded.
|
||||
add_task(async function test_unrelated_domain_no_upgrade() {
|
||||
let differentHttpUrl =
|
||||
getRootDirectory(gTestPath).replace(
|
||||
"chrome://mochitests/content",
|
||||
"http://example.org"
|
||||
) + "some_content.html";
|
||||
await BrowserTestUtils.openNewForegroundTab(gBrowser, differentHttpUrl);
|
||||
Assert.equal(gBrowser.selectedBrowser.currentURI.scheme, "http");
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
// http navigations in private contexts shouldn't use information from
|
||||
// non-private contexts, so no upgrade should occur.
|
||||
add_task(async function test_private_window_no_upgrade() {
|
||||
let privateWindow = OpenBrowserWindow({ private: true });
|
||||
await BrowserTestUtils.firstBrowserLoaded(privateWindow, false);
|
||||
let url =
|
||||
getRootDirectory(gTestPath).replace(
|
||||
"chrome://mochitests/content",
|
||||
"http://example.com"
|
||||
) + "some_content.html";
|
||||
await BrowserTestUtils.openNewForegroundTab(privateWindow.gBrowser, url);
|
||||
Assert.equal(
|
||||
privateWindow.gBrowser.selectedBrowser.currentURI.scheme,
|
||||
"http"
|
||||
);
|
||||
privateWindow.gBrowser.removeCurrentTab();
|
||||
privateWindow.close();
|
||||
});
|
||||
|
||||
// Since the header didn't specify "includeSubdomains", visiting a subdomain
|
||||
// should not result in an upgrade.
|
||||
add_task(async function test_subdomain_no_upgrade() {
|
||||
let subdomainHttpUrl =
|
||||
getRootDirectory(gTestPath).replace(
|
||||
"chrome://mochitests/content",
|
||||
"http://test1.example.com"
|
||||
) + "some_content.html";
|
||||
await BrowserTestUtils.openNewForegroundTab(gBrowser, subdomainHttpUrl);
|
||||
Assert.equal(gBrowser.selectedBrowser.currentURI.scheme, "http");
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
// Now visit a secure site that sends an HSTS header that also includes subdomains.
|
||||
add_task(async function see_hsts_header_include_subdomains() {
|
||||
let setHstsUrl =
|
||||
getRootDirectory(gTestPath).replace(
|
||||
"chrome://mochitests/content",
|
||||
"https://example.com"
|
||||
) + "hsts_headers.sjs?includeSubdomains";
|
||||
await BrowserTestUtils.openNewForegroundTab(gBrowser, setHstsUrl);
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
// Now visiting a subdomain should result in an upgrade.
|
||||
add_task(async function test_subdomain_upgrade() {
|
||||
let subdomainHttpUrl =
|
||||
getRootDirectory(gTestPath).replace(
|
||||
"chrome://mochitests/content",
|
||||
"http://test1.example.com"
|
||||
) + "some_content.html";
|
||||
await BrowserTestUtils.openNewForegroundTab(gBrowser, subdomainHttpUrl);
|
||||
Assert.equal(gBrowser.selectedBrowser.currentURI.scheme, "https");
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
// Visiting a subdomain with https should result in an https URL (this isn't an
|
||||
// upgrade - this test is essentially a consistency check).
|
||||
add_task(async function test_already_https() {
|
||||
let subdomainHttpsUrl =
|
||||
getRootDirectory(gTestPath).replace(
|
||||
"chrome://mochitests/content",
|
||||
"https://test2.example.com"
|
||||
) + "some_content.html";
|
||||
await BrowserTestUtils.openNewForegroundTab(gBrowser, subdomainHttpsUrl);
|
||||
Assert.equal(gBrowser.selectedBrowser.currentURI.scheme, "https");
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
// Test that subresources are upgraded.
|
||||
add_task(async function test_iframe_upgrade() {
|
||||
let framedUrl =
|
||||
getRootDirectory(gTestPath).replace(
|
||||
"chrome://mochitests/content",
|
||||
"https://example.com"
|
||||
) + "some_content_framed.html";
|
||||
await BrowserTestUtils.openNewForegroundTab(gBrowser, framedUrl);
|
||||
await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function() {
|
||||
await ContentTaskUtils.waitForCondition(() => {
|
||||
let frame = content.document.getElementById("frame");
|
||||
if (frame) {
|
||||
return frame.baseURI.startsWith("https://");
|
||||
}
|
||||
return false;
|
||||
});
|
||||
});
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
// Clear state.
|
||||
add_task(async function clear_hsts_state() {
|
||||
let sss = Cc["@mozilla.org/ssservice;1"].getService(
|
||||
Ci.nsISiteSecurityService
|
||||
);
|
||||
sss.clearAll();
|
||||
});
|
||||
|
||||
// Make sure this test is valid.
|
||||
add_task(async function test_no_hsts_information_no_upgrade_again() {
|
||||
let httpUrl =
|
||||
getRootDirectory(gTestPath).replace(
|
||||
"chrome://mochitests/content",
|
||||
"http://example.com"
|
||||
) + "some_content.html";
|
||||
await BrowserTestUtils.openNewForegroundTab(gBrowser, httpUrl);
|
||||
Assert.equal(gBrowser.selectedBrowser.currentURI.scheme, "http");
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
// Visit a site with an iframe that loads first-party content that sends an
|
||||
// HSTS header. The header should be heeded because it's first-party.
|
||||
add_task(async function see_hsts_header_in_framed_first_party_context() {
|
||||
let framedUrl =
|
||||
getRootDirectory(gTestPath).replace(
|
||||
"chrome://mochitests/content",
|
||||
"https://example.com"
|
||||
) + "hsts_headers_framed.html";
|
||||
await BrowserTestUtils.openNewForegroundTab(gBrowser, framedUrl);
|
||||
await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function() {
|
||||
await ContentTaskUtils.waitForCondition(() => {
|
||||
return content.document.getElementById("done");
|
||||
});
|
||||
});
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
// Check that the framed, first-party header was heeded.
|
||||
add_task(async function test_http_upgrade_after_framed_first_party_header() {
|
||||
let httpUrl =
|
||||
getRootDirectory(gTestPath).replace(
|
||||
"chrome://mochitests/content",
|
||||
"http://example.com"
|
||||
) + "some_content.html";
|
||||
await BrowserTestUtils.openNewForegroundTab(gBrowser, httpUrl);
|
||||
Assert.equal(gBrowser.selectedBrowser.currentURI.scheme, "https");
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
// Visit a site with an iframe that loads third-party content that sends an
|
||||
// HSTS header. The header should be ignored because it's third-party.
|
||||
add_task(async function see_hsts_header_in_third_party_context() {
|
||||
let framedUrl =
|
||||
getRootDirectory(gTestPath).replace(
|
||||
"chrome://mochitests/content",
|
||||
"https://example.com"
|
||||
) + "hsts_headers_framed.html?third-party";
|
||||
await BrowserTestUtils.openNewForegroundTab(gBrowser, framedUrl);
|
||||
await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function() {
|
||||
await ContentTaskUtils.waitForCondition(() => {
|
||||
return content.document.getElementById("done");
|
||||
});
|
||||
});
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
// Since the HSTS header was not received in a first-party context, no upgrade
|
||||
// should occur.
|
||||
add_task(async function test_no_upgrade_for_third_party_header() {
|
||||
let url =
|
||||
getRootDirectory(gTestPath).replace(
|
||||
"chrome://mochitests/content",
|
||||
"http://example.org"
|
||||
) + "some_content.html";
|
||||
await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
|
||||
Assert.equal(gBrowser.selectedBrowser.currentURI.scheme, "http");
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
// Clear state again.
|
||||
add_task(async function clear_hsts_state_again() {
|
||||
let sss = Cc["@mozilla.org/ssservice;1"].getService(
|
||||
Ci.nsISiteSecurityService
|
||||
);
|
||||
sss.clearAll();
|
||||
});
|
||||
|
||||
// HSTS information encountered in private contexts should not be used in
|
||||
// non-private contexts.
|
||||
add_task(
|
||||
async function test_no_upgrade_for_HSTS_information_from_private_window() {
|
||||
let privateWindow = OpenBrowserWindow({ private: true });
|
||||
await BrowserTestUtils.firstBrowserLoaded(privateWindow, false);
|
||||
let setHstsUrl =
|
||||
getRootDirectory(gTestPath).replace(
|
||||
"chrome://mochitests/content",
|
||||
"https://example.com"
|
||||
) + "hsts_headers.sjs";
|
||||
await BrowserTestUtils.openNewForegroundTab(
|
||||
privateWindow.gBrowser,
|
||||
setHstsUrl
|
||||
);
|
||||
privateWindow.gBrowser.removeCurrentTab();
|
||||
|
||||
let httpUrl =
|
||||
getRootDirectory(gTestPath).replace(
|
||||
"chrome://mochitests/content",
|
||||
"http://example.com"
|
||||
) + "some_content.html";
|
||||
await BrowserTestUtils.openNewForegroundTab(gBrowser, httpUrl);
|
||||
Assert.equal(gBrowser.selectedBrowser.currentURI.scheme, "http");
|
||||
gBrowser.removeCurrentTab();
|
||||
|
||||
privateWindow.close();
|
||||
}
|
||||
);
|
|
@ -1,15 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function handleRequest(request, response) {
|
||||
let hstsHeader = "max-age=300";
|
||||
if (request.queryString == "includeSubdomains") {
|
||||
hstsHeader += "; includeSubdomains";
|
||||
}
|
||||
response.setHeader("Strict-Transport-Security", hstsHeader);
|
||||
response.setHeader("Pragma", "no-cache");
|
||||
response.setHeader("Cache-Control", "no-cache", false);
|
||||
response.setHeader("Content-Type", "text/html", false);
|
||||
response.setStatusLine(request.httpVersion, 200);
|
||||
response.write("<!DOCTYPE html><html><body><h1>Ok!</h1></body></html>");
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
let src = document.location.href.replace("hsts_headers_framed.html", "hsts_headers.sjs");
|
||||
if (document.location.search == "?third-party") {
|
||||
src = src.replace("example.com", "example.org");
|
||||
}
|
||||
let frame = document.createElement("iframe");
|
||||
frame.setAttribute("src", src);
|
||||
frame.onload = () => {
|
||||
let done = document.createElement("h1");
|
||||
done.textContent = "done";
|
||||
done.setAttribute("id", "done");
|
||||
document.body.appendChild(done);
|
||||
};
|
||||
document.body.appendChild(frame);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,6 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<h1>Some Content!</h1>
|
||||
</body>
|
||||
</html>
|
|
@ -1,14 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
let src = document.location.href.replace("https://", "http://");
|
||||
let frame = document.createElement("iframe");
|
||||
frame.setAttribute("id", "frame");
|
||||
frame.setAttribute("src", src);
|
||||
document.body.appendChild(frame);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -7,4 +7,5 @@
|
|||
TEST_DIRS += [
|
||||
"browser",
|
||||
"mixedcontent",
|
||||
"stricttransportsecurity",
|
||||
]
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
[DEFAULT]
|
||||
tags = psm
|
||||
skip-if = os == 'android'
|
||||
support-files = page_blank.html
|
||||
|
||||
[test_sts_privatebrowsing_perwindowpb.html]
|
|
@ -0,0 +1,12 @@
|
|||
[DEFAULT]
|
||||
tags = psm
|
||||
support-files =
|
||||
nosts_bootstrap.html
|
||||
nosts_bootstrap.html^headers^
|
||||
plain_bootstrap.html
|
||||
plain_bootstrap.html^headers^
|
||||
subdom_bootstrap.html
|
||||
subdom_bootstrap.html^headers^
|
||||
verify.sjs
|
||||
|
||||
[test_stricttransportsecurity.html]
|
|
@ -0,0 +1,9 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
MOCHITEST_MANIFESTS += ["mochitest.ini"]
|
||||
|
||||
MOCHITEST_CHROME_MANIFESTS += ["chrome.ini"]
|
|
@ -0,0 +1,28 @@
|
|||
<!-- 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/. -->
|
||||
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>STS test iframe</title>
|
||||
<script>
|
||||
"use strict";
|
||||
let windowRef = window;
|
||||
window.addEventListener("load", function() {
|
||||
windowRef.parent.postMessage("BOOTSTRAP plain",
|
||||
"http://mochi.test:8888");
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<!-- This frame should be loaded over HTTPS to set the STS header. -->
|
||||
This frame was loaded using
|
||||
<script>
|
||||
"use strict";
|
||||
// eslint-disable-next-line no-unsanitized/method
|
||||
document.write(document.location.protocol);
|
||||
</script>
|
||||
and set the STS header to force this site and allow subdomain upgrading.
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-cache
|
|
@ -0,0 +1,5 @@
|
|||
<html>
|
||||
<body>
|
||||
PAGE BLANK
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,28 @@
|
|||
<!-- 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/. -->
|
||||
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>STS test iframe</title>
|
||||
<script>
|
||||
"use strict";
|
||||
let windowRef = window;
|
||||
window.addEventListener("load", function() {
|
||||
windowRef.parent.postMessage("BOOTSTRAP plain",
|
||||
"http://mochi.test:8888");
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<!-- This frame should be loaded over HTTPS to set the STS header. -->
|
||||
This frame was loaded using
|
||||
<script>
|
||||
"use strict";
|
||||
// eslint-disable-next-line no-unsanitized/method
|
||||
document.write(document.location.protocol);
|
||||
</script>
|
||||
and set the STS header to force this site and allow subdomain upgrading.
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,2 @@
|
|||
Cache-Control: no-cache
|
||||
Strict-Transport-Security: max-age=60
|
|
@ -0,0 +1,28 @@
|
|||
<!-- 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/. -->
|
||||
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>STS test iframe</title>
|
||||
<script>
|
||||
"use strict";
|
||||
let windowRef = window;
|
||||
window.addEventListener("load", function() {
|
||||
windowRef.parent.postMessage("BOOTSTRAP subdom",
|
||||
"http://mochi.test:8888");
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<!-- This frame should be loaded over HTTPS to set the STS header. -->
|
||||
This frame was loaded using
|
||||
<script>
|
||||
"use strict";
|
||||
// eslint-disable-next-line no-unsanitized/method
|
||||
document.write(document.location.protocol);
|
||||
</script>
|
||||
and set the STS header to force this site and allow subdomain upgrading.
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,2 @@
|
|||
Cache-Control: no-cache
|
||||
Strict-Transport-Security: max-age=60; includeSubDomains
|
|
@ -0,0 +1,126 @@
|
|||
<!-- 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/. -->
|
||||
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>opens additional content that should be converted to https</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
|
||||
<script class="testbody" type="text/javascript">
|
||||
"use strict";
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
const STSPATH =
|
||||
"tests/security/manager/ssl/tests/mochitest/stricttransportsecurity";
|
||||
|
||||
// initialized manually here
|
||||
var testsleft = {plain: 4, subdom: 4};
|
||||
var roundsLeft = 2;
|
||||
|
||||
var testframes = {
|
||||
samedom: {
|
||||
url: `http://example.com/${STSPATH}/verify.sjs`,
|
||||
expected: {plain: "SECURE", subdom: "SECURE"},
|
||||
},
|
||||
subdom: {
|
||||
url: `http://test1.example.com/${STSPATH}/verify.sjs`,
|
||||
expected: {plain: "INSECURE", subdom: "SECURE"},
|
||||
},
|
||||
otherdom: {
|
||||
url: `http://example.org/${STSPATH}/verify.sjs`,
|
||||
expected: {plain: "INSECURE", subdom: "INSECURE"},
|
||||
},
|
||||
alreadysecure: {
|
||||
url: `https://test2.example.com/${STSPATH}/verify.sjs`,
|
||||
expected: {plain: "SECURE", subdom: "SECURE"},
|
||||
},
|
||||
};
|
||||
|
||||
function startRound(round) {
|
||||
let frame = document.createElement("iframe");
|
||||
frame.setAttribute("id", "ifr_bootstrap");
|
||||
frame.setAttribute("src",
|
||||
`https://example.com/${STSPATH}/${round}_bootstrap.html`);
|
||||
document.body.appendChild(frame);
|
||||
}
|
||||
|
||||
function endRound(round) {
|
||||
// remove all the iframes in the document
|
||||
document.body.removeChild(document.getElementById("ifr_bootstrap"));
|
||||
for (let test in testframes) {
|
||||
document.body.removeChild(document.getElementById("ifr_" + test));
|
||||
}
|
||||
|
||||
// clean up the STS state
|
||||
SpecialPowers.cleanUpSTSData("http://example.com");
|
||||
}
|
||||
|
||||
function loadVerifyFrames(round) {
|
||||
for (let test in testframes) {
|
||||
let frame = document.createElement("iframe");
|
||||
frame.setAttribute("id", "ifr_" + test);
|
||||
frame.setAttribute("src", testframes[test].url + "?id=" + test);
|
||||
document.body.appendChild(frame);
|
||||
}
|
||||
}
|
||||
|
||||
/* Messages received are in this format:
|
||||
* (BOOTSTRAP|SECURE|INSECURE) testid
|
||||
* For example: "BOOTSTRAP plain"
|
||||
* or: "INSECURE otherdom"
|
||||
*/
|
||||
function onMessageReceived(event) {
|
||||
let result = event.data.split(/\s+/);
|
||||
if (result.length != 2) {
|
||||
SimpleTest.ok(false, event.data);
|
||||
return;
|
||||
}
|
||||
|
||||
// figure out which round of tests we're in
|
||||
let round = (roundsLeft == 2) ? "plain" : "subdom";
|
||||
|
||||
if (result[0] === "BOOTSTRAP") {
|
||||
loadVerifyFrames(round);
|
||||
return;
|
||||
}
|
||||
|
||||
// check if the result (SECURE/INSECURE) is expected for this round/test combo
|
||||
SimpleTest.is(result[0], testframes[result[1]].expected[round],
|
||||
"in ROUND " + round + ", test " + result[1]);
|
||||
testsleft[round]--;
|
||||
|
||||
// check if there are more tests to run.
|
||||
if (testsleft[round] < 1) {
|
||||
// if not, advance to next round
|
||||
endRound(round);
|
||||
roundsLeft--;
|
||||
|
||||
// defer this so it doesn't muck with the stack too much.
|
||||
if (roundsLeft == 1) {
|
||||
setTimeout(function () {
|
||||
startRound("subdom");
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (roundsLeft < 1) {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
// listen for calls back from the sts-setting iframe and then
|
||||
// the verification frames.
|
||||
window.addEventListener("message", onMessageReceived);
|
||||
window.addEventListener("load", () => { startRound("plain"); });
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
This test will load some iframes and do some tests.
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,268 @@
|
|||
<!-- 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/. -->
|
||||
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>opens additional content that should be converted to https</title>
|
||||
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
||||
|
||||
<script class="testbody" type="text/javascript">
|
||||
"use strict";
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
const STSPATH =
|
||||
"tests/security/manager/ssl/tests/mochitest/stricttransportsecurity";
|
||||
const NUM_TEST_FRAMES = 4;
|
||||
const CONTENT_PAGE =
|
||||
"http://mochi.test:8888/chrome/security/manager/ssl/tests/mochitest/stricttransportsecurity/page_blank.html";
|
||||
|
||||
const {BrowserTestUtils} = ChromeUtils.import("resource://testing-common/BrowserTestUtils.jsm");
|
||||
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
// This is how many sub-tests (testframes) in each round.
|
||||
// When the round begins, this will be initialized.
|
||||
var testsleftinround = 0;
|
||||
var currentround = "";
|
||||
var mainWindow = window.browsingContext.topChromeWindow;
|
||||
|
||||
SpecialPowers.Services.prefs.setIntPref("browser.startup.page", 0);
|
||||
SpecialPowers.Services.prefs.setBoolPref("privacy.partition.network_state", false);
|
||||
|
||||
var testframes = {
|
||||
samedom: {
|
||||
url: `http://example.com/${STSPATH}/verify.sjs`,
|
||||
expected: {plain: "SECURE", subdom: "SECURE", nosts: "INSECURE"},
|
||||
},
|
||||
subdom: {
|
||||
url: `http://test1.example.com/${STSPATH}/verify.sjs`,
|
||||
expected: {plain: "INSECURE", subdom: "SECURE", nosts: "INSECURE"},
|
||||
},
|
||||
otherdom: {
|
||||
url: `http://example.org/${STSPATH}/verify.sjs`,
|
||||
expected: {plain: "INSECURE", subdom: "INSECURE", nosts: "INSECURE"},
|
||||
},
|
||||
alreadysecure: {
|
||||
url: `https://test2.example.com/${STSPATH}/verify.sjs`,
|
||||
expected: {plain: "SECURE", subdom: "SECURE", nosts: "SECURE"},
|
||||
},
|
||||
};
|
||||
|
||||
function whenDelayedStartupFinished(aWindow, aCallback) {
|
||||
SpecialPowers.Services.obs.addObserver(function observer(aSubject, aTopic) {
|
||||
if (aWindow == aSubject) {
|
||||
SpecialPowers.Services.obs.removeObserver(observer, aTopic);
|
||||
SimpleTest.executeSoon(aCallback);
|
||||
}
|
||||
}, "browser-delayed-startup-finished");
|
||||
}
|
||||
|
||||
function testOnWindow(aIsPrivate, aCallback) {
|
||||
let win = mainWindow.OpenBrowserWindow({private: aIsPrivate});
|
||||
|
||||
(async function() {
|
||||
await new Promise(resolve => whenDelayedStartupFinished(win, resolve));
|
||||
|
||||
let browser = win.gBrowser.selectedBrowser;
|
||||
BrowserTestUtils.loadURI(browser, CONTENT_PAGE);
|
||||
await BrowserTestUtils.browserLoaded(browser);
|
||||
|
||||
aCallback(win);
|
||||
})();
|
||||
}
|
||||
|
||||
function startRound(win, isPrivate, round) {
|
||||
currentround = round;
|
||||
testsleftinround = NUM_TEST_FRAMES;
|
||||
SimpleTest.info("TESTS LEFT IN ROUND " + currentround + ": " + testsleftinround);
|
||||
|
||||
let browser = win.gBrowser.selectedBrowser;
|
||||
let src = `https://example.com/${STSPATH}/${round}_bootstrap.html`;
|
||||
|
||||
SpecialPowers.spawn(browser, [src], async function(contentSrc) {
|
||||
let frame = content.document.createElement("iframe");
|
||||
frame.setAttribute("id", "ifr_bootstrap");
|
||||
frame.setAttribute("src", contentSrc);
|
||||
|
||||
return new Promise(resolve => {
|
||||
frame.addEventListener("load", () => resolve(), { once: true });
|
||||
content.document.body.appendChild(frame);
|
||||
});
|
||||
}).then(() => {
|
||||
onMessageReceived(win, isPrivate, "BOOTSTRAP " + round);
|
||||
});
|
||||
}
|
||||
|
||||
function loadVerifyFrames(win, isPrivate, round) {
|
||||
loadVerifyFrame(win, isPrivate, testframes.samedom, "samedom", function() {
|
||||
loadVerifyFrame(win, isPrivate, testframes.subdom, "subdom", function() {
|
||||
loadVerifyFrame(win, isPrivate, testframes.otherdom, "otherdom", function() {
|
||||
loadVerifyFrame(win, isPrivate, testframes.alreadysecure, "alreadysecure");
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function loadVerifyFrame(win, isPrivate, test, testName, aCallback) {
|
||||
let id = "ifr_" + testName;
|
||||
let src = test.url + "?id=" + testName;
|
||||
let browser = win.gBrowser.selectedBrowser;
|
||||
|
||||
SpecialPowers.spawn(browser, [[id, src]], async function([contentId, contentSrc]) {
|
||||
let frame = content.document.createElement("iframe");
|
||||
frame.setAttribute("id", contentId);
|
||||
frame.setAttribute("src", contentSrc);
|
||||
|
||||
return new Promise(resolve => {
|
||||
frame.addEventListener("load", () => {
|
||||
resolve(frame.contentDocument.location.protocol);
|
||||
});
|
||||
|
||||
content.document.body.appendChild(frame);
|
||||
});
|
||||
}).then(scheme => {
|
||||
if (scheme == "https:") {
|
||||
onMessageReceived(win, isPrivate, "SECURE " + testName);
|
||||
} else {
|
||||
onMessageReceived(win, isPrivate, "INSECURE " + testName);
|
||||
}
|
||||
|
||||
if (aCallback) {
|
||||
aCallback();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {DOMWindow} win
|
||||
* Test window.
|
||||
* @param {Boolean} isPrivate
|
||||
* Whether the given window is in private browsing mode.
|
||||
* @param {String} data
|
||||
* A message that is expected to be in this format:
|
||||
* (BOOTSTRAP|SECURE|INSECURE) testid
|
||||
* For example: "BOOTSTRAP subdom"
|
||||
* or: "INSECURE otherdom"
|
||||
*/
|
||||
function onMessageReceived(win, isPrivate, data) {
|
||||
let result = data.split(/\s+/);
|
||||
if (result.length != 2) {
|
||||
SimpleTest.ok(false, data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (result[0] === "BOOTSTRAP") {
|
||||
loadVerifyFrames(win, isPrivate, currentround);
|
||||
return;
|
||||
}
|
||||
|
||||
// check if the result (SECURE/INSECURE) is expected for this round/test
|
||||
// combo
|
||||
dump_STSState(isPrivate);
|
||||
SimpleTest.is(result[0], testframes[result[1]].expected[currentround],
|
||||
"in ROUND " + currentround +
|
||||
", test " + result[1]);
|
||||
testsleftinround--;
|
||||
|
||||
// if this round is complete...
|
||||
if (testsleftinround < 1) {
|
||||
SimpleTest.info("DONE WITH ROUND " + currentround);
|
||||
// remove all the iframes in the document
|
||||
let browser = win.gBrowser.selectedBrowser;
|
||||
SpecialPowers.spawn(browser, [testframes], async function(contentTestFrames) {
|
||||
content.document.body.removeChild(
|
||||
content.document.getElementById("ifr_bootstrap"));
|
||||
for (let test in contentTestFrames) {
|
||||
content.document.body.removeChild(
|
||||
content.document.getElementById("ifr_" + test));
|
||||
}
|
||||
}).then(async () => {
|
||||
currentround = "";
|
||||
|
||||
if (!isPrivate) {
|
||||
await clean_up_sts_state(isPrivate);
|
||||
}
|
||||
// Close test window.
|
||||
win.close();
|
||||
// And advance to the next test.
|
||||
// Defer this so it doesn't muck with the stack too much.
|
||||
SimpleTest.executeSoon(nextTest);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function test_sts_before_private_mode() {
|
||||
testOnWindow(false, function(win) {
|
||||
SimpleTest.info("In public window");
|
||||
dump_STSState(false);
|
||||
startRound(win, false, "plain");
|
||||
});
|
||||
}
|
||||
|
||||
function test_sts_in_private_mode() {
|
||||
testOnWindow(true, function(win) {
|
||||
SimpleTest.info("In private window");
|
||||
dump_STSState(true);
|
||||
startRound(win, true, "subdom");
|
||||
});
|
||||
}
|
||||
|
||||
function test_sts_after_exiting_private_mode() {
|
||||
testOnWindow(false, function(win) {
|
||||
SimpleTest.info("In a new public window");
|
||||
dump_STSState(false);
|
||||
startRound(win, false, "nosts");
|
||||
});
|
||||
}
|
||||
|
||||
async function clean_up_sts_state(isPrivate) {
|
||||
// erase all signs that this test ran.
|
||||
SimpleTest.info("Cleaning up STS data");
|
||||
let flags = isPrivate ? Ci.nsISocketProvider.NO_PERMANENT_STORAGE : 0;
|
||||
await SpecialPowers.cleanUpSTSData("http://example.com", flags);
|
||||
dump_STSState(isPrivate);
|
||||
}
|
||||
|
||||
function dump_STSState(isPrivate) {
|
||||
let sss = Cc["@mozilla.org/ssservice;1"]
|
||||
.getService(Ci.nsISiteSecurityService);
|
||||
let flags = isPrivate ? Ci.nsISocketProvider.NO_PERMANENT_STORAGE : 0;
|
||||
SimpleTest.info("State of example.com: " +
|
||||
sss.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://example.com"), flags));
|
||||
}
|
||||
|
||||
// These are executed in the order presented.
|
||||
// 0. test that STS works before entering private browsing mode.
|
||||
// (load sts-bootstrapped "plain" tests)
|
||||
// ... clear any STS data ...
|
||||
// 1. test that STS works in private browsing mode
|
||||
// (load sts-bootstrapped "subdomain" tests)
|
||||
// 2. test that after exiting private browsing, STS data is forgotten
|
||||
// (verified with non-sts-bootstrapped pages)
|
||||
// ... clear any STS data ...
|
||||
var tests = [
|
||||
test_sts_before_private_mode,
|
||||
test_sts_in_private_mode,
|
||||
test_sts_after_exiting_private_mode,
|
||||
];
|
||||
|
||||
function finish() {
|
||||
SpecialPowers.Services.prefs.clearUserPref("browser.startup.page");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
function nextTest() {
|
||||
SimpleTest.executeSoon(tests.length ? tests.shift() : finish);
|
||||
}
|
||||
window.addEventListener("load", nextTest);
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
This test will load some iframes and do some tests.
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,47 @@
|
|||
/* 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/. */
|
||||
|
||||
// SJS file that serves un-cacheable responses for STS tests that postMessage
|
||||
// to the parent saying whether or not they were loaded securely.
|
||||
|
||||
function handleRequest(request, response)
|
||||
{
|
||||
var query = {};
|
||||
request.queryString.split('&').forEach(function (val) {
|
||||
var [name, value] = val.split('=');
|
||||
query[name] = unescape(value);
|
||||
});
|
||||
|
||||
response.setHeader("Cache-Control", "no-cache", false);
|
||||
response.setHeader("Content-Type", "text/html", false);
|
||||
|
||||
if ('id' in query) {
|
||||
var outstr = [
|
||||
" <!DOCTYPE html>",
|
||||
" <html> <head> <title>subframe for STS</title>",
|
||||
" <script type='text/javascript'>",
|
||||
" var self = window;",
|
||||
" window.addEventListener('load', function() {",
|
||||
" if (document.location.protocol === 'https:') {",
|
||||
" self.parent.postMessage('SECURE " + query['id'] + "',",
|
||||
" 'http://mochi.test:8888');",
|
||||
" } else {",
|
||||
" self.parent.postMessage('INSECURE " + query['id'] + "',",
|
||||
" 'http://mochi.test:8888');",
|
||||
" }",
|
||||
" }, false);",
|
||||
" </script>",
|
||||
" </head>",
|
||||
" <body>",
|
||||
" STS state verification frame loaded via",
|
||||
" <script>",
|
||||
" document.write(document.location.protocol);",
|
||||
" </script>",
|
||||
" </body>",
|
||||
" </html>"].join("\n");
|
||||
response.write(outstr);
|
||||
} else {
|
||||
response.write("ERROR: no id provided");
|
||||
}
|
||||
}
|
|
@ -140,8 +140,7 @@ add_task(async function test_subresource() {
|
|||
Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE
|
||||
);
|
||||
|
||||
// Load a secure subresource. HSTS won't be activated, since third
|
||||
// parties can't set HSTS.
|
||||
// Load a secure subresource to activate HSTS.
|
||||
await SpecialPowers.spawn(
|
||||
tab.linkedBrowser,
|
||||
[secureImgURL],
|
||||
|
@ -163,7 +162,7 @@ add_task(async function test_subresource() {
|
|||
Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE
|
||||
);
|
||||
|
||||
// Load an unsecure subresource. It should not be upgraded to https.
|
||||
// Load a unsecure subresource, this should be upgraded to https.
|
||||
await SpecialPowers.spawn(
|
||||
tab.linkedBrowser,
|
||||
[unsecureImgURL],
|
||||
|
@ -174,7 +173,7 @@ add_task(async function test_subresource() {
|
|||
}
|
||||
);
|
||||
|
||||
is(await finalURL, unsecureImgURL, "HSTS isn't set for 3rd parties");
|
||||
is(await finalURL, secureImgURL, "HSTS works for 3rd parties");
|
||||
|
||||
// Load the secure page with a different origin as first party.
|
||||
await promiseTabLoadEvent(
|
||||
|
@ -199,7 +198,11 @@ add_task(async function test_subresource() {
|
|||
}
|
||||
);
|
||||
|
||||
is(await finalURL, unsecureImgURL, "HSTS isn't set for 3rd parties");
|
||||
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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче