summaryrefslogtreecommitdiffstats
path: root/toolkit/components/extensions/test/xpcshell/test_ext_permission_xhr.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/extensions/test/xpcshell/test_ext_permission_xhr.js')
-rw-r--r--toolkit/components/extensions/test/xpcshell/test_ext_permission_xhr.js240
1 files changed, 240 insertions, 0 deletions
diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_permission_xhr.js b/toolkit/components/extensions/test/xpcshell/test_ext_permission_xhr.js
new file mode 100644
index 0000000000..88afd36dcc
--- /dev/null
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_permission_xhr.js
@@ -0,0 +1,240 @@
+"use strict";
+
+// This file tests the behavior of fetch/XMLHttpRequest in content scripts, in
+// relation to permissions, in MV2.
+// In MV3, the expectations are different, test coverage for that is in
+// test_ext_xhr_cors.js (along with CORS tests that also apply to MV2).
+
+const server = createHttpServer({
+ hosts: ["xpcshell.test", "example.com", "example.org"],
+});
+server.registerDirectory("/data/", do_get_file("data"));
+
+server.registerPathHandler("/example.txt", (request, response) => {
+ response.setStatusLine(request.httpVersion, 200, "OK");
+ response.write("ok");
+});
+
+server.registerPathHandler("/return_headers.sjs", (request, response) => {
+ response.setHeader("Content-Type", "text/plain", false);
+
+ let headers = {};
+ for (let { data: header } of request.headers) {
+ headers[header.toLowerCase()] = request.getHeader(header);
+ }
+
+ response.write(JSON.stringify(headers));
+});
+
+/* eslint-disable mozilla/balanced-listeners */
+
+add_task(async function test_simple() {
+ async function runTests(cx) {
+ function xhr(XMLHttpRequest) {
+ return url => {
+ return new Promise((resolve, reject) => {
+ let req = new XMLHttpRequest();
+ req.open("GET", url);
+ req.addEventListener("load", resolve);
+ req.addEventListener("error", reject);
+ req.send();
+ });
+ };
+ }
+
+ function run(shouldFail, fetch) {
+ function passListener() {
+ browser.test.succeed(`${cx}.${fetch.name} pass listener`);
+ }
+
+ function failListener() {
+ browser.test.fail(`${cx}.${fetch.name} fail listener`);
+ }
+
+ /* eslint-disable no-else-return */
+ if (shouldFail) {
+ return fetch("http://example.org/example.txt").then(
+ failListener,
+ passListener
+ );
+ } else {
+ return fetch("http://example.com/example.txt").then(
+ passListener,
+ failListener
+ );
+ }
+ /* eslint-enable no-else-return */
+ }
+
+ try {
+ await run(true, xhr(XMLHttpRequest));
+ await run(false, xhr(XMLHttpRequest));
+ await run(true, xhr(window.XMLHttpRequest));
+ await run(false, xhr(window.XMLHttpRequest));
+ await run(true, fetch);
+ await run(false, fetch);
+ await run(true, window.fetch);
+ await run(false, window.fetch);
+ } catch (err) {
+ browser.test.fail(`Error: ${err} :: ${err.stack}`);
+ browser.test.notifyFail("permission_xhr");
+ }
+ }
+
+ async function background(runTestsFn) {
+ await runTestsFn("bg");
+ browser.test.notifyPass("permission_xhr");
+ }
+
+ let extensionData = {
+ background: `(${background})(${runTests})`,
+ manifest: {
+ permissions: ["http://example.com/"],
+ content_scripts: [
+ {
+ matches: ["http://xpcshell.test/data/file_permission_xhr.html"],
+ js: ["content.js"],
+ },
+ ],
+ },
+ files: {
+ "content.js": `(${async runTestsFn => {
+ await runTestsFn("content");
+
+ window.wrappedJSObject.privilegedFetch = fetch;
+ window.wrappedJSObject.privilegedXHR = XMLHttpRequest;
+
+ window.addEventListener("message", function rcv({ data }) {
+ switch (data.msg) {
+ case "test":
+ break;
+
+ case "assertTrue":
+ browser.test.assertTrue(data.condition, data.description);
+ break;
+
+ case "finish":
+ window.removeEventListener("message", rcv);
+ browser.test.sendMessage("content-script-finished");
+ break;
+ }
+ });
+ window.postMessage("test", "*");
+ }})(${runTests})`,
+ },
+ };
+
+ let extension = ExtensionTestUtils.loadExtension(extensionData);
+ await extension.startup();
+
+ let contentPage = await ExtensionTestUtils.loadContentPage(
+ "http://xpcshell.test/data/file_permission_xhr.html"
+ );
+ await extension.awaitMessage("content-script-finished");
+ await contentPage.close();
+
+ await extension.awaitFinish("permission_xhr");
+ await extension.unload();
+});
+
+// This test case ensures that a WebExtension content script can still use the same
+// XMLHttpRequest and fetch APIs that the webpage can use and be recognized from
+// the target server with the same origin and referer headers of the target webpage
+// (see Bug 1295660 for a rationale).
+add_task(async function test_page_xhr() {
+ async function contentScript() {
+ const content = this.content;
+
+ const { webpageFetchResult, webpageXhrResult } = await new Promise(
+ resolve => {
+ const listenPageMessage = event => {
+ if (!event.data || event.data.type !== "testPageGlobals") {
+ return;
+ }
+
+ window.removeEventListener("message", listenPageMessage);
+
+ browser.test.assertEq(
+ true,
+ !!content.XMLHttpRequest,
+ "The content script should have access to content.XMLHTTPRequest"
+ );
+ browser.test.assertEq(
+ true,
+ !!content.fetch,
+ "The content script should have access to window.pageFetch"
+ );
+
+ resolve(event.data);
+ };
+
+ window.addEventListener("message", listenPageMessage);
+
+ window.postMessage({}, "*");
+ }
+ );
+
+ const url = new URL("/return_headers.sjs", location).href;
+
+ await Promise.all([
+ new Promise((resolve, reject) => {
+ const req = new content.XMLHttpRequest();
+ req.open("GET", url);
+ req.addEventListener("load", () =>
+ resolve(JSON.parse(req.responseText))
+ );
+ req.addEventListener("error", reject);
+ req.send();
+ }),
+ content.fetch(url).then(res => res.json()),
+ ])
+ .then(async ([xhrResult, fetchResult]) => {
+ browser.test.assertEq(
+ webpageFetchResult.referer,
+ fetchResult.referer,
+ "window.pageFetch referrer is the same of a webpage fetch request"
+ );
+ browser.test.assertEq(
+ webpageFetchResult.origin,
+ fetchResult.origin,
+ "window.pageFetch origin is the same of a webpage fetch request"
+ );
+
+ browser.test.assertEq(
+ webpageXhrResult.referer,
+ xhrResult.referer,
+ "content.XMLHttpRequest referrer is the same of a webpage fetch request"
+ );
+ })
+ .catch(error => {
+ browser.test.fail(`Unexpected error: ${error}`);
+ });
+
+ browser.test.notifyPass("content-script-page-xhr");
+ }
+
+ let extensionData = {
+ manifest: {
+ content_scripts: [
+ {
+ matches: ["http://xpcshell.test/*"],
+ js: ["content.js"],
+ },
+ ],
+ },
+ files: {
+ "content.js": `(${contentScript})()`,
+ },
+ };
+
+ let extension = ExtensionTestUtils.loadExtension(extensionData);
+ await extension.startup();
+
+ let contentPage = await ExtensionTestUtils.loadContentPage(
+ "http://xpcshell.test/data/file_page_xhr.html"
+ );
+ await extension.awaitFinish("content-script-page-xhr");
+ await contentPage.close();
+
+ await extension.unload();
+});