Search code examples
javascriptgoogle-chromegoogle-chrome-extension

Chrome Extension set toggle switch state in all tabs


I am making a simple Chrome Extension that contains a simple on/off switch, see below:

enter image description here

Whenever I enable this switch, I want it the new on/off state to reflect in all other active tabs/new tabs/chrome instances.

This is not currently happening, if I enable it in one tab, it is still disabled in another.

My approach was as follows:

  1. Add an event listener to the switch

  2. Toggle the value, and store the new value in chrome.storage

  3. Send a chrome.runtime message to the background script, and update all chrome instances.

The problem: Whenever I toggle the switch, I receive the following error:

enter image description here

Also, for some reason my background.js never initializes, perhaps related to the error above.

Here is my

background.js (listen for message to be sent, so that I can update other tabs)

console.log('?! loading background js !?') // this never fires :(

// Whenever a message has been passed, such as toggling the enable/disable switch, communicate that with other Chrome tabs/instances.
chrome.runtime.onMessage.addListener(
    function (request, sender, sendResponse) {
        // todo: update all chrome tabs with new switch state
        console.log('reached Background message handler!')
    }
);

popup.js (listens for click events, executes the script that toggles the chrome.storage toggle value)

// when the toggle is updated, run our script
document.getElementById('enable-site-blocking').onclick = executeBlocking;

function executeBlocking() {
    chrome.tabs.executeScript({
        code: "setToggleState()"
    });
}

content-script.js (executes when the toggle button is clicked, setting storage state, and sending runtime message)

setToggleState();

function setToggleState() {
    chrome.storage.sync.get(['isExtensionActive'], function (storage) {
        const invertedState = !storage.isExtensionActive;
        chrome.storage.sync.set({
            isExtensionActive: invertedState
        });

        console.log('sending message')

        // send an update to all other Chrome processes
        chrome.runtime.sendMessage({
            greeting: "hello"
        }, function (response) {
            console.log("done sending message");
        });
    });
}

So, my questions are as follows:

  1. Is my approach the correct one, for maintaining the state of the toggle switch across tabs? If not, what should I change?
  2. What might be the cause of the error shown above?
  3. Why does my background.js never execute?

Sorry if it is something simple, I am new to Chrome Extensions!

For additional context, here are the content_scripts/background in my manifest.json enter image description here

Thank you for any help


Solution

  • There's no need for background.js or messaging, simply set the value in popup.js and use chrome.storage.onChanged listener in the content script.

    popup.js:

    function setToggleState() {
      chrome.storage.sync.get('isExtensionActive', storage => {
        chrome.storage.sync.set({
          isExtensionActive: !storage.isExtensionActive,
        });
      });
    }
    

    background.js: not necessary

    content.js:

    chrome.storage.sync.get('isExtensionActive', storage => {
      toggleSomething(storage.isExtensionActive);
    });
    
    chrome.storage.onChanged.addListener(changes => {
      if (changes.isExtensionActive) {
        toggleSomething(changes.isExtensionActive.newValue);
      }
    });
    
    function toggleSomething(state) {
      console.log('new state:', state);
      // ........... do something
    }
    

    Notes:

    • The background script runs in a separate hidden background page which has its own devtools.

    • The popup is also a separate page in a separate window so it has separate devtools: right-click inside the popup, then click "inspect".