Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
463 views
in Technique[技术] by (71.8m points)

javascript - window.open returns undefined in chrome extension

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);
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...