window.close和self.close不会在Chrome中关闭窗口


173

问题是当我调用它window.close()self.close()它没有关闭窗口时。现在似乎有人相信,在Chrome中,您无法通过脚本关闭任何非脚本创建的窗口。这显然是错误的,但是即使它需要弹出一个警报进行确认,也不管它应该仍然这样做。这些都没有发生。

那么,有没有人有真正,实用且可靠的方法来关闭窗口,例如使用javascript:window.close()javascript:self.close()确实达到预期效果,并且在所有不基于Chrome的浏览器中都能正常运行?任何建议将不胜感激,我正在寻找Javascript特定的解决方案,没有JQuery或第三方实现。

更新:尽管很多建议都存在严重的局限性和可用性问题,但// @grant window.close即使在通常无法处理close方法的选项卡上,脚本标头中使用的最新建议(特定于TamperMonkey)也常常可以解决问题。尽管这并非完全理想,并且无法针对每种情况进行概括,但对于我而言,这是一个很好的解决方案。


window.close()在Chrome中为我工作。
mashing

3
@ GµårÐïåñ:嗯,不,不是。它与语言无关。这是浏览器实现的功能。如果您可以写一个最小的示例来说明如何window.close以应有的方式工作,那么我认为这比说“它不工作”更有用。
Blender

3
我给了你两个例子。为您完成拼写,<a href="javascript:window.close">CLOSE</a>
GµårÐïåñ

3
不正确的javascript的监护人。试试window.close(),它可以工作。window.close只是一个变量名,不会调用该函数(至少当我在chrome 37中对其进行测试时不会)。当我将您的示例更改为window.close()时,它适用于
乔治

3
@乔治说的不是什么意思(除非我完全误解了单词的意思)。他说您的示例中的javascript语法错误是正确的,如果您的应用程序代码中存在相同的错误,则很可能是问题的原因。但是,如果这些只是示例中的错别字,则应更正这些错别字以获得更好的答案。
Superole'Feb

Answers:


187

普通的javascript无法随意关闭Windows。这是一项安全功能,该功能已在不久前推出,用于阻止各种恶意攻击和烦扰。

根据最新的工作规范window.close()

close()如果满足以下所有条件,则Window对象上的方法应关闭浏览上下文A

  • 相应的浏览上下文A可关闭脚本的
  • 现任脚本的浏览器上下文是熟悉的浏览器上下文一个
  • 现任脚本的浏览器上下文允许导航浏览器上下文一个

如果浏览上下文是由脚本创建的辅助浏览上下文(而不是用户的操作),或者是会话历史记录仅包含一个Document的浏览上下文,则可以关闭脚本

这意味着,除了一个小小的例外,不得允许javascript关闭一个未由同一javascript打开的窗口。

Chrome允许该例外-不适用于用户脚本-但Firefox不允许。 Firefox的实施方式明确指出

仅允许脚本使用该window.open方法打开的窗口调用此方法。


如果您尝试window.close从Greasemonkey / Tampermonkey /用户脚本中使用,则会得到:
Firefox:错误消息“ Scripts may not close windows that were not opened by script.”,
Chrome:静默失败。



长期解决方案:

解决此问题的最佳方法是改用Chrome扩展程序和/或Firefox插件。 这些可以可靠地关闭当前窗口。

但是,window.close对于Greasemonkey / Tampermonkey脚本,由造成的安全风险要小得多;Greasemonkey和Tampermonkey可以在其API中合理地提供此功能(实际上是为您打包扩展工作)。
考虑提出功能请求。



hacky解决方法:

Chrome 目前容易受到“自我重定向”漏洞的攻击。因此,这样的代码通常可以正常工作:

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

IMO,这是错误的行为,目前(截至2015年4月)已大部分被阻止。当选项卡是新打开的并且在浏览历史记录中没有页面时,它仍然可以从注入的代码运行。因此,它仅在极少数情况下有用。

但是,变体仍可在Chrome(v43和v44)以及Tampermonkey(v3.11或更高版本)上运行。使用显式@grant和滑动window.close()。例如:

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

setTimeout (window.close, 5000);

感谢zanetu的更新。请注意,如果仅打开一个选项卡,则此功能将无效。它仅关闭其他选项卡。


Firefox对这种攻击是安全的。因此,唯一的javascript方法是限制安全设置,一次只关闭一个浏览器。

您可以打开about:config并设置
allow_scripts_to_close_windowstrue

如果您的脚本是供个人使用的,请继续执行此操作。如果您要求其他任何人打开该设置,则他们会明智且有理由拒绝偏见。

Chrome目前没有等效设置。


3
嘿,我的朋友,很高兴终于收到您的来信。刚一说明,对外汇可以绕过这一限制被翻转dom.allow_scripts_to_close_windows;falsetrue,但我想没有在Chrome没有黑客源/重建这是我周围如何到达现在。我知道并已经与TM开发人员进行了交谈,在最近的alpha / beta中,我们将其作为兼容选项(脚本的设置)以中间人的方式运行有效。我猜除了我们没有干净的解决方法外,可惜。
GµårÐïåñ

3
如果有人在使用window.close或浏览器之间的行为差​​异时遇到麻烦,请仔细阅读此答案-它确实具有所有正确的信息。
Bron Davies 2014年

有没有办法检查是否通过脚本打开了窗口?(我需要显示/隐藏后退按钮,我不想使用破解版)谢谢编辑:window.opener ===空
Cétia

自2014年7月16日星期三Chrome 36.0.1985.125起,hacky解决方法可能无法正常工作,请在我的回答中进行详细说明。
swcool 2014年

2
window.close()如果您将设置@grant为以外的值,则将在Tampermonkey中起作用none。看到这个线程
zanetu

32

Chrome修复了36.0.1985.125版本的安全问题

Chrome 36.0.1985.125 2014年7月16日,星期三, 发行说明

根据我的观察,此更新解决了window.close()用于关闭弹出窗口的问题。失败时,您将在控制台中看到此消息,“脚本只能关闭由它打开的窗口。” 这意味着hacky解决方法(Brock Adams的答案)可能在最新版本中不起作用

因此,在以前的Chrome版本中,以下代码块可能有效,但此更新不起作用。

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

对于此更新,您必须相应地更新代码以关闭弹出窗口。解决方案之一是获取弹出窗口ID并使用

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

删除方法。Chrome扩展程序Windows API可以在chrome.windows中找到。

实际上,我的Chrome扩展程序MarkView遇到了此问题,我必须更新代码以使其适用于此Chrome更新。顺便说一句,MarkView是用于读取和写入超赞Markdown文件的工具,它提供的功能包括内容大纲,可排序表和带有行号的代码块语法突出显示。

我也创建了此帖子,欢迎任何评论。


2
正确的破解方法是open(location, '_self').close();-注意使用的返回值open()。在Chrome上仍然可以使用36.0.1985.125 m
Brock Adams

就我而言,我只是用再次测试open(location, '_self').close();,因此出现“未经授权”错误。此错误与'window.close()(warning on this"Scripts may close only the windows that were opened by it."). It looked like open(location,'_self')。close();不同,但向前移动了一点,但在我的情况下无法完成。感谢@ brock-adams的评论。
swcool 2014年

我有打字稿,写的时候chrome.windows.remove说找不到铬符号。我该如何解决?我需要添加某种参考吗?
DevT

@devt chrome.windows.remove是Chrome扩展程序API,您的javascript应该会被chrome扩展程序识别。您可以在background.js中尝试使用,在您的Chrome扩展程序manifest.json中,您需要具有:“ background”:{“ scripts”:[“ background.js”],...},
swcool 2014年

我已经删除了MarkView登录功能,以便用户自由访问。因此,我上面提到的示例现在不可用。
swcool 2016年

21

现在,您可以在tampermonkey中使用

// @grant        window.close

然后只需打电话

window.close();

我已经证实,这种方法在许多情况下仍然有效,但偶尔仍然很顽固,但总比没有好,谢谢。我将其添加到帖子中。
GµårÐïåñ

2
请注意:在Greasemonkey 3.10中不为我工作
mt025 '17

17

我使用的是Brock Adams发布的方法,如果它是用户启动的,它甚至可以在Firefox中使用。

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

我是通过按按钮调用它的,所以它是用户启动的,并且在使用Chrome 35-40,Internet Explorer 11,Safari 7-8和ALSO Firefox 29-35的情况下仍可以正常工作。我使用Windows和Mac OS X 10.6、10.9和10.10的8.1版进行了测试(如果不同)。


自动关闭窗口代码(在自行关闭的页面上)

可以关闭的用户打开的窗口上使用的完整代码:

window_to_close.htm

JavaScript:

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

HTML:

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

尝试以下测试页:(现已在Chrome 40和Firefox 35中进行测试)

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


窗口开启程序代码(在打开上述页面的页面上)

为了使此工作有效,跨安全性要求的跨浏览器兼容性要求用户必须在同一站点域内单击按钮才能打开要关闭的窗口。

例如,可以使用以下代码从页面中打开使用上述方法关闭自身的窗口(此代码来自我的示例页面,上面提供了链接):

window_close_tester.htm

JavaScript:

function open_a_window() 
{
    window.open("window_to_close.htm"); 

    return false;
}

HTML:

<input type="button" onclick="return open_a_window();" value="Open New Window/Tab" />

忘记了用户发起的异常;接得好。我认为大多数用户脚本都希望全自动操作。他们已经有了一个方便的,用户启动的关闭机制-右上方的小X。(^_^)
布罗克·亚当斯

1
无论如何,这对我不起作用。既不是在firefox 30上也不是在Chrome 37上。它所做的只是使页面空白(确实很奇怪的行为)。我的代码是<button onclick="open(location,'_self').close()" >Close Window</button>。我做错了什么吗?在我看来,这也是用户发起的。请注意,如果使用<button>或,则会得到相同的结果<input type="button">
LordOfThePigs

在答案上方为您添加了测试页。
杰夫·克莱顿

@YumYumYum感谢后,bitbucket.org改变最近bitbucket.io链接-固定在现在答案
杰夫·克莱顿

它对我有用(页面上有一个按钮可以关闭窗口)。window.open('', '_self', ''); window.close();open(location, '_self').close();
没用的

10

许多人仍在尝试找到一种使用javascript关闭Chrome浏览器的方法。 仅当您将Chrome用作APP启动器时,以下方法才有效-例如信息亭!

我已经测试了以下内容:

我正在使用以下扩展程序:关闭信息亭

我正在按照使用说明进行操作,并且看起来工作正常(请确保在执行测试时清除缓存)。我使用的javascript是(附加到click事件):

window.location.href = '/closekiosk';

我希望这对我有所帮助,因为这是我找到的唯一可行的解​​决方案。

注意:该扩展程序似乎在后台运行,并添加了Chrome任务栏图标。它选中了以下选项:“让Chrome在后台运行”(或类似的文本)。您可能需要尝试一下,直到它适合您。我取消选中它,现在可以正常使用了!


9

尽管认为它“明显错误”,但您所说的“似乎是一种信念”实际上是正确的。Mozilla的window.close文档说

仅允许使用window.open方法由脚本打开的窗口调用此方法。如果未通过脚本打开窗口,则JavaScript控制台中会出现以下错误:脚本可能无法关闭不是由脚本打开的窗口

您说它“应该继续做”,但我认为您不会找到任何支持它的参考,也许您记错了什么?


9

我找到了一种对我有效的新方法

var win = window.open("about:blank", "_self");
win.close();

1
这是2017年,我仍然收到“脚本可能无法关闭不是由脚本打开的窗口”的错误。
Rotimi

IE 11确认按钮的好方法
。– Gopal00005

可在Chrome和Firefox上使用
Vineeth Pradhan

这个洞看起来已经被填补了。我什么时候还不知道,但是我正在使用最新的开发版本84.x。加载空白页,但关闭不会触发。
Scott Christensen

4

下面的代码为我工作-

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

Chrome 43.0.2357.81上测试


您可以添加您的Chrome版本吗?
斯蒂芬,2015年

我的Chrome版本是43.0.2357.81。
DfrDkn 2015年

7
对我来说,只是用/ location的窗口替换了当前窗口。
alianos-

@ alianos-对我也是。
RicardoGonzales 2015年

1
无法在最新版本的chrome中使用-版本61.0.3163.100(正式版本)(64位)
Subhajit

1

这可能很旧,但让我们回答一下。

我使用top.close()关闭标签页。window.close()或其他打开...关闭对我不起作用。


11
这也遭受"Scripts may not close windows that were not opened by script."其他答案中提到的问题。
kad81

1
请给出答案的解决方案。请不要只在您的答案上讨论问题。
Bimal Das

0

就我而言,该页面需要关闭,但可能已通过链接打开,因此 window.close将失败。

我选择的解决方案是发出window.close,然后发出window.setTimeout,重定向到另一个页面。

这样,如果window.close成功,该页面上的执行将停止,但是如果失败,则将在一秒钟内将其重定向到另一个页面。

window.close();
window.setTimeout(function(){location.href = '/some-page.php';},1000);

0

Brock的这个答案对我有用。不得禁止javascript关闭由同一javascript未打开的窗口。

如果要从父javascript关闭子窗口,则只能关闭它。所以在我父母那里我可以做这样的事情。

var myChildWindow;

function openWindow(){
myChildWindow = window.open("","myChildWindow","width=400,height=400");
}

function closeWindow() {
myChildWindow.close();
}

-1

您也可以尝试在下面使用我的代码。这也将帮助您重定向父窗口:

上级:

<script language="javascript">

function open_a_window() 
{
    var w = 200;
        var h = 200;
        var left = Number((screen.width/2)-(w/2));
        var tops = Number((screen.height/2)-(h/2));

        window.open("window_to_close.html", '', 'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=no, copyhistory=no, width='+w+', height='+h+', top='+tops+', left='+left);

   return false;
}

// opener:
window.onmessage = function (e) {
  if (e.data === 'location') {
    window.location.replace('https://www.google.com');
  }
};

</script>

<input type="button" onclick="return open_a_window();" value="Open New Window/Tab" />

弹出:

<!DOCTYPE html>
<html>
<body onload="quitBox('quit');">

<h1>The window closer:</h1>

<input type="button" onclick="return quitBox('quit');" value="Close This Window/Tab" /> 


<script language="javascript">

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

</script>

</body>
</html>


-2

只有使用window.open()打开新窗口,才能使用如上所述的代码关闭新窗口。这对我来说非常合适:)注意:切勿使用href在新标签页中打开页面。Window.close()不适用于“ href”。使用window.open()代替。


1
它只是在替换当前窗口。不再。
RicardoGonzales 2015年

-3

我想与这个问题分享我的“解决方案”。似乎我们大多数人都试图在标准浏览器会话中关闭浏览器窗口,在该会话中,用户在访问其他网站之后以及在访问其他网站之前正在访问某个网站或另一个网站。

但是,我的情况是,我正在为设备构建Web应用程序,这实际上将是该设备唯一要做的事情。您启动它,它会启动Chrome并导航到我们的应用程序。它甚至没有连接到互联网,它与之通信的任何服务器都在我们本地的Docker容器上。用户需要一种关闭应用程序的方式(也就是关闭Chrome),以便他们可以访问终端以执行系统更新。

因此,它会启动,并在信息亭模式下以正确的地址启动Chrome。碰巧很容易满足规范中的第二个选项:

如果浏览上下文是由脚本创建的辅助浏览上下文(而不是用户的操作),或者是会话历史记录仅包含一个Document的顶级浏览上下文,则可以关闭脚本

因此,只需window.close()从我的信息亭应用程序拨打电话即可


-5

尝试这样的事情onclick =“ return self.close()”

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.