Chrome 扩展清单 v3 内容安全策略
Chrome extension manifest v3 Content Security Policy
我正在尝试在页面中加载(注入)javascript 代码。 javascript 文件是扩展的本地文件。文件路径是 'js/somefile.js'.
const basePath = chrome.runtime.getURL('');
fetch(chrome.runtime.getURL(filePath), { mode: 'same-origin' }) // <-- important
.then((_res) => _res.blob())
.then((_blob) => {
const reader = new FileReader();
reader.addEventListener('loadend', (data) => {
callback(data.currentTarget.result, basePath);
});
reader.readAsText(_blob);
});
const scriptTag = document.createElement('script');
scriptTag.innerHTML = scriptText;
scriptTag.type = 'text/javascript';
const scriptElement = document[injectLocation].appendChild(scriptTag);
if (removeImmediately) document[injectLocation].removeChild(scriptElement);
我的 Web 可访问资源是:
"web_accessible_resources": [{
"resources": [
"js/*.js",
],
"matches": ["<all_urls>"]
}],
"content_security_policy": {
"extension_pages": "script-src 'self'; object-src 'self'",
"sandbox": "sandbox allow-scripts; script-src 'self' 'https://apis.google.com/' 'https://www.gstatic.com/' 'https://*.firebaseio.com' 'https://www.googleapis.com' 'https://ajax.googleapis.com'; object-src 'self'"
},
我得到的错误是:
Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self'". Either the 'unsafe-inline' keyword, a hash ('sha256-Wq/CW2mxkri68TjkuaA0+LnU0capVpyiEuSA5NOVNfU='), or a nonce ('nonce-...') is required to enable inline execution.
您可以通过将scriptTag.innerHTML = scriptText;
更改为scriptTag.src = chrome.runtime.getURL(filePath);
来解决内联执行错误,无需获取脚本。 Manifest v3 似乎只允许将静态脚本注入页面上下文。
如果你想 运行 动态来源的脚本,我认为这可以通过让静态(已经信任的)脚本获取远程脚本然后对其进行评估来实现。
更新:带有清单 v3 的示例扩展,它注入了一个在页面上下文中运行的脚本。
# myscript.js
window.variableInMainContext = "hi"
# manifest.json
{
"name": "example",
"version": "1.0",
"description": "example extension",
"manifest_version": 3,
"content_scripts": [
{
"matches": ["https://*/*"],
"run_at": "document_start",
"js": ["inject.js"]
}
],
"web_accessible_resources": [
{
"resources": [ "myscript.js" ],
"matches": [ "https://*/*" ]
}
]
}
# inject.js
const nullthrows = (v) => {
if (v == null) throw new Error("it's a null");
return v;
}
function injectCode(src) {
const script = document.createElement('script');
// This is why it works!
script.src = src;
script.onload = function() {
console.log("script injected");
this.remove();
};
// This script runs before the <head> element is created,
// so we add the script to <html> instead.
nullthrows(document.head || document.documentElement).appendChild(script);
}
injectCode(chrome.runtime.getURL('/myscript.js'));
下载脚本文件并将其放在您的项目中以使其成为本地项目。它解决了我的内容安全策略问题。
我正在尝试在页面中加载(注入)javascript 代码。 javascript 文件是扩展的本地文件。文件路径是 'js/somefile.js'.
const basePath = chrome.runtime.getURL('');
fetch(chrome.runtime.getURL(filePath), { mode: 'same-origin' }) // <-- important
.then((_res) => _res.blob())
.then((_blob) => {
const reader = new FileReader();
reader.addEventListener('loadend', (data) => {
callback(data.currentTarget.result, basePath);
});
reader.readAsText(_blob);
});
const scriptTag = document.createElement('script');
scriptTag.innerHTML = scriptText;
scriptTag.type = 'text/javascript';
const scriptElement = document[injectLocation].appendChild(scriptTag);
if (removeImmediately) document[injectLocation].removeChild(scriptElement);
我的 Web 可访问资源是:
"web_accessible_resources": [{
"resources": [
"js/*.js",
],
"matches": ["<all_urls>"]
}],
"content_security_policy": {
"extension_pages": "script-src 'self'; object-src 'self'",
"sandbox": "sandbox allow-scripts; script-src 'self' 'https://apis.google.com/' 'https://www.gstatic.com/' 'https://*.firebaseio.com' 'https://www.googleapis.com' 'https://ajax.googleapis.com'; object-src 'self'"
},
我得到的错误是:
Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self'". Either the 'unsafe-inline' keyword, a hash ('sha256-Wq/CW2mxkri68TjkuaA0+LnU0capVpyiEuSA5NOVNfU='), or a nonce ('nonce-...') is required to enable inline execution.
您可以通过将scriptTag.innerHTML = scriptText;
更改为scriptTag.src = chrome.runtime.getURL(filePath);
来解决内联执行错误,无需获取脚本。 Manifest v3 似乎只允许将静态脚本注入页面上下文。
如果你想 运行 动态来源的脚本,我认为这可以通过让静态(已经信任的)脚本获取远程脚本然后对其进行评估来实现。
更新:带有清单 v3 的示例扩展,它注入了一个在页面上下文中运行的脚本。
# myscript.js
window.variableInMainContext = "hi"
# manifest.json
{
"name": "example",
"version": "1.0",
"description": "example extension",
"manifest_version": 3,
"content_scripts": [
{
"matches": ["https://*/*"],
"run_at": "document_start",
"js": ["inject.js"]
}
],
"web_accessible_resources": [
{
"resources": [ "myscript.js" ],
"matches": [ "https://*/*" ]
}
]
}
# inject.js
const nullthrows = (v) => {
if (v == null) throw new Error("it's a null");
return v;
}
function injectCode(src) {
const script = document.createElement('script');
// This is why it works!
script.src = src;
script.onload = function() {
console.log("script injected");
this.remove();
};
// This script runs before the <head> element is created,
// so we add the script to <html> instead.
nullthrows(document.head || document.documentElement).appendChild(script);
}
injectCode(chrome.runtime.getURL('/myscript.js'));
下载脚本文件并将其放在您的项目中以使其成为本地项目。它解决了我的内容安全策略问题。