Safari扩展:如何仅在单击工具栏按钮后注入内容脚本

Safari Extension: How do you inject content scripts only after a toolbar button is clicked?

本文关键字:按钮 注入 脚本 工具栏 单击 扩展 何仅 Safari      更新时间:2023-09-26

在我的扩展中,我需要在单击工具栏图标时执行操作。然而,有很多脚本和样式表涉及,所以我想避免使用普通的"内容脚本",因为这些总是会加载到用户访问的每个页面,减慢他们的浏览器速度。相反,我想只在单击按钮之后注入脚本。

文档只说了以下内容:

如果您需要命令[即,单击工具栏按钮]来启动注入脚本中的操作,请在全局HTML页面或扩展栏中响应命令并向脚本发送消息。

在Chrome中,你可以使用Chrome .tabs. executescript ()

在Firefox中,可以使用tabs.activeTab.attach()

你在Safari里怎么做?

您可以使用以下四种方法有条件地向页面注入内容:

safari.extension.addContentScript
safari.extension.addContentScriptFromURL
safari.extension.addContentStyleSheet
safari.extension.addContentStyleSheetFromURL

文档。然而,请注意,这些方法在调用它们时不会将内容注入任何已经存在的制表符。因此,它们可能不适合您的用例。您可以使用其中一种方法,然后重新加载选项卡,但您可能不希望这样做,因为这会影响用户体验。

相反,您可能需要使用这样的技术:有一个非常轻量级的内容脚本注入到每个页面,其唯一的工作是监听来自扩展的全局页面的消息,并在指示时,为您想要注入的内容创建适当的<script><style><link>元素。然后,当单击工具栏按钮时,让全局页面将适当的消息传递给内容脚本,可能包括所需内容的url。

这种方法的一个缺点是注入的脚本(通过创建<script>标记添加的脚本)将不能直接与全局页面或扩展的其他部分通信。如果你需要他们沟通,他们将需要使用window.postMessage或其他一些技术。

这里有一个最小的例子。假设您的扩展有一个工具栏项,它发出命令"inject-content"。

全局页面:

safari.application.addEventListener('command', function (evt) {
    safari.application.activeBrowserWindow.activeTab.page.dispatchMessage(evt.command);
}, false);

在始终注入的内容脚本中:

safari.self.addEventListener('message', function (evt) {
    if (evt.name == 'inject-content') {
        var myScriptTag = document.createElement('script');
        myScriptTag.src = safari.extension.baseURI + 'my_script.js';
        document.body.appendChild(myScriptTag);
    }
}, false);