Firefox 插件 (JPM) - 如何将消息从面板的脚本传递到内容脚本?
Firefox addon(JPM) - How to pass message from panel's script to content script?
我正在尝试将点击事件从面板脚本 (popup.js) 发送到内容脚本 (content.js) 她的代码是我 tried.and 所需的输出未打印控制台。
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
});
为了将消息从 sdk/panel 传递到内容脚本,您必须通过后台脚本中继它。所以,通信看起来像面板脚本⟷后台脚本⟷内容脚本。
由于您可能有许多不同的内容脚本,所以这很复杂。您甚至可以为每个选项卡设置多个内容脚本。因此,您必须在内容脚本附加时跟踪它们,并至少按选项卡组织它们。这样您就可以最终将消息中继到正确的内容脚本。
面板,因为它是一个用户界面,通常会向活动选项卡发送消息。另一方面,它可能希望将消息发送到特定选项卡或特定选项卡中的特定脚本。您需要确定附加组件所需的粒度级别。
以下脚本将通过 Page-Mod 将内容脚本加载到每个选项卡中(根据问题,包含的 URL 是 '*'
)。每个内容脚本都按选项卡进行跟踪。没有规定每个选项卡有多个内容脚本。为了使内容脚本列表中的条目无效,应该真正监听 Tab 事件。然而,在这个例子中没有这样做。单击 ActionButton 将显示该面板。单击面板中的按钮时,面板会向后台脚本发送 relay
消息,然后后台脚本解码 relay
消息并将其发送到适当的内容脚本。
我为 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.
}
代码:
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"
]
}
我正在尝试将点击事件从面板脚本 (popup.js) 发送到内容脚本 (content.js) 她的代码是我 tried.and 所需的输出未打印控制台。
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
});
为了将消息从 sdk/panel 传递到内容脚本,您必须通过后台脚本中继它。所以,通信看起来像面板脚本⟷后台脚本⟷内容脚本。
由于您可能有许多不同的内容脚本,所以这很复杂。您甚至可以为每个选项卡设置多个内容脚本。因此,您必须在内容脚本附加时跟踪它们,并至少按选项卡组织它们。这样您就可以最终将消息中继到正确的内容脚本。
面板,因为它是一个用户界面,通常会向活动选项卡发送消息。另一方面,它可能希望将消息发送到特定选项卡或特定选项卡中的特定脚本。您需要确定附加组件所需的粒度级别。
以下脚本将通过 Page-Mod 将内容脚本加载到每个选项卡中(根据问题,包含的 URL 是 '*'
)。每个内容脚本都按选项卡进行跟踪。没有规定每个选项卡有多个内容脚本。为了使内容脚本列表中的条目无效,应该真正监听 Tab 事件。然而,在这个例子中没有这样做。单击 ActionButton 将显示该面板。单击面板中的按钮时,面板会向后台脚本发送 relay
消息,然后后台脚本解码 relay
消息并将其发送到适当的内容脚本。
我为 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.
}
代码:
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"
]
}