Firefox addon(JPM) - How to pass message from panel's script to content script?

 ̄綄美尐妖づ 提交于 2020-01-04 07:03:53

问题


Im trying to send a click event from panels script(popup.js) to content script(content.js) hers the code that i've tried.and the desired output isnt printing on the console.

popup.html

<button id="start-btn" onclick="myFunction()">Clip</button>

popup.js

function myFunction() {
  addon.port.emit('message', 'hello world');
}

content.js

self.port.on("message", function(text) {
  console.log(text);
});

index.js(main)

var panels = require("sdk/panel");
var self = require("sdk/self");
var data = require("sdk/self").data;
var pageMod = require("sdk/page-mod");

pageMod.PageMod({
  include: "*",
  contentScriptWhen: 'ready',
  contentScriptFile:
  [data.url("js/jquery-3.1.0.min.js"),
  data.url("js/content.js")]
});

var panel = panels.Panel({
 contentURL: self.data.url("popup.html"),
 onHide: handleHide
});

回答1:


In order to pass a message from an sdk/panel to a content script, you have to relay it through your background script. So, the communication looks like panel script ⟷ background script ⟷ content script.

This is complicated by the fact that you, potentially, have many different content scripts. You could even have multiple content scripts per tab. Thus, you have to track your content scripts as they attach and keep them organized, at least by tab. This is so you can end up relaying the message to the correct content script.

The panel, because it is a user interface, will normally want to send a message to the active tab. On the other hand, it might want to send a message to a specific tab, or a specific script within a specific tab. You will need to determine what level of granularity you need for your add-on.

The following script will load, via Page-Mod, a content script into every tab (as per the question the included URLs is '*'). Each content script is tracked by tab. No provision is made for having multiple content scripts per tab. Tab events should really be listened to in order to invalidate entries in the list of content scripts. However, that is not done in this example. The panel will be displayed upon clicking an ActionButton. When the button in the panel is clicked a relay message is sent by the panel to the background script which then decodes the relay message and emits it to the appropriate content script.

I have imposed a format for the relay messages. That format is:

{
     target: {
        type:targetType, //Currently, the only valid targetType is 'content'.
        id:targetId //A tab ID, or 'activeTab'
    },
    emitType:emitType, //The type of emit message that will be sent.
    data:message //The contents of the relayed message.
}

The code:

index.js:

var panels = require("sdk/panel");
var self = require("sdk/self");
var data = require("sdk/self").data;
var pageMod = require("sdk/page-mod");
var tabs = require("sdk/tabs");

//Open the Browser Console
var utils = require('sdk/window/utils');
activeWin = utils.getMostRecentBrowserWindow();
activeWin.document.getElementById('menu_browserConsole').doCommand();

var workers={};

//PageMod
pageMod.PageMod({
    include: "*",
    contentScriptWhen: 'ready',
    contentScriptFile: [
        //data.url("js/jquery-3.1.0.min.js"),
        data.url("js/content.js")
    ],
    onAttach: attachWorker
});

function attachWorker(worker){
    if(!workers.hasOwnProperty(worker.tab.id)){
        //Have not previously had this tab
        workers[worker.tab.id]={};
    }
    //This does not account for the possibility of having multiple workers
    //  per tab at one time.
    //Remember the worker
    console.log('index.js: Attached worker on tab=',worker.tab.id);
    workers[worker.tab.id].worker = worker;
}


//Panel
var panel = panels.Panel({
    contentURL: self.data.url("popup.html"),
    onHide: handleHide
});

panel.port.on('message',receiveMessage);
panel.port.on('relay',receiveRelay);

function handleHide(){
}

function receiveMessage(message){
    console.log('index.js: received message:',message);
}

function receiveRelay(data){
    console.log('index.js: received relay:',data);
    let emitPort;
    let targetId;
    if(typeof data !== 'object'){
        console.log('index.js: received relay: data was not an object');
        return;
    }//else
    if(!data.hasOwnProperty('target')){
        console.log('index.js: received relay: No target specified');
        return;
    }//else
    if(data.target.type === 'content'){
        if(data.target.id && data.target.id === 'activeTab'){
            targetId = tabs.activeTab.id;
        }else{
            targetId = data.target.id;
        }
        console.log('index.js: received relay: target ID: ', targetId);
        if(!workers.hasOwnProperty(targetId) || !workers[targetId].worker){
            console.log('index.js: received relay: No target worker available for ID: '
                        , targetId);
            return;
        }//else
        emitPort = workers[targetId].worker.port;
    }else{
        //None  yet defined
        console.log('index.js: received relay: Target type not understood. Type: '
                    , data.target.type);
        return;
    }
    console.log('index.js: received relay: emitType=', data.emitType, ' ::data='
                , data.data);
    emitPort.emit(data.emitType,data.data);
}


//Action button
var ui = require("sdk/ui");

var action_button = ui.ActionButton({
    id: "panel-show-button",
    label: "Show panel",
    icon: "./icon.png",
    onClick: function(state) {
        panel.show();
    }
});

data/js/content.js:

console.log('In  content.js');
self.port.on("message", function(text) {
  console.log('content.js: received message:',text);
});

data/popup.js:

function myFunction() {
    console.log('popup.js: Button clicked. Sending relayed message');
    //addon.port.emit('message', 'hello world');
    sendRelay('content','activeTab','message','Button clicked in panel');
}

function sendRelay(targetType,targetId,emitType,message) {
    addon.port.emit('relay', {
        target: {
            type:targetType, //Currently, the only valid targetType is 'content'.
            id:targetId //A tab ID, or 'activeTab'
        },
        emitType:emitType, //The type of emit message that will be sent.
        data:message //The contents of the relayed message.
    });
}

data/popup.html:

<html>
    <head>
        <meta charset='utf-8'>
        <script type="text/javascript" src="popup.js"></script>
    </head>
    <body>
        <button id="start-btn" onclick="myFunction()">Clip</button>
    </body>
</html>

package.json:

{
    "title": "Demo passing a message panel-background-content",
    "name": "relaymessge",
    "id": "relaymessage@ex",
    "version": "0.0.1",
    "description": "Demonstrate passing a message from a panel -> background script -> content script.",
    "main": "index.js",
    "author": "Makyen, vivek",
    "engines": {
        "firefox": ">=38.0a1",
        "fennec": ">=38.0a1"
    },
    "keywords": [
        "jetpack"
    ]
}


来源:https://stackoverflow.com/questions/39241698/firefox-addonjpm-how-to-pass-message-from-panels-script-to-content-script

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!