Dactyloidae/toolkit/components/webextensions/test/mochitest/test_ext_webrequest_suspend.html

216 lines
6.1 KiB
HTML

<!DOCTYPE HTML>
<html>
<head>
<title>Test for simple WebExtension</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/ExtensionTestUtils.js"></script>
<script type="text/javascript" src="head.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<script type="text/javascript">
"use strict";
add_task(function* test_suspend() {
let extension = ExtensionTestUtils.loadExtension({
manifest: {
permissions: [
"webRequest",
"webRequestBlocking",
],
},
background() {
browser.webRequest.onBeforeSendHeaders.addListener(
details => {
// Make sure that returning undefined or a promise that resolves to
// undefined does not break later handlers.
},
{urls: ["<all_urls>"]},
["blocking", "requestHeaders"]);
browser.webRequest.onBeforeSendHeaders.addListener(
details => {
return Promise.resolve();
},
{urls: ["<all_urls>"]},
["blocking", "requestHeaders"]);
browser.webRequest.onBeforeSendHeaders.addListener(
details => {
let requestHeaders = details.requestHeaders.concat({name: "Foo", value: "Bar"});
return new Promise(resolve => {
setTimeout(resolve, 500);
}).then(() => {
return {requestHeaders};
});
},
{urls: ["<all_urls>"]},
["blocking", "requestHeaders"]);
},
});
yield extension.startup();
let result = yield fetch(SimpleTest.getTestFileURL("return_headers.sjs"));
let headers = JSON.parse(yield result.text());
is(headers.foo, "Bar", "Request header was correctly set on suspended request");
yield extension.unload();
});
// Test that requests that were canceled while suspended for a blocking
// listener are correctly resumed.
add_task(function* test_error_resume() {
let chromeScript = SpecialPowers.loadChromeScript(() => {
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import("resource://gre/modules/Services.jsm");
let observer = channel => {
if (channel instanceof Ci.nsIHttpChannel && channel.URI.spec === "http://example.com/") {
Services.obs.removeObserver(observer, "http-on-modify-request");
// Wait until the next tick to make sure this runs after WebRequest observers.
Promise.resolve().then(() => {
channel.cancel(Cr.NS_BINDING_ABORTED);
});
}
};
Services.obs.addObserver(observer, "http-on-modify-request", false);
});
let extension = ExtensionTestUtils.loadExtension({
manifest: {
permissions: [
"webRequest",
"webRequestBlocking",
],
},
background() {
browser.webRequest.onBeforeSendHeaders.addListener(
details => {
browser.test.log(`onBeforeSendHeaders({url: ${details.url}})`);
if (details.url === "http://example.com/") {
browser.test.sendMessage("got-before-send-headers");
}
},
{urls: ["<all_urls>"]},
["blocking"]);
browser.webRequest.onErrorOccurred.addListener(
details => {
browser.test.log(`onErrorOccurred({url: ${details.url}})`);
if (details.url === "http://example.com/") {
browser.test.sendMessage("got-error-occurred");
}
},
{urls: ["<all_urls>"]});
},
});
yield extension.startup();
try {
yield fetch("http://example.com/");
ok(false, "Fetch should have failed.");
} catch (e) {
ok(true, "Got expected error.");
}
yield extension.awaitMessage("got-before-send-headers");
yield extension.awaitMessage("got-error-occurred");
yield extension.unload();
chromeScript.destroy();
});
// Test that response header modifications take effect before onStartRequest fires.
add_task(function* test_set_responseHeaders() {
let extension = ExtensionTestUtils.loadExtension({
manifest: {
permissions: [
"webRequest",
"webRequestBlocking",
"http://example.com/",
],
},
background() {
browser.webRequest.onHeadersReceived.addListener(
details => {
browser.test.log(`onHeadersReceived({url: ${details.url}})`);
details.responseHeaders.push({name: "foo", value: "bar"});
return {responseHeaders: details.responseHeaders};
},
{urls: ["http://example.com/?modify_headers"]},
["blocking", "responseHeaders"]);
},
});
yield extension.startup();
yield new Promise(resolve => setTimeout(resolve, 0));
let chromeScript = SpecialPowers.loadChromeScript(() => {
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import("resource://gre/modules/NetUtil.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
let ssm = Services.scriptSecurityManager;
let channel = NetUtil.newChannel({
uri: "http://example.com/?modify_headers",
loadingPrincipal: ssm.createCodebasePrincipalFromOrigin("http://example.com"),
contentPolicyType: Ci.nsIContentPolicy.TYPE_XMLHTTPREQUEST,
securityFlags: Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
});
channel.asyncOpen2({
QueryInterface: XPCOMUtils.generateQI([Ci.nsIStreamListener]),
onStartRequest(request, context) {
request.QueryInterface(Ci.nsIHttpChannel);
try {
sendAsyncMessage("response-header-foo", request.getResponseHeader("foo"));
} catch (e) {
sendAsyncMessage("response-header-foo", null);
}
request.cancel(Cr.NS_BINDING_ABORTED);
},
onStopRequest() {
},
onDataAvailable() {
throw new Components.Exception("", Cr.NS_ERROR_FAILURE);
},
});
});
let headerValue = yield chromeScript.promiseOneMessage("response-header-foo");
is(headerValue, "bar", "Expected Foo header value");
yield extension.unload();
chromeScript.destroy();
});
</script>
</body>
</html>