4

我在我的谷歌浏览器应用程序中使用了 knockoutjs。为了能够使用淘汰赛,我必须将真正的 application.html 定义为 Sandox 页面,并将其作为 iframe 包含在一个虚拟容器中。应用结构如下:

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

iframe 定义如下:

  <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 文档?

4

2 回答 2

2

做这样的事情:

清单.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() }, '*');
};

容器.html

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

容器.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 包含在虚拟容器中”可能不是您想要的。这个想法是将尽可能小的东西沙箱化,将消息发送到验证消息的网守页面,并让网守将窄消息转发到您的未沙箱化应用程序逻辑。如果你只是把所有东西都塞进沙箱,你就违背了沙箱的目的。

免责声明:我没有从安全角度仔细检查此代码。您需要假设恶意消息来自沙箱(或其他地方,就此而言),并尽您所能解决该威胁。

于 2013-04-30T21:54:33.193 回答
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 行为我解决了这个问题。

于 2013-05-01T15:24:25.217 回答