126 lines
3.7 KiB
JavaScript
126 lines
3.7 KiB
JavaScript
/*
|
|
* Description of the tests:
|
|
* Tests check that default-src can be overridden by manifest-src.
|
|
*/
|
|
/*globals Cu, is, ok*/
|
|
"use strict";
|
|
const { ManifestObtainer } = ChromeUtils.importESModule(
|
|
"resource://gre/modules/ManifestObtainer.sys.mjs"
|
|
);
|
|
const path = "/tests/dom/security/test/csp/";
|
|
const testFile = `${path}file_web_manifest.html`;
|
|
const mixedContentFile = `${path}file_web_manifest_mixed_content.html`;
|
|
const server = `${path}file_testserver.sjs`;
|
|
const defaultURL = new URL(`https://example.org${server}`);
|
|
const mixedURL = new URL(`http://mochi.test:8888${server}`);
|
|
|
|
// Enable web manifest processing.
|
|
Services.prefs.setBoolPref("dom.manifest.enabled", true);
|
|
|
|
const tests = [
|
|
// Check interaction with default-src and another origin,
|
|
// CSP allows fetching from example.org, so manifest should load.
|
|
{
|
|
expected: `CSP manifest-src overrides default-src of elsewhere.com`,
|
|
get tabURL() {
|
|
const url = new URL(defaultURL);
|
|
url.searchParams.append("file", testFile);
|
|
url.searchParams.append("cors", "*");
|
|
url.searchParams.append(
|
|
"csp",
|
|
"default-src http://elsewhere.com; manifest-src http://example.org"
|
|
);
|
|
return url.href;
|
|
},
|
|
run(manifest) {
|
|
is(manifest.name, "loaded", this.expected);
|
|
},
|
|
},
|
|
// Check interaction with default-src none,
|
|
// CSP allows fetching manifest from example.org, so manifest should load.
|
|
{
|
|
expected: `CSP manifest-src overrides default-src`,
|
|
get tabURL() {
|
|
const url = new URL(mixedURL);
|
|
url.searchParams.append("file", mixedContentFile);
|
|
url.searchParams.append("cors", "http://test:80");
|
|
url.searchParams.append(
|
|
"csp",
|
|
"default-src 'self'; manifest-src http://test:80"
|
|
);
|
|
return url.href;
|
|
},
|
|
run(manifest) {
|
|
is(manifest.name, "loaded", this.expected);
|
|
},
|
|
},
|
|
];
|
|
|
|
//jscs:disable
|
|
add_task(async function () {
|
|
//jscs:enable
|
|
const testPromises = tests.map(test => {
|
|
const tabOptions = {
|
|
gBrowser,
|
|
url: test.tabURL,
|
|
skipAnimation: true,
|
|
};
|
|
return BrowserTestUtils.withNewTab(tabOptions, browser =>
|
|
testObtainingManifest(browser, test)
|
|
);
|
|
});
|
|
await Promise.all(testPromises);
|
|
});
|
|
|
|
async function testObtainingManifest(aBrowser, aTest) {
|
|
const expectsBlocked = aTest.expected.includes("block");
|
|
const observer = expectsBlocked ? createNetObserver(aTest) : null;
|
|
// Expect an exception (from promise rejection) if there a content policy
|
|
// that is violated.
|
|
try {
|
|
const manifest = await ManifestObtainer.browserObtainManifest(aBrowser);
|
|
aTest.run(manifest);
|
|
} catch (e) {
|
|
const wasBlocked = e.message.includes(
|
|
"NetworkError when attempting to fetch resource"
|
|
);
|
|
ok(
|
|
wasBlocked,
|
|
`Expected promise rejection obtaining ${aTest.tabURL}: ${e.message}`
|
|
);
|
|
if (observer) {
|
|
await observer.untilFinished;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Helper object used to observe policy violations. It waits 1 seconds
|
|
// for a response, and then times out causing its associated test to fail.
|
|
function createNetObserver(test) {
|
|
let finishedTest;
|
|
let success = false;
|
|
const finished = new Promise(resolver => {
|
|
finishedTest = resolver;
|
|
});
|
|
// eslint-disable-next-line mozilla/no-arbitrary-setTimeout
|
|
const timeoutId = setTimeout(() => {
|
|
if (!success) {
|
|
test.run("This test timed out.");
|
|
finishedTest();
|
|
}
|
|
}, 1000);
|
|
var observer = {
|
|
get untilFinished() {
|
|
return finished;
|
|
},
|
|
observe(subject, topic) {
|
|
SpecialPowers.removeObserver(observer, "csp-on-violate-policy");
|
|
test.run(topic);
|
|
finishedTest();
|
|
clearTimeout(timeoutId);
|
|
success = true;
|
|
},
|
|
};
|
|
SpecialPowers.addObserver(observer, "csp-on-violate-policy");
|
|
return observer;
|
|
}
|