【问题标题】:Dynamically inject content scripts - Chrome Extension动态注入内容脚本 - Chrome 扩展
【发布时间】:2020-03-04 23:17:24
【问题描述】:

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

这是我目前的代码:

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 商店中是不允许的,因此此扩展程序不得与任何人共享。

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

【问题讨论】:

    标签: javascript google-chrome iframe google-chrome-extension content-script


    【解决方案1】:

    我无法访问 Chrome API(如 chrome.storage 或 chrome.runtime.sendMessage)

    您的代码当前生成的是page script,而不是内容脚本。对于后者,您需要在后台脚本中使用chrome.tabs.executeScript(另见content script documentation)。

    location.href 返回顶部网页的 URL,但我找不到在 iframe 本身中访问 iframe 当前 URL 的方法。

    不,您所描述的根本不可能发生,这将是对 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 会抛出异常。

    【讨论】:

    • 感谢您的回答,这帮助了很多。我不知道 executeScript 存在,它现在工作得更好。尽管@wOxxOm,我对您的最后一条注释有一个问题:我不希望我的脚本被注入到javascript:或srcdoc:iframe中,我只希望它在具有实际URL的“真实”iframe中运行,我需要一种方法抓取该 URL 以检查我是否要注入它,因为当前 location.href 确实返回与父网站相同的 URL...
    • 另外需要注意的是,我正在测试它的 iframe 是空的并且有 src='javascript:false',在该 iframe 上记录 frameElement.contentWindow.location.href 也会返回父 URL (我想要返回 javascript:false 的东西)。我说得通吗?
    • 网络安全基于 URL 来源。您看到的是同源 iframe - 所有那些没有 sandbox 属性的 javascript:about:srcdoc: 帧都在与嵌入帧/页面相同的源中运行,这就是为什么它们网址相同。
    • 有没有办法检查这些帧?我不想注入它们...
    • 干脆不要加match_about_blank。 Chrome 无论如何都不会注入到javascript:。要检查 iframe 是否同源,您还可以尝试访问属于父窗口的内容:let isSame; try { isSame = !!window.frameElement } catch (e) {}
    猜你喜欢
    • 1970-01-01
    • 2022-11-07
    • 1970-01-01
    • 2012-04-12
    • 2014-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多