Chrome extension message listener fires twice

Viewed 440

I'm working on Chrome extensions. I try to learn messaging between content and background. I develop simple project for this. But I have issue.

Basic idea is

  • User click button on extension popup
  • A function (bot.js) find image from content of tab then extension (background.js) will download it.

The issue ise port.onMessage.addListener() in background.js fired twice.

When background.js send message to contentscript.js there are two same messages in console or when I try to download in background.js (the code line "Do Something") it download the file twice.

How can I solve this problem?

popup.html

<!doctype html>
<html>
  <head>
    <title>Test Plugin</title> 
    <script src="background.js"></script>
    <script src="popup.js"></script>
  </head>
  <body>
    <h1>Test Plugin</h1>
    <button id="btnStart">Button</button>
  </body>
</html>

popup.js

document.addEventListener('DOMContentLoaded', function() {
    var checkPageButton = document.getElementById('btnStart');
    checkPageButton.addEventListener('click', function() {  
      GetImages("Some URL");
    }, false);
  }, false);


  var tab_title = '';
  function GetImages(pageURL){
    // Tab match for pageURL and return index
    chrome.tabs.query({}, function(tabs) {
      var tab=null;      
      for(var i=0;i<tabs.length;i++){
        if(tabs[i].url==undefined || tabs[i].url=="" || tabs[i]==null){}
        else{
          if(tabs[i].url.includes(pageURL)){
            tab=tabs[i];
            break;
          }
        } 
      }
      
      if(tab!=null){
          chrome.tabs.executeScript(tab.id, {
            file: "bot.js"
          }, function(results){
            console.log(results);
          });
      }
    });
  }

bot.js

var thumbImagesCount = document.querySelectorAll('.classifiedDetailThumbList .thmbImg').length;
var megaImageURL=document.querySelectorAll('.mega-photo-img img')[0].src;
console.log(megaImageURL + " from bot.js");
port.postMessage({key:"download", text: megaImageURL});

background.js

chrome.runtime.onConnect.addListener(function (port) {
    console.assert(port.name == "content-script");
    port.onMessage.addListener(function(message) {
        
        console.log(message);
        if(message.key=="download"){
            // Do Something
            // Event fires twice
            port.postMessage({key:"download", text: "OK"});
        }
    })
});

contentscript.js

console.log("content script loaded!");
var port = chrome.runtime.connect({name: "content-script"});
port.onMessage.addListener(function(message){
    console.log(message);
});

manifest.json

{
    "manifest_version": 2,
  
    "name": "Test Extension",
    "description": "This extension will download images from gallery",
    "version": "1.0",
    "icons": { 
        "16": "bot16.png",
        "48": "bot48.png",
       "128": "bot128.png" },
    "browser_action": {
        "default_icon": "bot48.png",
        "default_popup": "popup.html"
    },
    "permissions": [
        "activeTab",
        "downloads",
        "http://*/",
        "https://*/"
    ],
    "background": {
        "persistent": false,
        "scripts": ["background.js"]
    },
    "content_scripts": [
        {
            "matches": ["http://*/*", "https://*/*"],
            "js": ["contentscript.js"]
        }
    ]
  }
1 Answers

The background script declared in manifest.json already has its own page, a hidden background page where it runs, so you should not load it in the popup as it makes no sense in case there are listeners for API events, the background page is already listening for them. In this case the copy also creates the second listener while the popup is open.

Solution: don't load background.js in popup.

See also Accessing console and devtools of extension's background.js.

Related