Search code examples
javascriptgoogle-chrome-extensionevent-listener

How do I enable and disable an event listener when wanted in a Chrome Extension?


My background.js detects changes to tab focus. This is its code:

chrome.storage.sync.get("tab_focus_change",function(val){
    if(val.tab_focus_change===false)return;
    var activeTabId, lastUrl;

    function getTabInfo(tabId) {
      chrome.tabs.get(tabId, function(tab) {
        if(lastUrl != tab.url)
          lastUrl=tab.url;
          log('The focused tab changed to: <a href="'+tab.url+'">'+tab.url+'</a>');
      });
    }

    chrome.tabs.onActivated.addListener(function(activeInfo) {
      getTabInfo(activeTabId = activeInfo.tabId);
    });

    chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
      if(activeTabId == tabId) {
        getTabInfo(tabId);
      }
    });
});

As you can see, it is first checking if tab_focus_change is allowing detecting tab focus changing. Only if it allows it (the value should be true or false), then it will detect.

I also have an options page which allows you to change if tab_focus_change is true or false. The options page works perfectly (I've tested). The thing going wrong is that, although it has updated the value, then it keeps on tracking tab changes or it keeps not tracking tab changes - whichever one was before the update.

I've noticed that, although the value changes, it does not update if it tracks or not because I am using event handlers. I set it once, and it starts working forever (until the extension is refreshed/removed of course)! So setting it to false will not unset the handlers, and setting it to true did not start the handlers.

I am wondering on how I can (un)set the handlers when they should be (un)set.

Here is a directory listing of the files in my extension:

manifest.json // Extension manifest

popup.html // Popup page

options.html // Options page
options.js // Script for options page

background.js // background script

content.js // content script
content.css // content styles

html2canvas.min.js // Just an external library, shouldn't matter too much

I'm OK with adding code to any of my HTML or JS files (as long as you say which one to put what code).

So how would I update if the event listeners are tracking changes or not?

Also, if you need more details, please comment below and I will try to add them.


Solution

  • Use a) removeListener method, b) chrome.storage.onChanged event, and c) named functions declared in the scope of addListener or globally:

    const KEY = 'tab_focus_change';
    
    chrome.storage.sync.get(KEY, data => {
      let activeTabId, lastUrl;
      toggleListeners(data[KEY]);
      chrome.storage.onChanged.addListener(changes => {
        if (changes[KEY]) {
          toggleListeners(changes[KEY].newValue);
        }
      });
      function toggleListeners(enable = true) {
        const method = enable ? 'addListener' : 'removeListener';
        chrome.tabs.onActivated[method](onActivated);
        chrome.tabs.onUpdated[method](onUpdated);
      }
      function onActivated(activeInfo) {
        getTabInfo(activeTabId = activeInfo.tabId);
      }
      function onUpdated(tabId, changeInfo, tab) {
        if (activeTabId == tabId) {
          getTabInfo(tabId);
        }
      }
      function getTabInfo(tabId) {
        // console.log(tabId);
      }
    });