Kir*_*lev 11 javascript iframe google-chrome-extension
我正在开发一个镀铬扩展,并遇到了一个大问题.
我正在使用内容脚本在网站上注入我的javascript代码.该网站有一个iframe.我可以更改iframe的源代码,但似乎无法访问iframe的contentWindow属性.我需要它在当前的carret位置插入文本.
所以基本上这个代码在页面的上下文中完美地工作:
$("#iframe1").contentWindow.document.execCommand("InsertHTML", false, 'test text');
Run Code Online (Sandbox Code Playgroud)
但是,当我尝试在我的chrome扩展程序的上下文中运行时,我收到此错误:
TypeError: Cannot read property 'document' of undefined
Run Code Online (Sandbox Code Playgroud)
奇怪的是,我可以访问iframe的html.所以这段代码完全可以从chrome扩展程序中运行:
$("#iframe1").contents().find('div').html('test')
Run Code Online (Sandbox Code Playgroud)
我尝试在清单文件中放入"all_frames":true但没有运气:(
Rob*_*b W 19
要理解为什么你的代码不起作用,我将包含我之前答案的一个片段:
内容脚本无权访问页面的全局
window对象.对于内容脚本,以下内容适用:
- 该
window变量没有指向页面的全局对象.相反,它指的是新的上下文,页面上的"层".页面的DOM完全可访问.#执行环境鉴于一份文件包括
<iframe id="frameName" src="http://domain/"></iframe>:
- 对框架内容的访问受到页面的相同原始策略的限制; 您的扩展程序的权限不会放松该政策.
frames[0]并且frames['frameName'],(通常指的是包含全局window对象的框架)是undefined.var iframe = document.getElementById('frameName');
iframe.contentDocument返回document包含框架的对象,因为内容脚本可以访问页面的DOM.此属性null适用于同源策略.iframe.contentDocument.defaultView(指window与文档关联的对象)未定义.iframe.contentWindow是不确定的.
在您的情况下,以下任何一种都可以工作:
// 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);
Run Code Online (Sandbox Code Playgroud)
通用解决方案"all_frames": true在清单文件中使用,并使用以下内容:
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);
}
Run Code Online (Sandbox Code Playgroud)
此演示仅用于教育目的,请勿在真实扩展中使用此演示.为什么?因为它用于postMessage传递消息.这些事件也可以由客户端生成,这会导致安全漏洞(XSS:任意HTML注入).
另一种选择postMessage是Chrome的消息API.有关演示,请参阅此答案.您将无法比较window对象.你可以做的是依靠window.name财产.该window.name属性会自动设置为iframe name属性的值(加载iframe时只需一次).
| 归档时间: |
|
| 查看次数: |
13440 次 |
| 最近记录: |