Search code examples
javascriptgoogle-chrome-extensioncode-injectionopera-extension

remove listener from injected script


I have Opera sidebar extension
and when extension is fired (sb opened), I need to inject some code with message listener in active tab
code works fine, the problem is that if I close sidebar and open it again, I'll get another listener injected (console will log two times when message is send)...and on another reopen +1..and so on.

I tried to fix this with removing listener, but it doesn't work.
I'm still getting +1 on console for every new extension start (injecting).
And I can't place addListener in removeListener callback. Doesn't work at all
(I guess it doesn't support it in this form)

here is the code I've bee injecting:

chrome.tabs.executeScript({code: 
    "chrome.runtime.onMessage.removeListener(msgL);\
    chrome.runtime.onMessage.addListener(msgL);\
    function msgL(msg) {\
      if (msg.test) console.log('aaaaaaaaaaaaaaaaaaaaaaaaa');\
    }"
  }, function(result) {
    if (!result) console.log(chrome.runtime.lastError);
});

How can I clear previous listener when injecting new one?


Solution

  • In your code the msgL function is recreated each time so removeListener tries to remove this new instance instead of the previously attached one.

    Store the function in the window object (this doesn't seem safe), the injected code would be:

    if (window.msgL) chrome.runtime.onMessage.removeListener(window.msgL);
    window.msgL = function(msg) {
      if (msg.test) console.log('aaaaaaaaaaaaaaaaaaaaaaaaa');
    };
    chrome.runtime.onMessage.addListener(window.msgL);
    

    Or keep track of tab IDs with the listener attached in your extension and only add it when needed:

    var attachedIDs = {};
    chrome.tabs.query({currentWindow: true, active: true}, function(tabs) {
        var id = tabs[0].id;
        if (!attachedIDs[id]) {
            attachedIDs[id] = true;
            chrome.tabs.executeScript({code: 
                "chrome.runtime.onMessage.addListener(function msgL(msg) {\
                  if (msg.test) console.log('aaaaaaaaaaaaaaaaaaaaaaaaa');\
                });"
              }, function(result) {
                if (!result) console.log(chrome.runtime.lastError);
            });
        }
    });
    

    This code would save the attachedIDs when run in a persistent background page. Otherwise use sessionStorage API or chrome.storage API to save/restore it.