window.close a self.close nezatvárajú okno v prehliadači Chrome

Problém je, že keď zavolám window.close() alebo self.close(), okno sa nezatvorí. Zdá sa, že v súčasnosti panuje presvedčenie, že v prehliadači Chrome nemožno skriptom zatvoriť žiadne okno, ktoré nie je vytvorené skriptom. To je zjavne nepravdivé, ale bez ohľadu na to sa to má aj tak urobiť, aj keď to vyžaduje, aby vyskočilo upozornenie na potvrdenie. Tieto sa však nedeje.

Má teda niekto skutočnú, funkčnú a overenú metódu zatvorenia okna pomocou niečoho ako javascript:window.close() alebo javascript:self.close(), ktorá skutočne robí to, čo sa očakáva, a niečo, čo sa deje v poriadku v každom prehliadači, ktorý NIE JE založený na Chrome? Akékoľvek návrhy by som veľmi ocenil a hľadám riešenie špecifické pre Javascript, nič JQuery alebo implementáciu tretej strany.

Aktualizácia: Hoci väčšina z toho, čo bolo navrhnuté, má vážne obmedzenia a problémy s použiteľnosťou, najnovší návrh (špecifický pre TamperMonkey) pomocou // @grant window.close v hlavičke skriptu často urobí trik aj na tých kartách, ktoré normálne nedokážu spracovať metódu zatvorenia. Aj keď to nie je úplne ideálne a nezovšeobecňuje sa to na každý prípad, v mojom prípade je to dobré riešenie.

Bežný javascript nemôže svojvoľne zatvárať okná. Ide o bezpečnostnú funkciu, ktorá bola zavedená pred časom s cieľom zabrániť rôznym škodlivým útokom a nepríjemnostiam.

Z najnovšej pracovnej špecifikácie pre window.close():

Metóda close() na objektoch Window by mala, ak sú splnené všetky nasledujúce podmienky, zatvoriť kontext prehliadania A:

  • Príslušný kontext prehliadania A je skriptovo uzatvárateľný.
  • Kontext prehliadania úradujúceho skriptu je oboznámený s kontextom prehliadania A.
  • Kontext prehliadania súčasného skriptu môže prechádzať kontextom prehliadania A.

Kontext prehliadania je skriptovo uzatvárateľný, ak je to pomocný kontext prehliadania, ktorý bol vytvorený skriptom (na rozdiel od akcie používateľa), alebo ak je to kontext prehliadania, ktorého história relácií obsahuje iba jeden dokument.

To znamená, že až na jednu malú výnimku javascript nesmie dovoliť zatvoriť okno, ktoré nebolo otvorené tým istým javascriptom.

Chrome umožňuje túto výnimku - ktorá sa nevzťahuje na užívateľské skripty - avšak Firefox nie. V implementácii Firefoxu je uvedené priamo:

Túto metódu je povolené zavolať len pre okná, ktoré boli otvorené skriptom pomocou metódy window.open.


Ak sa pokúsite použiť metódu window.close z užívateľského skriptu Greasemonkey / Tampermonkey, dostanete:
Firefox: Chybové hlásenie: "Skripty nemôžu zatvoriť okná, ktoré neboli otvorené skriptom." Chrome: len ticho zlyhá.



Dlhodobé riešenie:

Najlepším spôsobom, ako to vyriešiť, je vyrobiť namiesto toho rozšírenie pre Chrome a/alebo doplnok pre Firefox. Tie dokážu spoľahlivo zatvoriť aktuálne okno.

Keďže však bezpečnostné riziká, ktoré predstavuje window.close, sú v prípade skriptu Greasemonkey/Tampermonkey oveľa menšie; Greasemonkey a Tampermonkey by mohli túto funkciu rozumne poskytnúť vo svojom API (v podstate by prácu rozšírenia zabalili za vás).
Zvážte podanie žiadosti o funkciu.



Hacky workarounds:

Chrome je v súčasnosti bol zraniteľný voči exploitu "self redirection". Takže takýto kód vo všeobecnosti fungoval:

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

Toto je IMO chybné správanie a teraz (približne od apríla 2015) je väčšinou zablokované. Stále bude fungovať z vloženého kódu len ak je karta čerstvo otvorená a nemá žiadne stránky v histórii prehliadania. Takže je to'užitočné len za veľmi malého množstva okolností.

Avšak varianta stále funguje v prehliadači Chrome (v43 & v44) plus Tampermonkey (v3.11 alebo novšia). Použite explicitný príkaz @grant a obyčajný príkaz window.close(). EG:

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

setTimeout (window.close, 5000);

Vďaka zanetu za aktualizáciu. Upozorňujeme, že to nebude fungovať, ak je otvorená len jedna karta. Zatvorí iba ďalšie karty.


Firefox je proti tomuto zneužitiu zabezpečený. Jediným javascriptovým spôsobom je teda ochromenie nastavení zabezpečenia, a to po jednom prehliadači.

Môžete otvoriť about:config a nastaviť allow_scripts_to_close_windows na true.

Ak je váš skript určený na osobné použitie, urobte to. Ak požiadate niekoho iného, aby toto nastavenie zapol, bude múdre a oprávnené, ak to s predsudkami odmietne.

V súčasnosti neexistuje žiadne ekvivalentné nastavenie pre prehliadač Chrome.

Komentáre (20)

Používam metódu, ktorú zverejnil Brock Adams, a funguje aj vo Firefoxe, ak ju iniciuje používateľ.

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

Vyvolávam ho zo stlačenia tlačidla, takže je iniciované používateľom, a stále funguje správne pri použití prehliadačov Chrome 35-40, Internet Explorer 11, Safari 7-8 a TIEŽ Firefox 29-35. Testoval som pomocou verzie 8.1 systému Windows a Mac OS X 10.6, 10.9 & 10.10, ak sa to líši.


Kód samočinného zatvárania okna (na stránke, ktorá sa sama zatvorí)

Kompletný kód, ktorý sa použije na okno otvorené používateľom, ktoré sa môže samo zatvoriť:

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

Vyskúšajte túto testovaciu stránku: (Teraz testované v prehliadači Chrome 40 a Firefox 35)

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


Kód otvárania okien (na stránke, ktorá otvára vyššie uvedenú stránku)

Aby to fungovalo, kompatibilita medzi prehliadačmi, ktorá je podmienená bezpečnosťou, vyžaduje, aby okno, ktoré sa má zatvoriť, už bolo otvorené kliknutím na tlačidlo v rámci tej istej domény stránky.

Napríklad okno, ktoré používa vyššie uvedenú metódu na zatvorenie, môže byť otvorené zo stránky, ktorá používa tento kód (kód poskytnutý z mojej ukážkovej stránky, na ktorú odkazujeme vyššie):

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" />
Komentáre (6)

Napriek tomu, že si myslíte, že je to "zjavne nepravdivé", to, čo hovoríte "zdá sa byť presvedčením", je v skutočnosti správne. V dokumentácii Mozilly pre window.close sa uvádza

Táto metóda sa smie volať len pre okná, ktoré boli otvorené skriptom pomocou metódy window.open. Ak okno nebolo otvorené skriptom, v konzole JavaScript sa zobrazí nasledujúca chyba: Skripty nesmú zatvárať okná, ktoré neboli otvorené skriptom

Píšeš, že sa to "má stále robiť", ale myslím, že'nenájdeš žiadny odkaz, ktorý by to podporoval, možno si'si niečo zle zapamätal?

Komentáre (0)