Last active
April 20, 2017 12:30
-
-
Save flapenguin/3b6045c9e81e7a95e0ea7cf9a74e9647 to your computer and use it in GitHub Desktop.
Firefox CSP foreignObject doesn't render
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<meta http-equiv="X-UA-Compatible" content="ie=edge"> | |
<meta http-equiv="Cache-Control" content="no-cache"> | |
<meta http-equiv="Content-Security-Policy" content="style-src 'self' 'nonce-foobar==';"> | |
<!-- Replace CSP with next line to make svg render correctly --> | |
<!--<meta http-equiv="Content-Security-Policy" content="style-src 'self' 'unsafe-inline';">--> | |
<title>Firefox foreignObject CSP</title> | |
<style nonce="foobar=="> | |
html, body { | |
margin: 0; | |
padding: 0; | |
width: 100%; | |
height: 100%; | |
} | |
#dst, #expected { | |
border: 1px solid black; | |
} | |
#text { | |
display: block; | |
width: 100%; | |
height: 200px; | |
} | |
</style> | |
</head> | |
<body> | |
<h4>Svg source:</h4> | |
<textarea id="text" readonly></textarea> | |
<h4>Svg image:</h4> | |
<img id="dst"> | |
<h4>Expected:</h4> | |
<img id="expected"> | |
<h4>Actual (Firefox 52.0.2):</h4> | |
onload fired. Image is blank. CSP errors reported to console. | |
<script> | |
document.body.onload = async () => { | |
try { | |
await main(); | |
} catch (e) { | |
console.error(e); | |
} | |
}; | |
async function main() { | |
const image = document.querySelector('#image'), | |
imageUrl = image.textContent.trim(), | |
{width, height} = image.dataset; | |
const expected = document.querySelector('#expected'); | |
expected.style.width = width; | |
expected.style.height = height; | |
expected.src = imageUrl; | |
let html; | |
if (location.search == '?style') { | |
html = ` | |
<div xmlns="http://www.w3.org/1999/xhtml"> | |
<style nonce="foobar=="> | |
.x1 { position: relative; } | |
.x2 { z-index: 10; background: url(${imageUrl}), white; width: ${width}px; height: ${height}px; } | |
</style> | |
<div class="x1"><div class="x2"></div></div> | |
</div> | |
`.replace(/^\n/, ''); | |
} else { | |
html = ` | |
<div xmlns="http://www.w3.org/1999/xhtml" style="position: relative;"> | |
<div style="z-index: 10; background: url(${imageUrl}), white; width: ${width}px; height: ${height}px;"></div> | |
</div> | |
`.replace(/^\n/, ''); | |
} | |
let svg = ` | |
<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}"> | |
<foreignObject width="100%" height="100%"> | |
${html} | |
</foreignObject> | |
</svg> | |
`.replace(/^\n/, ''); | |
const spaces = svg.match(/^\s+/)[0], | |
stripSpacesRe = new RegExp(`^${spaces}`); | |
svg = svg.split('\n').map(x => x.replace(stripSpacesRe, '')).join('\n'); | |
document.querySelector('#text').value = svg; | |
const svgUrl = URL.createObjectURL(new Blob([svg], { type: 'image/svg+xml' })); | |
const dst = document.querySelector('#dst'); | |
dst.style.width = width; | |
dst.style.height = height; | |
try { | |
await new Promise((resolve, reject) => { | |
dst.onload = resolve; | |
dst.onerror = reject; | |
dst.src = svgUrl; | |
}); | |
} finally { | |
URL.revokeObjectURL(svgUrl); | |
} | |
}; | |
</script> | |
<script id="image" type="text/plain" data-width="32" data-height="32"> | |
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgEAIAAACsiDHgAAAABGdBTUEAAYagMeiWXwAAAOVJREFUeJzVlsEKgzAQRKfgQX/Lfrf9rfaWHgYDkoYmZpPMehiGReQ91qCPEEIAPi/gmu9kcnN+GD0nM1/O4vNad7cC6850KHCiM5fz7fJwXdEBYPOygV/o7PICeXSmsMA/dKbkGShD51xsAzXo7DIC9ehMAYG76MypZ6ANnfNJG7BAZx8uYIfOHChgjR4F+MfuDx0AtmfnDfREZ+8m0B+9m8Ao9Chg9x0Yi877jTYwA529WWAeerPAbPQoUH8GNNA5r9yAEjp7sYAeerGAKnoUyJ8BbXTOMxvwgM6eCPhBTwS8oTO/5kL+Xge7xOwAAAAASUVORK5CYII= | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment