我有一个safari扩展名popover,需要与其全局页面进行通信。从我正在使用的内容脚本
safari.self.tab.dispatchMessage(name,data);
实现这一目标。从一个popover我没有找到办法做到这一点。我知道我可以直接访问全局页面中的方法
safari.extension.globalPage.contentWindow
但我的目标是重用已经在内容脚本中使用的代码片段。我对插件的chrome版本做了同样的事情。
是否存在一个模拟
的聪明代理的代码safari.self.tab.dispatchMessage(name,data);
来自popover?
答案 0 :(得分:3)
老实说,在你的popover和注入脚本中使用不同的代码可能更容易。如果你真的想要,你可以这样做:
function dispatchMessage(name, message) {
if (safari.self.tab) {
safari.self.tab.dispatchMessage(name, message);
} else if (safari.extension.globalPage.contentWindow) {
safari.extension.globalPage.contentWindow.handleMessage({name: name, message: message});
}
}
然后在弹出窗口和注入脚本中使用dispatchMessage('foo', 'bar')
。但是有点hacky,因为消息事件对象通常比name
和message
有更多的信息,你必须确保你的handleMessage
函数实际上是同一个函数在全局页面中被指定为message
事件侦听器。
答案 1 :(得分:2)
在popover中完成重用基于消息的内容脚本代码的简单方法是将safari.self.tab.dispatchMessage
调用包装在我将在下面描述的抽象函数中...
但首先,您需要确保在全局页面中有一个处理所有消息的命名处理函数,如下所示:
function handleMessage(evt) {
switch (evt.name) {
case 'Message1':
// do something with evt.message
break;
case 'Message2':
// do something else with evt.message
break;
}
}
safari.application.addEventListener('message', handleMessage, false);
如果每个不同的消息都有单独的处理程序,或者如果您使用的是匿名函数,则此方法将无效。
现在,popover和内容脚本中的包装函数非常简单:
function tellGlobalPage(msgName, msgData) {
if (safari.self instanceof SafariExtensionPopover) {
// this script is running in a popover
var fakeMsgEvt = { name: msgName, message: msgData };
safari.extension.globalPage.contentWindow.handleMessage(fakeMsgEvt);
} else {
// this script is a content script
safari.self.tab.dispatchMessage(msgName, msgData);
}
}
然后使用safari.self.tab.dispatchMessage(name, data),
tellGlobalPage(name, data).
请注意,这种简单的方法不涉及往返消息传递,其中popover或内容脚本将消息发送到全局页面,而全局页面则回复另一条消息。还有其他方法可以解决这个问题。