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

时间:2020-03-04 23:17:24

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

我正在尝试创建一个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);
    }
});

如您所见,由于我的JavaScript代码是动态的,因此我正在尝试重新创建chrome在manifest.json的“ content_script”部分中已经执行的操作。

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

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

1 个答案:

答案 0 :(得分: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,当然, ll检查iframe的真实URL(frameElement.contentWindow.location.href)是否不以http开头,因为可以在内部导航框架而无需在外部更改其src属性。在try / catch内进行检查,因为从其他来源访问iframe会抛出该错误。