可以通过在扩展清单文件中声明来以编程方式或永久方式注入内容脚本。程序注入需要主机权限,通常由浏览器或页面操作授予。
在我的用例中,我想在没有用户操作的情况下注入gmail,outlook.com和yahoo邮件网站。我可以通过声明所有这些显示来做,但这样做需要所有数据访问这些帐户。某些用途可能只想授予outlook.com,但不授予gmail。程序注射不起作用,因为我需要知道何时注射。使用制表符权限也需要另一个权限。
有没有什么好方法可以选择注入网站?
答案 0 :(得分:10)
如果没有适当的权限,您无法在网站上运行代码。幸运的是,您可以在清单文件中将主机权限添加到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
),但前提是您的扩展程序允许访问标签的网址(或设置frameId
时框架的网址)。
答案 1 :(得分:4)
我将其分为两部分。
有一个新的contentScripts.register()
API,可以以编程方式注册内容脚本,并且它们的加载方式与清单中定义的content_scripts
完全一样:
browser.contentScripts.register({
matches: ['https://your-dynamic-domain.example.com/*'],
js: [{file: 'content.js'}]
});
此API仅在Firefox中可用,但是您可以使用Chrome polyfill。
通过使用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 */
}
});
});
并且您必须在optional_permissions
中添加manifest.json
才能请求新的来源:
{
"optional_permissions": [
"http://*/*",
"https://*/*"
]
}
我还编写了一些工具来进一步简化您和最终用户的操作,例如
webext-domain-permission-toggle
and webext-dynamic-content-scripts
。他们将在下次浏览器启动时自动注册您的脚本,并允许用户删除新的权限和脚本。
答案 2 :(得分:0)
由于现有答案已有数年历史,因此可选注入现在变得更加容易,并且described here。它说要有条件地注入新文件,可以使用以下代码:
// The lines I have commented are in the documentation, but the uncommented
// lines are the only important part
//chrome.runtime.onMessage.addListener((message, callback) => {
// if (message == “runContentScript”){
chrome.tabs.executeScript({
file: 'contentScript.js'
});
// }
//});
您将需要Active Tab Permission来完成此操作。