【问题标题】:how to communicate between safari app and html page loaded from safari app extension resources folder如何在 safari 应用程序和从 safari 应用程序扩展资源文件夹加载的 html 页面之间进行通信
【发布时间】:2019-02-28 19:31:18
【问题描述】:

我正在尝试构建一个简单的 Safari 应用程序扩展。在about:blank 上,我从扩展的资源文件夹中加载了一个 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 页面/选项卡上不可用)我的意思是在资源选项卡中打开网络检查器时,我们看不到任何 extension scripts

【问题讨论】:

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


    【解决方案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 将通过注册事件侦听器来捕获此事件,然后可以将数据传递到扩展程序的本机主机应用程序。获取到native host的response后,就可以将response事件回传给页面了。

    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);
    }
    

    【讨论】:

    • 非常感谢您的回答,但您错过了这样一个事实,即(注入的脚本 script.js 在加载的 html 页面/标签页上不可用)因此它不能真正听到页面中js派发的事件,反之亦然
    • 你是对的,注入的脚本本身不适用于页面。然而,从页面监听事件到注入的 JS 和返回工作(Safari 11,尚未测试 12)。我做了一个浓度证明,因为我只是在处理一个类似的问题。
    • 好了(注入脚本 script.js 在加载的 html 页面/选项卡上不可用)我的意思是在资源选项卡中打开网络检查器时,我们看不到任何 @ 987654325@,你说的我试过了,还是不行。当我在扩展资源的html页面上时没有script.js,即在url中使用safari-extensions://协议
    • 好的,也许我错过了你的用例。我有一个普通的 HTML 页面(由 URL 打开,例如localhost/test.html),它想与扩展程序通信(在我的情况下,我需要调用本机代码来替代 NPAPI)。对于这种情况,通信就像我写的那样工作。您能否指定您的用例 - 如何从扩展中打开页面,提供更多示例代码来模拟问题?
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      这看起来像是 Apple 的一个错误。我已经向 BugReporter 提交了一份。

      【讨论】:

        【解决方案4】:

        您可以在 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);
           });
        }
        

        结果:

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-07-23
          • 2013-04-07
          • 1970-01-01
          • 1970-01-01
          • 2013-12-04
          相关资源
          最近更新 更多