2 const { TestUtils } = ChromeUtils.importESModule(
3 "resource://testing-common/TestUtils.sys.mjs"
5 const { XPCShellContentUtils } = ChromeUtils.importESModule(
6 "resource://testing-common/XPCShellContentUtils.sys.mjs"
8 const { ExtensionTestUtils } = ChromeUtils.importESModule(
9 "resource://testing-common/ExtensionXPCShellUtils.sys.mjs"
12 XPCShellContentUtils.init(this);
13 ExtensionTestUtils.init(this);
15 const server = XPCShellContentUtils.createHttpServer({
16 hosts: ["example.com", "example.org"],
19 server.registerPathHandler("/static_frames", (request, response) => {
20 response.setHeader("Content-Type", "text/html");
22 <iframe name="same_origin" sandbox="allow-scripts allow-same-origin" src="http://example.com/frame"></iframe>
23 <iframe name="same_origin_sandbox" sandbox="allow-scripts" src="http://example.com/frame"></iframe>
24 <iframe name="cross_origin" sandbox="allow-scripts allow-same-origin" src="http://example.org/frame"></iframe>
25 <iframe name="cross_origin_sandbox" sandbox="allow-scripts" src="http://example.org/frame"></iframe>
26 <iframe name="data_uri" sandbox="allow-scripts allow-same-origin" src="data:text/html,<h1>Data Subframe</h1>"></iframe>
27 <iframe name="data_uri_sandbox" sandbox="allow-scripts" src="data:text/html,<h1>Data Subframe</h1>"></iframe>
28 <iframe name="srcdoc" sandbox="allow-scripts allow-same-origin" srcdoc="<h1>Srcdoc Subframe</h1>"></iframe>
29 <iframe name="srcdoc_sandbox" sandbox="allow-scripts" srcdoc="<h1>Srcdoc Subframe</h1>"></iframe>
30 <iframe name="blank" sandbox="allow-scripts allow-same-origin"></iframe>
31 <iframe name="blank_sandbox" sandbox="allow-scripts"></iframe>
32 <iframe name="redirect_com" sandbox="allow-scripts allow-same-origin" src="/redirect?com"></iframe>
33 <iframe name="redirect_com_sandbox" sandbox="allow-scripts" src="/redirect?com"></iframe>
34 <iframe name="redirect_org" sandbox="allow-scripts allow-same-origin" src="/redirect?org"></iframe>
35 <iframe name="redirect_org_sandbox" sandbox="allow-scripts" src="/redirect?org"></iframe>
36 <iframe name="ext_redirect_com_com" sandbox="allow-scripts allow-same-origin" src="/ext_redirect?com"></iframe>
37 <iframe name="ext_redirect_com_com_sandbox" sandbox="allow-scripts" src="/ext_redirect?com"></iframe>
38 <iframe name="ext_redirect_org_com" sandbox="allow-scripts allow-same-origin" src="http://example.org/ext_redirect?com"></iframe>
39 <iframe name="ext_redirect_org_com_sandbox" sandbox="allow-scripts" src="http://example.org/ext_redirect?com"></iframe>
40 <iframe name="ext_redirect_com_org" sandbox="allow-scripts allow-same-origin" src="/ext_redirect?org"></iframe>
41 <iframe name="ext_redirect_com_org_sandbox" sandbox="allow-scripts" src="/ext_redirect?org"></iframe>
42 <iframe name="ext_redirect_org_org" sandbox="allow-scripts allow-same-origin" src="http://example.org/ext_redirect?org"></iframe>
43 <iframe name="ext_redirect_org_org_sandbox" sandbox="allow-scripts" src="http://example.org/ext_redirect?org"></iframe>
44 <iframe name="ext_redirect_com_data" sandbox="allow-scripts allow-same-origin" src="/ext_redirect?data"></iframe>
45 <iframe name="ext_redirect_com_data_sandbox" sandbox="allow-scripts" src="/ext_redirect?data"></iframe>
46 <iframe name="ext_redirect_org_data" sandbox="allow-scripts allow-same-origin" src="http://example.org/ext_redirect?data"></iframe>
47 <iframe name="ext_redirect_org_data_sandbox" sandbox="allow-scripts" src="http://example.org/ext_redirect?data"></iframe>
49 <!-- XXX(nika): These aren't static as they perform loads dynamically - perhaps consider testing them separately? -->
50 <iframe name="client_replace_org_blank" sandbox="allow-scripts allow-same-origin" src="http://example.org/client_replace?blank"></iframe>
51 <iframe name="client_replace_org_blank_sandbox" sandbox="allow-scripts" src="http://example.org/client_replace?blank"></iframe>
52 <iframe name="client_replace_org_data" sandbox="allow-scripts allow-same-origin" src="http://example.org/client_replace?data"></iframe>
53 <iframe name="client_replace_org_data_sandbox" sandbox="allow-scripts" src="http://example.org/client_replace?data"></iframe>
57 server.registerPathHandler("/frame", (request, response) => {
58 response.setHeader("Content-Type", "text/html");
59 response.write(`<h1>HTTP Subframe</h1>`);
62 server.registerPathHandler("/redirect", (request, response) => {
64 if (request.queryString == "com") {
65 redirect = "http://example.com/frame";
66 } else if (request.queryString == "org") {
67 redirect = "http://example.org/frame";
69 response.setStatusLine(request.httpVersion, 404, "Not found");
73 response.setStatusLine(request.httpVersion, 302, "Found");
74 response.setHeader("Location", redirect);
77 server.registerPathHandler("/client_replace", (request, response) => {
79 if (request.queryString == "blank") {
80 redirect = "about:blank";
81 } else if (request.queryString == "data") {
82 redirect = "data:text/html,<h1>Data Subframe</h1>";
84 response.setStatusLine(request.httpVersion, 404, "Not found");
88 response.setHeader("Content-Type", "text/html");
91 window.location.replace(${JSON.stringify(redirect)});
96 add_task(async function sandboxed_precursor() {
97 // Bug 1725345: Make XPCShellContentUtils.createHttpServer support https
98 Services.prefs.setBoolPref("dom.security.https_first", false);
100 let extension = await ExtensionTestUtils.loadExtension({
102 permissions: ["webRequest", "webRequestBlocking", "<all_urls>"],
105 // eslint-disable-next-line no-undef
106 browser.webRequest.onBeforeRequest.addListener(
108 let url = new URL(details.url);
109 if (!url.pathname.includes("ext_redirect")) {
114 if (url.search == "?com") {
115 redirectUrl = "http://example.com/frame";
116 } else if (url.search == "?org") {
117 redirectUrl = "http://example.org/frame";
118 } else if (url.search == "?data") {
119 redirectUrl = "data:text/html,<h1>Data Subframe</h1>";
121 return { redirectUrl };
123 { urls: ["<all_urls>"] },
128 await extension.startup();
130 registerCleanupFunction(async function () {
131 await extension.unload();
134 for (let userContextId of [undefined, 1]) {
135 let comURI = Services.io.newURI("http://example.com");
136 let comPrin = Services.scriptSecurityManager.createContentPrincipal(
140 let orgURI = Services.io.newURI("http://example.org");
141 let orgPrin = Services.scriptSecurityManager.createContentPrincipal(
146 let page = await XPCShellContentUtils.loadContentPage(
147 "http://example.com/static_frames",
150 remoteSubframes: true,
154 let bc = page.browsingContext;
157 bc.currentWindowGlobal.documentPrincipal.equals(comPrin),
158 "toplevel principal matches"
161 // XXX: This is sketchy as heck, but it's also the easiest way to wait for
162 // the `window.location.replace` loads to finish.
163 await TestUtils.waitForCondition(
167 !child.currentWindowGlobal.documentURI.spec.includes(
171 "wait for every client_replace global to be replaced"
175 for (let child of bc.children) {
176 notEqual(child.name, "", "child frames must have names");
177 ok(!(child.name in principals), "duplicate child frame name");
178 principals[child.name] = child.currentWindowGlobal.documentPrincipal;
181 function principal_is(name, expected) {
182 let principal = principals[name];
183 info(`${name} = ${principal.origin}`);
184 ok(principal.equals(expected), `${name} is correct`);
186 function precursor_is(name, precursor) {
187 let principal = principals[name];
188 info(`${name} = ${principal.origin}`);
189 ok(principal.isNullPrincipal, `${name} is null`);
191 principal.precursorPrincipal.equals(precursor),
192 `${name} has the correct precursor`
196 // Basic loads should have the principals or precursor principals for the
197 // document being loaded.
198 principal_is("same_origin", comPrin);
199 precursor_is("same_origin_sandbox", comPrin);
201 principal_is("cross_origin", orgPrin);
202 precursor_is("cross_origin_sandbox", orgPrin);
204 // Loads of a data: URI should complete with a sandboxed principal based on
205 // the principal which tried to perform the load.
206 precursor_is("data_uri", comPrin);
207 precursor_is("data_uri_sandbox", comPrin);
209 // Loads which inherit principals, such as srcdoc an about:blank loads,
210 // should also inherit sandboxed precursor principals.
211 principal_is("srcdoc", comPrin);
212 precursor_is("srcdoc_sandbox", comPrin);
214 principal_is("blank", comPrin);
215 precursor_is("blank_sandbox", comPrin);
217 // Redirects shouldn't interfere with the final principal, and it should be
218 // based only on the final URI.
219 principal_is("redirect_com", comPrin);
220 precursor_is("redirect_com_sandbox", comPrin);
222 principal_is("redirect_org", orgPrin);
223 precursor_is("redirect_org_sandbox", orgPrin);
225 // Extension redirects should act like normal redirects, and still resolve
226 // with the principal or sandboxed principal of the final URI.
227 principal_is("ext_redirect_com_com", comPrin);
228 precursor_is("ext_redirect_com_com_sandbox", comPrin);
230 principal_is("ext_redirect_com_org", orgPrin);
231 precursor_is("ext_redirect_com_org_sandbox", orgPrin);
233 principal_is("ext_redirect_org_com", comPrin);
234 precursor_is("ext_redirect_org_com_sandbox", comPrin);
236 principal_is("ext_redirect_org_org", orgPrin);
237 precursor_is("ext_redirect_org_org_sandbox", orgPrin);
239 // When an extension redirects to a data: URI, we use the last non-data: URI
240 // in the chain as the precursor principal.
241 // FIXME: This should perhaps use the extension's principal instead?
242 precursor_is("ext_redirect_com_data", comPrin);
243 precursor_is("ext_redirect_com_data_sandbox", comPrin);
245 precursor_is("ext_redirect_org_data", orgPrin);
246 precursor_is("ext_redirect_org_data_sandbox", orgPrin);
248 // Check that navigations triggred by script within the frames will have the
249 // correct behaviour when navigating to blank and data URIs.
250 principal_is("client_replace_org_blank", orgPrin);
251 precursor_is("client_replace_org_blank_sandbox", orgPrin);
253 precursor_is("client_replace_org_data", orgPrin);
254 precursor_is("client_replace_org_data_sandbox", orgPrin);
258 Services.prefs.clearUserPref("dom.security.https_first");