gpt4 book ai didi

javascript - 从 chrome 扩展访问 iframe

转载 作者:可可西里 更新时间:2023-11-01 02:33:48 26 4
gpt4 key购买 nike

我正在开发一个 chrome 扩展并遇到了一个大问题。

我正在使用内容脚本在网站上注入(inject)我的 javascript 代码。该网站有一个 iframe。我可以更改 iframe 的源代码,但似乎无法访问 iframe 的 contentWindow 属性。我需要它在当前插入位置插入文本。

基本上这段代码在页面上下文中完美运行:

$("#iframe1").contentWindow.document.execCommand("InsertHTML", false, 'test text');

但是当我尝试在我的 chrome 扩展的上下文中运行它时,我得到了这个错误:

TypeError: Cannot read property 'document' of undefined

奇怪的是我可以访问iframe的html。所以这段代码在 chrome 扩展中完美运行:

$("#iframe1").contents().find('div').html('test')

我尝试将 "all_frames": true 放入 list 文件中,但没有成功 :(

最佳答案

为了理解为什么您的代码不起作用,我加入了 a fragment of my previous answer :

Content scripts do not have any access to a page's global window object. For content scripts, the following applies:

  • The window variable does not refer to the page's global object. Instead, it refers to a new context, a "layer" over the page. The page's DOM is fully accessible. #execution-environment

Given a document consisting of   <iframe id="frameName" src="http://domain/"></iframe>:

  • Access to the contents of a frame is restricted by the Same origin policy of the page; the permissions of your extension does not relax the policy.
  • frames[0] and frames['frameName'], (normally referring to the the frame's containing global window object) is undefined.
  • var iframe = document.getElementById('frameName');
    • iframe.contentDocument returns a document object of the containing frame, because content scripts have access to the DOM of a page. This property is null when the Same origin policy applies.
    • iframe.contentDocument.defaultView (refers to the window object associated with the document) is undefined.
    • iframe.contentWindow is undefined.

同源框架解决方案

在您的情况下,以下任一方法都有效:

// jQuery:
$("#iframe1").contents()[0].execCommand( ... );

// VanillaJS
document.getElementById("iframe1").contentDocument.execCommand( ... );

// "Unlock" contentWindow property by injecting code in context of page
var s = document.createElement('script');
s.textContent = 'document.getElementById("iframe1").contentWindow.document.execCommand( ... );';
document.head.appendChild(s);

通用解决方案

通用解决方案是使用 "all_frames": true在 list 文件中,并使用如下内容:

if (window != top) {
parent.postMessage({fromExtension:true}, '*');
addEventListener('message', function(event) {
if (event.data && event.data.inserHTML) {
document.execCommand('insertHTML', false, event.data.insertHTML);
}
});
} else {
var test_html = 'test string';
// Explanation of injection at https://stackoverflow.com/a/9517879/938089 :
// Run code in the context of the page, so that the `contentWindow`
// property becomes accessible
var script = document.createElement('script');
script.textContent = '(' + function(s_html) {
addEventListener('message', function(event) {
if (event.data.fromExtension === true) {
var iframe = document.getElementById('iframe1');
if (iframe && (iframe.contentWindow === event.source)) {
// Window recognised, post message back
iframe.contentWindow.postMessage({insertHTML: s_html}, '*');
}
}
});
} + ')(' + JSON.stringify(test_html) + ');';
(document.head||document.documentElement).appendChild(script);
script.parentNode.removeChild(script);
}

此演示仅用于教育目的,请勿在真正的扩展中使用此演示。为什么?因为它使用 postMessage 传递消息。这些事件也可能由客户端生成,从而导致安全漏洞(XSS:任意 HTML 注入(inject))。

postMessage 的替代品是 Chrome 的消息 API。有关演示,请参阅 this answer .您将无法比较 window虽然对象。您可以做的是依靠 window.name属性(property)。 window.name属性自动设置为 iframe 的 name 的值属性(只有一次,当加载 iframe 时)。

关于javascript - 从 chrome 扩展访问 iframe,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13266192/

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