window.close и self.close не закрывают окно в Chrome

174

Проблема в том, что когда я вызываю window.close()или self.close()он не закрывает окно. Теперь кажется, что в Chrome невозможно закрыть с помощью скрипта любое окно, которое не было создано скриптом. Это явно неверно, но независимо от того, что он все еще должен это делать, даже если для подтверждения требуется всплывающее предупреждение. Это не происходит.

Так есть ли у кого-нибудь реальный, функциональный и проверенный метод закрытия окна с использованием чего-то подобного javascript:window.close()или javascript:self.close()действительно выполняющий то, что ожидается, и то, что происходит просто отлично в каждом браузере, НЕ основанном на Chrome? Любые предложения будут с благодарностью, и я ищу Javascript для конкретного решения, ничего JQuery или сторонней реализации.

Обновление: хотя большая часть из того, что было предложено, имеет серьезные ограничения и проблемы с удобством использования, последнее предложение (специфичное для TamperMonkey), используемое // @grant window.closeв заголовке скрипта, часто помогает, даже на тех вкладках, которые обычно не могут обработать метод close. Хотя это не совсем идеально и не обобщается на каждый случай, в моем случае это хорошее решение.

GμårÐïåñ
источник
window.close()у меня работает в хроме.
пюре
3
@ ГмбХ: Хмм, нет, это не так. Это не имеет ничего общего с языком. Это функция, реализованная браузерами. Если вы можете написать минимальный пример, показывающий, как window.closeне работает так, как должен, я думаю, что это может быть более полезным, чем сказать: «это не работает».
Блендер
3
Я дал вам два примера. Рассказываю это для вас,<a href="javascript:window.close">CLOSE</a>
GåårÐïññ
3
опекун, который является неподходящим javascript. Попробуйте window.close (), и это работает. window.close является просто именем переменной и не будет вызывать функцию (по крайней мере, это не так, когда я тестирую ее в chrome 37). Когда я изменяю ваш пример на window.close (), он работает в chrome 37.
Джордж,
3
GμårÐïåñ Что @George сказал НЕ спорными (если я не полностью понял смысл этого слова). Он прав, утверждая, что у вас есть синтаксическая ошибка в javascript в ваших примерах, и если у вас такая же ошибка в коде приложения, то это, скорее всего, является причиной вашей проблемы. Если, однако, это просто опечатки в ваших примерах, то вы должны исправить эти опечатки, чтобы получить лучшие ответы.
Superole

Ответы:

187

Обычный javascript не может закрывать окна волей-неволей. Это функция безопасности, представленная некоторое время назад, для предотвращения различных злонамеренных эксплойтов и неприятностей.

Из последней рабочей спецификации дляwindow.close() :

close()Метод на Window объекты должны, если все следующие условия, близко контекст просмотра :

  • Соответствующий контекст просмотра A является закрываемым сценарием .
  • Контекстное просмотр действующего сценария знаком с контекстным просмотра 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. Они могут надежно закрыть текущее окно.

Тем не менее, поскольку риски безопасности, связанные с этим window.close, намного меньше для сценария Greasemonkey / Tampermonkey; Greasemonkey и Tampermonkey могли бы разумно предоставить эту функциональность в их API (по сути, упаковывая работу расширения для вас).
Рассмотрите возможность запроса функции.



Хакерские обходные пути:

В настоящее время Chrome был уязвим для эксплойта «самостоятельного перенаправления». Так что код, подобный этому, работал в целом:

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

Это ошибочное поведение, IMO, и сейчас (по состоянию на апрель 2015 года) в основном заблокировано. Он все равно будет работать из введенного кода, только если вкладка была недавно открыта и не имеет страниц в истории просмотра. Так что это полезно только в очень небольших обстоятельствах.

Тем не менее, вариант все еще работает на 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 за обновление. Обратите внимание, что это не будет работать, если открыта только одна вкладка. Закрывает только дополнительные вкладки.


Fire Fox защищен от этой атаки. Таким образом, единственный способ javascript - нанести вред настройкам безопасности, по одному браузеру за раз.

Вы можете открыть about:configи установить
allow_scripts_to_close_windowsна true.

Если ваш сценарий предназначен для личного использования, сделайте это. Если вы попросите кого-нибудь еще включить эту настройку, он будет разумным и оправданным отказаться с предубеждением.

Там в настоящее время нет эквивалентной настройки для Chrome.

Брок Адамс
источник
3
Эй, мой друг, рад наконец услышать от тебя. Просто обратите внимание, что в Fx вы можете обойти это ограничение, переключив dom.allow_scripts_to_close_windows;falseto, trueно я ничего не догадываюсь в Chrome, не взломав источник / перестройку, как я обошел это сейчас. Я знаю и поговорил с разработчиком ТМ, и в недавней альфа / бета-версии мы определили его как вариант совместимости (настройка сценария) для работы в стиле «человек посередине», работает. Думаю, если не считать взломов, у нас нет чистого решения, жалко.
2011 г.
3
Если у кого-то возникли проблемы с window.close или из-за различий в поведении браузеров, внимательно прочитайте этот ответ - он действительно содержит всю необходимую информацию.
Брон Дэвис
Есть ли способ проверить, было ли окно открыто скриптом или нет? (Мне нужно показать / скрыть кнопку возврата, я не хочу использовать хак) Спасибо EDIT: window.opener === null
Cétia
Начиная с Chrome 36.0.1985.125 СРЕДА, 16 ИЮЛЯ 2014, Хакерские обходные пути могут не работать, подробно в моем ответе.
swcool
2
window.close()будет работать в Tampermonkey, если вы установите @grantзначение, отличное от none. Смотрите эту тему .
Занету
32

Chrome Исправлены проблемы безопасности в версии 36.0.1985.125

Chrome 36.0.1985.125 СРЕДА, 16 ИЮЛЯ 2014 выпуске

По моим наблюдениям, это обновление исправило проблему с использованием window.close()для закрытия всплывающего окна. Вы увидите это в консоли, когда произойдет сбой: «Сценарии могут закрывать только те окна, которые были открыты им». Это означает, что хакерские обходные пути (ответ Брока Адамса) могут не работать в последней версии.

Таким образом, в предыдущих выпущенных сборках Chrome приведенный ниже блок кода мог работать, но не с этим обновлением.

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

Для этого обновления вы должны соответствующим образом обновить свой код, чтобы закрыть всплывающее окно. Одним из решений является захват идентификатора всплывающего окна и использование

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

способ удалить это. API-интерфейс расширений Chrome можно найти по адресу chrome.windows .

Собственно мое хромовое расширение MarkView столкнулось с этой проблемой, и мне пришлось обновить свой код, чтобы он работал для этого обновления Chrome. Кстати, MarkView - это инструмент для чтения и записи Awesome Markdown Files, он предоставляет такие функции, как структура содержимого, сортируемые таблицы и подсветка синтаксиса блока кода с номером строки.

Я также создал этот пост , любые комментарии приветствуются.

swcool
источник
2
Правильный взлом open(location, '_self').close();- обратите внимание на использование возвращаемого значения из open(). Это все еще работает на Chrome36.0.1985.125 m
Брок Адамс
В моем случае, я просто протестирую снова 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
У меня есть машинопись, и когда я положил chrome.windows.removeего, я не могу найти символ хрома. как я могу решить это? мне нужно добавить какую-то ссылку?
DevT
@devt chrome.windows.remove - API расширения Chrome, ваш javascript должен быть распознан вашей программой расширения chrome. Вы можете попробовать это внутри background.js, в вашем расширении chrome manifest.json вам необходимо иметь: "background": {"scripts": ["background.js"], ...},
swcool
Я удалил функцию входа в MarkView для свободного доступа пользователей. Так что пример, который я упоминал выше, сейчас недоступен.
swcool
21

В Tampermonkey теперь вы можете использовать

// @grant        window.close

А потом просто позвоните

window.close();
balping
источник
Я подтвердил, что это работает во многих случаях, но все же иногда упрямые, но лучше, чем ничего, спасибо. Я добавлю это в пост.
GμårÐïåñ
2
Так же, как примечание: не работает для меня в Greasemonkey 3.10
mt025
17

Я использую метод, опубликованный Броком Адамсом, и он даже работает в Firefox, если он инициирован пользователем.

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

Я звоню по нажатию кнопки, чтобы он был инициирован пользователем , и он все еще работает нормально, используя Chrome 35-40, Internet Explorer 11, Safari 7-8 и ALSO Firefox 29-35. Я проверил, используя версию 8.1 Windows и Mac OS X 10.6, 10.9 и 10.10, если это отличается.


Самозакрывающийся код окна (на закрывающейся странице)

Полный код, который будет использоваться в открытом пользователем окне, которое может закрыться:

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" />
Джефф Клэйтон
источник
Забыл про инициированные пользователем исключения; хороший улов. Я думаю, что большинство пользователей-скриптеров хотят полностью автоматическую работу. У них уже есть удобный, инициированный пользователем механизм закрытия - этот маленький Х в правом верхнем углу. (^_^)
Брок Адамс
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();
krystonen
10

Многие люди все еще пытаются найти способ закрыть браузер Chrome с помощью JavaScript. Следующий метод работает только в том случае, если вы используете Chrome в качестве программы запуска приложений - например, киоск!

Я проверил следующее:

Я использую следующее расширение: Close Kiosk

Я следую инструкциям по использованию, и, похоже, все работает нормально (убедитесь, что вы очищаете кеш при выполнении тестов). Я использую javascript (прикрепленный к событию клика):

window.location.href = '/closekiosk';

Надеюсь, это кому-нибудь поможет, так как это единственное рабочее решение, которое я нашел.

Примечание. Похоже, расширение работает в фоновом режиме и добавляет значок Chrome в трее. У него отмечена следующая опция: «Дать Chrome работать в фоновом режиме» (или аналогичный текст). Возможно, вам придется поиграть с ним, пока он не сработает для вас. Я снял флажок, и теперь он работает просто отлично!

министр
источник
9

Несмотря на то, что вы думаете, что это «явно ложно», то, что вы говорите «кажется верой», на самом деле правильно. Документация Mozilla для window.close говорит

Этот метод разрешается вызывать только для окон, которые были открыты скриптом с использованием метода window.open. Если окно не было открыто скриптом, в консоли JavaScript появляется следующая ошибка: Скрипты могут не закрывать окна, которые не были открыты скриптом

Вы говорите, что «он все еще должен это делать», но я не думаю, что вы найдете какую-либо ссылку, подтверждающую это, может быть, вы что-то неправильно запомнили?

Gareth
источник
9

Я нашел новый способ, который работает для меня безупречно

var win = window.open("about:blank", "_self");
win.close();
Херардо Абдо
источник
1
это 2017 год, и я все еще получаю сообщение об ошибке «Скрипты могут не закрывать окна, которые не были открыты скриптом».
Rotimi
Хороший взлом для кнопки подтверждения IE 11.
Gopal00005
Работает над Chrome и Firefox
Vineeth Pradhan
1
Эта дыра выглядит заполненной. Я не знаю, когда, но я использую последнюю версию сборки 84.x. Пустая страница загружается, но закрытие не запускается.
Скотт Кристенсен
4

Приведенный ниже код работал для меня -

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

Протестировано на Chrome 43.0.2357.81

DfrDkn
источник
Можете ли вы добавить свою версию Chrome, пожалуйста?
Стефан
Моя версия Chrome 43.0.2357.81.
DfrDkn
7
Для меня это просто заменяет текущее окно на окно в / location.
alianos-
@ alianos- для меня тоже.
Рикардо Гонзалес
1
Не работает в последнем Chrome - Версия 61.0.3163.100 (Официальная сборка) (64-разрядная
версия
1

Это может быть старым, но давайте ответим.

Я использую top.close (), чтобы закрыть вкладку. window.close () или другой метод open ... close для меня не работает.

Soley
источник
11
Это также страдает от "Scripts may not close windows that were not opened by script."проблемы, упомянутой в других ответах.
kad81
1
пожалуйста, дайте решение на ваш ответ. пожалуйста, не обсуждайте проблему только на вашем ответе.
Бимал дас
0

В моем случае страница должна была закрыться, но, возможно, была открыта по ссылке и, таким образом window.close, потерпела неудачу.

Решение, которое я выбрал, состоит в том window.close, чтобы выпустить , а затем window.setTimeoutперенаправить на другую страницу.

Таким образом, в случае window.closeуспеха выполнение на этой странице останавливается, но если происходит сбой, через секунду он перенаправляет на другую страницу.

window.close();
window.setTimeout(function(){location.href = '/some-page.php';},1000);
user2182349
источник
0

Этот ответ от Брока, чтобы он работал на меня. javascript не должен закрывать окно, которое не было открыто этим же javascript.

Я могу закрыть дочернее окно, только если я буду закрывать его из родительского javascript. так что в моем родителе я могу сделать что-то вроде этого.

var myChildWindow;

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

function closeWindow() {
myChildWindow.close();
}
Crismogram
источник
-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 ().

DfrDkn
источник
1
Это просто замена текущего окна. Больше не надо.
Рикардо Гонсалес,
-3

Я хотел поделиться своим «решением» с этой проблемой. Похоже, что большинство из нас пытается закрыть окно браузера в стандартном сеансе браузера, когда пользователь посещает тот или иной веб-сайт, после того, как он посетил другие веб-сайты, и до того, как они посетят еще несколько.

Однако моя ситуация такова, что я создаю веб-приложение для устройства, которое, по сути, будет единственным, что делает устройство. Вы загружаете его, он запускает Chrome и переходит к нашему приложению. Он даже не подключен к Интернету, все серверы, к которым он обращается, находятся в наших локальных контейнерах Docker. Пользователю нужен способ закрыть приложение (или закрыть Chrome), чтобы он мог получить доступ к терминалу для выполнения обновлений системы.

Таким образом, он загружается, запускает Chrome в режиме киоска, по правильному адресу уже. Это легко удовлетворяет второму варианту в спецификации:

Контекст просмотра может быть закрыт сценарием, если он является вспомогательным контекстом просмотра, созданным сценарием (в отличие от действий пользователя), или если это контекст просмотра верхнего уровня, история сеанса которого содержит только один Документ.

Так что просто звонить window.close()из моего киоска приложение просто работает !

Джонатан Тузман
источник
-5

Попробуйте что-то вроде этого onclick = "return self.close ()"

Ragven
источник