201

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

那么有没有人有真正的、功能性的和经过验证的方法来关闭一个窗口,使用类似的东西javascript:window.close()或者javascript:self.close()实际上做了预期的事情,并且在每个不是基于 Chrome 的浏览器中发生的事情都很好?任何建议将不胜感激,我正在寻找 Javascript 特定的解决方案,没有 JQuery 或第三方实现。

更新:虽然建议的大部分内容都存在严重的限制和可用性问题,但// @grant window.close在脚本标题中使用的最新建议(特定于 TamperMonkey)即使在那些通常无法处理 close 方法的选项卡上也通常会起到作用。虽然并不完全理想并且不能推广到每种情况,但在我的情况下它是一个很好的解决方案。

4

17 回答 17

210

普通的 javascript 不能随意关闭窗口。这是不久前引入的一项安全功能,用于阻止各种恶意攻击和干扰。

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

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

  • 相应的浏览上下文Ascript-closeable
  • 现任脚本的浏览上下文熟悉浏览上下文A
  • 现任脚本的浏览上下文被允许导航浏览上下文A

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

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

Chrome 允许该例外——它不适用于用户脚本——但 Firefox 不允许。 Firefox 的实现直截了当地指出

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


如果您尝试window.close从 Greasemonkey / Tampermonkey / userscript 使用,您将得到:
Firefox:错误消息,“ Scripts may not close windows that were not opened by script.
Chrome:只是静默失败。



长期解决方案:

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

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



骇人听闻的解决方法:

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 的等效设置。

于 2013-11-04T12:50:49.010 回答
34

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 是用于读写 Awesome Markdown 文件的工具,它提供了包括内容大纲、可排序表和代码块语法高亮以及行号的功能。

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

于 2014-07-20T23:11:15.767 回答
24

在 Tampermonkey 现在你可以使用

// @grant        window.close

然后只需简单地调用

window.close();
于 2016-01-19T11:30:15.217 回答
21

为此工作的要求:

您必须从窗口启动器打开窗口/选项卡以获取 javascript 句柄才能使其工作,因为它并不总是在未通过窗口启动器脚本打开的选项卡上工作。此测试页面向您展示如何:

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

如果您在我的启动器中看不到它,那么发布您的浏览器、您的设备和版本是必要的。不同版本的浏览器在不同的设备上表现不同。(例如 iPad 上的 Firefox 和 Chrome,它们并不是他们所说的那样。它们是具有不同皮肤的 Safari!)

因此,重要的是要说例如“我在使用 iOs 14.5 的 iPad 上使用 Safari 10.14 ”,这样我(或 stackoverflow 上的其他一些有用的人)可以为您研究它并发布结果以帮助其他用户。提前感谢您这样做。如果您使用启动器并且它适用于我的示例,那么它可以工作。

我正在使用 Brock Adams 发布的方法,如果它是通过按钮或来自另一个窗口的链接启动的用户启动的,它甚至可以在 Firefox 中使用。

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

我通过按下按钮调用它,因此它是用户启动的,并且使用 Chrome 90、Internet Explorer 11、Edge、Safari 7-10 和 ALSO Firefox 35 和 88 仍然可以正常工作。我使用 Windows 的 8.1 和 10 版进行了测试和 Mac OS X 10.6、10.9 & 10.10 & 10.14(如果不同)。


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

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

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 90.0 和 Firefox 88.0 中进行了测试——在 Windows 10 和 Mac 10.14 Mojave 上都进行了测试)

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


Window Opener Code(在打开上述页面的页面上)

为了实现这一点,安全性强加的跨浏览器兼容性要求要关闭的窗口必须已经由用户单击同一站点域中的按钮打开。

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

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" />
于 2014-05-15T13:30:00.550 回答
14

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

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

你说它“应该仍然这样做”,但我认为你不会找到任何支持这一点的参考资料,也许你记错了什么?

于 2013-11-04T07:19:38.813 回答
13

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

我已经测试了以下内容:

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

我正在遵循使用说明,它似乎工作得很好(确保在进行测试时清除缓存)。我使用的javascript是(附加到点击事件):

window.location.href = '/closekiosk';

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

注意:扩展程序似乎在后台运行并添加了一个 Chrome 托盘图标。它选中了以下选项:“让 Chrome 在后台运行”(或类似文本)。你可能需要玩它,直到它适合你。我取消选中它,现在它工作得很好!

于 2014-08-05T18:30:10.457 回答
12

我找到了一种非常适合我的新方法

var win = window.open("about:blank", "_self");
win.close();
于 2014-12-03T23:18:27.610 回答
8

下面的代码对我有用 -

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

在Chrome 43.0.2357.81上测试

于 2015-05-28T10:52:39.423 回答
2

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

我使用top.close()关闭选项卡。window.close()或其他 open...close 对我不起作用。

于 2014-08-10T13:32:05.980 回答
2

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

我选择的解决方案是发出window.close, 后跟window.setTimeout重定向到不同页面的 a 。

这样,如果window.close成功,该页面上的执行将停止,但如果失败,一秒钟后,它将重定向到不同的页面。

window.close();
window.setTimeout(function(){location.href = '/some-page.php';},1000);
于 2018-10-08T14:22:08.400 回答
2

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

然而,我的情况是我正在为一个设备构建一个网络应用程序,这基本上是设备唯一的功能。您启动它,它会启动 Chrome 并导航到我们的应用程序。它甚至没有连接到互联网,它与之交谈的任何服务器都在我们本地的 Docker 容器上。用户需要一种方法来关闭应用程序(也就是关闭 Chrome),以便他们可以访问终端来执行系统更新。

所以它会启动,在 kiosk 模式下启动 Chrome,地址已经正确。这恰好很容易满足规范中的第二个选项:

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

window.close()所以只需从我的信息亭应用程序调用就可以了

于 2020-02-13T17:57:28.017 回答
2

如果您无法关闭脚本未打开的窗口,则可以使用以下代码销毁您的页面:

 document.getElementsByTagName ('html') [0] .remove ();
于 2020-09-05T00:51:12.163 回答
1

对于使用锚标记打开子窗口的用户,本文介绍了解决此问题的方法。

我的理解是,在新版本的 Chrome 中,该rel属性noopener默认设置为带有 target 的锚标记_blank。因此,通过将其设置为opener您可以恢复旧的行为。

请注意,这是为了避免tab-napping攻击而引入的。

于 2021-06-24T16:53:20.413 回答
-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>
于 2019-12-05T10:48:35.463 回答
-2

只有当您使用 window.open() 打开一个新窗口时,新窗口才能使用我上面提到的代码关闭。这对我来说非常有效:) 注意:切勿使用 href 在新选项卡中打开页面。Window.close() 不适用于 "href" 。请改用 window.open()。

于 2015-05-28T15:56:15.900 回答
-3

对于 TamperMonkey:

@grant window.close 

参考:https ://www.tampermonkey.net/documentation.php#_grant

于 2020-04-06T01:38:05.137 回答
-7

试试这样的 onclick="return self.close()"

于 2015-08-27T09:11:38.313 回答