2013-04-30 126 views
4

我在我的谷歌浏览器应用中使用了knockoutjs。为了能够使用knockout,我必须将真正的application.html定义为sandox页面,并将其作为iframe包含在虚拟容器中。应用结构如下:Chrome应用:从父窗口访问沙箱化的iframe

- container.html 
| 
+-- application.html as iframe 
    | 
    +-knockout and application.js 

I帧被定义为如下:

<iframe src="application.html" frameborder="0" 
      sandbox="allow-same-origin allow-scripts" ></iframe> 

运行

document.getElementsByTagName("iframe")[0] 

检查上container.html工具抛出以下错误。

Sandbox access violation: Blocked a frame at "chrome-extension://hllbklabnppjkmnngfanldbllljfeaia" 
from accessing a frame at "chrome-extension://hllbklabnppjkmnngfanldbllljfeaia". 
The frame being accessed is sandboxed and lacks the "allow-same-origin" flag. 

我怎样才能从它的父母访问iframed文件?

回答

1

找到了罪魁祸首。这是我的proxy.js,它被container.html包含在内,用作在应用程序iframe和background.js之间传输消息的桥梁。以下部分是侦听源自iframe的消息的部分。

window.addEventListener("message", 
    function(evt){ 
     console.log(evt); <= this is the problem 
     var iframe = document.getElementById("application").contentWindow; <= not this one 
     if (evt.source == iframe) { 
      return chrome.runtime.sendMessage(null, evt.data); 
     } 
    } 
); 

我没有想到console.log会导致问题。相反,我怀疑document.getElem ..行。因为试图在应用程序的检查窗口中运行该代码时抛出了相同的错误。

但似乎console.log(控制台似乎属于container.html的作用域)访问一些内部的事件对象,这些内部事件并不意味着可以从iframe的作用域中访问(这就解释了为什么我得到相同的错误检查控制台)。删除console.log行为我解决了这个问题。

2

做这样的事情:

的manifest.json

"sandbox": { 
    "pages": ["my_ui.html"] 
    } 

my_ui.html

<script type="text/javascript" src="knockout-1.2.3.4.js"></script> 
    <script type="text/javascript" src="my_ui.js"></script> 

my_ui.js

this.onSomethingChange = function() { 
    window.top.postMessage(
    { command: 'please-do-something', myArgument: this.myArgument() }, '*'); 
}; 

container.html

<script type="text/javascript" src="container.js"></script> 
    <iframe id="knockoutFrame" src="my_ui.html"></iframe> 

container.js

window.addEventListener('message', function(event) { 
    var kocw = document.getElementById('knockoutFrame').contentWindow; 
    var anotherContentWindow = // etc. 
    var dest; 

    if (event.source == kocw) { 
     // The knockout iframe sent us a message. So we'll forward it to our 
     // app code. 
     dest = anotherContentWindow; 
    } 
    if (event.source == anotherContentWindow) { 
     // Our app code is responding to the knockout message (or initiating 
     // a conversation with that iframe). Forward it to the knockout code. 
     dest = kocw; 
    } 
    if (dest == null) { 
     console.log('huh?'); 
    } 

    // This makes container.js like a gatekeeper, bouncing valid messages between 
    // the sandboxed page and the other page in your app. You should do 
    // better validation here, making sure the command is real, the source 
    // is as expected for the kind of command, etc. 
    dest.postMessage(event.data, '*'); 
    } 

你的声明“我不得不定义实application.html为沙箱页面,并将其包含在虚拟容器中的iframe”可能不是你想要的。这个想法是将最小的可能事件发送到沙箱,发送到网守页面以验证消息,并让网守将窄消息转发给您的非沙盒应用程序逻辑。如果你只是将所有东西都塞进沙箱中,那你就是击败了沙箱的目的。

声明:我从安全角度没有仔细检查过这段代码。您会想要假设敌对消息来自沙箱(或来自其他地方),并尽力解决该威胁。

+0

谢谢你的回复。我正在做几乎完全一样的事情。我的整个应用程序需要淘汰赛,并访问其他一些apis,这些扩展程序无法使用。我正在使用与您的代理非常相似的代理在应用程序iframe和后台页面之间传输消息。 “document.getElementById('knockoutFrame')。contentWindow”是我得到代理代码中的“沙箱访问冲突”错误。 – hinoglu 2013-05-01 03:34:52