从 chrome 的扩展内容脚本访问 iframe 内容

Posted

技术标签:

【中文标题】从 chrome 的扩展内容脚本访问 iframe 内容【英文标题】:access iframe content from a chrome's extension content script 【发布时间】:2012-07-04 17:47:04 【问题描述】:

我正在做一个插件来对界面进行一些转换。我不断收到unsafe javascript attempt to access frame with url.... Domains, protocols and ports must match(典型的跨站点问题)

但作为一个扩展,它应该可以访问 iframe 的内容 http://code.google.com/chrome/extensions/content_scripts.html ...

有没有人知道如何访问它的内容以便被捕获?

【问题讨论】:

你到底想做什么?在大多数情况下,您可以将 "all_frames":true 添加到清单文件的 "content_scripts" 部分,并在内容脚本中编写特定于页面的逻辑。 @RobW 添加 all_frames:true 将使 content_script 在所有内部框架中运行一次。这会使它的逻辑复杂化很多。我只想通过content_script访问内框的内容。 (如:content_script --> target_page --> inner_content) 不可能:内容脚本无法访问页面的任何window 对象(包括框架)。使用"all_frames": false 注入一个内容脚本,您可以在其中设置一个标志。然后,使用all_frames": true 注入一个脚本,检查该标志的存在。如果标志不存在,则假定内容脚本在框架中运行。然后,您可以对其应用特定于帧的逻辑,并使用消息传递将任何获取的数据传递给主内容脚本。 嗯,好的,谢谢:p,但你可以在回答中添加它来标记它,我已经在考虑像你说的那样做,但希望存在直接访问 我不确定你想要什么。对于深度嵌套的 iframe,建议的解决方案不起作用。我将发布一个简洁的示例。 【参考方案1】:

通常没有直接的方法可以访问不同来源的window 对象。如果您想安全地在不同框架中的内容脚本之间进行通信,您必须向后台页面发送一条消息,然后后台页面将消息发送回选项卡。

这是一个例子:

manifest.json的一部分:

"background": "scripts":["bg.js"],
"content_scripts": [
    "js": ["main.js"], "matches": ["<all_urls>"],
    "js": ["sub.js"], "matches": ["<all_urls>"], "all_frames":true
]

main.js:

var isTop = true;
chrome.runtime.onMessage.addListener(function(details) 
    alert('Message from frame: ' + details.data);
);

sub.js:

if (!window.isTop)  // true  or  undefined
    // do something...
    var data = 'test';
    // Send message to top frame, for example:
    chrome.runtime.sendMessage(sendBack:true, data:data);

后台脚本'bg.js':

chrome.runtime.onMessage.addListener(function(message, sender) 
    if (message.sendBack) 
        chrome.tabs.sendMessage(sender.tab.id, message.data);
    
);

另一种方法是在bg.js 中使用chrome.tabs.executeScript 来触发主内容脚本中的函数。

相关文档

Message passing c.runtime.sendMessage / c.tabs.sendMessage / c.runtime.onMessage MessageSenderTab 类型。 Content scripts chrome.tabs.executeScript

【讨论】:

您的声明“无法访问页面的任何窗口对象。”似乎并不完全准确。我刚刚创建了一个基本扩展,我能够访问 window.frames 并获得对同一来源的框架的完整 DOM 访问。自从您写下答案以来,这可能已经改变了?似乎这可能仍在开发中,并且没有完全记录在案。见:code.google.com/p/chromium/issues/detail?id=20773 @kzahel 在撰写本文时,所有is 的window.frames[i] 尚未定义。这确实已经修复了一段时间。但是,同源策略仍然适用,因此答案仍然有效,至少对于所提出的问题(OP 遇到跨域框架访问问题)。 @stt 感谢bringing the fault in my answer to my attention。它被审稿人拒绝了,但我还是编辑了我的答案。 我需要访问一个由运行内容脚本的页面定义的变量;怎么样? @theonlygusti 见***.com/questions/9602022/…。【参考方案2】:

我知道这是一个老问题,但我最近花了半天时间来解决它。 通常创建 iframe 看起来像这样:

var iframe = document.createElement('iframe');
iframe.src = chrome.extension.getURL('iframe-content-page.html');

此框架与页面的来源不同,您将无法获取其 DOM。但是,如果您创建 iframe 只是为了隔离 css,您可以通过另一种方式执行此操作:

var iframe = document.createElement('iframe');
document.getElementById("iframe-parent").appendChild(iframe);
iframe.contentDocument.write(getFrameHtml('html/iframe-content-page.html'));
.......
function getFrameHtml(htmlFileName) 
    var xmlhttp = new XMLHttpRequest();
    xmlhttp.open("GET", chrome.extension.getURL(html/htmlFileName), false);
    xmlhttp.send();

    return xmlhttp.responseText;

.......
"web_accessible_resources": [   
    "html/htmlFileName.html",
    "styles/*",
    "fonts/*"
]

之后你可以使用 iframe.contentDocument 来访问 iframe 的 DOM

【讨论】:

我还没有尝试过,只是想知道这是否只返回 iframe 的 HTML 代码,还是为您提供对该 iframe 的 DOM 的实际引用。 这将是对 DOM 的实际引用 - 您可以获取/设置输入值、隐藏 div 等。 聪明的方法。刚投了赞成票。另外我想知道我们是否想反之亦然。例如; iframe 中的父(当前选项卡)dom?? 不,这只是因为我正在创建没有 src 的 iframe,所以它的域将与父页面相同。 @EugeneTitarchuk 谢谢!将引导程序注入 gmail 扩展程序时正是您所需要的。

以上是关于从 chrome 的扩展内容脚本访问 iframe 内容的主要内容,如果未能解决你的问题,请参考以下文章

无法使用 jquery 访问通过 google chrome 内容脚本注入的 iframe 的内容

无法从 Chrome 扩展生成的 iframe 更改元素

如何允许 chrome 扩展访问第三方 API 脚本?

在 iFrame 中激活 Zurb Foundation 的 Joyride,来自 Chrome 扩展内容脚本

授予 Chrome 扩展程序访问 iframe 内容的权限

访问从不同来源加载的 iframe 的内容