Javascript 如何在safari应用程序和从safari应用程序扩展资源文件夹加载的html页面之间进行通信

Javascript 如何在safari应用程序和从safari应用程序扩展资源文件夹加载的html页面之间进行通信,javascript,xcode,macos,safari,safari-app-extension,Javascript,Xcode,Macos,Safari,Safari App Extension,我正在尝试构建一个简单的safari应用程序扩展。在about:blank上,我从extension的resources文件夹加载一个html页面。下面是代码 //script.js - injected script if(window.location.href=="about:blank"){ window.location.href = safari.extension.baseURI + "page.html"; } 我想在这个加载的页面和safari应用程序之间进行通信。显

我正在尝试构建一个简单的safari应用程序扩展。在
about:blank
上,我从extension的resources文件夹加载一个html页面。下面是代码

//script.js - injected script
if(window.location.href=="about:blank"){
    window.location.href = safari.extension.baseURI + "page.html";
}
我想在这个加载的页面和safari应用程序之间进行通信。显然,注入的脚本
script.js
在加载的html页面上不可用

我尝试将
script.js
内联链接到html页面,但是
safari
对象本身不可用于
safari.extension.dispatchMessage
safari.self.addEventListener

编辑:

有了这个(注入脚本script.js在加载页面的html页面/选项卡上不可用)我的意思是,在“资源”选项卡中打开web inspector时,如果我正确理解您的问题,我们就看不到任何扩展脚本,您需要在页面的javascript和Safari应用程序扩展的本机主机应用程序之间进行通信。只能使用API safari.extension.dispatchMessage联系主机应用程序,该应用程序只能从注入的script.js脚本访问,而不能从页面的js访问

您可以通过从页面发送和请求事件并注册响应事件来解决此问题。您的HTML页面将包含以下脚本:

function sendEventToInjected() {
    var storeEvent = new CustomEvent('myCustomEvent', {"detail": "testData"});
    document.dispatchEvent(storeEvent);

    var responseEventID = 'myResponseEvent';
    document.addEventListener(responseEventID, function respListener(event)
    {
        console.log("Got data from injected script: " + event.detail);
        document.removeEventListener(responseEventID, respListener);
    });
}
您的script.js将通过注册事件侦听器捕获此事件,然后将数据传递给扩展的本机主机应用程序。在获得本机主机的响应后,可以将响应事件调度回页面

document.addEventListener("myCustomEvent", function(event) {
    console.log("myCustomEvent:" + event.detail);
    safari.extension.dispatchMessage(event.detail);
});

// Listens for messages sent from the app extension's Swift code.
safari.self.addEventListener("message", messageHandler);

function messageHandler(event)
{
    var resp = {detail: "respData"};
    var respEvent = new CustomEvent('myResponseEvent', resp);
    document.dispatchEvent(respEvent);
}
您不能将页面“重新定位”到safari extensions://url,但可以从safari应用程序扩展获取要显示的HTML代码(使用消息传递),然后将代码插入“关于:空白”页面。
结果将是一样的,只是页面url将保持为:空白

这看起来像是苹果的一个bug。我已经向BugReporter提交了一个。

您可以将零高度
iframe
添加到HTML中,以“强制注入”扩展脚本


我的分机!
很抱歉,没有启用JavaScript,应用程序无法正常工作。请使其继续。

以下是可能的JS:

函数句柄消息(事件){
console.log(event.name);
console.log(事件消息);
}
如果(window.top==窗口){
document.addEventListener(“DOMContentLoaded”),函数(事件){
console.log(“[app]内容加载:main”);
safari.extension.dispatchMessage(“来自Main的你好!”);
safari.self.addEventListener(“消息”,handleMessage);
});
}否则{
document.addEventListener(“DOMContentLoaded”),函数(事件){
console.log(“[app]内容加载:iframe”);
safari.extension.dispatchMessage(“来自iframe的你好!”);
safari.self.addEventListener(“消息”,handleMessage);
});
}
结果:


非常感谢您的回答,但您忽略了一个事实(注入脚本
script.js
在加载页面的html页面/选项卡上不可用),因此它无法真正侦听js在页面中发送的事件,反之亦然。您是对的,注入脚本在页面上不可用。但是,从页面到注入JS和后台工作(Safari 11,尚未测试12)都可以收听事件。我做了一个concent的证明,因为我正在处理一个类似的问题。好吧,这样做(注入的script script.js在加载的html页面/页面加载的选项卡上不可用)我的意思是,在资源选项卡中打开web inspector时,我们看不到任何
扩展脚本,我尝试了您所说的,但它不起作用。当我在by扩展资源的html页面上时,没有
script.js
存在,即使用urlOK中的
safari扩展://
协议,可能我错过了您的用例。我有一个普通的HTML页面(例如,由URL打开),希望与扩展通信(在我的情况下,我需要调用本机代码来替换NPAPI)。在这种情况下,沟通就像我写的那样有效。您可以指定您的用例吗?如何从扩展打开页面,提供更多的示例代码来模拟问题?