从safari扩展名弹出到全局页面的消息

时间:2013-05-13 18:53:50

标签: safari-extension browser-extension

我有一个safari扩展名popover,需要与其全局页面进行通信。从我正在使用的内容脚本

safari.self.tab.dispatchMessage(name,data); 

实现这一目标。从一个popover我没有找到办法做到这一点。我知道我可以直接访问全局页面中的方法

safari.extension.globalPage.contentWindow

但我的目标是重用已经在内容脚本中使用的代码片段。我对插件的chrome版本做了同样的事情。

是否存在一个模拟

的聪明代理的代码
safari.self.tab.dispatchMessage(name,data); 

来自popover?

2 个答案:

答案 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,因为消息事件对象通常比namemessage有更多的信息,你必须确保你的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或内容脚本将消息发送到全局页面,而全局页面则回复另一条消息。还有其他方法可以解决这个问题。