Bug 1839315: part 4) Link from `SheetLoadData::mWasAlternate` to spec. r=emilio DONTBUILD
[gecko.git] / caps / tests / unit / test_precursor_principal.js
blob37c1ae13bcdeab4ceab45de8685f9d5085e6bb0a
1 "use strict";
2 const { TestUtils } = ChromeUtils.importESModule(
3   "resource://testing-common/TestUtils.sys.mjs"
4 );
5 const { XPCShellContentUtils } = ChromeUtils.importESModule(
6   "resource://testing-common/XPCShellContentUtils.sys.mjs"
7 );
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"],
17 });
19 server.registerPathHandler("/static_frames", (request, response) => {
20   response.setHeader("Content-Type", "text/html");
21   response.write(`
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>
54   `);
55 });
57 server.registerPathHandler("/frame", (request, response) => {
58   response.setHeader("Content-Type", "text/html");
59   response.write(`<h1>HTTP Subframe</h1>`);
60 });
62 server.registerPathHandler("/redirect", (request, response) => {
63   let redirect;
64   if (request.queryString == "com") {
65     redirect = "http://example.com/frame";
66   } else if (request.queryString == "org") {
67     redirect = "http://example.org/frame";
68   } else {
69     response.setStatusLine(request.httpVersion, 404, "Not found");
70     return;
71   }
73   response.setStatusLine(request.httpVersion, 302, "Found");
74   response.setHeader("Location", redirect);
75 });
77 server.registerPathHandler("/client_replace", (request, response) => {
78   let redirect;
79   if (request.queryString == "blank") {
80     redirect = "about:blank";
81   } else if (request.queryString == "data") {
82     redirect = "data:text/html,<h1>Data Subframe</h1>";
83   } else {
84     response.setStatusLine(request.httpVersion, 404, "Not found");
85     return;
86   }
88   response.setHeader("Content-Type", "text/html");
89   response.write(`
90     <script>
91       window.location.replace(${JSON.stringify(redirect)});
92     </script>
93   `);
94 });
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({
101     manifest: {
102       permissions: ["webRequest", "webRequestBlocking", "<all_urls>"],
103     },
104     background() {
105       // eslint-disable-next-line no-undef
106       browser.webRequest.onBeforeRequest.addListener(
107         details => {
108           let url = new URL(details.url);
109           if (!url.pathname.includes("ext_redirect")) {
110             return {};
111           }
113           let redirectUrl;
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>";
120           }
121           return { redirectUrl };
122         },
123         { urls: ["<all_urls>"] },
124         ["blocking"]
125       );
126     },
127   });
128   await extension.startup();
130   registerCleanupFunction(async function () {
131     await extension.unload();
132   });
134   for (let userContextId of [undefined, 1]) {
135     let comURI = Services.io.newURI("http://example.com");
136     let comPrin = Services.scriptSecurityManager.createContentPrincipal(
137       comURI,
138       { userContextId }
139     );
140     let orgURI = Services.io.newURI("http://example.org");
141     let orgPrin = Services.scriptSecurityManager.createContentPrincipal(
142       orgURI,
143       { userContextId }
144     );
146     let page = await XPCShellContentUtils.loadContentPage(
147       "http://example.com/static_frames",
148       {
149         remote: true,
150         remoteSubframes: true,
151         userContextId,
152       }
153     );
154     let bc = page.browsingContext;
156     ok(
157       bc.currentWindowGlobal.documentPrincipal.equals(comPrin),
158       "toplevel principal matches"
159     );
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(
164       () =>
165         bc.children.every(
166           child =>
167             !child.currentWindowGlobal.documentURI.spec.includes(
168               "/client_replace"
169             )
170         ),
171       "wait for every client_replace global to be replaced"
172     );
174     let principals = {};
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;
179     }
181     function principal_is(name, expected) {
182       let principal = principals[name];
183       info(`${name} = ${principal.origin}`);
184       ok(principal.equals(expected), `${name} is correct`);
185     }
186     function precursor_is(name, precursor) {
187       let principal = principals[name];
188       info(`${name} = ${principal.origin}`);
189       ok(principal.isNullPrincipal, `${name} is null`);
190       ok(
191         principal.precursorPrincipal.equals(precursor),
192         `${name} has the correct precursor`
193       );
194     }
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);
256     await page.close();
257   }
258   Services.prefs.clearUserPref("dom.security.https_first");