Bug 1823877 - Part 2: Adjust tests to account for parent filtered responses. r=sefeng,smaug

Differential Revision: https://phabricator.services.mozilla.com/D174768
This commit is contained in:
Andreas Farre 2023-05-10 14:35:52 +00:00
Родитель 476835e1c7
Коммит 99240722e4
16 изменённых файлов: 185 добавлений и 408 удалений

Просмотреть файл

@ -453,10 +453,6 @@ fetch(
{ mode: "no-cors" }
).then(
function(res) {
my_ok(
!new URLSearchParams(location.search).has("orbEnabled"),
"no-cors Fetch request with invalid javascript content should be blocked if ORB is enabled"
);
my_ok(res.type == "opaque", "Response type should be opaque");
my_ok(res.status == 0, "Status should be 0");
res.text().then(function(body) {
@ -465,10 +461,7 @@ fetch(
});
},
function(e) {
my_ok(
new URLSearchParams(location.search).has("orbEnabled"),
"no-cors Fetch request with invalid javascript content should not be blocked if ORB disabled"
);
my_ok(false, "no-cors Fetch failed");
finish();
}
);
@ -494,10 +487,6 @@ fetch("opaque-on-same-origin").then(
expectAsyncResult();
fetch("http://example.com/opaque-no-cors", { mode: "no-cors" }).then(
function(res) {
my_ok(
!new URLSearchParams(location.search).has("orbEnabled"),
"intercepted opaque response for no-cors request with invalid javascript content should be blocked when ORB is enabled."
);
my_ok(
res.type == "opaque",
"intercepted opaque response for no-cors request should have type opaque."
@ -506,8 +495,8 @@ fetch("http://example.com/opaque-no-cors", { mode: "no-cors" }).then(
},
function(e) {
my_ok(
new URLSearchParams(location.search).has("orbEnabled"),
"intercepted opaque response for no-cors request wth invalid javascript content should not be blocked when ORB is disabled."
false,
"intercepted opaque response for no-cors request should pass."
);
finish();
}

Просмотреть файл

@ -172,13 +172,7 @@
};
gExpected++;
var fetch_worker_script_url = 'fetch_worker_script.js';
const params = new URLSearchParams(window.location.search);
if (params.has("orbEnabled")) {
fetch_worker_script_url += "?orbEnabled";
}
var worker = new Worker(fetch_worker_script_url);
var worker = new Worker('fetch_worker_script.js');
worker.onmessage = function(e) {
if (e.data == "finish") {
finish();

Просмотреть файл

@ -249,12 +249,8 @@ skip-if =
skip-if = (os == "win" && processor == "aarch64") #bug 1535784
[test_fetch_event.html]
skip-if = debug # Bug 1262224
[test_fetch_event_no_orb.html]
skip-if = debug # Bug 1262224
[test_fetch_event_with_thirdpartypref.html]
skip-if = debug # Bug 1262224
[test_fetch_event_with_thirdpartypref_no_orb.html]
skip-if = debug # Bug 1262224
[test_fetch_integrity.html]
skip-if = serviceworker_e10s
support-files = console_monitor.js

Просмотреть файл

@ -47,7 +47,7 @@
}
});
var w = window.open("fetch/index.html?orbEnabled");
var w = window.open("fetch/index.html");
return p;
}
@ -68,8 +68,6 @@
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true],
["browser.opaqueResponseBlocking", true],
["browser.opaqueResponseBlocking.javascriptValidator", true]
]}, runTest);
</script>
</pre>

Просмотреть файл

@ -1,76 +0,0 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 94048 - test install event.</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<script src="utils.js"></script>
<script class="testbody" type="text/javascript">
SimpleTest.requestCompleteLog();
var registration;
function simpleRegister() {
return navigator.serviceWorker.register("fetch_event_worker.js", { scope: "./fetch" })
.then(swr => {
registration = swr;
return waitForState(swr.installing, 'activated');
});
}
function unregister() {
return registration.unregister().then(function(success) {
ok(success, "Service worker should be unregistered successfully");
}, function(e) {
dump("SW unregistration error: " + e + "\n");
});
}
function testController() {
var p = new Promise(function(resolve, reject) {
window.onmessage = function(e) {
if (e.data.status == "ok") {
ok(e.data.result, e.data.message);
} else if (e.data.status == "done") {
window.onmessage = null;
w.close();
resolve();
}
}
});
var w = window.open("fetch/index.html");
return p;
}
function runTest() {
simpleRegister()
.then(testController)
.then(unregister)
.then(function() {
SimpleTest.finish();
}).catch(function(e) {
ok(false, "Some test failed with error " + e);
SimpleTest.finish();
});
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true],
["browser.opaqueResponseBlocking", false],
]}, runTest);
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -59,7 +59,7 @@
}
});
var w = window.open("fetch/index.html?orbEnabled");
var w = window.open("fetch/index.html");
return p;
}
@ -83,8 +83,6 @@
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true],
["network.cookie.cookieBehavior", COOKIE_BEHAVIOR_REJECTFOREIGN],
["browser.opaqueResponseBlocking", true],
["browser.opaqueResponseBlocking.javascriptValidator", true]
]}, runTest);
</script>
</pre>

Просмотреть файл

@ -1,91 +0,0 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 94048 - test install event.</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<script src="utils.js"></script>
<script class="testbody" type="text/javascript">
// NOTE: This is just test_fetch_event.html but with an alternate cookie
// mode preference set to make sure that setting the preference does
// not break interception as observed in bug 1336364.
// TODO: Refactor this test so it doesn't duplicate so much code logic.
SimpleTest.requestCompleteLog();
var registration;
function simpleRegister() {
return navigator.serviceWorker.register("fetch_event_worker.js", { scope: "./fetch" })
.then(swr => {
registration = swr;
return waitForState(swr.installing, 'activated');
});
}
function unregister() {
return registration.unregister().then(function(success) {
ok(success, "Service worker should be unregistered successfully");
}, function(e) {
dump("SW unregistration error: " + e + "\n");
});
}
function testController() {
var p = new Promise(function(resolve, reject) {
var reloaded = false;
window.onmessage = function(e) {
if (e.data.status == "ok") {
ok(e.data.result, e.data.message);
} else if (e.data.status == "done") {
if (reloaded) {
window.onmessage = null;
w.close();
resolve();
} else {
w.location.reload();
reloaded = true;
}
}
}
});
var w = window.open("fetch/index.html");
return p;
}
function runTest() {
simpleRegister()
.then(testController)
.then(unregister)
.then(function() {
SimpleTest.finish();
}).catch(function(e) {
ok(false, "Some test failed with error " + e);
SimpleTest.finish();
});
}
const COOKIE_BEHAVIOR_REJECTFOREIGN = 1;
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true],
["network.cookie.cookieBehavior", COOKIE_BEHAVIOR_REJECTFOREIGN],
["browser.opaqueResponseBlocking", false],
]}, runTest);
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -1,11 +1,9 @@
function testScript(script) {
function makeWrapperUrl(wrapper, orbEnabled) {
let url = wrapper + "?script=" + script;
if (orbEnabled) {
url += "&orbEnabled";
}
return url;
function makeWrapperUrl(wrapper) {
return wrapper + "?script=" + script;
}
let workerWrapperUrl = makeWrapperUrl("worker_wrapper.js");
// The framework runs the entire test in many different configurations.
// On slow platforms and builds this can make the tests likely to
// timeout while they are still running. Lengthen the timeout to
@ -54,11 +52,9 @@ function testScript(script) {
});
}
function nestedWorkerTest(orbEnabled) {
function nestedWorkerTest() {
return new Promise(function(resolve, reject) {
var worker = new Worker(
makeWrapperUrl("nested_worker_wrapper.js", orbEnabled)
);
var worker = new Worker(makeWrapperUrl("nested_worker_wrapper.js"));
worker.onmessage = function(event) {
if (event.data.context != "NestedWorker") {
return;
@ -141,57 +137,32 @@ function testScript(script) {
// We have to run the window, worker and service worker tests sequentially
// since some tests set and compare cookies and running in parallel can lead
// to conflicting values.
function run(orbEnabled) {
const shouldFinishTest = !orbEnabled;
return setupPrefs()
.then(function() {
// No need to set ORB pref for windowTest because windowTest will
// do it by itself since it can access SpecialPowers.
return windowTest();
})
.then(function() {
return SpecialPowers.pushPrefEnv({
set: [
["browser.opaqueResponseBlocking", orbEnabled],
["browser.opaqueResponseBlocking.javascriptValidator", orbEnabled],
],
});
})
.then(function() {
return workerTest();
})
.then(function() {
return nestedWorkerTest(orbEnabled);
})
.then(function() {
return serviceWorkerTest();
})
.catch(function(e) {
ok(false, "Some test failed in " + script);
info(e);
info(e.message);
return Promise.resolve();
})
.then(function() {
try {
if (parent && parent.finishTest) {
if (shouldFinishTest) {
parent.finishTest();
}
return;
}
} catch {}
if (shouldFinishTest) {
SimpleTest.finish();
setupPrefs()
.then(function() {
return windowTest();
})
.then(function() {
return workerTest();
})
.then(function() {
return nestedWorkerTest();
})
.then(function() {
return serviceWorkerTest();
})
.catch(function(e) {
ok(false, "Some test failed in " + script);
info(e);
info(e.message);
return Promise.resolve();
})
.then(function() {
try {
if (parent && parent.finishTest) {
parent.finishTest();
return;
}
});
}
let orbEnabled = true;
let workerWrapperUrl = makeWrapperUrl("worker_wrapper.js", orbEnabled);
run(orbEnabled).then(function() {
orbEnabled = false;
workerWrapperUrl = makeWrapperUrl("worker_wrapper.js", orbEnabled);
run(orbEnabled);
});
} catch {}
SimpleTest.finish();
});
}

Просмотреть файл

@ -1,10 +1,5 @@
function getScriptUrl() {
const params = new URL(location.href).searchParams;
let scriptUrl = params.get("script");
if (params.has("orbEnabled")) {
scriptUrl += "&orbEnabled";
}
return scriptUrl;
return new URL(location.href).searchParams.get("script");
}
// Hold the nested worker alive until this parent worker closes.

Просмотреть файл

@ -80,7 +80,7 @@ function testNoCorsCtor() {
var corsServerPath =
"/tests/dom/security/test/cors/file_CrossSiteXHR_server.sjs?";
function testModeNoCors(withoutORB) {
function testModeNoCors() {
// Fetch spec, section 4, step 4, response tainting should be set opaque, so
// that fetching leads to an opaque filtered response in step 8.
var r = new Request("http://example.com" + corsServerPath + "status=200", {
@ -88,20 +88,13 @@ function testModeNoCors(withoutORB) {
});
return fetch(r).then(
function(res) {
ok(
withoutORB,
"no-cors Request fetch with invalid javascript content should be blocked when ORB is enabled"
);
ok(
isOpaqueResponse(res),
"no-cors Request fetch should result in opaque response"
);
},
function(e) {
ok(
!withoutORB,
"no-cors Request fetch with invalid javascript content should not be blocked when ORB is not enabled"
);
ok(false, "no-cors Request fetch should not error");
}
);
}
@ -1204,45 +1197,44 @@ function testCrossOriginCredentials() {
return finalPromise;
}
function testModeNoCorsCredentials(withoutORB) {
function testModeNoCorsCredentials() {
var cookieStr = "type=chocolatechip";
var tests = [
{
// Initialize by setting a cookie.
pass: withoutORB,
pass: 1,
setCookie: cookieStr,
withCred: "include",
bypassORB: true,
},
{
pass: withoutORB,
pass: 1,
noCookie: 1,
withCred: "omit",
},
{
pass: withoutORB,
pass: 1,
noCookie: 1,
withCred: "same-origin",
},
{
pass: withoutORB,
pass: 1,
cookie: cookieStr,
withCred: "include",
},
{
pass: withoutORB,
pass: 1,
cookie: cookieStr,
withCred: "omit",
status: 500,
},
{
pass: withoutORB,
pass: 1,
cookie: cookieStr,
withCred: "same-origin",
status: 500,
},
{
pass: withoutORB,
pass: 1,
noCookie: 1,
withCred: "include",
status: 500,
@ -1291,13 +1283,16 @@ function testModeNoCorsCredentials(withoutORB) {
status,
"wrong status in test for " + JSON.stringify(test)
);
return unfiltered.text().then(function(v) {
if (status === 200) {
is(
v,
"<res>hello pass</res>\n",
"wrong text in test for " + JSON.stringify(test)
);
if (test.status === 200) {
const expected =
SpecialPowers.getIntPref(
"browser.opaqueResponseBlocking.filterFetchResponse"
) > 0
? ""
: "<res>hello pass</res>\n";
is(v, expected, "wrong text in test for " + JSON.stringify(test));
}
});
}
@ -1712,29 +1707,25 @@ function testCORSRedirects() {
return Promise.all(fetches);
}
function testNoCORSRedirects(withoutORB) {
function testNoCORSRedirects() {
var origin = "http://mochi.test:8888";
var tests = [
{ pass: 1, method: "GET", hops: [{ server: "http://example.com" }] },
{
pass: withoutORB,
method: "GET",
hops: [{ server: "http://example.com" }],
},
{
pass: withoutORB,
pass: 1,
method: "GET",
hops: [{ server: origin }, { server: "http://example.com" }],
},
{
pass: withoutORB,
pass: 1,
method: "GET",
// Must use a simple header due to no-cors header restrictions.
headers: { "accept-language": "en-us" },
hops: [{ server: origin }, { server: "http://example.com" }],
},
{
pass: withoutORB,
pass: 1,
method: "GET",
hops: [
{ server: origin },
@ -1743,7 +1734,7 @@ function testNoCORSRedirects(withoutORB) {
],
},
{
pass: withoutORB,
pass: 1,
method: "POST",
body: "upload body here",
hops: [{ server: origin }, { server: "http://example.com" }],
@ -1880,41 +1871,13 @@ function runTest() {
return promise
.then(testModeSameOrigin)
.then(testModeNoCors)
.then(testModeCors)
.then(testSameOriginCredentials)
.then(testCrossOriginCredentials)
.then(testModeNoCorsCredentials)
.then(testCORSRedirects)
.then(function() {
return SpecialPowers.pushPrefEnv({
set: [["browser.opaqueResponseBlocking", false]],
});
})
.then(() => {
return testModeNoCorsCredentials(1); // Without ORB
})
.then(function() {
return testModeNoCors(1); // Without ORB
})
.then(function() {
return testNoCORSRedirects(1); // Without ORB
})
.then(function() {
return SpecialPowers.pushPrefEnv({
set: [
["browser.opaqueResponseBlocking", true],
["browser.opaqueResponseBlocking.javascriptValidator", true],
],
});
})
.then(() => {
return testModeNoCorsCredentials(0); // With ORB
})
.then(function() {
return testModeNoCors(0); // With ORB
})
.then(() => {
return testNoCORSRedirects(0); // With ORB
})
.then(testNoCORSRedirects)
.then(testReferrer);
// Put more promise based tests here.
}

Просмотреть файл

@ -97,59 +97,35 @@ function testClone() {
});
}
function testCloneUnfiltered(orbEnabled) {
function testCloneUnfiltered() {
var url =
"http://example.com/tests/dom/security/test/cors/file_CrossSiteXHR_server.sjs?status=200";
return fetch(url, { mode: "no-cors" }).then(function(response) {
// By default the chrome-only function should not be available.
is(response.type, "opaque", "response should be opaque");
is(
response.cloneUnfiltered,
undefined,
"response.cloneUnfiltered should be undefined"
);
// Due to the test step and the fact this script is imported by worker,
// so we had to do some extra parsing to get whether orbEnabled has
// been provided.
// location.search could be something like: ?script=test_response.js?orbEnabled
var isORBEnabled;
if (orbEnabled !== undefined) {
// Window Context
isORBEnabled = orbEnabled;
} else {
// Worker Context
const params = new URLSearchParams(location.search);
isORBEnabled = params.has("orbEnabled");
}
// When the test is run in a worker context we can't actually try to use
// the chrome-only function. SpecialPowers is not defined.
if (typeof SpecialPowers !== "object") {
return;
}
return fetch(url, { mode: "no-cors" })
.then(function(response) {
// By default the chrome-only function should not be available.
ok(!isORBEnabled, "This request should be blocked when ORB is enabled");
is(response.type, "opaque", "response should be opaque");
is(
response.cloneUnfiltered,
undefined,
"response.cloneUnfiltered should be undefined"
);
// When the test is run in a worker context we can't actually try to use
// the chrome-only function. SpecialPowers is not defined.
if (typeof SpecialPowers !== "object") {
return;
}
// With a chrome code, however, should be able to get an unfiltered response.
var chromeResponse = SpecialPowers.wrap(response);
is(
typeof chromeResponse.cloneUnfiltered,
"function",
"chromeResponse.cloneFiltered should be a function"
);
var unfiltered = chromeResponse.cloneUnfiltered();
is(unfiltered.type, "default", "unfiltered response should be default");
is(unfiltered.status, 200, "unfiltered response should have 200 status");
})
.catch(function(e) {
ok(
isORBEnabled,
"This request should not be blocked when ORB is disabled"
);
is(e.name, "TypeError", "ORB should throw TypeError");
});
// With a chrome code, however, should be able to get an unfiltered response.
var chromeResponse = SpecialPowers.wrap(response);
is(
typeof chromeResponse.cloneUnfiltered,
"function",
"chromeResponse.cloneFiltered should be a function"
);
var unfiltered = chromeResponse.cloneUnfiltered();
is(unfiltered.type, "default", "unfiltered response should be default");
is(unfiltered.status, 200, "unfiltered response should have 200 status");
});
}
function testError() {
@ -360,33 +336,7 @@ function runTest() {
.then(testBodyUsed)
.then(testBodyExtraction)
.then(testClone)
.then(async function() {
const inWindowContext = typeof SpecialPowers === "object";
// We want to use SpecialPowers to flip the prefs directly
// if we are in window context.
if (inWindowContext) {
return SpecialPowers.pushPrefEnv({
set: [
["browser.opaqueResponseBlocking", true],
["browser.opaqueResponseBlocking.javascriptValidator", true],
],
})
.then(function() {
return testCloneUnfiltered(true);
})
.then(function() {
return SpecialPowers.pushPrefEnv({
set: [["browser.opaqueResponseBlocking", false]],
});
})
.then(function() {
return testCloneUnfiltered(false);
});
}
// Worker Context uses query strings to determine the
// status of ORB.
return testCloneUnfiltered();
})
.then(testCloneUnfiltered)
// Put more promise based tests here.
.catch(function(e) {
dump("### ### " + e + "\n");

Просмотреть файл

@ -1,4 +1,6 @@
let { setTimeout } = ChromeUtils.import("resource://gre/modules/Timer.jsm");
const { setTimeout } = ChromeUtils.importESModule(
"resource://gre/modules/Timer.sys.mjs"
);
function handleRequest(request, response) {
response.processAsync();

Просмотреть файл

@ -0,0 +1,10 @@
[content-range.sub.any.html]
prefs: [browser.opaqueResponseBlocking:true,
browser.opaqueResponseBlocking.filterFetchResponse:2]
[ORB should block opaque range of image/png not starting at zero, that isn't subsequent]
expected: FAIL
[content-range.sub.any.worker.html]
[ORB should block opaque range of image/png not starting at zero, that isn't subsequent]
expected: FAIL

Просмотреть файл

@ -0,0 +1,38 @@
[known-mime-type.sub.any.html]
prefs: [browser.opaqueResponseBlocking:true,
browser.opaqueResponseBlocking.filterFetchResponse:2]
[ORB should block opaque font/ttf]
expected: FAIL
[ORB should block opaque text/plain]
expected: FAIL
[ORB should block opaque application/json (non-empty)]
expected: FAIL
[ORB should block opaque application/json (empty)]
expected: FAIL
[ORB should block opaque application/json which contains non ascii characters]
expected: FAIL
[known-mime-type.sub.any.worker.html]
prefs: [browser.opaqueResponseBlocking:true,
browser.opaqueResponseBlocking.filterFetchResponse:2]
[ORB should block opaque font/ttf]
expected: FAIL
[ORB should block opaque text/plain]
expected: FAIL
[ORB should block opaque application/json (non-empty)]
expected: FAIL
[ORB should block opaque application/json (empty)]
expected: FAIL
[ORB should block opaque application/json which contains non ascii characters]
expected: FAIL

Просмотреть файл

@ -1,7 +1,30 @@
[nosniff.sub.any.html]
prefs: [browser.opaqueResponseBlocking:true,
browser.opaqueResponseBlocking.filterFetchResponse:2]
expected:
if (os == "android") and fission: [OK, TIMEOUT]
[ORB should block opaque text/plain with nosniff]
expected: FAIL
[ORB should block opaque-response-blocklisted MIME type with nosniff]
expected: FAIL
[ORB should block opaque response with empty Content-Type and nosniff]
expected: FAIL
[nosniff.sub.any.worker.html]
prefs: [browser.opaqueResponseBlocking:true,
browser.opaqueResponseBlocking.filterFetchResponse:2]
expected:
if (os == "android") and fission: [OK, TIMEOUT]
[ORB should block opaque text/plain with nosniff]
expected: FAIL
[ORB should block opaque-response-blocklisted MIME type with nosniff]
expected: FAIL
[ORB should block opaque response with empty Content-Type and nosniff]
expected: FAIL

Просмотреть файл

@ -1,7 +1,24 @@
[status.sub.any.html]
prefs: [browser.opaqueResponseBlocking:true,
browser.opaqueResponseBlocking.filterFetchResponse:2]
expected:
if (os == "android") and fission: [OK, TIMEOUT]
[ORB should block opaque-response-blocklisted MIME type with status 206]
expected: FAIL
[ORB should block opaque response with non-ok status]
expected: FAIL
[status.sub.any.worker.html]
prefs: [browser.opaqueResponseBlocking:true,
browser.opaqueResponseBlocking.filterFetchResponse:2]
expected:
if (os == "android") and fission: [OK, TIMEOUT]
[ORB should block opaque-response-blocklisted MIME type with status 206]
expected: FAIL
[ORB should block opaque response with non-ok status]
expected: FAIL