我有一个具有以下结构的WebExtension:
webextension [directory]
- background.js
- page1.html
- page1.js
- page2.html
- page2.js
background.js 侦听错误。如果有,它会指示其回调函数使用包含按钮的HTML页面 page2.js 更新选项卡。
HTML脚本 page2.js 首先向 background.js 发送消息,然后 background.js 回复 page2的.js 。这部分工作正常。
然后,正如您在代码中看到的那样, page2.html 包含一个按钮,如果单击它,它将在回调函数中执行代码。然后,它会调用refreshIndexPage
,它应该向 page1.js 发送消息,该消息附加到 page1.html 。
问题:当我在refreshIndexPage
中的 page2.js 和 page1.js 之间添加了消息传递API时,来自page2的消息被发送到 background.js 。我不希望这种情况发生。正如我将在输出中显示的那样,我得到:In background.js: received: undefined
问题:
以下是将 page2.js 的消息添加到 page1.js 后的输出。 控制台输出
inside refreshIndexPage
In background.js: received: undefined
inside handleRefreshResponse
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<h1>Pag1.html</h1>
<input type="button" id="page1-button" value="click"></input>
<script src="page1.js"></script>
</body>
</html>
function displayAll() {
console.log("inside display all");
} //end displayAll
//should listen to messages from pag2.js
browser.runtime.onMessage.addListener(handleRefreshMessage);
function handleRefreshMessage(request, sender, sendResponse) {
console.log("In page1.js: message received" + request.refreshRequest);
sendResponse("response from page1.js to page2.js");
}
console.log("inside background");
//add a listener for the toolbar icon. If clicked, open page1.html
browser.browserAction.onClicked.addListener((tab) => {
// disable the active tab
var creating = browser.tabs.create({"url": "page1.html"});
creating.then((tab) => {
browser.browserAction.setIcon({tabId: tab.id, path: "icons/red-64.png"});
});//end creating.then
});//end addListener
var target = "<all_urls>";
function log(responseDetails) {
console.log("inside response details");
errorTab = responseDetails.tabId;
if(true) {
console.log("inside if");
browser.tabs.update(responseDetails.tabId,{url: "page2.html"});
//this message to wait request from page2.js
browser.runtime.onMessage.addListener(handleMessage);
} //end if
}//end log
function handleMessage(request, sender, sendResponse) {
console.log("In background.js: received: " + request.scriptRequest);
sendResponse({errorTab: errorTab});
}
var errorListening = browser.webRequest.onErrorOccurred.addListener(log, {
urls: [target],
types: ["main_frame"]
});
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<h1>Pag2.html</h1>
<input type="button" id="page2-button" value="click"></input>
<script src="page2.js"></script>
</body>
</html>
/*self-calling function conatins sendMessage to background script*/
(function notifyBackgroundPage() {
var sending = browser.runtime.sendMessage({
scriptRequest: "From pag2.js. request for data"
});
sending.then(handleResponse);
})();
function handleResponse(message) {
console.log(`In page2.js: data from background is: ${message.errorTab}`);
} //handleResponse
function myFunction() {
refreshIndexPage();//end .then
}//end myFunction
//refreshIndexPage should send message to page1.js only when the button is clicked.
function refreshIndexPage() {
console.log("inside refreshIndexPage");
var sending = browser.runtime.sendMessage({
refreshRequest: "From page2.js"
});
sending.then(handleRefreshResponse);
}//end refreshIndex
function handleRefreshResponse() {
console.log("inside handleRefreshResponse");
}//end handleRefreshResponse
var page2Button = document.getElementById("page2-button");
page2Button.addEventListener('click', myFunction);
答案 0 :(得分:1)
runtime.sendMessage()
发送的消息在后台上下文中的所有脚本中都被接收,其中注册了runtime.onMessage
个侦听器,但发送消息的脚本除外。 1 那里您无权限制此类邮件的收件人。
因此,您必须创建一些方法来确定该消息是否适用于接收它的每个脚本。这可以通过多种方式完成,但所有方法都基于:
message
和/或sender
这两个都作为runtime.onMessage()
监听器的参数提供。
message
要使用message
,您必须选择以在message
上施加一些结构。 message
可以是您选择发送的任何JSON可用数据。通过强加某种结构,您可以更轻松地使用更复杂的消息,并在脚本之间更可靠地传递信息。没有任何预定义的东西。你可以随意使用。但是,在您的选择中保持一致通常会使编程更容易,并且几乎总是使代码更易于维护。
就个人而言,我通常会出于不同的原因发送消息。对于每个扩展程序,我们通常会选择始终发送具有特定格式的Object。每种扩展名的格式可能不同,但通常看起来像:
var message = {
type: 'requestFoo',
//subType: 'Used if the type needs to be further split',
data: dataNeededForRequest
//You can add whatever other properties you want here.
};
如果扩展程序有多个可能的收件人,那么A)只有一个收件人会理解如何处理requestFoo
type
个邮件,而其他所有收件人都会忽略此类message
{{1或者,如果有多个后台上下文脚本可以处理types
类型,那么我会添加requestFoo
或recipient
属性。因此,destination
看起来像:
message
当每个脚本收到var message = {
type: 'requestFoo',
//subType: 'Used if the type needs to be further split',
recipient: 'page2.js',
data: dataNeededForRequest
//You can add whatever other properties you want here.
};
时,他们会检查message
是否与收到消息的脚本匹配,以及代码是否理解如何处理recipient
type
}}
请记住,上面的结构正是我碰巧使用的。您可以定义您想要的任何结构,以满足您的需求。
message
如果脚本从不对来自特定发件人的邮件采取行动,或者仅对来自特定发件人的邮件采取行动,那么脚本可以检查sender
runtime.MessageSender
对象,以查看参数是否与发件人的参数匹配sender
。如果您使用此方法,则最常检查sender.url
。
根据message
选择仅对message
采取行动比基于sender
的内容更为有限。但是,除message
中提供的信息外,它还非常有用。它还提供了一种了解不能被欺骗的消息发送者的方法。此外,这意味着您不需要传达有关哪个范围是邮件发件人的信息,当然,除非您在范围内有多个可能的发件人(即在URL /页面中)
1。 51之前的版本中的bug in Firefox导致在脚本中接收发送消息的消息。如果您希望在该版本或更早版本中使用您的扩展程序,则必须考虑到这种可能性(即忽略它们),因为某些情况可能导致锁定Firefox(例如,如果您始终发送新消息)当你收到消息时。)