Background: Hello everyone, I’m a high school student building an addon to modify font-size and color properties of our school’s website.
Structure of files:
/popup
├── options.html with 2 checkboxes (Font-Size, Change Color)
├── options.js to save state and retrieve value of checkboxes from localStorage.
├── options.css to style the popup.
manifest.json
content_script.js which targets elements on DOM with Document.getElementsByClassName() and toggles custom classnames customSize and customColor.
custom.css gives rules to the custom classnames.
icon128.png
icon256.png
Problem: I am able to store and retrieve boolean values of checkboxes inside the popup, but can’t send them across to content_script.js. Even using browser.tabs.executeScript().
Manually appending custom classnames from the browser console works like a charm.
Relevant code:
options.js
function restoreOptions() {
document.getElementById("font-size").checked=JSON.parse(localStorage.getItem("size")); //assigning retrieved value to checkbox
const executing = browser.tabs.executeScript({
file: "/content-script.js",
allFrames: true
});
executing.then(onExecuted, onError);
}
function onExecuted(result) {
console.log(`Color changed`); }
function onError(error) {
console.log(`Error: ${error}`); }
content_script.js
let bigger = JSON.parse(localStorage.getItem("size"));
if (bigger) {
document.getElementsByClassName("paragraph")[0].classList.add("customSize");
}
else {
document.getElementsByClassName("paragraph")[0].classList.remove("customSize");
}
But where do you inject the CSS file? The page won’t see your CSS file unless you inject it there.
Either manually by modifying DOM from your injected script. In that case you need to list your custom css file in the list of web-accessible resources:
Hi @juraj.masiar, thanks for the suggestions. I’ll look into it right now.
To clarify though - the file custom.css is getting loaded. I know this cause there are other “universal” rules in the file (like a sepia background that the user doesn’t get option to toggle). These changes are reflected on the webpage on every reload.
Do I still need to manually inject the CSS file using web_accessible_resources? My manifest.json says
I don’t think so, having it in manifest for the specific host is for sure enough.
Anyway, if your CSS is loaded and your JS is indeed modifying those classes (you can inspect that easily) then the only thing that can cause issues is a lower priority of your CSS selectors. So as a proof of concept, try to add !important suffix .
No, if the script could be injected into the current tab, then you wouldn’t need to provide the param. The issue is that about:addons can’t have content scripts at all. Though arguably, you control the contents of your options page, so you shouldn’t need a content script in the first place in it. To get another tab, tabs.query is probably the best method.
Yes, you can send a message to a content script using this. Though if you don’t know if the content script actually exists in that tab, you might want to send a message using runime.sendMessage from the content script requesting the value instead. If you are intending to have a persistent setting, storing the value in storage.local might be much better, since that can be read directly by the content script without the options having to be open.
sendMessage has nothing to do with where the script gets loaded, it is only to send an already running script a message to its runtime.onMessage listener.
You probably want to use the contentScript API for that (or have it declared in the manifest.json).
Thank you Martin! All these little pointers really helped me get the gist of it. I re-implemented my message passing with browser.runtime.sendMessage like you recommended. Also – instead of the whole popup shenanigans, wrote a simple options.html that sits inside the addon-manager page. On testing, the classNames get added/removed just right!
Unfortunately, it only works when I have the options page open in another tab otherwise I get the error Could not establish connection. Receiving end does not exist.
ps : suppose I should mark this answered because you solved my intended question though.