Chrome 带有 iframe 的扩展内容脚本 "blocked a frame with origin from accessing a cross-origin frame"

Chrome extension contentscript with iframe "blocked a frame with origin from accessing a cross-origin frame"

我浏览了 SO 上的一些相关问题和解决方案,none 似乎有最新的解决方案或与我的问题类似的问题。

这是基本问题。我有一个内容脚本 https://example.com/* 上的 运行s 与更改页面上的 HTML5 <video> 播放器的目标相匹配。然而,实际的播放器位于 iframe 中。为了获得实际的 HTMLMediaElement,我应该能够 运行

document.querySelector("iframe").contentWindow.document.querySelector("video")

然而,这失败并出现错误

Uncaught DOMException: Blocked a frame with origin "https://example.com" from accessing a cross-origin frame.

更多信息document.querySelector("iframe").srcreturnshttps://static.example.com/.../player.html。 "origin" 不同,但与原始站点的根域相同。

所以我想知道如何使用内容脚本(或者,我想,任何其他方法)来操纵 iframe 中的媒体播放器。


这是扩展的大致样子。

manifest.json

{
    "manifest_version": 2,
    //...
    "permissions": ["activeTab", "storage", "https://example.com/*"],
    //...
    "content_scripts": [
        {
            "all_frames": true,
            "matches": [
                "https://example.com/*"
            ],
            "js": [
                "inject.js"
            ]
        }
    ],
    //...
}

inject.js

winndow.onload = () => {
    document
        .querySelector("iframe.video-player")
        .contentWindow.document
        .querySelector("video#player_html5_api");
};

更新:

我不太确定为什么我没有早点想到这一点,但正如答案中提到的那样,将其视为完全不同的内容注入的关键。假设您不需要任何跨 iframe 边界的交互(这仍然可以通过消息传递来实现),您可以按如下方式修改清单。关键是匹配 iframe 的源,而不是页面的源。 “all frames: true 行是必不可少的,因为默认情况下不匹配不是最顶部的帧。

manifest.json

{
    //...
    "content_scripts": [
        {
            "all_frames": true,
            "matches": [
                "https://static.example.com/.../player.html"
            ],
            "js": [
                "inject.js"
            ]
        }
    ],
    //...
}

这里的重要内容来自这句话:

For additional information document.querySelector("iframe").src returns https://static.example.com/.../player.html. The "origin" is different, but is the same root-domain of the original site.

来源不同 (static.example.com != example.com) 虽然根域相同,但来源是不是。 (这就是 tuckerchapin.sketchyfreewebhost.com 无法提供和修改来自 j6m8.sketchyfreewebhost.com 的内容的原因)。所以从理论上讲,这是 "better" 行为。

摘自this answer

Protocol, hostname and port must be the same of your domain, if you want to access a frame.

(强调我的)