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").src
returnshttps://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.
(强调我的)
我浏览了 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").src
returnshttps://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.
(强调我的)