1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
|
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script src="/tests/SimpleTest/ExtensionTestUtils.js"></script>
<script type="text/javascript" src="head_webrequest.js"></script>
<script type="text/javascript" src="head.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script>
"use strict";
let extensionData = {
manifest: {
permissions: ["webRequest", "webRequestBlocking", "<all_urls>", "tabs"],
},
background() {
browser.webRequest.onBeforeRequest.addListener(details => {
if (details.url.endsWith("/favicon.ico")) {
// We don't care about favicon.ico in this test. It is hard to control
// whether the request happens.
browser.test.log(`Ignoring favicon request: ${details.url}`);
return;
}
browser.test.sendMessage("onBeforeRequest", details);
}, {urls: ["<all_urls>"]}, ["blocking"]);
let tab;
browser.tabs.onCreated.addListener(newTab => {
browser.test.sendMessage("tab-created");
tab = newTab;
});
browser.test.onMessage.addListener(msg => {
if (msg === "close-tab") {
browser.tabs.remove(tab.id);
browser.test.sendMessage("tab-closed");
}
});
},
};
let expected = {
"file_simple_xhr.html": {
type: "main_frame",
toplevel: true,
},
"file_image_good.png": {
type: "image",
toplevel: true,
origin: "file_simple_xhr.html",
},
"example.txt": {
type: "xmlhttprequest",
toplevel: true,
origin: "file_simple_xhr.html",
},
// sub frames will have the origin and first ancestor is the
// parent document
"file_simple_xhr_frame.html": {
type: "sub_frame",
toplevelParent: true,
origin: "file_simple_xhr.html",
parent: "file_simple_xhr.html",
},
// a resource in a sub frame will have origin of the subframe,
// but the ancestor chain starts with the parent document
"xhr_resource": {
type: "xmlhttprequest",
origin: "file_simple_xhr_frame.html",
parent: "file_simple_xhr.html",
},
"file_image_bad.png": {
type: "image",
depth: 2,
origin: "file_simple_xhr_frame.html",
parent: "file_simple_xhr.html",
},
"file_simple_xhr_frame2.html": {
type: "sub_frame",
depth: 2,
origin: "file_simple_xhr_frame.html",
parent: "file_simple_xhr_frame.html",
},
"file_image_redirect.png": {
type: "image",
depth: 2,
origin: "file_simple_xhr_frame2.html",
parent: "file_simple_xhr_frame.html",
},
"xhr_resource_2": {
type: "xmlhttprequest",
depth: 2,
origin: "file_simple_xhr_frame2.html",
parent: "file_simple_xhr_frame.html",
},
// This is loaded in a sandbox iframe. originUrl is not available for that,
// and requests within a sandboxed iframe will additionally have an empty
// url on their immediate parent/ancestor.
"file_simple_sandboxed_frame.html": {
type: "sub_frame",
depth: 3,
parent: "file_simple_xhr_frame2.html",
},
"xhr_sandboxed": {
type: "xmlhttprequest",
sandboxed: true,
depth: 3,
parent: "",
},
"file_image_great.png": {
type: "image",
sandboxed: true,
depth: 3,
parent: "",
},
"file_simple_sandboxed_subframe.html": {
type: "sub_frame",
depth: 4,
parent: "",
},
};
function checkDetails(details) {
let url = new URL(details.url);
let filename = url.pathname.split("/").pop();
ok(filename in expected, `Should be expecting a request for ${filename}`);
let expect = expected[filename];
is(expect.type, details.type, `${details.type} type matches`);
if (details.parentFrameId == -1) {
is(details.frameAncestors.length, 0, "no ancestors for main_frame requests");
} else if (details.parentFrameId == 0) {
is(details.frameAncestors.length, 1, "one ancestors for sub_frame requests");
} else {
ok(details.frameAncestors.length > 1, "have multiple ancestors for deep subframe requests");
is(details.frameAncestors.length, expect.depth, "have multiple ancestors for deep subframe requests");
}
if (details.parentFrameId > -1) {
ok(!expect.origin || details.originUrl.includes(expect.origin), "origin url is correct");
is(details.frameAncestors[0].frameId, details.parentFrameId, "first ancestor matches request.parentFrameId");
ok(details.frameAncestors[0].url.includes(expect.parent), "ancestor parent page correct");
is(details.frameAncestors[details.frameAncestors.length - 1].frameId, 0, "last ancestor is always zero");
// All our tests should be somewhere within the frame that we set topframe in the query string. That
// frame will always be the last ancestor.
ok(details.frameAncestors[details.frameAncestors.length - 1].url.includes("topframe=true"), "last ancestor is always topframe");
}
if (expect.toplevel) {
is(details.frameId, 0, "expect load at top level");
is(details.parentFrameId, -1, "expect top level frame to have no parent");
} else if (details.type == "sub_frame") {
ok(details.frameId > 0, "expect sub_frame to load into a new frame");
if (expect.toplevelParent) {
is(details.parentFrameId, 0, "expect sub_frame to have top level parent");
is(details.frameAncestors.length, 1, "one ancestor for top sub_frame request");
} else {
ok(details.parentFrameId > 0, "expect sub_frame to have parent");
ok(details.frameAncestors.length > 1, "sub_frame has ancestors");
}
expect.subframeId = details.frameId;
expect.parentId = details.parentFrameId;
} else if (expect.sandboxed) {
is(details.documentUrl, undefined, "null principal documentUrl for sandboxed request");
} else {
// get the parent frame.
let purl = new URL(details.documentUrl);
let pfilename = purl.pathname.split("/").pop();
let parent = expected[pfilename];
is(details.frameId, parent.subframeId, "expect load in subframe");
is(details.parentFrameId, parent.parentId, "expect subframe parent");
}
return filename;
}
add_task(async function test_webRequest_main_frame() {
// Clear the image cache, since it gets in the way otherwise.
let imgTools = SpecialPowers.Cc["@mozilla.org/image/tools;1"].getService(SpecialPowers.Ci.imgITools);
let cache = imgTools.getImgCacheForDocument(document);
cache.clearCache(false);
await SpecialPowers.spawnChrome([], async () => {
Services.cache2.clear();
});
let extension = ExtensionTestUtils.loadExtension(extensionData);
await extension.startup();
let a = addLink(`file_simple_xhr.html?topframe=true&nocache=${Math.random()}`);
a.click();
let remaining = new Set(Object.keys(expected));
let totalExpectedCount = remaining.size;
for (let i = 0; i < totalExpectedCount; i++) {
info(`Waiting for request ${i + 1} out of ${totalExpectedCount}`);
info(`Expecting one of: ${Array.from(remaining)}`);
let details = await extension.awaitMessage("onBeforeRequest");
info(`Checking details for request ${i}: ${JSON.stringify(details)}`);
let filename = checkDetails(details);
ok(remaining.delete(filename), `Got only one request for ${filename}`);
}
await extension.awaitMessage("tab-created");
extension.sendMessage("close-tab");
await extension.awaitMessage("tab-closed");
await extension.unload();
});
</script>
</head>
<body>
<div id="test">Sample text</div>
</body>
</html>
|