2

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 is port.onMessage.addListener() in background.js fired twice.

When background.js sends 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"]
        }
    ]
  }
Paolo
  • 20,112
  • 21
  • 72
  • 113
BK52
  • 754
  • 2
  • 11
  • 33
  • 1
    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 this case it also creates the second listener. See also [Accessing console and devtools of extension's background.js](https://stackoverflow.com/a/10258029) – wOxxOm Sep 12 '20 at 14:27
  • Thank you for your answer. It solve my problem. – BK52 Sep 12 '20 at 15:49
  • @wOxxOm Looks like we have a classic example of why not to post answers or partial answers in comments - the OP's problem is solved, but the Question still shows as Unanswered and no one can vote on, improve, or accept your solution. :( – IMSoP Sep 12 '20 at 15:52
  • @IMSoP, Thing is, extensions have so many moving parts that sometimes it's wasteful to post an answer without confirmation the guess was right. – wOxxOm Sep 12 '20 at 15:57
  • @wOxxOm Yeah, the platform's not great for that kind of thing, but the ideal is to keep comments to questions that clarify, and post guesses as answers, which can always be deleted if clarifications make them obsolete. – IMSoP Sep 12 '20 at 15:59

1 Answers1

2

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.

Paolo
  • 20,112
  • 21
  • 72
  • 113
wOxxOm
  • 65,848
  • 11
  • 132
  • 136