window.close()提示 "script may close only the windows that were opened by it"

      由于在脚本中使用了 window.close(), 当前非弹出窗口在最新版本的chrome和firefox里总是不能关闭,而在 IE中是可以关闭的 。在console中弹出提示"script may close only the windows that were opened by it" (脚本只能关闭它所打开的窗口), 不明白是什么原因。


window.close()提示 "script may close only the windows that were opened by it"

研究了好几天。终于明白了问题所在。

首先,什么是非弹出窗口呢?

      非弹出窗口,即是指(opener=null及非window.open()打开的窗口)。


其次,window.close() 怎么理解呢?


https://developer.mozilla.org/en-US/docs/Web/API/window.close 可知: 

Closes the current window, or the window on which it was called.
When this method is called, the referenced window is closed.

This method is only allowed to be called for windows that were opened by a script using thewindow.open() method. If the window was not opened by a script, the following error appears in the JavaScript Console: Scripts may not close windows that were not opened by script.

Examples

Closing a window opened with window.open()

This example demonstrates how to use this method to close a window opened by script callingwindow.open().

<script type="text/javascript">
//Global var to store a reference to the opened window
var openedWindow;

function openWindow()
{
  openedWindow = window.open(‘moreinfo.htm‘);
}

function closeOpenedWindow()
{
  openedWindow.close();
}
</script>

Closing the current window

When you call the window object‘s close() method directly, rather than calling close() on a windowinstance, the browser will close the frontmost window, whether your script created that window or not.

<script type="text/javascript">
function closeCurrentWindow()
{
  window.close();
}
</script>
在某些实际应用中,window.close() and self.close() 是不能关闭非弹出窗口(opener=null及非window.open()打开的窗口)。

其它参考:
A:

‘p‘ is new window that i opened, i‘m using jquery to test what browser you have, this is example when i open new window, populate it, call print dialog, then close it 

it‘s not solution to original problem but just in case someone find it useful 

if ( $.browser.msie ) p.location.reload();  //for IE if you want print dialog to show 
p.window.print(); 
if ( $.browser.msie || $.browser.opera || $.browser.mozilla) p.window.close(); 
else p.window.self.close(); //for chrome

B:

Ordinary javascript cannot close windows willy-nilly. This is a security feature, introduced a while ago, to stop various malicious exploits and annoyances.

From the latest working spec for window.close():

The close() method on Window objects should, if all the following conditions are met, close the browsing context A:

  • The corresponding browsing context A is script-closable.
  • The browsing context of the incumbent script is familiar with the browsing context A.
  • The browsing context of the incumbent script is allowed to navigate the browsing context A.

A browsing context is script-closable if it is an auxiliary browsing context that was created by a script(as opposed to by an action of the user), or if it is a browsing context whose session history contains only one Document.

This means, with one small exception, javascript must not be allowed to close a window that was not opened by that same javascript.

Chrome allows that exception -- which it doesn‘t apply to userscripts -- however Firefox does not. The Firefox implementation flat out states:

This method is only allowed to be called for windows that were opened by a script using the window.open method.


If you try to use window.close from a Greasemonkey / Tampermonkey / userscript you will get:
Firefox: The error message, "Scripts may not close windows that were not opened by script."
Chrome: just silently fails.


The long-term solution:

The best way to deal with this is to make a Chrome extension and/or Firefox add-on instead. These can reliably close the current window.

However, since the security risks, posed by window.close, are much less for a Greasemonkey/Tampermonkey script; Greasemonkey and Tampermonkey could reasonably provide this functionality in their API (essentially packaging the extension work for you).
Consider making a feature request.


The hacky workarounds:

Chrome is currently vulnerable to the "self redirection" exploit. So code like this will currently work in Tampermonkey scripts:

open(location, ‘_self‘).close();

This is buggy behavior, IMO, and is liable to be blocked by future releases of Chrome, so use this hack with that in mind.


Firefox is secure against that exploit. So, the only javascript way is to cripple the security settings, one browser at a time.

You can open up about:config and set
allow_scripts_to_close_windows to true.

If your script is for personal use, go ahead and do that. If you ask anyone else to turn that setting on, they would be smart, and justified, to decline with prejudice.

There currently is no equivalent setting for Chrome.


C: 

From my observation, this update fixed the issue on using window.close() to close the popup window. You will see this in the console when it fail, "Scripts may close only the windows that were opened by it.". That means The hacky workarounds (Brock Adams‘s answer) may not work in the latest release.

So, in the previous Chrome released builds, the below code block may worked but not with this update.

window.open(‘‘, ‘_self‘, ‘‘);
window.close();

For this update, you have to update your code accordingly to close the popup window. One of the solution is to grab the popup window id and use

chrome.windows.remove(integer windowId, function callback)

method to remove it. Chrome extension windows API can be found at chrome.windows.

Actually my chrome extension MarkView was facing this issue and I had to update my code to make it work for this Chrome Update. By the way, MarkView is tool to read and write Awesome Markdown Files, it provides features including Content Outline, Sortable Tables and code block syntax highlight with line number.

I also created this post, any comments are welcome.

参考网址:


window.close()提示 "script may close only the windows that were opened by it"

上一篇:Windows环境变量


下一篇:c# Dictionary 简介