Skip to content

Commit

Permalink
Bug 1699892 - Allow the Firefox Accounts avatar server to use SVG con…
Browse files Browse the repository at this point in the history
…text properties. r=dholbert

Differential Revision: https://phabricator.services.mozilla.com/D111169
  • Loading branch information
mikeconley committed Apr 8, 2021
1 parent 430c8d5 commit 9278500
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 1 deletion.
7 changes: 7 additions & 0 deletions browser/app/profile/firefox.js
Original file line number Diff line number Diff line change
Expand Up @@ -2557,3 +2557,10 @@ pref("first-startup.timeout", 30000);
pref("app.normandy.test-prefs.integer", 0);
pref("app.normandy.test-prefs.string", "");
#endif

// Mozilla-controlled domains that are allowed to use non-standard
// context properties for SVG images for use in the browser UI. Please
// keep this list short. This preference (and SVG `context-` keyword support)
// are expected to go away once a standardized alternative becomes
// available.
pref("svg.context-properties.content.allowed-domains", "profile.accounts.firefox.com,profile.stage.mozaws.net");
11 changes: 10 additions & 1 deletion layout/svg/SVGContextPaint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ bool SVGContextPaint::IsAllowedForImageFromURI(nsIURI* aURI) {
// extension developers coming to rely on image context paint either, we only
// enable context-paint for extensions that are signed by Mozilla.
//
// We also allow this for browser UI icons that are served up from
// Mozilla-controlled domains listed in the
// svg.context-properties.content.allowed-domains pref.
//
nsAutoCString scheme;
if (NS_SUCCEEDED(aURI->GetScheme(scheme)) &&
(scheme.EqualsLiteral("chrome") || scheme.EqualsLiteral("resource") ||
Expand All @@ -63,14 +67,19 @@ bool SVGContextPaint::IsAllowedForImageFromURI(nsIURI* aURI) {
}
RefPtr<BasePrincipal> principal =
BasePrincipal::CreateContentPrincipal(aURI, OriginAttributes());

nsString addonId;
if (NS_SUCCEEDED(principal->GetAddonId(addonId))) {
if (StringEndsWith(addonId, u"@mozilla.org"_ns) ||
StringEndsWith(addonId, u"@mozilla.com"_ns)) {
return true;
}
}
return false;

bool isInAllowList = false;
principal->IsURIInPrefList("svg.context-properties.content.allowed-domains",
&isInAllowList);
return isInAllowList;
}

/**
Expand Down
11 changes: 11 additions & 0 deletions layout/svg/tests/file_context_fill_fallback_red.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<style>
img {
-moz-context-properties: fill;
fill: green;
}
</style>
<img src="file_context_fill_fallback_red.svg" style="width: 100px; height: 100px;"/>
8 changes: 8 additions & 0 deletions layout/svg/tests/file_context_fill_fallback_red.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions layout/svg/tests/mochitest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
support-files =
file_disabled_iframe.html

[test_context_properties_allowed_domains.html]
support-files =
file_context_fill_fallback_red.html
file_context_fill_fallback_red.svg
[test_disabled.html]
[test_embed_sizing.html]
support-files =
Expand Down
86 changes: 86 additions & 0 deletions layout/svg/tests/test_context_properties_allowed_domains.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<head>
<meta charset="utf-8">
<title>Bug 1699892 - SVG context properties for allowed domains</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script src="/tests/SimpleTest/WindowSnapshot.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
<script>

/**
* Returns a Promise that resolves when target fires a load event.
*/
function waitForLoad(target) {
return new Promise(resolve => {
target.addEventListener("load", () => {
if (event.target == target) {
resolve();
}}, { once: true });
});
}

/**
* Given an iframe, loads src in it, and waits for the load event
* for the iframe to fire. Then it snapshots the iframe and returns
* the snapshot.
*
* src can be a URL starting with http, or is otherwise assumed to be
* a srcdoc string.
*/
async function loadSrcImageAndSnapshot(frame, src) {
frame.removeAttribute("src");
frame.removeAttribute("srcdoc");

if (!src.startsWith("http")) {
frame.srcdoc = src;
} else {
frame.src = src;
}
await waitForLoad(frame);
return await snapshotWindow(frame, false);
}

add_task(async () => {
const ALLOWED_DOMAIN = "example.org";
const DISALLOWED_DOMAIN = "example.com";

const CONTEXT_FILL_SVG = "tests/layout/svg/tests/file_context_fill_fallback_red.html";
const ALLOWED = `http://${ALLOWED_DOMAIN}/${CONTEXT_FILL_SVG}`;
const DISALLOWED = `http://${DISALLOWED_DOMAIN}/${CONTEXT_FILL_SVG}`;

await SpecialPowers.pushPrefEnv({
set: [["svg.context-properties.content.allowed-domains", ALLOWED_DOMAIN]]
});

let frame = document.getElementById("frame");

// When the context properties are allowed, we expect a green square. When they are
// not allowed, we expected a red square.

let redReference = await loadSrcImageAndSnapshot(
frame,
`<div style="width: 100px; height: 100px; background: red"></div>`
);

let greenReference = await loadSrcImageAndSnapshot(
frame,
`<div style="width: 100px; height: 100px; background: green"></div>`
);

let allowedSnapshot = await loadSrcImageAndSnapshot(frame, ALLOWED);
let disallowedSnapshot = await loadSrcImageAndSnapshot(frame, DISALLOWED);

let result = compareSnapshots(redReference, greenReference, false);
ok(result[0], "First, ensure that red and green do not match.");

result = compareSnapshots(allowedSnapshot, greenReference, true);
ok(result[0], "The allowed domain should show green.");

result = compareSnapshots(disallowedSnapshot, redReference, true);
ok(result[0], "The disallowed domain should show red.");
});
</script>
</head>
<body>
<iframe id="frame"></iframe>
</body>
</html>
13 changes: 13 additions & 0 deletions modules/libpref/init/StaticPrefList.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10260,6 +10260,19 @@
value: false
mirror: always

# Enables the 'context-fill' and 'context-stroke' keywords for particular
# domains. We expect this list to be Mozilla-controlled properties, since the
# 'context-*' keywords are not part of any spec. We expect to remove this
# preference and the 'context-` keyword support entirely in the
# not-too-distant future when a standardized alternative ships. This preference
# is _not_ for allowing web content to use these keywords. For performance
# reasons, the list of domains in this preference should remain short in
# length.
- name: svg.context-properties.content.allowed-domains
type: String
value: ""
mirror: never

# Enable the use of display-lists for SVG hit-testing.
- name: svg.display-lists.hit-testing.enabled
type: bool
Expand Down

0 comments on commit 9278500

Please sign in to comment.