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

时间:2018-09-25 08:25:08

标签: javascript xcode macos safari safari-app-extension

我正在尝试构建一个简单的Safari应用扩展程序。在about:blank上,我从扩展名的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.dispatchMessagesafari.self.addEventListener

编辑:
这样做(注入的脚本script.js在加载的html页面/加载页面的选项卡上不可用)是指在资源选项卡中打开Web检查器时,我们看不到任何extension scripts

4 个答案:

答案 0 :(得分:1)

如果我正确理解了您的问题,则需要在页面的javascript和Safari应用程序扩展的本机主机应用程序之间进行通信。只能使用API​​ safari.extension.dispatchMessage 与主机应用程序联系,该API仅可从注入的 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);
}

答案 1 :(得分:0)

您可能不会将页面“重定位”到safari-extensions://网址,而是从Safari应用程序扩展(使用消息传递)获取要显示的HTML代码,然后将代码插入about:blank页面。 结果将是相同的,除了页面网址将保持大约:空白

答案 2 :(得分:0)

这似乎是Apple的错误。我已经向BugReporter提交了文件。

答案 3 :(得分:0)

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

<!DOCTYPE html>
<html lang=en>
   <head>
      <title>My Extension!</title>
   </head>
   <body>
      <noscript><strong>We're sorry but App doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript>
      <p>Hi!</p>
      <iframe id="myID" src="https://example.com" height="0" style="border: none;"></iframe>
   </body>
</html>

这是可能的 JS:

function handleMessage(event) {
    console.log(event.name);
    console.log(event.message);
}

if (window.top === window) {
   document.addEventListener("DOMContentLoaded", function(event) {
       console.log("[app] Content loaded: main");
       safari.extension.dispatchMessage("Hello from Main!");
       safari.self.addEventListener("message", handleMessage);
   });
} else {
   document.addEventListener("DOMContentLoaded", function(event) {
       console.log("[app] Content loaded: iframe");
       safari.extension.dispatchMessage("Hello from iframe!");
       safari.self.addEventListener("message", handleMessage);
   });
}

结果:

Image 1 Image 2 Image 3