Search code examples
javascriptfirefox-addon-sdk

How to send message from panel to page-mod's content script directly?


If there is a code snippet in Firefox addon like following:

var pagemod = PageMod({
    include: ['*'],
    contentScriptFile: [data.url('content.js')]
});

panel = require("sdk/panel").Panel({
  width: 322,
  height: 427,
  contentURL: data.url("main.html"),
  include:["http://*/*","https://*/*"],
  contentScriptFile: [data.url('panel.js')]  
});

I have found some example code in the Chrome extension. They use window.parent.postMessage(message, "*") to send message and use window.addEventListener("message",function (e) {//do something} to receive message. How can I send message from "panel.js" to "content.js" directly in the Firefox addon?


Solution

  • The concept of the solution is very similar to this answer:

    1. Maintain a list of message ports for each tab.
    2. Whenever you want to send a message, send a message to all listed ports.

    The following code is used to maintain a list of ports:

    var ports = [];
    var pagemod = PageMod({
        include: ['*'],
        contentScriptFile: [data.url('content.js')],
        onAttach: function(worker) {
            ports.push(worker.port);
            worker.on('detach', function() {
                var index = ports.indexOf(worker.port);
                if (index !== -1) ports.splice(index, 1);
            });
        }
    });
    

    Now, whenever you want to send a message from panel.js, just use:

    // panel.js
    self.port.emit('message-to-tabs', 'example of message');
    

    The message has to be handled in the main script, after creation of the panel:

    panel = require('sdk/panel').Panel({
        width: 322,
        height: 427,
        contentURL: data.url('main.html'),
        include: ['http://*/*', 'https://*/*'],
        contentScriptFile: [data.url('panel.js')]  
    });
    panel.port.on('message-to-tabs', function(message) {
        for (var i=0; i<ports.length; i++) {
            ports[i].emit('message-to-tab', message);
        }
    });
    

    In the tab's content script (content.js), you can listen to this event and handle it as follows:

    self.port.on('message-to-tab', function(message) {
        // Do something with message
    });