window.close i self.close nie zamykają okna w przeglądarce Chrome

174

Problem polega na tym, że kiedy wywołuję window.close()lub self.close()nie zamyka okna. Teraz wydaje się, że w Chrome nie można zamknąć skryptem żadnego okna, które nie zostało utworzone przez skrypt. Jest to ewidentnie fałszywe, ale mimo wszystko ma to nadal robić, nawet jeśli wymaga pojawienia się ostrzeżenia w celu potwierdzenia. To się nie dzieje.

Czy więc ktoś ma prawdziwą, funkcjonalną i sprawdzoną metodę zamykania okna za pomocą czegoś podobnego javascript:window.close()lub javascript:self.close()faktycznie robi to, czego się oczekuje i coś, co dzieje się dobrze w każdej przeglądarce, która NIE jest oparta na Chrome? Wszelkie sugestie byłyby bardzo mile widziane i szukam rozwiązania specyficznego dla Javascript, nic JQuery lub implementacja strony trzeciej.

Aktualizacja: Chociaż wiele z tego, co zostało zasugerowane, ma poważne ograniczenia i problemy z użytecznością, najnowsza sugestia (specyficzna dla TamperMonkey) dotycząca użycia // @grant window.closew nagłówku skryptu często załatwia sprawę nawet na tych kartach, które zwykle nie radzą sobie z metodą close. Chociaż nie jest do końca idealny i nie uogólniany na każdy przypadek, w moim przypadku jest dobrym rozwiązaniem.

GµårÐïåñ
źródło
window.close()działa dla mnie w chrome.
mash
3
@ GµårÐïåñ: Umm, nie jest. Nie ma to nic wspólnego z językiem. Jest to funkcja zaimplementowana przez przeglądarki. Jeśli możesz napisać minimalny przykład pokazujący, jak window.closenie działa tak, jak powinien, myślę, że może to być bardziej pomocne niż powiedzenie „to nie działa”.
Blender
3
Podałem dwa przykłady. <a href="javascript:window.close">CLOSE</a>
Mówiąc
3
opiekun, który jest nieprawidłowym javascriptem. Spróbuj window.close () i działa. window.close to tylko nazwa zmiennej i nie wywoła funkcji (przynajmniej nie wywołuje, gdy testuję ją w chrome 37). Kiedy zmienię twój przykład na window.close (), to działa w chrome 37.
George
3
GµårÐïåñ To, co powiedział @George, NIE jest dyskusyjne (chyba że całkowicie źle zrozumiałem znaczenie tego słowa). Ma rację, twierdząc, że masz błąd składniowy w javascript w swoich przykładach, a jeśli masz ten sam błąd w kodzie aplikacji, jest to bardziej niż prawdopodobne, że przyczyną problemu. JEŚLI jednak są to tylko literówki w twoich przykładach, powinieneś je poprawić, aby uzyskać lepsze odpowiedzi.
Superole

Odpowiedzi:

187

Zwykły javascript nie może zamknąć systemu Windows chcąc nie chcąc. Jest to funkcja bezpieczeństwa, wprowadzona jakiś czas temu, aby powstrzymać różne złośliwe exploity i irytacje.

Z najnowszej specyfikacji roboczej dlawindow.close() :

close()Metoda na okno obiekty powinny, jeśli spełnione są wszystkie poniższe warunki, blisko kontekst przeglądania :

  • Odpowiedni kontekst przeglądania A jest zamykany przez skrypt .
  • Kontekst przeglądanie urzędującego skryptu jest zaznajomiony z kontekstu przeglądania A .
  • Przeglądanie kontekst skryptu zasiedziałego może poruszać się kontekstowe przeglądania A .

Kontekst przeglądania jest zamykany przez skrypt, jeśli jest to pomocniczy kontekst przeglądania, który został utworzony przez skrypt (w przeciwieństwie do działania użytkownika) lub jeśli jest to kontekst przeglądania, którego historia sesji zawiera tylko jeden dokument.

Oznacza to, że z jednym małym wyjątkiem javascript nie może zamknąć okna, które nie zostało otwarte przez ten sam skrypt javascript.

Chrome dopuszcza ten wyjątek - którego nie ma w przypadku skryptów użytkownika - jednak Firefox tego nie robi. Implementacja Firefoksa jasno stwierdza :

Tę metodę można wywołać tylko w przypadku okien, które zostały otwarte przez skrypt korzystający z tej window.openmetody.


Jeśli spróbujesz użyć window.closeskryptu Greasemonkey / Tampermonkey / userscript, otrzymasz:
Firefox: komunikat o błędzie „ Scripts may not close windows that were not opened by script.
Chrome: po prostu nie działa.



Długoterminowe rozwiązanie:

Najlepszym sposobem radzenia sobie z tym problemem jest utworzenie rozszerzenia do Chrome i / lub dodatku do przeglądarki Firefox. Mogą one niezawodnie zamknąć bieżące okno.

Jednakże, ponieważ zagrożenia bezpieczeństwa, jakie stwarza window.close, są znacznie mniejsze w przypadku skryptu Greasemonkey / Tampermonkey; Greasemonkey i Tampermonkey mogą rozsądnie zapewnić tę funkcjonalność w swoim API (zasadniczo pakując rozszerzenie dla Ciebie).
Rozważ zgłoszenie prośby o funkcję.



Hacky obejścia:

Chrome jest obecnie podatny na exploit „samodzielnego przekierowania”. Tak więc kod taki działał ogólnie:

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

To jest błędne zachowanie, IMO, i obecnie (mniej więcej od kwietnia 2015 r.) Jest w większości blokowane. Będzie działać po wstrzyknięciu kodu tylko wtedy, gdy karta jest świeżo otwarta i nie ma stron w historii przeglądania. Jest więc przydatny tylko w bardzo małych okolicznościach.

Jednak odmiana nadal działa w przeglądarce Chrome (wersja 43 i 44) oraz Tampermonkey (wersja 3.11 lub nowsza) . Użyj wyraźnego @granti prostego window.close(). NA PRZYKŁAD:

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

setTimeout (window.close, 5000);

Dzięki zanetu za aktualizację. Zauważ, że to nie zadziała, jeśli jest otwarta tylko jedna karta. Zamyka tylko dodatkowe zakładki.


Firefox jest zabezpieczony przed tym exploitem. Tak więc jedynym sposobem javascript jest uszkodzenie ustawień bezpieczeństwa, jedna przeglądarka na raz.

Można otworzyć about:configi ustawić
allow_scripts_to_close_windowssię true.

Jeśli twój skrypt jest do użytku osobistego, zrób to. Jeśli poprosisz kogoś innego o włączenie tego ustawienia, mądry i uzasadniony będzie odmówienie z uprzedzeniem.

Obecnie nie ma odpowiednika ustawienia dla przeglądarki Chrome.

Brock Adams
źródło
3
Hej przyjacielu, cieszę się, że w końcu się odezwałeś. Tylko uwaga, na Fx można obejście tego ograniczenia, odchylając dom.allow_scripts_to_close_windows;falsesię true, ale nic w Chrome odgadnąć bez włamania źródło / rebuild czyli jak mam wokół niego teraz. Wiem i rozmawiałem z deweloperem TM, aw ostatniej wersji alfa / beta umieściliśmy ją jako opcję kompatybilności (ustawienie skryptu), aby działała w stylu man-in-the-middle. Chyba poza hackami nie mamy czystego rozwiązania, szkoda.
GµårÐïåñ
3
Jeśli ktoś ma problem z window.close lub szczególną różnicą w zachowaniu między przeglądarkami, przeczytaj bardzo uważnie tę odpowiedź - naprawdę zawiera wszystkie potrzebne informacje.
Bron Davies,
Czy istnieje sposób, aby sprawdzić, czy okno zostało otwarte przez skrypt, czy nie? (Muszę pokazać / ukryć przycisk Wstecz, nie chcę używać hackowania) Dzięki EDYCJA: window.opener === null
Cétia
Od wersji Chrome 36.0.1985.125 ŚRODA, 16 LIPCA 2014 r., Hacky mogą nie działać. Szczegóły w mojej odpowiedzi.
swcool
2
window.close()będzie działać w Tampermonkey, jeśli ustawisz @grantwartość inną niż none. Zobacz ten wątek .
zanetu
32

Chrome Naprawiono problemy bezpieczeństwa w wersji 36.0.1985.125

Chrome 36.0.1985.125 ŚRODA, 16 LIPCA 2014 Informacje o wersji

Z moich obserwacji wynika, że ​​ta aktualizacja rozwiązała problem z używaniem window.close()do zamykania wyskakującego okienka. Zobaczysz to w konsoli, gdy się nie powiedzie, „Skrypty mogą zamykać tylko te okna, które zostały przez niego otwarte”. Oznacza to, że hacky obejścia (odpowiedź Brocka Adamsa) mogą nie działać w najnowszej wersji.

Tak więc w poprzednich wydanych kompilacjach Chrome poniższy blok kodu mógł działać, ale nie w przypadku tej aktualizacji.

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

W przypadku tej aktualizacji musisz odpowiednio zaktualizować kod, aby zamknąć wyskakujące okienko. Jednym z rozwiązań jest pobranie identyfikatora wyskakującego okna i użycie

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

metoda, aby go usunąć. Interfejs API systemu Windows dla rozszerzenia Chrome można znaleźć pod adresem chrome.windows .

Właściwie moje rozszerzenie Chrome, MarkView, miało ten problem i musiałem zaktualizować kod, aby działał w tej aktualizacji Chrome. Nawiasem mówiąc, MarkView jest narzędziem do odczytu i zapisu niesamowitych plików Markdown, zapewnia funkcje, w tym kontur zawartości, sortowalne tabele i podświetlanie składni bloku kodu z numerem wiersza.

Stworzyłem również ten post , wszelkie komentarze są mile widziane.

swcool
źródło
2
Prawidłowy hack to open(location, '_self').close();- zwróć uwagę na użycie wartości zwracanej z open(). To nadal działa w Chrome36.0.1985.125 m
Brock Adams,
W moim przypadku po prostu testuję ponownie z open(location, '_self').close();, otrzymałem błąd „Unauthorized”. Ten błąd jest inny z 'window.close () (warning on this"Scripts may close only the windows that were opened by it."). It looked like open (location,' _self '). Close (); `przesunięto trochę do przodu, ale w moim przypadku nie można go zakończyć. Dzięki @ brock-adams za komentarz.
swcool
Mam maszynopis i kiedy chrome.windows.removeto umieściłem , mówi, że nie mogę znaleźć chromowanego symbolu. jak mogę to rozwiązać? czy muszę dodać jakieś odniesienie?
DevT
@devt chrome.windows.remove to interfejs API rozszerzenia Chrome. Twój skrypt javascript powinien zostać rozpoznany przez program rozszerzający do Chrome. Możesz to wypróbować w background.js, w swoim pliku manifest.json rozszerzenia Chrome, musisz mieć: "background": {"scripts": ["background.js"], ...},
swcool
Usunąłem funkcję logowania MarkView, aby użytkownicy mieli swobodny dostęp. Tak więc przykład, o którym wspomniałem powyżej, nie jest teraz dostępny.
swcool
21

W tampermonkey możesz teraz użyć

// @grant        window.close

A potem po prostu zadzwoń

window.close();
łysienie
źródło
Potwierdziłem, że to działa w wielu przypadkach, ale czasami jest to uparte, ale lepsze niż nic, dziękuję. Dodam to do postu.
GµårÐïåñ
2
Uwaga: nie działa dla mnie w Greasemonkey 3.10
mt025
17

Używam metody opublikowanej przez Brocka Adamsa i działa ona nawet w przeglądarce Firefox, jeśli jest inicjowana przez użytkownika.

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

Wywołuję go za pomocą przycisku, więc jest inicjowany przez użytkownika i nadal działa dobrze, używając przeglądarki Chrome 35-40, Internet Explorer 11, Safari 7-8 i RÓWNIEŻ Firefox 29-35. Testowałem przy użyciu wersji 8.1 systemu Windows i Mac OS X 10.6, 10.9 i 10.10, jeśli jest inaczej.


Kod samozamykającego się okna (na stronie, która się zamyka)

Kompletny kod używany w oknie otwartym przez użytkownika, które może się zamknąć:

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');" />

Wypróbuj tę stronę testową: (teraz testowana w Chrome 40 i Firefox 35)

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


Kod otwieracza okna (na stronie, która otwiera powyższą stronę)

Aby to zadziałało, narzucona przez zabezpieczenia zgodność z różnymi przeglądarkami wymaga, aby okno, które ma zostać zamknięte, zostało już otwarte przez użytkownika klikającego przycisk w tej samej domenie witryny.

Na przykład okno, które używa powyższej metody do zamykania się, można otworzyć ze strony przy użyciu tego kodu (kod dostarczony z mojej przykładowej strony, do której link powyżej):

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" />
Jeff Clayton
źródło
Zapomniałem o wyjątkach inicjowanych przez użytkownika; dobry chwyt. Myślę jednak, że większość skryptów użytkowników chce w pełni automatycznej obsługi. Mają już poręczny, inicjowany przez użytkownika mechanizm zamykania - ten mały X w prawym górnym rogu. (^_^)
Brock Adams
1
Jakoś to nie działa dla mnie. Ani w Firefoksie 30, ani w Chrome 37. Wszystko, co robi, to powoduje, że strona staje się pusta (naprawdę dziwne zachowanie). Mój kod to <button onclick="open(location,'_self').close()" >Close Window</button>. Czy robię coś ewidentnie nie tak? Wydaje mi się, że jest to również inicjowane przez użytkownika. Zwróć uwagę, że uzyskam ten sam wynik, jeśli użyję a <button>lub <input type="button">.
LordOfThePigs
Dodano stronę testową powyżej w odpowiedzi dla Ciebie.
Jeff Clayton
@YumYumYum dzięki za post, bitbucket.org ostatnio zmienił link do bitbucket.io - naprawiono teraz w odpowiedzi
Jeff Clayton
U mnie to działa (mając przycisk na stronie, aby zamknąć okno). To, co nie działało, to: window.open('', '_self', ''); window.close(); ale działało open(location, '_self').close();
krystonen
10

Wiele osób wciąż próbuje znaleźć sposób na zamknięcie przeglądarki Chrome za pomocą javascript. Poniższa metoda działa tylko wtedy, gdy używasz Chrome jako programu uruchamiającego aplikacje - na przykład kiosk!

Przetestowałem następujące elementy:

Używam następującego rozszerzenia: Zamknij Kiosk

Postępuję zgodnie z instrukcjami użytkowania i wydaje się, że działa dobrze (upewnij się, że wyczyściłeś pamięć podręczną podczas wykonywania testów). Używam javascript (dołączonego do zdarzenia kliknięcia):

window.location.href = '/closekiosk';

Mam nadzieję, że to komuś pomoże, bo to jedyne działające rozwiązanie, jakie znalazłem.

Uwaga: wygląda na to, że rozszerzenie działa w tle i dodaje ikonę paska Chrome. Ma zaznaczoną opcję: „Pozwól Chrome działać w tle” (lub podobny tekst). Być może będziesz musiał się nim bawić, dopóki nie zadziała. Odznacziłem to i teraz działa dobrze!

Minister
źródło
9

Pomimo myślenia, że ​​jest to „ewidentnie fałszywe”, to, co mówisz „wydaje się być przekonaniem”, jest w rzeczywistości poprawne. Dokumentacja Mozilli dla window.close mówi

Tę metodę można wywołać tylko w przypadku okien, które zostały otwarte przez skrypt przy użyciu metody window.open. Jeśli okno nie zostało otwarte przez skrypt, w konsoli JavaScript pojawia się następujący błąd: Skrypty mogą nie zamykać okien, które nie zostały otwarte przez skrypt

Mówisz, że ma „nadal to robić”, ale nie sądzę, abyś znalazł jakieś odniesienie, które by to potwierdzało, może źle coś zapamiętałeś?

Gareth
źródło
9

Znalazłem nowy sposób, który doskonale mi pasuje

var win = window.open("about:blank", "_self");
win.close();
Gerardo Abdo
źródło
1
jest rok 2017 i nadal pojawia się błąd „Skrypty mogą nie zamykać okien, które nie zostały otwarte przez skrypt”.
Rotimi
Niezły hack do przycisku potwierdzenia w IE 11.
Gopal00005
Działa na Chrome i Firefox
Vineeth Pradhan
1
Wygląda na to, że ta dziura została wypełniona. Nie wiem, kiedy, ale używam najnowszej wersji deweloperskiej 84.x. Pusta strona ładuje się, ale zamknięcie nie jest uruchamiane.
Scott Christensen
4

Poniższy kod zadziałał dla mnie -

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

Przetestowano na Chrome 43.0.2357.81

DfrDkn
źródło
Czy możesz dodać swoją wersję Chrome?
Stephan
Moja wersja Chrome to 43.0.2357.81.
DfrDkn
7
Dla mnie to po prostu zastępuje bieżące okno oknem w / location.
alianos-
@ alianos- dla mnie też.
RicardoGonzales
1
Nie działa w najnowszym chrome - Wersja 61.0.3163.100 (oficjalna kompilacja) (64-bitowa)
Subhajit
1

To może być stare, ale odpowiedzmy na to.

Używam top.close (), aby zamknąć kartę. window.close () lub inne open ... close nie działa dla mnie.

Soley
źródło
11
To również cierpi na "Scripts may not close windows that were not opened by script."problem wspomniany w innych odpowiedziach.
kad81
1
proszę podać rozwiązanie swojej odpowiedzi. nie omawiaj problemu tylko w odpowiedzi.
Bimal Das
0

W moim przypadku strona musiała zostać zamknięta, ale mogła zostać otwarta przez łącze, a zatem window.closezakończyła się niepowodzeniem.

Rozwiązaniem, które wybrałem, jest wydanie window.close, po window.setTimeoutktórym następuje przekierowanie na inną stronę.

W ten sposób, jeśli się window.closepowiedzie, wykonanie na tej stronie zostanie zatrzymane, ale jeśli się nie powiedzie, w ciągu sekundy przekieruje na inną stronę.

window.close();
window.setTimeout(function(){location.href = '/some-page.php';},1000);
user2182349
źródło
0

Ta odpowiedź od Brocka sprawdziła się dla mnie. javascript nie może mieć możliwości zamknięcia okna, które nie zostało otwarte przez ten sam skrypt javascript.

Mogę zamknąć okno potomne tylko wtedy, gdy będę je zamykać z javascript nadrzędnego. więc w moim rodzicu mogę zrobić coś takiego.

var myChildWindow;

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

function closeWindow() {
myChildWindow.close();
}
Kryzmogram
źródło
-1

Możesz także spróbować użyć mojego kodu poniżej. Pomoże Ci to również w przekierowaniu okna nadrzędnego:

Rodzic:

<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" />

Popup:

<!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>
Harshal Lonare
źródło
-2

Tylko jeśli otworzysz nowe okno za pomocą window.open (), nowe okno będzie mogło zostać zamknięte za pomocą kodu, jak wspomniałem powyżej. U mnie to działa idealnie :) Uwaga: Nigdy nie używaj href do otwierania strony w nowej karcie. Window.close () nie działa z „href”. Zamiast tego użyj window.open ().

DfrDkn
źródło
1
To tylko wymiana obecnego okna. Już nie.
RicardoGonzales
-3

Chciałem podzielić się moim „rozwiązaniem” w tej kwestii. Wygląda na to, że większość z nas próbuje zamknąć okno przeglądarki podczas standardowej sesji przeglądarki, kiedy użytkownik odwiedza jakąś witrynę internetową po odwiedzeniu innych witryn, a zanim odwiedzą kolejne.

Jednak moja sytuacja jest taka, że ​​tworzę aplikację internetową dla urządzenia, które będzie zasadniczo jedyną rzeczą, jaką robi to urządzenie. Uruchamiasz go, uruchamia Chrome i przechodzi do naszej aplikacji. Nie jest nawet połączony z Internetem, wszystkie serwery, z którymi rozmawia, znajdują się w naszych lokalnych kontenerach Docker. Użytkownik potrzebuje sposobu na zamknięcie aplikacji (czyli zamknięcie przeglądarki Chrome), aby uzyskać dostęp do terminala w celu wykonania aktualizacji systemu.

Więc się uruchamia, uruchamia Chrome w trybie kiosku, już pod właściwym adresem. Dzieje się tak, aby łatwo spełnić drugą opcję w specyfikacji:

Kontekst przeglądania jest zamykany przez skrypt, jeśli jest to pomocniczy kontekst przeglądania, który został utworzony przez skrypt (w przeciwieństwie do działania użytkownika) lub jeśli jest to kontekst przeglądania najwyższego poziomu, którego historia sesji zawiera tylko jeden dokument.

Więc po prostu dzwonienie window.close()z mojej aplikacji kiosku po prostu działa !

Jonathan Tuzman
źródło
-5

Spróbuj czegoś takiego onclick = "return self.close ()"

Ragven
źródło