【问题标题】:Convert Web Extension to Safari App Extension将 Web 扩展转换为 Safari 应用扩展
【发布时间】:2020-11-13 17:47:41
【问题描述】:

我有目前在 Chrome、Firefox 和 Opera 上运行的 Web 扩展程序。 现在我想知道是否有一种方法可以使用相同的代码来构建 Safari 应用程序扩展,可能类似于 PhoneGap(将所有现有的 JS 代码包装在 Safari 应用程序扩展项目中),或者有一些限制,比如 javascript 的标签处理和一些事情只需要用本机代码编写。

谢谢

【问题讨论】:

    标签: google-chrome-extension firefox-addon-webextensions safari-extension safari-app-extension


    【解决方案1】:

    您应该能够重用 Web 扩展中的内容脚本(但您需要重写代码才能发送/接收带有“背景”的消息)。 后台脚本必须用 Swift 或 Objective-C 重写。

    你需要开发:

    • Mac 主机应用程序(将与扩展程序配套使用):Swift 或 Objective-C(此应用程序必须具备最低功能才能通过 Apple 审核 - 请查看 Apple 的 Mac 应用程序指南)
    • 扩展:在 Swift 或 Objective-C + HTML/JS 中(对于其他浏览器) 用于扩展的 Swift(或 Obj-C)中的代码相当于您在 Web 扩展中拥有的背景页面。它将控制工具栏按钮、扩展程序的生命周期并可以与注入的脚本对话。

    您在 Apple 网站上有一个(小)示例:https://developer.apple.com/documentation/safariservices/safari_app_extensions?changes=_2&language=objc

    您不应再使用 Extension Builder(可从 Safari 的开发者菜单访问),因为这仅适用于旧版(纯 JS)扩展。所以你需要进入 XCode。

    最后,但并非最不重要的... Safari 应用程序扩展与 Safari 旧版扩展相比,“有点”受限(例如,您将无法像使用 Chrome 一样以编程方式打开工具栏弹出窗口实际上是网络扩展)。

    【讨论】:

    • 我为 Safari App Extensions 开发者创建了一个 Slack 社区,欢迎大家加入我们:slofile.com/slack/safariappextdevs
    • 对此的一些更新。关于应用程序审查,您可以改为自己分发 Mac 应用程序并避免其中一些要求。 Safari App Extensions 仍在开发中,并且正在添加新的 API。所以请密切关注release notes。例如,我认为,自从编写了此答案以来,现在有一种方法可以以编程方式打开弹出框。但是有些东西仍然存在,它仍然非常严格,文档和示例严重缺乏
    • Quin 是对的,我们可以通过编程方式打开弹出窗口(如果我没记错的话,从 10.14.2 开始)。但是,API 仍然不如 WebExtensions 丰富。
    • 这也是一个过时的信息,不要跟着这个。
    • Outdated... 适用于 Safari 的最新版本,因为它支持 Web 扩展。但是,如果您需要支持旧版本或者您已经拥有这种扩展(并且不想“回来”使用 chrome 扩展),仍然有效。
    【解决方案2】:

    现在官方支持这种转换:

    Converting a Web Extension for Safari

    【讨论】:

    【解决方案3】:

    分享我的发现可能为时已晚,但尽管如此。

    将网络扩展转换为 Safari 应用扩展的可能性的简短回答是 是。绝对有可能,但很难做到。

    我很难找出将 Web 扩展移植到 safari 应用程序扩展的最佳且最少的方法。

    移植 Web 扩展的问题

    1. Safari 应用程序扩展不提供用于选项卡/窗口管理的 API。 (即添加、删除或更新选项卡或窗口时,窗口和选项卡的唯一标识符)
    2. 需要一些关于 swift/objective -c 的学习或先前经验才能实现后台功能。
    3. 调试成为开发过程中的痛点。

    解决方案

    编写一些 swift/objective-c 代码是不可避免的。但是用 swift/objective C 编写桥接代码以促进内容脚本和后台脚本之间的通信使生活更轻松。

    在图中,Content-script 保持不变,背景脚本是通过创建 webview 来注入的。现在从内容脚本收到的任何消息都转发到 webView 后台脚本。同时使用evaluvateJavascript设置浏览器扩展API

    webView.evaluateJavaScript("chrome.runtime.id=function() { return "+ extensionId + " }")
    
    • 方法 2:使用 Electron 驱动的浏览器扩展

    Electron JS 使用简单的 HTML、CSS 和 JavaScript 等网络技术。除非您想做一些高级的事情,否则它不需要本机技能。它可以设计用于单个浏览器。它的文件系统属于 Node.js API,适用于 Linux、Mac OS X、Windows。

    通过使用native node modules,您可以使用 C++ 和 ObjectiveC(或 Swift)编写并使用 v8 向 node.js 公开 API。这为您提供了很大的灵活性和功能,但需要最多的时间来开发,并且仍然通过在电子上下文中运行来重用您的后台脚本。

    使用这种方法构建的示例应用程序 https://github.com/AdguardTeam/AdGuardForSafari

    如果您想在 safari 应用扩展中进行窗口/选项卡管理,请参考 WindowTabManagement

    更新

    如果您打算使用零本机代码 (Objective-c/swift) 移植旧版扩展。请关注这个回购 https://github.com/avast/topee

    【讨论】:

    • 您能说出为什么在 20 年 2 月您的信息可能已过时时传播虚假信息并这样做吗?对于“标签/窗口管理” - 它工作得很好。我注意到小扩展只有一个区别 - 如果您尝试将它们发送到本地 url (safari-web-extension://),Safari 无法识别 browser.tabs.sendMessage 消息。其他浏览器可以很好地处理它。除此之外,我的应用程序能够从窗口/选项卡中获取大部分数据。 ID、标题等。它无法获得文档(兼容性表)中所述的favIconUrls。我不知道你为什么对此投赞成票。
    • 这基本上是一大块非常虚假和过时的信息,您可以使用 XCode 12+ 轻松移植 WebExtension(甚至只是 Chrome 扩展)。
    • 对于我的第一条评论,您必须使用browser.runtime.sendMessage,它只会在 Safari 本地 url 窗口中被捕获。
    • @yegorchik ehm,什么?这里的虚假信息是什么意思? Safari 应用程序扩展与其他浏览器扩展的工作方式完全不同。后台脚本本身完全用 Native 编写。 1. Safari 应用扩展没有任何标签管理功能,例如查询标签,getTabUsingId [developer.apple.com/documentation/safariservices/… 这里)。
    • Safari 仅支持页面,在其他扩展中,我们可以查询选项卡,其中每个选项卡可以包含多个页面(iframe),并且在 Safari 应用程序扩展中无法检索使用的选项卡 ID。当 safari 后来在 WWDC20 活动(2020 年 6 月 22 日至 2020 年 6 月 26 日)中同意支持与“Safari 应用程序扩展”不同的“Safari 网络扩展”时,这些已经过时了。这个问题特别是关于 safari 应用程序扩展,我建议仔细阅读这个问题。
    【解决方案4】:

    你实际上可以很容易地做到这一点。

    • 请记住,您需要 Xcode v.12 和 Safari 12 才能正常工作。
    1. 从 chrome 商店下载 .crx 文件。
      1. 我用过这个:https://crxextractor.com
    2. 用终端«unzip»解压。
    3. 从终端输入 xcrun safari-web-extension-converter /path/to/manifest/ 并运行它 - 当询问是否 swift 时输入 yes。这应该会打开 Xcode。
    4. 来自 Xcode - 编译并运行。
    5. 现在激活它:
      1. 转到 Safari、偏好设置、启用开发模式。
      2. 然后转到新的“开发”标签 - 在书签旁边。
      3. «允许无符号扩展»
    6. 然后转到首选项和扩展程序,您应该会看到您的扩展程序。

    【讨论】:

      【解决方案5】:

      您可以参考link 了解如何将 Google Chrome 扩展程序转换为 Firefox 或 Safari 扩展程序。

      目前有一些手动工作要做。

      https://github.com/kritollm/chrome-extension-api-for-safari-and-firefox

      在我第一次写这篇文章之后,我知道了另外两个项目 非常相似。

      https://code.google.com/p/adblockforchrome/source/browse/trunk/port.js 和

      https://github.com/jetpack-labs/chrome-tailor-jetpack

      另外,这里是official guide 如何使用 WebExtensions 将 Chrome 扩展转换为 Firefox 插件。

      【讨论】:

      【解决方案6】:

      如果我们谈论的是 Safari 应用程序扩展而不是旧版 Safari 扩展(在 Safari v12 中已弃用),那么我的理解是需要用 swift 重写后台脚本。 关于内容脚本,它们仍然是 JS,但所有使用 chrome API 调用编写的消息都必须使用 Safari 应用程序 API 重写。

      【讨论】:

        【解决方案7】:

        并非所有东西都可以用 Swift 编写。例如,我尝试从 extensionHandler 调用 dylib,但失败了。

        【讨论】:

          【解决方案8】:

          如上所述,内容脚本可以与您在 Firefox 和 Chrome 扩展程序中创建的捆绑包保持相同。您只需要将它包含在您的 plist 中。 为了避免重写 Swift 中的所有后台逻辑,我使用了 Apple 提供的名为 JavascriptCore 的库。这允许您创建一个 JavaScript 上下文并将数据从 Swift 后台传递到您的 JavaScript 后台包。

          例如:safariExtensionHandler.swift 有一个名为 messageReceived 的函数。这个函数可以在你的代码中使用JavascriptCore在你的代码中调用一个全局JavaScript函数。

          【讨论】:

          • 您在JavaScriptCore 环境中是否有localStorage 和/或IndexedDB?你如何发出 AJAX 请求? CORS 请求是否可行?
          • @DUzun 关于localStorage: 1- 在我的Safari App Extension javascript 包装器中,每次在localStorage 中存储数据的调用实际上都会调用一个全局函数global.setInKeychain(data)。 2- global.setInKeychain(_ data:JSValue) 从 Swift 端实现,然后注入我的Javascript Context。我实现了从Keychain 存储/获取/删除数据。如果我错了,请纠正我,对于 CORS,我相信只需将 plist 中的 url 列入白名单并将 标记的 src 属性设置为 baseURI + url 即可让您在网页上显示图像。
          猜你喜欢
          • 2022-08-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-12-30
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多