This is a fairly firefox specific issue it seems... not sure ofc! (but I tested in chrome, and it works, whereas i get garbled canvas data in firefox)
In short, I wanted to dynamically insert an emoji to the favicon, leading me on a small journey through rendering an emoji to a canvas (dynamically), reading that canvas thru .toDataURL()
, and finally setting the favicon href to point to that "url". Problems arose when reading the canvas data!
I read stuff here https://bugzilla.mozilla.org/show_bug.cgi?id=1376865 about this feature being implemented, but they also seem to mention "canvas permissions"... they're not referring to the Permissions API right? (i looked here https://w3c.github.io/permissions/#permission-registry), and there's no such thing :(
I've encountered various internet hearsay about canvas being added to the Permissions API, but I haven't found anything concrete... do I give up on this? is this coming in the future?
I have no "user input" on my page, so adding this in retrospect just to trigger the pop-up asking for permission seems... hacky!
If you go to a page like http://www.faviconer.com/ where you can draw your favicon, you'll see what I mean. Firefox shows a pop-up on "user input triggered canvas data access", but chromium seems to just allow it outright.
code:
const createIconElement = () => {
var link = document.createElement('link');
link.rel = 'icon';
link.type = 'image/png';
return link;
};
// original: https://github.com/EvanHahn/canvas-to-favicon/blob/master/canvas-to-favicon.js
const canvasToFavicon = (canvas) => {
let head = document.head;
var existingIcons = document.querySelectorAll('link[rel="icon"]');
for (var i = 0, len = existingIcons.length; i < len; i++) {
head.removeChild(existingIcons[i]);
}
iconElement = createIconElement();
head.appendChild(iconElement);
iconElement.href = canvas.toDataURL('image/png');
}
document.addEventListener("DOMContentLoaded", () => {
console.log('running setFavicon.js');
// get an emoji from the DOM somewhere
// const emojicontainingstring = document.querySelectorAll('*');
// const emojis = emojicontainingstring.map(extractEmoji).filter(e => !!e);
// const emoji = emojis[0];
const emoji = '📋';
// render emoji to canvas
const canvas = document.createElement('canvas');
canvas.width = 32;
canvas.height = 32;
const ctx = canvas.getContext("2d");
ctx.font = '26px serif'
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText(emoji, canvas.width / 2, canvas.height / 2)
canvasToFavicon(canvas);
});
ok, turns out it's my CanvasBlocker plugin (even though I specifically whitelisted my own domain?... tested on vanilla FF and it works!)