我浏览了一些与SO相关的问题和解决方案,但似乎都没有最新的解决方案或与我类似的问题。
所以这是基本问题。我有一个在https://example.com/*
上运行的内容脚本,目的是更改页面上的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
返回https://static.example.com/.../player.html
。 “来源”不同,但与原始站点的根域相同。
所以我想知道如何使用内容脚本(或者,我猜其他方法)在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"
]
}
],
//...
}
答案 0 :(得分:1)
这里的重要要点来自于这句话:
有关更多信息,document.querySelector(“ iframe”)。src返回https://static.example.com/.../player.html。 “来源”不同,但与原始站点的根域相同。
来源不同。(static.example.com
!= example.com
)即使根域相同,但来源不是 。 (这就是tuckerchapin.sketchyfreewebhost.com无法提供和修改j6m8.sketchyfreewebhost.com内容的原因)。因此,从理论上讲,这是“更好”的行为。
取自this answer:
如果要访问框架,协议,主机名和端口必须与您的域相同。
(重点是我的)