【问题标题】:Opening and writing to a new window from a Google Chrome extension sandbox page从 Google Chrome 扩展沙箱页面打开并写入新窗口
【发布时间】:2025-11-28 20:35:01
【问题描述】:

(交叉发布here

嗨,

我有一个沙盒页面(在我的清单中指定),它被加载到我的扩展程序背景页面的 iframe 中。在我的沙盒页面中,我想打开一个新窗口并写入它,即:

var win = window.open(); win.document.write('

');

这适用于我的扩展程序的背景页面和常规网页,但是当从内容脚本或我的沙盒页面调用时,窗口会打开,但我无法访问 win 对象(它已定义,但为空---控制台。日志输出“窗口 {}”)。

我认为这是由于同源策略(在沙盒环境中每个窗口都被赋予一个 uinque-origin)。但是,由于窗口打开了 about:blank 页面,我很困惑为什么这很重要。

这是一个功能吗?我可以在清单中添加一个参数来避免这种情况吗?有没有人知道不涉及使用 postMessage 返回我的背景页面的解决方法?我理想的解决方案是让我的沙盒脚本打开一个新窗口并直接与之交互,而不是通过消息传递。

如有必要,我可以提供一个完整的示例,但我希望有人可能会立即知道。如果有帮助,我在 Mac 上运行 Chrome 24.0.1312.57,在 Ubuntu 上运行 24.0.1312.68。

谢谢,

汉克

【问题讨论】:

    标签: google-chrome-extension


    【解决方案1】:

    根据定义,内容脚本是您加载的外部常规网页的一部分,因此我不确定您的脚本如何在“常规网页”上运行,但不是内容脚本。您的意思是当您将代码嵌入到您自己的页面中时代码有效,但通过内容脚本在其他页面中无效?

    无论如何,如果脚本在您的后台页面上正常运行,您可以随时尝试发送消息。 (更多:http://developer.chrome.com/extensions/messaging.html

    沙盒/内容脚本的脚本:

    //send message to background page
    chrome.extension.sendMessage({todo: "newWindow"}); 
    

    在后台页面中:

    //create a listener
    chrome.extension.onMessage.addListener(
      function(request, sender) {   
        if (request.todo === "newWindow") {
        //do your stuff here
            var win = window.open(); win.document.write('<p&gtHello!</p>');
        }
      });
    

    【讨论】:

    • 我的意思是,完全忽略扩展名,如果您编写一个执行var win = window.open(); win.document.write('&amp;lt;p&amp;gt;Hello!&amp;lt;/p&amp;gt;') 的网页,它会按预期工作。但是,在我的扩展程序的沙箱中,情况并非如此。回到我的交叉帖子中,来自 chrome 团队的某个人确认问题是从沙盒打开的任何窗口都具有唯一的来源。
    【解决方案2】:

    根据here 的交叉帖子,问题确实是打开的窗口被赋予了唯一的来源。这是故意的,因为标准工作组 (SWG) 的成员认为,对于继承沙盒起源的 about:blank 页面不做例外处理会更安全。

    但是,为了解决这个问题,至少出于我的目的,我可以使用以下方法。首先,忘记沙盒。此解决方法使用嵌入在背景页面中的 iframe,并将 src url 设置为 data:text/html,...。这为 iframe 提供了一个独特的来源,因此它不再位于扩展空间中。这意味着可以使用 eval 并且无法访问 chrome api。与沙盒不同,从 iframe 打开的窗口与 iframe 共享相同的来源,允许访问创建的窗口。例如:

    在后台 html 页面中:

    <html>
    <head>
        ...
        <script src="background.js"></script>
        ...
    </head>
    <body>
        ...
        <iframe id="myframe"></iframe>
        ...
    </body>
    </html>
    

    在 background.js 中:

    ...
    document.getElementById('myframe').setAttribute('src', 'data:text/html,'+ 
        encodeURI('<html><head>'+
        '<script src='+chrome.extension.getURL('jquery.js')+'></script>'+
        '<script src='+chrome.extension.getURL('myscript.js')+'></script>'+
        ...
        '</head><body></body></html>'
    ));
    ...
    

    在 myscript.js 中

    jQuery(document).ready(function(){
        ...
        // To receive messages from background.js.
        window.addEventListener('message', function(e){ ... } );
    
        // To send messages to background.js.
        parent.postMessage({...}, '*');
    
        // To open AND ACCESS a window.
        var win = window.open();
        win.document.write('Hello'); // Fails in sandbox, works here.
    
        // Eval code, if you want. Can't do this from an extension
        // page loaded normally unless you allow eval in your manifest.
        // Here, it's okay!
        eval( 'var x = window.open(); x.document.write("Hi!")' );
    
        // No chrome apis.
        chrome.log( chrome.extension ); // -> undefined
        chrome.log( chrome.windows ); // -> undefined
    
        // No direct access to background page (e.g., parent).
        chrome.log( parent ); // -> Window with no properties.
        ...
    });
    

    【讨论】:

      最近更新 更多