谢谢。
您应该能够重用您的Web扩展中的内容脚本(但您需要重写代码以便能够发送/接收与"背景"相关的消息)。
必须使用Swift或Objective-C重新编写后台脚本。
您需要开发:
您可以在Apple网站上找到一个(小)示例:https://developer.apple.com/documentation/safariservices/safari_app_extensions?changes=_2&language=objc
您不应再使用扩展构建器(从Safari的开发者菜单中访问),因为这仅适用于遗留(纯JS)扩展名。所以您需要进入XCode。
最后一件事,但并非最不重要的...与Safari遗留扩展相比,Safari应用程序扩展名有“一点”更受限制(例如,您无法以编程方式打开工具栏弹出窗口,实际上与Chrome网络扩展名一样)。
现在,官方支持进行此转换:
也许分享我的发现已经太晚了,但是不管怎样。
简短回答关于将Web扩展转换为Safari应用程序扩展的可能性是肯定的。它确实是可能的,但很难做到。
我花了很长时间找出将Web扩展移植到Safari应用程序扩展的最佳可能和最小化的方法。
移植Web扩展的问题
解决方案
编写一些Swift/Objective-C代码是不可避免的。但是编写一个桥接代码来促进内容脚本和后台脚本之间的通信会使生活更加轻松。
在这个图示中,内容脚本保持不变,通过创建webview注入背景脚本。现在从内容脚本接收到的任何消息都会转发到webView背景脚本。同时,使用evaluvateJavascript
设置浏览器扩展API。
webView.evaluateJavaScript("chrome.runtime.id=function() { return "+ extensionId + " }")
Electron JS使用像简单的HTML、CSS和JavaScript这样的Web技术,不需要原生技能,除非您想要做一些高级操作。它可以为单个浏览器设计。其文件系统属于Node.js API,并可在Linux、Mac OS X、Windows上运行。
通过使用本地节点模块,您可以使用C++和ObjectiveC(或Swift)编写代码,并使用v8向node.js公开API。这给了你很大的灵活性和能力,但需要最多的时间来开发,并仍然可以通过在electron上下文中运行来重用你的后台脚本。
使用此方法构建的示例应用程序 https://github.com/AdguardTeam/AdGuardForSafari
如果您想在Safari应用程序扩展中进行窗口/标签管理,请参考WindowTabManagement
更新
如果您计划使用零本地代码(Objective-c/swift)移植您的遗留扩展,请按照此存储库进行操作https://github.com/avast/topee。safari-web-extension://
)上的browser.tabs.sendMessage
消息。其他浏览器处理得很好。除此之外,我的应用程序可以从窗口/选项卡中获取大部分数据。ID、标题等都可以获取。它无法获取文档中所述的favIconUrls
(兼容性表)。我不知道你为什么会在这上面得到赞。 - yegorchikbrowser.runtime.sendMessage
,只有在Safari本地URL窗口中才会被捕获。 - yegorchik您可以很容易地完成这个操作。
并不是所有的东西都可以用Swift编写。例如,我尝试从extensionHandler调用dylib,但失败了。
您可以参考此链接了解如何将Google Chrome扩展程序转换为Firefox或Safari扩展程序。
此外,这里有一个官方指南,介绍如何使用WebExtensions将Chrome扩展转换为Firefox插件。目前需要进行一些手动操作。
https://github.com/kritollm/chrome-extension-api-for-safari-and-firefox
在我撰写此文章后,我已经注意到另外两个非常相似的项目。
https://code.google.com/p/adblockforchrome/source/browse/trunk/port.js 和
根据上述内容,内容脚本可以保持与您在Firefox和Chrome扩展中创建的捆绑包相同。您只需要将其包含在您的plist中即可。
为了避免在Swift中重写所有后台逻辑,我使用了一个名为JavascriptCore
的由Apple提供的库。这允许您创建一个JavaScript上下文,并从Swift后台将数据传递到JavaScript后台捆绑包。
例如:safariExtensionHandler.swift
有一个名为messageReceived
的函数。此函数可以使用JavascriptCore
从Swift调用代码中的全局JavaScript函数。
JavaScriptCore
环境中有localStorage
和/或IndexedDB
吗?
你如何发起AJAX请求?CORS请求是否可行? - DUzunlocalStorage
:
1- 在我的 Safari 应用程序扩展 JavaScript 包装器中,每次调用将数据存储在 localStorage
中实际上都会调用一个全局函数 global.setInKeychain(data)。
2- global.setInKeychain(_ data:JSValue) 是从 Swift 端实现的,然后注入到我的 Javascript Context
中。我实现了从 Keychain
存储/获取/删除数据。请纠正我如果我错了,对于 CORS,我认为只需在您的 plist 中列出白名单 URL,并将 <img> 标签的 src 属性设置为 baseURI + url 就可以让您在网页上显示图像。 - RawiSader