4

我有一个需要与其全局页面通信的 Safari 扩展弹出框。从我正在使用的内容脚本

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

来实现这一点。从弹出窗口中我没有找到办法做到这一点。我知道我可以直接访问全局页面中的方法

safari.extension.globalPage.contentWindow

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

是否有模拟的聪明代理的代码

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

从弹出窗口?

4

2 回答 2

3

老实说,在弹出窗口和注入脚本中使用不同的代码可能更容易。如果你真的想要,你可以这样做:

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,因为 message 事件对象通常包含更多的信息,而不仅仅是nameand message,而且您必须确保您的handleMessage函数实际上与message在全局页面中分配为事件侦听器的函数相同。

于 2013-05-14T16:18:42.493 回答
2

在弹出窗口中重复使用基于消息的内容脚本代码的一种简单方法是将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);

如果您对每条不同的消息都有单独的处理程序,或者您使用的是匿名函数,那么这种方法将不起作用。

现在,弹出框和内容脚本中的包装函数非常简单:

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).

请注意,这种简单的方法不处理往返消息,其中弹出框或内容脚本将消息发送到全局页面,全局页面回复另一条消息。还有其他方法可以解决这个问题。

于 2013-05-14T16:34:05.707 回答