JavaScript È°¿ëÆÁ
2017.05.09 / 19:46

¸ð¹ÙÀÏ ºê¶ó¿ìÀú °­Á¦ â´Ý±â

MultiPlayer
Ãßõ ¼ö 306

window.close and self.close do not close the window in Chrome


The issue is that when I invoke window.close() or self.close() it doesn't close the window. Now there seems to be a belief that in Chrome you can't close by script any window that is not script created. That is patently false but regardless it is supposed to still do it, even if it requires to pop up an alert to confirm. These are not happening.

So does anyone have real, functional and proven method of closing a window using something like javascript:window.close() or javascript:self.close() that actually does what is expected and something that happens just fine in every browser that is NOT Chrome based? Any suggestions would be greatly appreciated and I am looking for Javascript specific solution, nothing JQuery or third party implementation.

Update: While much of what has been suggested has serious limitations and usability issues, the latest suggestion (specific to TamperMonkey) using // @grant window.close in the script header will often do the trick even on those tabs that normally can't handle the close method. While not entirely ideal and doesn't generalized to every case, it is a good solution in my case.




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 was vulnerable to the "self redirection" exploit. So code like this used to work in general:

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

This is buggy behavior, IMO, and is now (as of roughly April 2015) mostly blocked. It will still work from injected code only if the tab is freshly opened and has no pages in the browsing history. So it's only useful in a very small set of circumstances.

However, a variation still works on Chrome (v43 & v44) plus Tampermonkey (v3.11 or later). Use an explicit @grant and plain window.close(). EG:

// ==UserScript==
// @name        window.close demo
// @include     http://YOUR_SERVER.COM/YOUR_PATH/*
// @grant       GM_addStyle
// ==/UserScript==

setTimeout (window.close, 5000);

Thanks to zanetu for the update. Note that this will not work if there is only one tab open. It only closes additional tabs.


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.

Hey my friend, glad to finally hear from you. Just a note, on Fx you can bypass that limitation by flipping the dom.allow_scripts_to_close_windows;false to true but I guess nothing in Chrome without hacking the source/rebuild which is how I got around it for now. I know and have talked to the TM developer and in the recent alpha/beta we have put it as a compatibility option (setting of the script) to run in man-in-the-middle style, works. I guess short of the hacks we have no clean solution, pity

If anyone is having trouble with window.close or the particular behavior difference among browsers, read this answer very carefully - it really does have all the right information

Is there a way to check if the window was opened by script or not ? (I need to show/hide a back button, I don't want to use the hack) Thanks EDIT: window.opener === null 

it is not working for me right now

window.close() will work in Tampermonkey if you set @grant to a value other than none. See this thread. – zanetu




Chrome Fixed the security issues on version 36.0.1985.125

Chrome 36.0.1985.125 WEDNESDAY, JULY 16, 2014 Release note

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.



The correct hack is open(location, '_self').close(); -- note the use of the return value from open(). This still works on Chrome 36.0.1985.125 m – Brock Adams Jul 21 '14 at 0:26 
   
In my case, I just test again with open(location, '_self').close();, I got "Unauthorized" error on this. This error is different with 'window.close()(warning on this"Scripts may close only the windows that were opened by it."). It looked like open(location, '_self').close();` moved forward a little bit, but it can't complete in my case. Thanks @brock-adams for the comment. – swcool Jul 21 '14 at 15:42
   
I have typescript and when i put chrome.windows.remove it says could not find symbol chrome. how can i resolve this? do i need to add some sort of reference? – DevT Jul 22 '14 at 12:03
   
@devt chrome.windows.remove is Chrome extension API, your javascript should be recognized by your chrome extension program. You can try it inside background.js, in your chrome extension manifest.json you need to have: "background": { "scripts": ["background.js"], ... }, – swcool Jul 22 '14 at 19:28
   
I had removed MarkView login function for users to access freely. So the example I mentioned in above is not available now. – swcool Dec 3 '16 at 15:05





I am using the method posted by Brock Adams and it even works in Firefox, if it's user initiated.

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

I am calling it from a button press so it is user initiated, and it is still working fine using Chrome 35-40, Internet Explorer 11, Safari 7-8 and ALSO Firefox 29-35. I tested using version 8.1 of Windows and Mac OS X 10.6, 10.9 & 10.10 if that is different.


The complete code:

HTML:

<input type="button" name="Quit" id="Quit" value="Quit" onclick="return quitBox('quit');" />

JavaScript:

function quitBox(cmd)
{   
    if (cmd=='quit')
    {
        open(location, '_self').close();
    }   
    return false;   
}

Try this test page: (Now tested in Chrome 40 and Firefox 35)

http://browserstrangeness.bitbucket.io/window_close_tester.htm


Forgot about the user initiated exceptions; good catch. I think most userscripters want fully automatic operation though. They already have a handy, user initiated close mechanism -- that little X in the upper right. (^_^) – Brock Adams May 16 '14 at 0:51
   
Somehow, this doesn't work for me. Neither on firefox 30 nor on Chrome 37. All it does is make the page become blank (really weird behavior). My code is <button onclick="open(location,'_self').close()" >Close Window</button>. Am I doing something obviously wrong? It seems to me that this is also user initiated. Note that I get the same result if I use a <button> or an <input type="button">. – LordOfThePigs Aug 28 '14 at 22:47 
   
Added a test page above in the answer for you. – Jeff Clayton Aug 28 '14 at 23:12 
   
Link is dead????????????????????????????? where is it????????? – YumYumYum Apr 15 at 23:24
   
@YumYumYum thanks for the post, bitbucket.org changed the link to bitbucket.io recently - fixed in the answer now – Jeff Clayton Apr 16 at 2:58