用于后台上下文中一个脚本的消息由所有人接收



我有一个具有以下结构的WebExtension:

webextension [directory]
- background.js
- page1.html
- page1.js
- page2.html
- page2.js

后台.js侦听错误。如果有,它会指示其回调函数使用包含按钮的 HTML 页面page2.js更新选项卡。

HTML 脚本page2.js首先向后台发送消息.js和后台.js回复page2.js这部分工作正常。

然后,正如您在代码中看到的,page2.html包含一个按钮,如果单击,它将在回调函数中执行代码。然后,它将调用refreshIndexPage,该消息应将消息发送到附加到page1.html.js page1

问题:当我在page2.jspage1refreshIndexPage.js之间添加消息传递 API 时 ,来自 page2 的消息被发送到后台.js。我不希望这种情况发生。正如我将在输出中显示的,我得到:In background.js: received: undefined

问题:

  1. 如何在不制作背景的情况下将消息从page2.js发送到page1.js.js该消息也会侦听来自page2 的消息.js感到困惑并收到不适合它的消息?如何指定此消息是从第 2 页.js到第 1 页.js

这是将消息从第2 页.js添加到第 1 页.js后的输出。控制台输出

inside refreshIndexPage
In background.js: received: undefined
inside handleRefreshResponse
  1. 页1.html
<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>
  1. page1.js
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");
}
  1. background.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"]
});
  1. page2.html
<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>
  1. page2.js
/*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);

runtime.sendMessage()发送的消息在后台上下文中注册了runtime.onMessage侦听器的所有脚本中接收,但发送消息的脚本除外。1您无法限制此类邮件的收件人。

因此,您必须创建一些方法来确定消息是否适用于接收消息的每个脚本。 这可以通过多种方式完成,但所有这些方式都基于:

  1. message的内容和/或
  2. sender

这两者都作为参数提供给runtime.onMessage()侦听器。

使用message

要使用message您必须选择message上强加一些结构。message可以是您选择发送的任何 JSON 可发送的数据。通过强制实施某些结构,您可以更轻松地使用更复杂的消息,并在脚本之间更可靠地传达信息。没有预定义的内容。你可以使用任何你想要的东西。但是,在选择上保持一致通常使编程更容易,并且几乎总是使代码更易于维护。

就个人而言,我通常出于不同的原因发送消息。对于每个扩展,我通常会选择始终发送具有特定格式的对象。每个扩展的格式可能不同,但通常如下所示:

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) 只有一个收件人会理解如何处理requestFootype消息,而所有其他收件人都会忽略这样的messagetypes,或者如果有多个后台上下文脚本可以处理requestFoo类型,那么我会添加一个recipientdestination属性。因此,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是否与接收消息的脚本匹配,以及代码是否理解如何处理messagetype

请记住,上面的结构正是我碰巧使用的。您可以定义所需的任何结构,这也满足您的需求。

使用sender

如果脚本从不对从特定发件人接收的消息执行操作,或者如果它对来自特定发件人的消息执行操作,则该脚本可以检查senderruntime.MessageSender对象,以查看参数是否与来自要对其执行message操作的发件人的参数匹配。如果使用此方法,则通常检查sender.url

仅根据sendermessage采取行动的选择比基于message的内容要有限得多。但是,除了message中提供的信息外,它还非常有用。它还提供了一种了解无法欺骗的消息发件人的方法。此外,这意味着您不需要传达有关哪个范围是消息发送者的信息,当然,除非您在范围中有多个可能的发件人(即在 URL/页面中)。

<小时 />

1。在 51 之前的版本中,Firefox 中的一个错误会导致在发送它们的脚本中收到消息。如果您希望在该版本或更早版本中使用扩展,则必须考虑这种可能性(即忽略它们),因为某些情况可能会导致锁定 Firefox(例如,如果您总是在收到消息时发送新消息)。

最新更新