window.open在chrome扩展中返回undefined [英] window.open returns undefined in chrome extension

查看:464
本文介绍了window.open在chrome扩展中返回undefined的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有基于内容脚本的Chrome扩展程序。我通过内容脚本中的弹出窗口启动登录过程。



我用下面的代码打开一个弹出窗口,然后等到它关闭。



然而,我得到来自 window.open 方法的'undefined'。有人知道为什么会发生这种情况吗?



loginwin undefined 在下面的代码中,尽管弹出窗口在指定的 login_url 中可以正常打开。下面的代码是从我的内容脚本中调用的。

  var loginWin = window.open(login_url,'LoginWindow',width = 655,高度= 490\" ); 
console.log(loginWin);
//如果弹出窗口关闭,则每隔100 ms检查一次。
var finishedInterval = setInterval(function(){
console.log('checking the loginWin closed');
if(loginWin.closed){
clearInterval(finishedInterval);
console.log('popup is closed');
Backbone.history.navigate('index',true);
}
},1000);


解决方案


已过时。 Chrome扩展程序中的 window.open()总是会返回 null (当弹出窗口被阻止时)或 window 对象。以下信息仅适用于非常旧的(2012年)Chrome版本。







内容脚本无法访问页面的全局窗口对象。对于内容脚本,以下内容适用:




  • 窗口 变量不会引用页面的全局对象。相反,它引用了一个新的上下文,即页面上的图层。该页面的DOM是完全可访问的。 #execution-environment



给定一个包含  < iframe id =frameNamesrc =http:// domain />< / iframe>


  • 访问框架的内容受相同来源政策的页面;您的扩展的权限不会放宽策略。

  • frames [0] frames ['frameName '] ,(通常指的是框架包含的全局窗口对象)是 undefined
  • var iframe = document.getElementById('frameName');


    • iframe.contentDocument 返回 文档 对象,因为内容脚本可以访问页面的DOM。此属性为 null ,适用于相同原产地政策。 iframe.contentDocument.defaultView (引用与文档关联的窗口对象) undefined

    • iframe.contentWindow 未定义。$你可以看到, window.open()
  • $ c>不会返回 Window 实例( window.opener 等等)。






    替代品




    • < a href =https://stackoverflow.com/questions/9515704/building-a-chrome-extension-inject-code-in-a-page-using-a-content-script/9517879#9517879>注入代码在页面中,以便它在页面的上下文中运行。注意:如果您正在操作的页面可以信任,请仅使用此方法。要在注入的脚本和内容脚本之间进行通信,您可以使用:

        var login_url ='http://example.com /'; 
      var event_name ='robwuniq'+ Math.random()。toString(16); //唯一名称
      document.addEventListener(event_name,function localName(){
      document.removeEventListener(event_name,localName); //清理
      //您的逻辑:
      Backbone.history.navigate('index',true);
      });
      //方法2b:注入在页面上下文中运行的代码
      var actualCode ='('+ function(login_url,event_name){
      var loginWin = window.open(login_url, 'LoginWindow',width = 655,height = 490);
      console.log(loginWin);
      //如果弹出窗口关闭,则每隔100毫秒检查
      var finishedInterval = setInterval (函数(){
      console.log('检查loginWin是否关闭');
      if(loginWin.closed){
      clearInterval(finishedInterval);
      console.log('弹出窗口已关闭');
      //通知内容脚本
      var event = document.createEvent('Events');
      event.initEvent(event_name,false,false);
      document.dispatchEvent(event);
      }
      },1000);
      } +')('+ JSON.stringify(login_url +'')+',''+ event_name +' )';
      var script = document.createElement('script');
      script.textContent = actualCode;
      (document.head || document.documentElement).appendChild(script);
      script.parentNode.removeChild(script);


    • 使用 window.open( )。这将返回一个窗口对象,它具有可靠的关闭属性。有关通信流程的更多详细信息,请参阅下一个要点。


    • 从内容脚本传递讯息后台页面。在后台页面中,使用 chrome.windows。创建 打开一个窗口。在回调中,分配 chrome.tabs。 onRemoved 和/或 chrome.tabs.onUpdated 事件。当这些事件监听器被触发时,他们应该删除自己,并使用函数 chrome.extension.onMessage中的 sendResponse 函数通知原始调用者(内容脚本)


    I have content script based Chrome extension. I initiate the sign in process through a popup window in the content script.

    I open a popup window using the below code and then wait till its closed.

    However, I get an 'undefined' from window.open method. Does anybody know why this happens?

    loginwin is undefined in below code although the popup window opens up fine with the specified login_url. The code below is called from my content script.

    var loginWin = window.open(login_url, 'LoginWindow', "width=655,height=490");
    console.log(loginWin);
    // Check every 100 ms if the popup is closed.
    var finishedInterval = setInterval(function() {
        console.log('checking if loginWin closed');
        if (loginWin.closed) {
            clearInterval(finishedInterval);
            console.log('popup is now closed');
            Backbone.history.navigate('index', true);
        }
    }, 1000);
    

    解决方案

    Note: This answer is obsolete. window.open() in a Chrome extension always returns either null (when the popup is blocked) or a window object. The information below only applies to very old (2012) versions of Chrome.


    Content scripts do not have any access to a page's global window object. For content scripts, the following applies:

    • The window variable does not refer to the page's global object. Instead, it refers to a new context, a "layer" over the page. The page's DOM is fully accessible. #execution-environment

    Given a document consisting of   <iframe id="frameName" src="http://domain/"></iframe>:

    • Access to the contents of a frame is restricted by the Same origin policy of the page; the permissions of your extension does not relax the policy.
    • frames[0] and frames['frameName'], (normally referring to the the frame's containing global window object) is undefined.
    • var iframe = document.getElementById('frameName');
      • iframe.contentDocument returns a document object of the containing frame, because content scripts have access to the DOM of a page. This property is null when the Same origin policy applies.
      • iframe.contentDocument.defaultView (refers to the window object associated with the document) is undefined.
      • iframe.contentWindow is undefined.

    As you can see, window.open() does not return a Window instance (neither does window.opener, and so forth).


    Alternatives

    • Inject the code in the page, so that it runs in the context of the page. Note: Only use this method if the page you're operating on can be trusted. To communicate between the injected script and the content script, you could use:

      var login_url = 'http://example.com/';
      var event_name = 'robwuniq' + Math.random().toString(16); // Unique name
      document.addEventListener(event_name, function localName() {
          document.removeEventListener(event_name, localName); // Clean-up
          // Your logic:
          Backbone.history.navigate('index', true);
      });
      // Method 2b: Inject code which runs in the context of the page
      var actualCode = '(' + function(login_url, event_name) {
          var loginWin = window.open(login_url, 'LoginWindow', "width=655,height=490");
          console.log(loginWin);
          // Check every 100 ms if the popup is closed.
          var finishedInterval = setInterval(function() {
              console.log('checking if loginWin closed');
              if (loginWin.closed) {
                  clearInterval(finishedInterval);
                  console.log('popup is now closed');
                  // Notify content script
                  var event = document.createEvent('Events');
                  event.initEvent(event_name, false, false);
                  document.dispatchEvent(event);
              }
          }, 1000);
      } + ')(' + JSON.stringify(login_url+'') + ', "' + event_name + '")';
      var script = document.createElement('script');
      script.textContent = actualCode;
      (document.head||document.documentElement).appendChild(script);
      script.parentNode.removeChild(script);
      

    • Launch the window from the background page using window.open(). This returns a window object which has a reliable closed property. See the next bullet point for more details on the communication flow.

    • From the content script, pass a message to the background page. In the background page, use chrome.windows.create to open a window. In the callback, assign an chrome.tabs.onRemoved and/or chrome.tabs.onUpdated event. When these event listeners are triggered, they should remove themselves, and notify the original caller (content script) using the sendResponse function of chrome.extension.onMessage.

    这篇关于window.open在chrome扩展中返回undefined的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆