Firefox extension custom fonts
Asked Answered
P

3

7

I am using the Firefox Add-on SDK to create an extension and am performing a PageMod. This code is in main.js.

...
exports.main = function() {
  var pageMod = require("sdk/page-mod");

  pageMod.PageMod({
    include: "*",
    contentScriptWhen: 'end',
    contentStyleFile: [
      self.data.url("css/style.css"),
      self.data.url("css/font-awesome.css")
    ],
    contentScriptFile: [
      self.data.url("js/jquery.js"),
      self.data.url("js/spritzify.js")
    ],
    onAttach: function onAttach(worker) {
      worker.postMessage("Hello World");
    }
  });
};
...

my css/font-awesome.css gets loaded into the page although the font files do not.

@font-face {
  font-family: 'FontAwesome';
  src: url('fonts/fontawesome-webfont.eot?v=4.1.0');
  src: url('fonts/fontawesome-webfont.eot?#iefix&v=4.1.0') format('embedded-opentype'), url('fonts/fontawesome-webfont.woff?v=4.1.0') format('woff'), url('fonts/fontawesome-webfont.ttf?v=4.1.0') format('truetype'), url('fonts/fontawesome-webfont.svg?v=4.1.0#fontawesomeregular') format('svg');
  font-weight: normal;
  font-style: normal;
}

The fonts folder is in the data folder of my extension. Could someone please explain how I can load custom fonts into a webpage using PageMod!

Ptyalin answered 23/6, 2014 at 2:13 Comment(1)
Interestingly, there are already at least two duplicates of your question (https://mcmap.net/q/540499/-how-to-add-external-resource-font-into-firefox-extension-duplicate/785541 and https://mcmap.net/q/535759/-firefox-extension-custom-fonts/785541), both without a proper answer.Vorfeld
V
18

If you look into the console messages, this is what you should see:

downloadable font: download not allowed (font-family: "FontAwesome" style:normal weight:normal stretch:normal src index:0): bad URI or cross-site access not allowed

Unfortunately for you, web fonts are subject to the same-origin policy which can only be relaxed via CORS. This means that there is no way to load the font file from an extension URL as there is no way to use CORS there.

This leaves you with two options:

  1. You host the font on a web server with proper CORS headers or use some existing font hosting.
  2. You encode the font as a data: URI. There is a number of data: URI generators available, e.g. this one.

IMHO the second solution is the preferable one as your extension won't be dependent on any web servers, especially not third-party web servers. Also, it won't introduce any delays caused by font downloading. I tried it and it worked fine:

@font-face {
  font-family: 'FontAwesome';
  src: url('data:application/octet-stream;base64,d09GRgAB...') format('woff');
  font-weight: normal;
  font-style: normal;
} 

Side-note: You don't need the full backwards compatibility dance in a Firefox extension, it's sufficient to have the font in the WOFF format.

Vorfeld answered 23/6, 2014 at 6:35 Comment(20)
What about making it a chrome path and setting contentaccessible=yes in the chrome.manifest?Assertion
@Noitidart: I think chrome URLs have the same issue, at least according to some Google search results. Not that it is a practicable solution for an SDK extension.Vorfeld
does not seem to be working @font-face { font-family: 'FontAwesome'; src: url('data:application/octet-stream;base64,ARs...') format('embedded-opentype'); font-weight: normal; font-style: normal; }. Am I doing anything wrong?Ptyalin
@AndrewM: Embedded OpenType format is a proprietary Internet Explorer feature. You should really be using the WOFF format.Vorfeld
@WladimirPalant still does not seem to be working using WOFF format.Ptyalin
@AndrewM: See pastebin.com/P0ttkDmw - that's the complete CSS file I used for testing, it worked correctly for me.Vorfeld
@WladimirPalant Thanks a lot. Working now!Ptyalin
I tried solution 1 and it still failed with Content Security Policy: The page's settings blocked the loading of a resource at http://fonts.gstatic.com/s/opensans/v10/cJZKeOuBrn4kERxqtaUH3bO3LdcAZYWl9Si6vvxL-qU.woff. Any thoughts?Guss
@willlma: Content Security Policy settings are configurable in manifest.json, you have to allow that domain.Vorfeld
Thanks for the response. It was only failing on https pages, so I changed the protocol to https and it is now working on all pages (I was hoping protocol agnostic //fonts… would do the trick, but not so).Guss
@WladimirPalant what is the manifest.json file? I'm building a Firefox extension, having the same issue, but my code has a package.json (developer.mozilla.org/en-US/Add-ons/SDK/Tools/package_json), not manifest.json. Any info is much appreciated.Cunctation
I'm trying to load icon fonts on github.com from my Firefox add-on but GitHub's CSP includes “font-src assets-cdn.github.com” which makes it impossible to load font files via data URI (“content blocked”). F.Y.I. In Chrome, local files can be loaded directly but the data URI solution fails too. In Firefox I haven't found a solution to this yet. @WladimirPalant do you know any work around here?Tiliaceous
@Justineo: Using remotely downloaded fonts in an extension is a bad idea. You should download and add them to your extension, as data: URIs.Vorfeld
@WladimirPalant I was actually serving fonts as data URI but it doesn't work because of GitHub's CSP (you probably missed that in my last comment). In Firefox I only got the error message "content blocked" and I figured it out after I tried in Chrome. I was addressing the difference that Chrome allow local Web fonts (provided by the extension, not remotely downloaded) but not data URI in content script, while under same CSP, Firefox forbids both.Tiliaceous
@Justineo: Got it, I thought that the fonts were hosted on GitHub, not that you are trying to use them there. Frankly, I have no idea whether it's possible to work around CSP here.Vorfeld
@Tiliaceous did you ever manage to get past github's csp? somehow? anyhow? Im facing this bug too :(Rexer
@Rexer Nope. I was trying to load Octicon into GitHub in my browser extension because they switched to SVG icons some time ago. I finally ended up with switching to SVG icons as well.Tiliaceous
@Palant - I have a bootstrap.js addon with my page being an about page with flag Ci.nsIAboutModule.URI_SAFE_FOR_UNTRUSTED_CONTENT. I set a chrome path in my chrome.manifest and set it to contentaccessible=true - github.com/Noitidart/Topick/blob/master/chrome.manifest - however I still get the same "downloadable font: download no...." error for only fonts inside, even though i used the full chrome://topick/content/... path. Is there anyway to modify the CORS so this gets allowed. Paths to images work fine, its so weird.Assertion
@Noitidart: Frankly, I have no idea how this works with non-HTTP schemes. It's a CORS-enabled request and the only channel implementing CORS handling is the HTTP channel. It might be that a custom channel could be used as well but it looks like using it here requires understanding Gecko internals better than I do right now.Vorfeld
Darn. Thanks though @WladimirPalant for spending the time to look into it! :)Assertion
V
1

The best answer I have found is here: https://mcmap.net/q/540500/-how-to-use-font-face-on-a-firefox-webextension

src: url('moz-extension://MSG@@extension_id_/css/fonts/webFonts/font-awesome/fontawesome-webfont.eot?v=4.5.0');

Which is analogous to this method for Chrome: src: url('chrome-extension://MSG@@extension_id_/fonts/...

Vicissitude answered 19/12, 2020 at 4:14 Comment(0)
A
0

I think you need to use absolute paths in those url fields. So figure out what seld.data.url('fonts') (by like console.log'ing it) (the path should be something like resource://weraweraer-at-jetpack/data/fonts) and then update your url's to use that path.

I'm pretty sure this should work because resource url's don't have security restrictions. See this page here: https://developer.mozilla.org/en-US/docs/Chrome_Registration#resource

It says:

Note: There are no security restrictions preventing web content from including content at resource: URIs, so take care what you make visible there.

Assertion answered 23/6, 2014 at 4:21 Comment(2)
"I'm pretty sure this should work because resource url's don't have security restrictions" - well, you are wrong :)Vorfeld
@WladimirPalant You were right. I verified that this does not work. I tried setting them as a resource path in chrome.manifest. :(Assertion

© 2022 - 2024 — McMap. All rights reserved.