Loading an asset stored within a chrome extension
Asked Answered
S

3

20

Let's say I have a JSON file stored within my extension called settings.json. I can get the URL of the file using:

chrome.extension.getURL("settings.json");

But now that I have the URL, how do I actually load the contents of that file so I can JSON.parse it and use it? The reason I'm doing this is that there is a server component, and I want to make deployment and testing on multiple servers easier (dev, staging, production, etc.) Alternatively if there's a way to add custom attributes to the manifest.json and access them, that would also work.

Shend answered 15/9, 2010 at 17:45 Comment(0)
A
30

If you make your setting.js look like:

var settings =  {"param":value,...};

Then you can just include it on a background page and use settings variable:

<script src="settings.js"></script>

If you want to have pure json in your file without assigning it to any variables then you can load it using XMLHttpRequest:

var xhr = new XMLHttpRequest();
xhr.onreadystatechange = handleStateChange; // Implemented elsewhere.
xhr.open("GET", chrome.extension.getURL('/config_resources/config.json'), true);
xhr.send();

or if you included jquery into your project:

$.getJSON(chrome.extension.getURL('/config_resources/config.json'), function(settings) {
  //..
});

(btw using chrome.extension.getURL is required only if you are accessing a file from a content script, otherwise you can just use relative path /config_resources/config.json)

Armpit answered 15/9, 2010 at 18:0 Comment(4)
I may end up doing your first suggestion. With the second, I get the following error (from within a content script): XMLHttpRequest cannot load chrome-extension://<APPID>/settings.json. Cross origin requests are only supported for HTTP. Uncaught Error: NETWORK_ERR: XMLHttpRequest Exception 101Shend
@Shend Ok then I was wrong about content script, sorry. If you need it in a content script you can send a request to background page using chrome.extension.sendRequest and ask it to get settings for you (you will need to send a request in any case, even with first method).Armpit
otherwise you can just use relative path - unless it would be a CORB request, which it would probably be, as Chrome extensions work alongside any website.Nymphet
Unfortunately, not allowed any more: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.Observable
F
2

I can verify that requesting the resource from an XHR in the background page works as previously described. Just be sure to add 'self' to the connect-src portion of your content_security_policy.

Fridge answered 19/4, 2012 at 20:40 Comment(1)
Another point should be also considered: web_accessible_resources https://mcmap.net/q/490325/-get-local-file-inside-the-extension-folder-in-chromeBirthstone
C
0

A modern solutions using web_accessible_resources and fetch.

manifest.json

{
    // ...
    "web_accessible_resources": [
        {
            "matches": ["<all_urls>"], // adjust if needed
            "resources": ["Test.json"]
        }
    ],
    // ...
}

content-script.js

function getResourceContent(fileName) {
    return fetch(chrome.runtime.getURL(fileName))
    .then(resp => resp.json()); // important line
}

// ...

// Use somewhere else in the script like this
(async () => {
    const content = await getResourceContent("Test.json");
    // Use the content here
})();

// or like this
getResourceContent("Test.json").then(content => {
    // Use the content here
});

Note on important line: for other types of files use appropriate handling methods (i.e. .text() for plain text files). See the docs for more information.

If you plan on having more files with useful content in your extension I suggest making your manifest more flexible so you won't have to modify when you add another file. Just create subfolder "resources" and put all the useful files there.

manifest.json

{
    // ...
    "web_accessible_resources": [
        {
            "matches": ["<all_urls>"], // adjust if needed
            "resources": ["resources/*"]
        }
    ],
    // ...
}

content-script.js

function getResourceContent(fileName) {
    return fetch(chrome.runtime.getURL(`resources/${fileName}`))
    .then(resp => resp.json());
}
Commutation answered 3/5 at 22:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.