Bug 1745818 - Treat host permissions as optional in mv3, r=robwu
[gecko.git] / toolkit / components / extensions / test / mochitest / test_ext_scripting_insertCSS.html
blob3e2cef87214d28d29bf9c8b639d15cfd37152fe3
1 <!DOCTYPE HTML>
2 <html>
3 <head>
4 <meta charset="utf-8">
5 <title>Tests scripting.insertCSS()</title>
6 <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
7 <script type="text/javascript" src="/tests/SimpleTest/ExtensionTestUtils.js"></script>
8 <script type="text/javascript" src="head.js"></script>
9 <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
10 </head>
11 <body>
13 <script type="text/javascript">
14 "use strict";
16 const MOCHITEST_HOST_PERMISSIONS = [
17 "*://mochi.test/",
18 "*://mochi.xorigin-test/",
19 "*://test1.example.com/",
22 const makeExtension = ({ manifest: manifestProps, ...otherProps }) => {
23 return ExtensionTestUtils.loadExtension({
24 manifest: {
25 manifest_version: 3,
26 permissions: ["scripting"],
27 host_permissions: [
28 ...MOCHITEST_HOST_PERMISSIONS,
29 // Used in `file_contains_iframe.html`
30 "https://example.org/",
32 granted_host_permissions: true,
33 ...manifestProps,
35 useAddonManager: "temporary",
36 ...otherProps,
37 });
40 add_task(async function setup() {
41 await SpecialPowers.pushPrefEnv({
42 set: [["extensions.manifestV3.enabled", true]],
43 });
44 });
46 add_task(async function test_insertCSS_and_removeCSS_params_validation() {
47 let extension = makeExtension({
48 async background() {
49 const tabs = await browser.tabs.query({ active: true });
51 const TEST_CASES = [
53 title: "no files and no css",
54 cssParams: {},
55 expectedError: "Exactly one of files and css must be specified.",
58 title: "both files and css are passed",
59 cssParams: {
60 files: ["styles.css"],
61 css: "* { background: rgb(1, 1, 1) }",
63 expectedError: "Exactly one of files and css must be specified.",
66 title: "both allFrames and frameIds are passed",
67 cssParams: {
68 target: {
69 tabId: tabs[0].id,
70 allFrames: true,
71 frameIds: [1, 2, 3],
73 files: ["styles.css"],
75 expectedError: "Cannot specify both 'allFrames' and 'frameIds'.",
78 title: "empty css string with a file",
79 cssParams: {
80 css: "",
81 files: ["styles.css"],
83 expectedError: "Exactly one of files and css must be specified.",
87 for (const { title, cssParams, expectedError } of TEST_CASES) {
88 await browser.test.assertRejects(
89 browser.scripting.insertCSS({
90 target: { tabId: tabs[0].id },
91 ...cssParams,
92 }),
93 expectedError,
94 `${title} - expected error for insertCSS()`
97 await browser.test.assertRejects(
98 browser.scripting.removeCSS({
99 target: { tabId: tabs[0].id },
100 ...cssParams,
102 expectedError,
103 `${title} - expected error for removeCSS()`
107 browser.test.notifyPass("checks-done");
111 await extension.startup();
112 await extension.awaitFinish("checks-done");
113 await extension.unload();
116 add_task(async function test_insertCSS_with_invalid_tabId() {
117 let extension = makeExtension({
118 async background() {
119 // This tab ID should not exist.
120 const tabId = 123456789;
122 await browser.test.assertRejects(
123 browser.scripting.insertCSS({
124 target: { tabId },
125 css: "* { background: rgb(1, 1, 1) }",
127 `Invalid tab ID: ${tabId}`
130 browser.test.notifyPass("insert-css");
134 await extension.startup();
135 await extension.awaitFinish("insert-css");
136 await extension.unload();
139 add_task(async function test_insertCSS_with_wrong_host_permissions() {
140 let extension = makeExtension({
141 manifest: {
142 host_permissions: [],
144 async background() {
145 const tabs = await browser.tabs.query({ active: true });
147 browser.test.assertEq(1, tabs.length, "expected 1 tab");
149 browser.test.assertRejects(
150 browser.scripting.insertCSS({
151 target: { tabId: tabs[0].id },
152 css: "* { background: rgb(1, 1, 1) }",
154 /Missing host permission for the tab/,
155 "expected host permission error"
158 browser.test.notifyPass("insert-css");
162 await extension.startup();
163 await extension.awaitFinish("insert-css");
164 await extension.unload();
167 add_task(async function test_insertCSS_and_removeCSS() {
168 let extension = makeExtension({
169 manifest: {
170 permissions: ["scripting", "webNavigation"],
172 async background() {
173 const tabs = await browser.tabs.query({ active: true });
174 browser.test.assertEq(1, tabs.length, "expected 1 tab");
176 const tabId = tabs[0].id;
178 const frames = await browser.webNavigation.getAllFrames({ tabId });
179 // 1. Top-level frame that loads `file_contains_iframe.html`
180 // 2. Frame that loads `file_contains_img.html`
181 browser.test.assertEq(2, frames.length, "expected 2 frames");
182 const frameIds = frames.map(frame => frame.frameId);
184 const cssColor1 = "rgb(1, 1, 1)";
185 const cssColor2 = "rgb(2, 2, 2)";
186 const cssColorInFile1 = "rgb(3, 3, 3)";
187 const defaultColor = "rgba(0, 0, 0, 0)";
189 const TEST_CASES = [
191 title: "with css prop",
192 elementId: "div-1",
193 cssParams: [
195 target: { tabId },
196 css: `#div-1 { background: ${cssColor1} }`,
199 expectedResults: [cssColor1, defaultColor],
202 title: "with a file",
203 elementId: "div-2",
204 cssParams: [
206 target: { tabId },
207 files: ["file1.css"],
210 expectedResults: [cssColorInFile1, defaultColor],
213 title: "css prop in a single frame",
214 elementId: "div-3",
215 cssParams: [
217 target: { tabId, frameIds: [frameIds[0]] },
218 css: `#div-3 { background: ${cssColor2} }`,
221 expectedResults: [cssColor2, defaultColor],
224 title: "css prop in multiple frames",
225 elementId: "div-4",
226 cssParams: [
228 target: { tabId, frameIds },
229 css: `#div-4 { background: ${cssColor1} }`,
232 expectedResults: [cssColor1, cssColor1],
235 title: "allFrames is true",
236 elementId: "div-5",
237 cssParams: [
239 target: { tabId, allFrames: true },
240 css: `#div-5 { background: ${defaultColor} }`,
243 expectedResults: [defaultColor, defaultColor],
246 title: "origin: 'AUTHOR'",
247 elementId: "div-6",
248 cssParams: [
250 target: { tabId },
251 css: `#div-6 { background: ${cssColor1} }`,
252 origin: "AUTHOR",
255 target: { tabId },
256 css: `#div-6 { background: ${cssColor2} }`,
257 origin: "AUTHOR",
260 expectedResults: [cssColor2, defaultColor],
263 title: "origin: 'USER'",
264 elementId: "div-7",
265 cssParams: [
267 target: { tabId },
268 css: `#div-7 { background: ${cssColor1} !important }`,
269 origin: "USER",
272 target: { tabId },
273 css: `#div-7 { background: ${cssColor2} !important }`,
274 origin: "AUTHOR",
277 // User has higher importance.
278 expectedResults: [cssColor1, defaultColor],
281 title: "empty css string",
282 elementId: "div-8",
283 cssParams: [
285 target: { tabId },
286 css: "",
289 expectedResults: [defaultColor, defaultColor],
292 title: "allFrames is false",
293 elementId: "div-9",
294 cssParams: [
296 target: { tabId, allFrames: false },
297 css: `#div-9 { background: ${cssColor1} }`,
300 expectedResults: [cssColor1, defaultColor],
304 const getBackgroundColor = elementId => {
305 return window.getComputedStyle(document.getElementById(elementId))
306 .backgroundColor;
309 for (const {
310 title,
311 elementId,
312 cssParams,
313 expectedResults,
314 } of TEST_CASES) {
315 // Create a unique element for the current test case.
316 await browser.scripting.executeScript({
317 target: { tabId, allFrames: true },
318 func: elementId => {
319 const element = document.createElement("div");
320 element.setAttribute("id", elementId);
321 document.body.appendChild(element);
323 args: [elementId],
326 for (const params of cssParams) {
327 const result = await browser.scripting.insertCSS(params);
328 // `insertCSS()` should not resolve to a value.
329 browser.test.assertEq(undefined, result, "got expected empty result");
332 let results = await browser.scripting.executeScript({
333 target: { tabId, allFrames: true },
334 func: getBackgroundColor,
335 args: [elementId],
337 results.sort((a, b) => a.frameId - b.frameId);
339 browser.test.assertEq(
340 expectedResults.length,
341 results.length,
342 `${title} - got the expected number of results`
344 results.forEach((result, index) => {
345 browser.test.assertEq(
346 expectedResults[index],
347 result.result,
348 `${title} - got expected result (index=${index}): ${title}`
352 results = await Promise.all(
353 cssParams.map(params => browser.scripting.removeCSS(params))
355 // `removeCSS()` should not resolve to a value.
356 results.forEach(result => {
357 browser.test.assertEq(undefined, result, "got expected empty result");
360 results = await browser.scripting.executeScript({
361 target: { tabId, allFrames: true },
362 func: getBackgroundColor,
363 args: [elementId],
366 browser.test.assertTrue(
367 results.every(({ result }) => result === defaultColor),
368 "got expected default color in all frames"
372 browser.test.notifyPass("insert-and-remove-css");
374 files: {
375 "file1.css": "#div-2 { background: rgb(3, 3, 3) }",
379 let tab = await AppTestDelegate.openNewForegroundTab(
380 window,
381 "https://test1.example.com/tests/toolkit/components/extensions/test/mochitest/file_contains_iframe.html",
382 true
385 await extension.startup();
386 await extension.awaitFinish("insert-and-remove-css");
387 await extension.unload();
389 await AppTestDelegate.removeTab(window, tab);
392 </script>
394 </body>
395 </html>