【问题标题】:Chrome extension manifest v3 Content Security PolicyChrome 扩展清单 v3 内容安全政策
【发布时间】:2021-07-30 00:02:49
【问题描述】:

我正在尝试在页面中加载(注入)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_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.

【问题讨论】:

  • 您显示的代码与错误无关,即您有一个内联脚本,这是弹出窗口或选项页面中的常见问题:more info。
  • 你是对的,确实我正在尝试在页面中注入所述脚本。我看到 executeScript 是一个可行的替代方案。如何在当前选项卡中注入脚本代码?
  • 使用content script。
  • 我用有问题的行更新了代码。因为 V3 不允许注入脚本,所以阻塞的是 appendchild 部分。我正在使用内容脚本来执行此操作,但仍然失败。
  • 目前您使用内容脚本在page context 中注入另一个脚本,这是从页面中提取/访问JS变量/函数所需的非常特殊的东西。要注入你不需要的代码。只需将 js 文件作为内容脚本注入(以声明方式或通过 executeScript)。

标签: javascript google-chrome-extension chrome-extension-manifest-v3


【解决方案1】:

您可以通过将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'));

【讨论】:

  • 我在 v3 发布时尝试过此操作,但无法从顶部窗口(网站上下文)访问任何 javascript 变量。我的意思是访问。假设有一个 window.text 变量。我可以注入一个执行 window.text='something'; 的脚本吗?所以我无法读取变量,但我仍然可以更改它。据我了解,这在 v3 下是不可能的。
  • 绝对可以注入执行window.text='something' 的脚本。我正在用一个例子更新我的答案。
  • 是的,它确实有效。我也能够验证它。多么优雅而简单的解决方案!非常感谢!
  • 这可以与外部脚本(如 paypal 的智能按钮)一起使用吗?
  • 当我尝试在 typecipt 中使用 remove 调用时遇到此错误:“TS2339: 类型 'GlobalEventHandlers' 上不存在属性 'remove'。”
猜你喜欢
  • 1970-01-01
  • 2019-07-24
  • 2020-02-28
  • 1970-01-01
  • 2013-02-01
  • 2021-09-24
  • 2015-01-26
  • 1970-01-01
  • 2013-12-23
相关资源
最近更新 更多