Search code examples
javascriptcssgoogle-chrome-extension

Loading embedded fonts from a Chrome Extension content script


This is how I'm loading embedded fonts in my Chrome Extension:

manifest.json:

{
    // more stuff
    "content_scripts": [
        {
            "matches": ["<all_urls>"],
            "css": ["style.css"],
            "js": ["content.js"]
        }
    ],
    // more stuff
    "web_accessible_resources": [
        {
            "resources": ["*.ttf"],
            "matches": ["<all_urls>"]
        }
    ]
}

style.css:

@font-face {
    font-family: 'Nunito';
    font-style: normal;
    font-weight: 500;
    src: url('chrome-extension://__MSG_@@extension_id__/fonts/Nunito-Medium.ttf');
}

The font loads in my Chrome Extension if the font is being called from style.css. However, if it's being called from content.js (inserted with Webpack), I get this error:

GET chrome-extension://invalid/ net::ERR_FAILED

I think, for some reason, __MSG_@@extension_id__ isn't working when called from content.js.

___CSS_LOADER_EXPORT___.push([module.id, "extension://__MSG_@@extension_id__/fonts/Nunito-Medium.ttf') // more stuff 

What could be the reason, and how to make __MSG_@@extension_id__ work in content.js? Or how to load embedded fonts from content.js or any JavaScript file in a Chrome Extension?


Solution

  • The documentation says that these magical MSG constants are for "manifest.json and CSS files" and then mistakenly says that @@extension_id can be used in JavaScript files, but it's not true.

    In JS code we can use chrome.runtime.getURL:

    var url = chrome.runtime.getURL('fonts/Nunito-Medium.ttf');
    

    It's also compatible with "use_dynamic_url": true in web_accessible_resources which uses a special random id instead of the extension id.