Bug 1970075 - Relax img-src CSP in alert.xhtml + tests a=pascalc
Original Revision: https://phabricator.services.mozilla.com/D253561 Differential Revision: https://phabricator.services.mozilla.com/D253828
This commit is contained in:
committed by
pchevrel@mozilla.com
parent
e9b26188b9
commit
fff97f3ade
@@ -1356,6 +1356,7 @@ static nsLiteralCString sImgSrcDataBlobAllowList[] = {
|
||||
"chrome://devtools/content/responsive/toolbar.xhtml"_ns,
|
||||
"chrome://devtools/content/shared/sourceeditor/codemirror/cmiframe.html"_ns,
|
||||
"chrome://devtools/content/webconsole/index.html"_ns,
|
||||
"chrome://global/content/alerts/alert.xhtml"_ns,
|
||||
"chrome://global/content/print.html"_ns,
|
||||
};
|
||||
// img-src https:
|
||||
@@ -1382,6 +1383,7 @@ static nsLiteralCString sImgSrcHttpAllowList[] = {
|
||||
"chrome://devtools/content/framework/browser-toolbox/window.html"_ns,
|
||||
"chrome://devtools/content/framework/toolbox-window.xhtml"_ns,
|
||||
"chrome://browser/content/preferences/dialogs/applicationManager.xhtml"_ns,
|
||||
"chrome://global/content/alerts/alert.xhtml"_ns,
|
||||
"chrome://mozapps/content/handling/appChooser.xhtml"_ns,
|
||||
// STOP! Do not add anything to this list.
|
||||
};
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<?csp default-src chrome: resource:; img-src chrome: resource: https: ?>
|
||||
<?csp default-src chrome: resource:; img-src chrome: resource: https: http:
|
||||
data: blob: ?>
|
||||
|
||||
<!DOCTYPE window>
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@ support-files = [
|
||||
["browser_ext_management_themes.js"]
|
||||
skip-if = ["verify"]
|
||||
|
||||
["browser_ext_notifications_useSystemBackend_false.js"]
|
||||
|
||||
["browser_ext_process_crash_handling.js"]
|
||||
skip-if = ["!crashreporter"]
|
||||
|
||||
|
||||
@@ -0,0 +1,184 @@
|
||||
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set sts=2 sw=2 et tw=80: */
|
||||
"use strict";
|
||||
|
||||
// Regression test for: https://bugzilla.mozilla.org/show_bug.cgi?id=1970075
|
||||
//
|
||||
// This test verifies that iconUrl as passed to browser.notifications.create()
|
||||
// can be loaded. By default, the system backend is enabled, for which we can
|
||||
// do little more than verifying that the options are set, but in case the
|
||||
// system backend is disabled, we can verify that the image is actually loaded,
|
||||
// because in this case Firefox is responsible for rendering the notification.
|
||||
|
||||
const { AddonTestUtils } = ChromeUtils.importESModule(
|
||||
"resource://testing-common/AddonTestUtils.sys.mjs"
|
||||
);
|
||||
AddonTestUtils.initMochitest(this);
|
||||
const server = AddonTestUtils.createHttpServer();
|
||||
const serverHost = server.identity.primaryHost;
|
||||
const serverPort = server.identity.primaryPort;
|
||||
|
||||
add_setup(async () => {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["alerts.useSystemBackend", false]],
|
||||
});
|
||||
});
|
||||
|
||||
async function testCreateNotification({ iconUrl, testOnShown }) {
|
||||
function background() {
|
||||
function createBlobUrlForTest() {
|
||||
const imgData = Uint8Array.fromBase64(
|
||||
// PNG image of size 5x5. test_blob_icon will verify the width.
|
||||
"iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAADElEQVQImWNgoBMAAABpAAFEI8ARAAAAAElFTkSuQmCC"
|
||||
);
|
||||
const blob = new Blob([imgData], { type: "image/png" });
|
||||
return URL.createObjectURL(blob);
|
||||
}
|
||||
browser.test.onMessage.addListener(async (msg, iconUrl) => {
|
||||
browser.test.assertEq("iconUrl", msg, "Expected message");
|
||||
|
||||
if (iconUrl == "blob:REPLACE_WITH_REAL_URL_IN_TEST") {
|
||||
iconUrl = createBlobUrlForTest();
|
||||
}
|
||||
if (iconUrl === "moz-extension:REPLACE_WITH_REAL_URL_IN_TEST") {
|
||||
iconUrl = browser.runtime.getURL("5x5.png");
|
||||
}
|
||||
|
||||
let shownPromise = new Promise(resolve => {
|
||||
browser.notifications.onShown.addListener(resolve);
|
||||
});
|
||||
let closedPromise = new Promise(resolve => {
|
||||
browser.notifications.onClosed.addListener(resolve);
|
||||
});
|
||||
let createdId = await browser.notifications.create("notifid", {
|
||||
iconUrl,
|
||||
type: "basic",
|
||||
title: "title",
|
||||
message: "msg",
|
||||
});
|
||||
let shownId = await shownPromise;
|
||||
browser.test.assertEq(createdId, shownId, "ID of shown notification");
|
||||
browser.test.sendMessage("notification_shown");
|
||||
let closedId = await closedPromise;
|
||||
browser.test.assertEq(createdId, closedId, "ID of closed notification");
|
||||
browser.test.assertEq(
|
||||
"{}",
|
||||
JSON.stringify(await browser.notifications.getAll()),
|
||||
"no notifications left"
|
||||
);
|
||||
browser.test.sendMessage("notification_closed");
|
||||
});
|
||||
}
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
permissions: ["notifications"],
|
||||
},
|
||||
background,
|
||||
files: {
|
||||
"5x5.png": imageBufferFromDataURI(
|
||||
"iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAADElEQVQImWNgoBMAAABpAAFEI8ARAAAAAElFTkSuQmCC"
|
||||
),
|
||||
},
|
||||
});
|
||||
await extension.startup();
|
||||
extension.sendMessage("iconUrl", iconUrl);
|
||||
await extension.awaitMessage("notification_shown");
|
||||
let alertWindow = Services.wm.getMostRecentWindow("alert:alert");
|
||||
ok(alertWindow, "Found alert.xhtml window");
|
||||
await testOnShown(alertWindow);
|
||||
info("Closing alert.xhtml window");
|
||||
alertWindow.document.querySelector(".close-icon").click();
|
||||
await extension.awaitMessage("notification_closed");
|
||||
await extension.unload();
|
||||
}
|
||||
|
||||
// Ideally we'd also repeat the following test for https, but the test server
|
||||
// does not support https (bug 1742061).
|
||||
add_task(async function test_http_icon() {
|
||||
const requestPromise = new Promise(resolve => {
|
||||
let count = 0;
|
||||
server.registerPathHandler("/test_http_icon.png", () => {
|
||||
// We only care about the request happening, we don't care about the
|
||||
// actual response.
|
||||
is(++count, 1, "Got one request to test_http_icon.png");
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @microsoft/sdl/no-insecure-url
|
||||
const httpUrl = `http://${serverHost}:${serverPort}/test_http_icon.png`;
|
||||
|
||||
await testCreateNotification({
|
||||
iconUrl: httpUrl,
|
||||
async testOnShown(alertWindow) {
|
||||
info("Waiting for test_http_icon.png request to be detected.");
|
||||
const img = alertWindow.document.getElementById("alertImage");
|
||||
is(img.src, httpUrl, "Got http:-URL");
|
||||
await requestPromise;
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function test_data_icon() {
|
||||
// data-URL with a valid 5x5 image.
|
||||
const dataUrl =
|
||||
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAADElEQVQImWNgoBMAAABpAAFEI8ARAAAAAElFTkSuQmCC";
|
||||
|
||||
await testCreateNotification({
|
||||
iconUrl: dataUrl,
|
||||
async testOnShown(alertWindow) {
|
||||
const img = alertWindow.document.getElementById("alertImage");
|
||||
is(img.src, dataUrl, "Got data:-URL");
|
||||
|
||||
info("Verifying that data:-URL can be loaded in the document.");
|
||||
// img is not an <img> but an <image> element, so we cannot read its
|
||||
// intrinsic size directly to guess whether it was loaded.
|
||||
// To see whether it is NOT blocked by CSP, create a new image and see if
|
||||
// it can be loaded.
|
||||
|
||||
const testImg = alertWindow.document.createElement("img");
|
||||
testImg.src = dataUrl;
|
||||
await testImg.decode();
|
||||
is(testImg.naturalWidth, 5, "Test image was loaded successfully");
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function test_blob_icon() {
|
||||
await testCreateNotification({
|
||||
iconUrl: "blob:REPLACE_WITH_REAL_URL_IN_TEST",
|
||||
async testOnShown(alertWindow) {
|
||||
const img = alertWindow.document.getElementById("alertImage");
|
||||
ok(img.src.startsWith("blob:moz-extension"), `Got blob:-URL: ${img.src}`);
|
||||
|
||||
info("Verifying that blob:-URL can be loaded in the document.");
|
||||
|
||||
const testImg = alertWindow.document.createElement("img");
|
||||
testImg.src = img.src;
|
||||
await testImg.decode();
|
||||
// The 5 here is the size of the test image, see createBlobUrlForTest.
|
||||
is(testImg.naturalWidth, 5, "Test image was loaded successfully");
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function test_moz_extension_icon() {
|
||||
await testCreateNotification({
|
||||
iconUrl: "moz-extension:REPLACE_WITH_REAL_URL_IN_TEST",
|
||||
async testOnShown(alertWindow) {
|
||||
const img = alertWindow.document.getElementById("alertImage");
|
||||
ok(
|
||||
img.src.startsWith("moz-extension:/") && img.src.endsWith("/5x5.png"),
|
||||
`Got moz-extension:-URL: ${img.src}`
|
||||
);
|
||||
|
||||
info("Verifying that moz-extension:-URL can be loaded in the document.");
|
||||
|
||||
const testImg = alertWindow.document.createElement("img");
|
||||
testImg.src = img.src;
|
||||
await testImg.decode();
|
||||
// The 5 here is the size of the test image (5x5.png).
|
||||
is(testImg.naturalWidth, 5, "Test image was loaded successfully");
|
||||
},
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user