gpt4 book ai didi

google-chrome - 扩展页面中嵌套 iframe 的编程注入(inject)

转载 作者:行者123 更新时间:2023-12-04 12:39:05 28 4
gpt4 key购买 nike

摘要:我需要找到一种方法来完成与使用 content_scripts 相同的行为的程序化注入(inject)。 > matches"all_frames": true在 list 上。为什么?因为这是我发现注入(inject) iframe 的唯一方法的内容在扩展页面中没有跨域错误。

我要搬到 optional_permissions在 Chrome 扩展程序上,我走上了死胡同。

我想要的是:

将此行为移至 optional_permissions以便将来能够添加更多主机。使用当前代码,通过在 content_scripts 上添加一个新主机> matches该扩展程序已被 Chrome 禁用。

对于移动,我删除了 content_scripts在 list 中,我添加了 "optional_permissions": ["*://*/"], .然后,我成功实现了一个对话框,向具有 chrome.permissions.request 的用户询问新权限。 .

正如我之前所说,问题是如何注入(inject) iframe的内容在扩展页面中。

我试过的:

  • chrome.declarativeContent.RequestContentScript (提到 here )与 allFrames: true .如果我直接输入 URL,我只能看到脚本正在运行,当该 URL 设置在 iframe 中时没有任何 react 。 .
  • chrome.tabs.onUpdated : urlundefined用于扩展页面。此外,iframe未检测到网址。
  • 调用 chrome.tabs.executeScript allFrames: true我一加载第一个 iframe .通过这样做,我得到一个异常 Cannot access contents of the page. Extension manifest must request permission to access the respective host.并且“各自的主机”是chrome-extension:// ,如果要将其添加到权限中,则它不是有效的主机。

  • 我迷路了。我找不到模拟与 content_scripts 相同的行为的方法> matchesprogrammatic injection .

    注:使用 webNavigation API 不是一个选项,因为扩展是实时的并且它有成千上万的用户。因此,我不能使用 frameId executeScript 的属性.因此,我唯一的选择 executeScript是注入(inject)所有帧,但 chrome-extension主机问题不要让我继续。

    更新:我能够完成我想要的,但只能在 HTTP 主机上完成。我用了 chrome.tabs.executeScript (选项 3)。

    问题仍然在于如何在扩展页面上进行这项工作。

    最佳答案

    您不能在任何扩展页面中运行内容脚本,包括您自己的页面。

    如果要在扩展页面的子框架中运行代码,则必须使用 frameId .有两种方法可以做到这一点,有和没有 webNavigation .

    我已将这个答案中的所有代码片段放在一起(以及一些用于调用各个代码片段的按钮)并在 https://robwu.nl/s/optional_permissions-script-subframe.zip 上共享它
    要试用它,请下载并解压缩 zip 文件,在 chrome://extensions 加载扩展程序,然后单击扩展程序按钮打开测试页面。

    请求可选权限

    由于目标是使用 optional permissions 以编程方式运行脚本,您需要请求权限。我的示例将使用 example.com。
    如果您也想使用 webNavigation API,请将其权限也包含在权限请求中。

    chrome.permissions.request({
    // permissions: ['webNavigation'], // uncomment if you want this.
    origins: ['*://*.example.com/*'],
    }, function(granted) {
    alert('Permission was ' + (granted ? '' : 'not ') + 'granted!');
    });

    在子帧中注入(inject)脚本

    一旦有了标签 ID 和 frameId,在特定框架中注入(inject)脚本就很容易了。由于 tabId 的要求,这个方法只适用于 tabs 中的框架,而不适用于 browserAction/pageAction 弹出或背景页面中的框架!

    为了证明代码执行成功,我下面的示例将调用下一个 injectInFrame一旦知道 tabId 和 frameId 就可以运行。

    function injectInFrame(tabId, frameId) {
    chrome.tabs.executeScript(tabId, {
    frameId,
    code: 'document.body.textContent = "The document content replaced with content at " + new Date().toLocaleString();',
    });
    }

    如果您不仅要在特定帧中运行代码,还要在该帧的所有子帧中运行代码,只需添加 allFrames: true chrome.tabs.executeScript 称呼。

    选项 1:使用 webNavigation 查找 frameId

    使用 chrome.tabs.getCurrent 查找运行脚本的选项卡的 ID(或 chrome.tabs.query {active:true,currentWindow:true},如果您想从另一个脚本(例如后台脚本)知道当前的 tabId。

    之后,使用 chrome.webNavigation.getAllFrames 查询选项卡中的所有帧。识别框架的主要方法是通过页面的 URL,因此如果框架页面重定向到其他地方,或者如果有多个框架具有相同的 URL,则会出现问题。这是一个例子:

    // Assuming that you already have a frame in your document,
    // i.e. <iframe src="https://example.com"></iframe>
    chrome.tabs.getCurrent(function(tab) {
    chrome.webNavigation.getAllFrames({
    tabId: tab.id,
    }, function(frames) {
    for (var frame of frames) {
    if (frame.url === 'https://example.com/') {
    injectInFrame(tab.id, frame.frameId);
    break;
    }
    }
    });
    });

    选项 2:使用框架中的帮助页面查找 frameId
    webNavigation 的选项看起来很简单,但有两个主要缺点:
  • 它需要 webNavigation 权限(导致“阅读您的浏览历史”权限警告)
  • 如果存在多个具有相同 URL 的框架,则框架的识别可能会失败。

  • 另一种方法是先打开一个发送扩展消息的扩展页面,然后找到 frameId chrome.runtime.onMessage 的第二个参数中提供的元数据中的(和选项卡 ID)听众。此代码比其他选项更复杂,但更可靠且不需要任何额外权限。

    框架助手.html

    <script src="framehelper.js"></script>

    框架助手.js

    var parentOrigin = location.ancestorOrigins[location.ancestorOrigins.length - 1];
    if (parentOrigin === location.origin) {
    // Only send a message if the frame was opened by ourselves.
    chrome.runtime.sendMessage(location.hash.slice(1));
    }

    要在扩展页面中运行的代码:

    chrome.runtime.onMessage.addListener(frameMessageListener);
    var randomMessage = 'Random message: ' + Math.random();

    var f = document.createElement('iframe');
    f.src = chrome.runtime.getURL('framehelper.html') + '#' + randomMessage;
    document.body.appendChild(f);

    function frameMessageListener(msg, sender) {
    if (msg !== randomMessage) return;
    var tabId = sender.tab.id;
    var frameId = sender.frameId;

    chrome.runtime.onMessage.removeListener(frameMessageListener);
    // Note: This will cause the script to be run on the first load.
    // If the frame redirects elsewhere, then the injection can seemingly fail.
    f.addEventListener('load', function onload() {
    f.removeEventListener('load', onload);
    injectInFrame(tabId, frameId);
    });
    f.src = 'https://example.com';
    }

    关于google-chrome - 扩展页面中嵌套 iframe 的编程注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44425102/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com