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

IT技术 javascript google-chrome greasemonkey tampermonkey
2021-02-01 23:03:35

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

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

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

6个回答

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

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

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

  • 相应的浏览上下文A脚本可关闭的
  • 现有脚本的浏览上下文与浏览上下文A相似
  • 允许现有脚本的浏览上下文导航浏览上下文A

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

这意味着,除了一个小例外,不允许 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 的等效设置。

嘿,我的朋友,很高兴终于收到你的来信。请注意,在 Fx 上,您可以通过翻转dom.allow_scripts_to_close_windows;falseto来绕过该限制,true但我想在 Chrome 中没有任何内容,而无需破解源代码/重建,这就是我现在绕过它的方法。我知道并与 TM 开发人员交谈过,在最近的 alpha/beta 中,我们将其作为兼容性选项(脚本设置)以中间人风格运行,有效。我想除了黑客我们没有干净的解决方案,可惜。
2021-03-14 23:03:35
有没有办法检查窗口是否被脚本打开?(我需要显示/隐藏后退按钮,我不想使用 hack)谢谢 编辑:window.opener === null
2021-03-16 23:03:35
自 2014 年 7 月 16 日星期三 Chrome 36.0.1985.125 起,hacky 解决方法可能不起作用,详细信息在我的回答中。
2021-03-21 23:03:35
window.close()如果您设置@grant的值不是none. 看到这个线程
2021-04-02 23:03:35
如果有人在使用 window.close 或浏览器之间的特定行为差异时遇到问题,请仔细阅读此答案 - 它确实包含所有正确的信息。
2021-04-05 23:03:35

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 扩展窗口 API 可以在chrome.windows找到

实际上我的 chrome 扩展MarkView面临这个问题,我不得不更新我的代码以使其适用于这个 Chrome 更新。顺便说一下,MarkView 是一款读写 Awesome Markdown 文件的工具,它提供的功能包括内容大纲、可排序表和代码块语法高亮和行号。

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

我已经删除了MarkView登录功能,供用户自由访问。所以我上面提到的例子现在不可用。
2021-03-12 23:03:35
就我而言,我只是再次测试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 的评论。
2021-03-17 23:03:35
@devt chrome.windows.remove 是 Chrome 扩展 API,你的 javascript 应该被你的 chrome 扩展程序识别。您可以在 background.js 中尝试它,在您的 chrome 扩展 manifest.json 中,您需要: "background": { "scripts": ["background.js"], ... },
2021-03-20 23:03:35
正确的技巧是open(location, '_self').close();——注意从open(). 这仍然适用于 Chrome36.0.1985.125 m
2021-03-23 23:03:35
我有typescript,当我chrome.windows.remove说找不到符号铬时。我该如何解决这个问题?我需要添加某种参考吗?
2021-03-27 23:03:35

在 tampermonkey 现在你可以使用

// @grant        window.close

然后只需简单地调用

window.close();
我已经确认这在很多情况下都有效,但偶尔还是很顽固,但总比没有好,谢谢。我会把它添加到帖子中。
2021-03-11 23:03:35
请注意:在 Greasemonkey 3.10 中对我不起作用
2021-03-23 23:03:35
你能添加正确的指令吗,我是tampermonkey的新手
2021-03-23 23:03:35

使其工作的要求:

您必须从窗口启动器打开窗口/选项卡才能获得 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 和 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_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。(^_^)
2021-03-14 23:03:35
@YumYumYum 感谢您的帖子,bitbucket.org 最近更改了指向 bitbucket.io 的链接 - 现在在答案中修复
2021-03-14 23:03:35
不知何故,这对我不起作用。无论是在 Firefox 30 还是 Chrome 37 上。它所做的只是使页面变为空白(非常奇怪的行为)。我的代码是<button onclick="open(location,'_self').close()" >Close Window</button>. 我做错了什么吗?在我看来,这也是用户发起的。请注意,如果我使用 a<button><input type="button">.
2021-03-17 23:03:35
它对我有用(页面上有一个按钮可以关闭窗口)。不起作用的是:window.open('', '_self', ''); window.close(); 但它与 open(location, '_self').close();
2021-03-18 23:03:35
在上面的答案中为您添加了一个测试页面。
2021-04-02 23:03:35

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

我已经测试了以下内容:

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

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

window.location.href = '/closekiosk';

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

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