Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test gets skipped with pattern: os == 'win' && socketprocess_networking && fission
- Manifest: toolkit/components/extensions/test/xpcshell/xpcshell-remote.toml includes toolkit/components/extensions/test/xpcshell/xpcshell-common.toml
- Manifest: toolkit/components/extensions/test/xpcshell/xpcshell.toml includes toolkit/components/extensions/test/xpcshell/xpcshell-common.toml
"use strict";
const server = createHttpServer({ hosts: ["example.com"] });
server.registerPathHandler("/dummy", (request, response) => {
response.setStatusLine(request.httpVersion, 200, "OK");
response.setHeader("Content-Type", "text/html", false);
response.write("<!DOCTYPE html><html></html>");
});
// contentScript is serialized and run as a content script.
async function testContentScript(contentScript) {
async function runContentScript(contentScriptFn) {
try {
await contentScriptFn();
} catch (e) {
browser.test.fail(`Unexpected error: ${e}`);
}
browser.test.sendMessage("done");
}
let extension = ExtensionTestUtils.loadExtension({
manifest: {
content_scripts: [
{
js: ["contentscript.js"],
run_at: "document_end",
matches: ["*://example.com/dummy"],
},
],
},
files: {
"contentscript.js": `(${runContentScript})(${contentScript})`,
},
});
await extension.startup();
let contentPage = await ExtensionTestUtils.loadContentPage(
);
await extension.awaitMessage("done");
await contentPage.close();
await extension.unload();
}
add_task(async function test_document_adoptedStyleSheets_assign_array() {
await testContentScript(async () => {
const sheet = new CSSStyleSheet();
sheet.replaceSync("body { color: pink; }");
document.adoptedStyleSheets = [sheet];
browser.test.assertEq(
"rgb(255, 192, 203)",
getComputedStyle(document.body).color,
"Style applied through array assignment to adoptedStyleSheets"
);
});
});
add_task(async function test_document_adoptedStyleSheets_push_sheet() {
await testContentScript(async () => {
const sheet = new CSSStyleSheet();
sheet.replaceSync("body { color: pink; }");
document.adoptedStyleSheets.push(sheet);
browser.test.assertEq(
"rgb(255, 192, 203)",
getComputedStyle(document.body).color,
"Style applied through document.adoptedStyleSheets.push(sheet)"
);
});
});
add_task(async function test_document_adoptedStyleSheets_assign_index() {
await testContentScript(async () => {
const sheet = new CSSStyleSheet();
sheet.replaceSync("body { color: pink; }");
document.adoptedStyleSheets[0] = sheet;
browser.test.assertEq(
"rgb(255, 192, 203)",
getComputedStyle(document.body).color,
"Style applied through document.adoptedStyleSheets[0] = sheet"
);
});
});
// Test that adoptedStyleSheets is shared between content script and web page.
add_task(async function test_document_adoptedStyleSheets_visibility() {
await testContentScript(async () => {
// eslint-disable-next-line no-eval
window.eval(`{
const sheet = new CSSStyleSheet();
sheet.replaceSync("body { color: yellow; }");
document.adoptedStyleSheets = [sheet];
}`);
browser.test.assertEq(
"body { color: yellow; }",
document.adoptedStyleSheets[0].cssRules[0].cssText,
"adoptedStyleSheets from page is visible in content script"
);
const sheet = new CSSStyleSheet();
sheet.replaceSync("body { color: pink; }");
document.adoptedStyleSheets.push(sheet);
browser.test.assertEq(
"body { color: pink; }",
// eslint-disable-next-line no-eval
window.eval(`document.adoptedStyleSheets[1].cssRules[0].cssText`),
"adoptedStyleSheets from content script is visible in page"
);
document.adoptedStyleSheets = [];
browser.test.assertEq(
0,
// eslint-disable-next-line no-eval
window.eval(`document.adoptedStyleSheets.length`),
"adoptedStyleSheets length in page is 0 after assigning []"
);
});
});
// For completeness, verify behavior against shadowRoot.adoptedStyleSheets, in
// case its implementation may differ from document.adoptedStyleSheets.
add_task(async function test_shadowRoot_adoptedStyleSheets() {
await testContentScript(async () => {
const host = document.createElement("div");
document.body.append(host);
const shadowRoot = host.attachShadow({ mode: "closed" });
const sheet = new CSSStyleSheet();
sheet.replaceSync(":host { color: pink; }");
shadowRoot.adoptedStyleSheets = [sheet];
browser.test.assertEq(
"rgb(255, 192, 203)",
getComputedStyle(host).color,
"Style applied on shadowRoot.adoptedStyleSheets"
);
});
});
add_task(async function test_adoptedStyleSheets_protected_by_xrays() {
await testContentScript(async () => {
// eslint-disable-next-line no-eval
window.eval(`
Array.prototype.customProp = 1;
Array.prototype.push = () => { throw new Error("Intercepted!"); };
Array.prototype[Symbol.iterator] = () => { throw new Error("No iter!"); };
`);
const sheet = new CSSStyleSheet();
sheet.replaceSync("body { color: pink; }");
// Should not be intercepted by web page.
document.adoptedStyleSheets.push(sheet);
browser.test.assertEq(1, document.adoptedStyleSheets.length, "Has style");
document.adoptedStyleSheets = [];
browser.test.assertEq(0, document.adoptedStyleSheets.length, "Cleared");
browser.test.assertThrows(
() => {
// As a sanity check, verify behavior of JSXrayTraits::defineProperty.
document.adoptedStyleSheets.pop = () => {};
},
"Not allowed to define cross-origin object as property on [Object] or [Array] XrayWrapper",
"document.adoptedStyleSheets is a JS XrayWrapper"
);
browser.test.assertEq(
undefined,
document.adoptedStyleSheets.customProp,
"XrayWrapper hides custom property on adoptedStyleSheets"
);
browser.test.assertEq(
1,
document.adoptedStyleSheets.wrappedJSObject.customProp,
"With Xrays waived, custom property exposed on adoptedStyleSheets"
);
let proto = Object.getPrototypeOf(document.adoptedStyleSheets);
browser.test.assertTrue(
proto === window.Array.prototype,
"Prototype is window's Array.prototype"
);
browser.test.assertTrue(
proto !== Array.prototype,
"Prototype is distinct from the content script's Array.prototype"
);
});
});