动态注入内容脚本 - Chrome 扩展

Dynamically inject content scripts - Chrome Extension

我正在尝试制作一个 chrome 扩展,它从后端接收 javascript 代码并将其保存在 localStorage(作为 base64)中,以便稍后我可以将其作为内容脚本注入加载了正确的页面,除了有几个问题外,它大部分时间都可以工作...第一个问题(不是那么重要)是我无法访问 Chrome API(如 chrome.storage 或 chrome.runtime.sendMessage), 第二个问题是它没有向子 iframe 注入正确的代码...因为 location.href returns 顶部网页的 URL 我找不到在 iframe 本身内访问当前 URL iframe 的方法。

到目前为止,这是我的代码:

manifest.json

//....
"content_scripts": [{
    "run_at": "document_end",
    "all_frames": true,
    "matches": [
        "<all_urls>"
    ],
    "js": [
        "src/inject/InjectManager.js"
    ]
}],
//...

InjectManager.js:

// Some functions were not included for brevity
chrome.runtime.sendMessage({ action: "get_supported_urls" }, function(supported_urls) {
    let current_url = window.location.href;

    // Check if we support current_url
    let js_code_to_inject = isWebsiteSupported(supported_urls, current_url); // this function returns string that is javascript code.
    if(js_code_to_inject){
        // Append the code to the body
        let script = document.createElement("script");
        script.type = "text/javascript";
        script.innerHTML = js_code_to_inject;

        document.body.appendChild(script);
    }
});

如您所见,我正在尝试重新创建 chrome 在 manifest.json 的 "content_script" 部分中所做的事情,因为我的 javascript 代码是动态的。

注意:我知道 chrome 商店不允许这样做,因此不得与任何人共享此扩展程序。

感谢阅读。 任何帮助将不胜感激。

I cannot access Chrome APIs (like chrome.storage or chrome.runtime.sendMessage)

您的代码当前在后台脚本中生成 page script, not a content script. For the latter you need to use chrome.tabs.executeScript (see also content script documentation)。

location.href returns the URL of the top webpage and I couldn't find a way to access current URL of iframe within the iframe itself.

不,你所描述的根本不可能发生,这将是对 URL 源安全的世界末日级别的违反,所以其他事情正在发生。例如,您的 manifest.json 没有 match_about_blank 意味着 InjectManager.js 根本不处理动态添加的 about:blank 帧。


manifest.json:

"content_scripts": [{
  "match_about_blank": true,
  .....................

InjectManager.js:

chrome.runtime.sendMessage({ action: 'inject', data: location.href });

后台脚本:

chrome.runtime.onMessage.addListener(({ action, data }, sender, sendResponse) => {
  if (action === 'inject') {
    chrome.tabs.executeScript(sender.tab.id, {
      code: getInjectionCode(data),
      frameId: sender.frameId,
    });
  }
});

请注意,javascript:srcdoc: 等 iframe 根本不会 运行 Chrome 中的内容脚本,因此您必须直接在 InjectManager.js 因为它们不能被 executeScript() 注入。例如,您可以使用 document.querySelectorAll('iframe') 找到所有 iframe,并像当前一样在其中创建 DOM script 元素,但您将使用 frameElement.contentDocument 而不是 document 和当然,您将检查 iframe 的真实 URL (frameElement.contentWindow.location.href) 是否不是以 http 开头,因为框架可以在内部导航而无需更改外部的 src 属性.在 try/catch 内部进行检查,因为从不同来源访问 iframe 会抛出异常。