可选择注入内容脚本
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
中包含tabs
或https://*/*
。如果需要,他们只能是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 来执行此操作。
【讨论】:
以上是关于可选择注入内容脚本的主要内容,如果未能解决你的问题,请参考以下文章