可选择注入内容脚本

Posted

技术标签:

【中文标题】可选择注入内容脚本【英文标题】:Optionally inject Content Script 【发布时间】:2015-04-06 19:27:45 【问题描述】:

内容脚本可以通过在扩展清单文件中声明以编程方式或永久注入。程序式注入需要主机权限,一般由浏览器或页面操作授予。

在我的用例中,我想在没有用户操作的情况下注入 gmail、outlook.com 和 yahoo 邮件网站。我可以通过声明所有这些清单来做到这一点,但这样做需要对这些帐户的所有数据访问。某些用户可能只想授予 outlook.com,而不是 gmail。程序化注入不起作用,因为我需要知道何时注入。使用标签权限也需要其他权限。

有什么好方法可以选择性地注入网站吗?

【问题讨论】:

【参考方案1】:

如果没有适当的权限,您无法在网站上运行代码。幸运的是,您可以在清单文件中将主机权限添加到 optional_permissions 以声明它们是可选的,并且仍然允许扩展程序使用它们。

响应用户手势,您可以使用chrome.permission.request 请求额外权限。此 API 只能用于扩展页面(背景页面、弹出页面、选项页面……)。从 Chrome 36.0.1957.0 开始,所需的用户手势也从内容脚本中继承,因此,如果您愿意,可以从内容脚本中添加点击事件侦听器并使用 chrome.runtime.sendMessage 将请求发送到后台页面,这依次调用chrome.permissions.request

选项卡中的可选代码执行

在获得主机权限(可选或强制)后,您必须以某种方式在匹配页面中注入内容脚本(或 CSS 样式)。有几个选项,按我的喜好排列:

    使用chrome.declarativeContent.RequestContentScript 操作在页面中插入内容脚本。如果您想了解如何使用此 API,请阅读 the documentation。

    使用webNavigation API(例如chrome.webNavigation.onCommitted)检测用户何时导航到页面,然后使用chrome.tabs.executeScript 在选项卡中插入内容脚本(或chrome.tabs.insertCSS 插入样式)。

    使用tabs API (chrome.tabs.onUpdated) 检测页面可能已更改,并使用chrome.tabs.executeScript 在页面中插入内容脚本。

我强烈推荐选项 1,因为它是专门为这个用例设计的。注意:此 API 是在 Chrome 38 中添加的,但仅适用于可选权限 since Chrome 39。尽管文档中有“WARNING: This action is still experimental and is not supported on stable builds of Chrome.”,但实际上稳定版支持 API。最初的想法是发给wait for a review before publishing the API on stable,但没有收到评论,所以现在这个 API 已经运行了将近两年。

第二个和第三个选项类似。两者的区别在于使用webNavigation API 添加了额外的权限警告(“阅读您的浏览历史记录”)。对于此警告,您将获得一个可以有效过滤导航的 API,因此可以最大限度地减少 chrome.tabs.executeScript 的调用次数。

如果您不想将此额外的权限警告放在权限对话框中,那么您可以盲目地尝试在每个选项卡上注入。如果你的扩展有权限,那么注入就会成功。否则,它会失败。这听起来效率不高,而且也不是... ...从好的方面来说,这种方法不需要任何额外的权限。

通过使用后两种方法中的任何一种,您的内容脚本必须以能够处理多次插入的方式设计(例如with a guard)。也支持在框架中插入 (allFrames:true),但前提是您的扩展程序被允许访问选项卡的 URL(如果设置了 frameId,则为框架的 URL)。

【讨论】:

哇,declarativeContent 新动作!酷。 文档中的信息相互矛盾。 “自 Chrome 38 起”和“警告:此操作仍处于试验阶段,Chrome 的稳定版本不支持此操作。” @Xan 是的,请参阅我的答案中的链接错误:crbug.com/409147。目的是在审查完成之前使其远离稳定,但无论如何该功能都已登陆。并且文档并不完全矛盾,因为可以在稳定版本上禁用功能(例如,查看 infobars 或 chrome.declarativeWebRequest)。 @RobW 您是否能够使用 chrome.declarativeContent.RequestContentScript 方法获取样式表注入?我的 js 文件正在正确注入,但我的 css 文件似乎根本没有通过 RequestContentScript(js: [...], css: [...]) 注入 @istan "css" 似乎不起作用,我在这里报告了它:crbug.com/708115 作为解决方法,您可以使用 "js" 插入 <style><link> 元素在页面中。【参考方案2】:

我将把它分成两部分。

程序化脚本注入

有一个新的contentScripts.register() API 可以以编程方式注册内容脚本,并且它们将完全按照清单中定义的content_scripts 进行加载:

browser.contentScripts.register(
    matches: ['https://your-dynamic-domain.example.com/*'],
    js: [file: 'content.js']
);

此 API 仅在 Firefox 中可用,但您可以使用 Chrome polyfill。将来您将可以使用chrome.scripting.registerContentScript,但它是not yet implemented。

获取新权限

通过使用chrome.permissions.request,您可以添加可以注入内容脚本的新域。一个例子是:

// In a content script or options page
document.querySelector('button').addEventListener('click', () => 
    chrome.permissions.request(
        origins: ['https://your-dynamic-domain.example.com/*']
    , granted => 
        if (granted) 
            /* Use contentScripts.register */
        
    );
);

您必须在您的manifest.json 中添加optional_permissions 以允许请求新的来源:


    "optional_permissions": [
        "*://*/*"
    ]


我还编写了一些工具来为您和最终用户进一步简化此过程,例如 webext-domain-permission-toggle and webext-dynamic-content-scripts。他们将在下次浏览器启动时自动注册您的脚本,并允许用户删除新的权限和脚本。

【讨论】:

您为您解答!只是想澄清一下,如果我以编程方式注册内容脚本,chrome 会在安装扩展程序之前显示警告消息“可以读取和更改所有网站数据”吗?我的脚本设计为在每个页面上运行。 不,只要您不在清单中的permissions 中包含tabshttps://*/*。如果需要,他们只能是optional_permissions。澄清一下,通过此设置,您的脚本将在用户通过chrome.permissions.request 明确授予权限的 any 页面上运行【参考方案3】:

由于现有答案现在已有几年历史,因此可选注入现在要容易得多,并且是 described here。它说要有条件地注入新文件,您可以使用以下代码:

// The lines I have commented are in the documentation, but the uncommented
// lines are the important part

//chrome.runtime.onMessage.addListener((message, callback) => 
//   if (message == “runContentScript”)

        chrome.tabs.executeScript(
          file: 'contentScript.js'
        );

//   
//);

您需要Active Tab Permission 来执行此操作。

【讨论】:

以上是关于可选择注入内容脚本的主要内容,如果未能解决你的问题,请参考以下文章

Linux shell脚本流程控制

注入自动应答文件什么意思

SQL注入大全实用收藏

sqlmap爆库名时选择的注入方式

Fuzz安全狗注入绕过

sqlmap使用手册