javascript window.open 在 chrome 扩展中返回未定义
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11812786/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
window.open returns undefined in chrome extension
提问by user1566788
I have content script based Chrome extension. I initiate the sign in process through a popup window in the content script.
我有基于内容脚本的 Chrome 扩展。我通过内容脚本中的弹出窗口启动登录过程。
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?
但是,我从window.open
方法中得到一个“未定义” 。有人知道为什么会这样吗?
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.
loginwin
是undefined
在下面的代码,虽然与指定的弹出窗口打开了罚款login_url
。下面的代码是从我的内容脚本中调用的。
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);
采纳答案by Rob W
Note: This answer is obsolete.
window.open()
in a Chrome extension always returns eithernull
(when the popup is blocked) or awindow
object. The information below only applies to very old (2012) versions of Chrome.
注意:此答案已过时。
window.open()
在 Chrome 扩展程序中总是返回null
(当弹出窗口被阻止时)或一个window
对象。以下信息仅适用于非常旧 (2012) 版本的 Chrome。
Content scripts do not have any access to a page's global window
object. For content scripts, the following applies:
内容脚本无权访问页面的全局window
对象。对于内容脚本,以下适用:
- 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
- 该
window
变量不引用页面的全局对象。相反,它指的是一个新的上下文,页面上的一个“层”。页面的 DOM 是完全可访问的。#执行环境
Given a document consisting of <iframe id="frameName" src="http://domain/"></iframe>
:
给定一个包含以下内容的文档 <iframe id="frameName" src="http://domain/"></iframe>
:
- Access to the contents of a frame is restricted by the Same origin policyof the page; the permissions of your extension does not relax the policy.
frames[0]
andframes['frameName']
, (normally referring to the the frame's containing globalwindow
object) isundefined
.var iframe = document.getElementById('frameName');
iframe.contentDocument
returns adocument
object of the containing frame, because content scripts have access to the DOM of a page. This property isnull
when the Same origin policy applies.iframe.contentDocument.defaultView
(refers to thewindow
object associated with the document) is undefined.iframe.contentWindow
is undefined.
- 对框架内容的访问受到页面同源策略的限制;您的扩展程序的权限不会放宽政策。
frames[0]
和frames['frameName']
,(通常是指包含框架的全局window
对象)是undefined
。var iframe = document.getElementById('frameName');
iframe.contentDocument
返回document
包含框架的对象,因为内容脚本可以访问页面的 DOM。此属性null
适用于同源策略。iframe.contentDocument.defaultView
(指window
与文档关联的对象)是undefined。iframe.contentWindow
是未定义的。
As you can see, window.open()
does not return a Window
instance (neither does window.opener
, and so forth).
如您所见,window.open()
不返回Window
实例(也不返回window.opener
,等等)。
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 awindow
object which has a reliableclosed
property. See the next bullet point for more details on the communication flow.- From the content script, pass a messageto the background page. In the background page, use
chrome.windows.create
to open a window. In the callback, assign anchrome.tabs.onRemoved
and/orchrome.tabs.onUpdated
event. When these event listeners are triggered, they should remove themselves, and notify the original caller (content script) using thesendResponse
function ofchrome.extension.onMessage
.
在页面中注入代码,使其在页面上下文中运行。注意:仅当您正在操作的页面可以信任时才使用此方法。要在注入的脚本和内容脚本之间进行通信,您可以使用:
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);
使用
window.open()
.从后台页面启动窗口。这将返回一个window
具有可靠closed
属性的对象。有关通信流程的更多详细信息,请参阅下一个要点。- 从内容脚本中,将消息传递到后台页面。在后台页面中,用于
chrome.windows.create
打开一个窗口。在回调中,分配一个chrome.tabs.onRemoved
和/或chrome.tabs.onUpdated
事件。当这些事件监听器被触发时,应自行拆除,并通知使用原调用者(内容脚本)sendResponse
的功能chrome.extension.onMessage
。
回答by ScottyB
In my case, Chrome was blocking the popup and the user had to unblock by clicking the "blocked popup" icon in the upper-right corner of the window. (They can also enable/disable exceptions under "Content settings..." in Chrome settings.)
就我而言,Chrome 阻止了弹出窗口,用户必须通过单击窗口右上角的“阻止的弹出窗口”图标来取消阻止。(他们还可以在 Chrome 设置中的“内容设置...”下启用/禁用例外。)
I would suggest adding some code after window.open() so that the user knows what to do. For example:
我建议在 window.open() 之后添加一些代码,以便用户知道该怎么做。例如:
if (!loginWin)
alert("You must first unblock popups and try again for this to work!");