6

I'm making my first chrome extension and noticed that messages being sent from my popup.html page were getting duplicated in my content.js message event listener. I've console logged "sending message" before every message send and "message received" before every message, and I don't understand how the messages are being duplicated. I've also checked the chrome dev docs for sendMessage and onMessage and it specifies that the onMessage listener should only be fired once per sendMessage event.

Any help would be appreciated.

popup.html

<!DOCTYPE html>
<html>
<head>
    <title>Messaging Practice</title>
</head>
<body>
    <h1>Messaging Practice</h1>

    <input type="button" id="send-message" value="Button">
    <script src="popup.js"></script>
</body>
</html>

content.js

chrome.runtime.onMessage.addListener(
    function(request, sender, sendResponse) {
        console.log('message received')
        console.log(request);
    }
);

popup.js

var messageButton = document.querySelector("#send-message");

messageButton.onclick = function() {
    chrome.tabs.query({currentWindow: true, active: true},
    function(tabs) {
        chrome.tabs.executeScript(
            tabs[0].id, {file: "content.js"}
        )
        console.log("sending message")
        chrome.tabs.sendMessage(tabs[0].id, "string message")
    });
}

background.js

chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {
  chrome.declarativeContent.onPageChanged.addRules([{
    conditions: [new chrome.declarativeContent.PageStateMatcher({
      pageUrl: {hostEquals: 'stackoverflow.com'},
    })],
        actions: [new chrome.declarativeContent.ShowPageAction()]
  }]);
});

manifest.json

{
    "name": "Send Messages Practice",
    "version": "1.0",
    "manifest_version": 2,
    "description": "Simple messaging practice with the chrome api",
    "permissions": ["declarativeContent", "activeTab"],
    "background": {
        "scripts": ["background.js"],
        "persistant": true
    },

    "page_action": {
        "default_popup": "popup.html",
        "scripts": ["content.js"],
        "matches": ["http://*/*","https://*/*"]
    }

}
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
Codezilla
  • 95
  • 1
  • 7
  • 3
    You reinsert the content script on each click and the content script registers a new function reference each time in onMessage. The simplest solution is to check `window.init === true` in the content script code and do nothing, otherwise set this property and register the listener. – wOxxOm Apr 17 '18 at 05:02
  • @wOxxOm Great explanation! This worked perfectly. I've been banging my head on my computer for days because of this. Thanks – Codezilla Apr 17 '18 at 23:35
  • 2
    A [comment on another question](https://stackoverflow.com/q/30802260/630530) provided the fix for me, recommending that `all_frames` be set to false in the manifest file. – Wayne Smallman Jun 04 '19 at 17:07

2 Answers2

3

Adding "return true;" to event handlers will prevent your code from firing again and again:

chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
  if (request.action == "show_alert") {
    alert(request.alert);
    return true;
  }
});
Denis Abakumov
  • 355
  • 3
  • 11
srnitk
  • 31
  • 4
2

Get the same problem when I run my extension with multiple frames. @Wayne Smallman solution works for me:

recommending that all_frames be set to false in the manifest file

Jianwu Chen
  • 5,336
  • 3
  • 30
  • 35