window.close et self.close ne ferment pas la fenêtre dans Chrome

174

Le problème est que lorsque j'invoque window.close()ou que self.close()cela ne ferme pas la fenêtre. Maintenant, il semble y avoir une croyance que dans Chrome, vous ne pouvez pas fermer par script une fenêtre qui n'est pas créée par un script. C'est manifestement faux, mais quoi qu'il en soit, il est censé le faire, même s'il faut afficher une alerte pour confirmer. Cela ne se produit pas.

Alors, est-ce que quelqu'un a une méthode réelle, fonctionnelle et éprouvée pour fermer une fenêtre en utilisant quelque chose comme javascript:window.close()ou javascript:self.close()qui fait réellement ce qui est attendu et quelque chose qui se passe très bien dans chaque navigateur qui n'est PAS basé sur Chrome? Toute suggestion serait grandement appréciée et je recherche une solution spécifique Javascript, rien de JQuery ou une implémentation tierce.

Mise à jour: Bien qu'une grande partie de ce qui a été suggéré présente de graves limitations et des problèmes d'utilisabilité, la dernière suggestion (spécifique à TamperMonkey) utilisée // @grant window.closedans l'en-tête du script fera souvent l'affaire même sur les onglets qui ne peuvent normalement pas gérer la méthode de fermeture. Bien que ce ne soit pas tout à fait idéal et ne se généralise pas à tous les cas, c'est une bonne solution dans mon cas.

GµårÐïåñ
la source
window.close()fonctionne pour moi en chrome.
écraser
3
@ GµårÐïåñ: Euh, non, ce n'est pas le cas. Cela n'a rien à voir avec la langue. C'est une fonction implémentée par les navigateurs. Si vous pouvez écrire un exemple minimal montrant comment window.closene fonctionne pas comme il se doit, je pense que cela peut être plus utile que de dire "ça ne marche pas".
Blender
3
Je vous ai donné DEUX exemples. <a href="javascript:window.close">CLOSE</a>
Épeler
3
tuteur qui est javascript incorrect. Essayez window.close () et cela fonctionne. window.close est juste un nom de variable et n'appellera pas la fonction (du moins ce n'est pas le cas lorsque je le teste dans chrome 37). Lorsque je change votre exemple en window.close (), cela fonctionne dans Chrome 37.
George
3
GµårÐïåñ Ce que @George a dit n'est PAS sans objet (sauf si j'ai totalement mal compris le sens du mot). Il a raison de dire que vous avez une erreur syntaxique dans le javascript dans vos exemples, et si vous avez la même erreur dans votre code d'application, c'est plus que probablement la cause de votre problème. SI, cependant, ce ne sont que des fautes de frappe dans vos exemples, vous devez corriger ces fautes de frappe pour obtenir de meilleures réponses.
Superole

Réponses:

187

Le javascript ordinaire ne peut pas fermer les fenêtres bon gré mal gré. Il s'agit d'une fonctionnalité de sécurité, introduite il y a quelque temps, pour arrêter divers exploits et ennuis malveillants.

De la dernière spécification de travail pourwindow.close() :

La close()méthode sur les objets Window doit, si toutes les conditions suivantes sont remplies, fermer le contexte de navigation A :

  • Le contexte de navigation A correspondant peut être fermé par script .
  • Le contexte de navigation du script sortant connaît le contexte de navigation A .
  • Le contexte de navigation du script historique est autorisé à naviguer dans le contexte de navigation A .

Un contexte de navigation peut être fermé par script s'il s'agit d'un contexte de navigation auxiliaire créé par un script (par opposition à une action de l'utilisateur), ou s'il s'agit d'un contexte de navigation dont l'historique de session ne contient qu'un seul document.

Cela signifie, à une petite exception près, que javascript ne doit pas être autorisé à fermer une fenêtre qui n'a pas été ouverte par ce même javascript.

Chrome autorise cette exception - qui ne s'applique pas aux scripts utilisateur - mais pas Firefox. L'implémentation de Firefox déclare :

Cette méthode ne peut être appelée que pour les fenêtres ouvertes par un script utilisant la window.openméthode.


Si vous essayez d'utiliser à window.closepartir d'un Greasemonkey / Tampermonkey / userscript, vous obtiendrez:
Firefox: Le message d'erreur " Scripts may not close windows that were not opened by script."
Chrome: échoue silencieusement.



La solution à long terme:

La meilleure façon de gérer cela est de créer une extension Chrome et / ou un module complémentaire Firefox. Ceux-ci peuvent fermer de manière fiable la fenêtre actuelle.

Cependant, puisque les risques de sécurité, posés par window.close, sont bien moindres pour un script Greasemonkey / Tampermonkey; Greasemonkey et Tampermonkey pourraient raisonnablement fournir cette fonctionnalité dans leur API (essentiellement le travail d'extension pour vous).
Pensez à faire une demande de fonctionnalité.



Les solutions de contournement hacky:

Chrome est actuellement vulnérable à l'exploit «d'auto-redirection». Donc, un code comme celui-ci fonctionnait en général:

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

Il s'agit d'un comportement bogué, IMO, et est maintenant (à peu près en avril 2015) principalement bloqué. Cela fonctionnera toujours à partir du code injecté uniquement si l'onglet est fraîchement ouvert et n'a pas de pages dans l'historique de navigation. Ce n'est donc utile que dans un très petit ensemble de circonstances.

Cependant, une variante fonctionne toujours sur Chrome (v43 et v44) plus Tampermonkey (v3.11 ou version ultérieure) . Utilisez un explicite @grantet simple window.close(). PAR EXEMPLE:

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

setTimeout (window.close, 5000);

Merci à zanetu pour la mise à jour. Notez que cela ne fonctionnera pas s'il n'y a qu'un seul onglet ouvert. Il ne ferme que les onglets supplémentaires.


Firefox est protégé contre cet exploit. Ainsi, le seul moyen javascript est de paralyser les paramètres de sécurité, un navigateur à la fois.

Vous pouvez ouvrir about:configet définir
allow_scripts_to_close_windowssur true.

Si votre script est destiné à un usage personnel, allez-y et faites-le. Si vous demandez à quelqu'un d'autre d'activer ce paramètre, il serait intelligent et justifié de refuser avec préjugé.

Il n'existe actuellement aucun paramètre équivalent pour Chrome.

Brock Adams
la source
3
Hé mon ami, heureux de vous entendre enfin. Juste une note, sur Fx, vous pouvez contourner cette limitation en basculant le dom.allow_scripts_to_close_windows;falsevers, truemais je suppose que rien dans Chrome sans pirater la source / reconstruire, c'est ainsi que je l'ai contourné pour le moment. Je sais et j'ai parlé au développeur TM et dans la récente version alpha / bêta, nous l'avons mis comme option de compatibilité (réglage du script) pour fonctionner dans un style man-in-the-middle, fonctionne. Je suppose qu'en dehors des hacks, nous n'avons pas de solution propre, dommage.
GµårÐïåñ
3
Si quelqu'un a des problèmes avec window.close ou la différence de comportement particulière entre les navigateurs, lisez cette réponse très attentivement - elle contient vraiment toutes les bonnes informations.
Bron Davies
Existe-t-il un moyen de vérifier si la fenêtre a été ouverte par script ou non? (J'ai besoin d'afficher / masquer un bouton de retour, je ne veux pas utiliser le hack) Merci EDIT: window.opener === null
Cétia
Depuis Chrome 36.0.1985.125 MERCREDI 16 JUILLET 2014, les solutions de contournement de piratage peuvent ne pas fonctionner, détail dans ma réponse.
swcool
2
window.close()fonctionnera dans Tampermonkey si vous définissez @grantune valeur autre que none. Voir ce fil .
zanetu
32

Chrome Correction des problèmes de sécurité sur la version 36.0.1985.125

Chrome 36.0.1985.125 MERCREDI 16 JUILLET 2014 Note de mise à jour

D'après mon observation, cette mise à jour a résolu le problème d'utilisation window.close()de la fermeture de la fenêtre contextuelle. Vous verrez ceci dans la console en cas d'échec, "Les scripts peuvent fermer uniquement les fenêtres qui ont été ouvertes par lui.". Cela signifie que les solutions de contournement hacky (réponse de Brock Adams) peuvent ne pas fonctionner dans la dernière version.

Ainsi, dans les versions précédentes de Chrome, le bloc de code ci-dessous peut fonctionner, mais pas avec cette mise à jour.

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

Pour cette mise à jour, vous devez mettre à jour votre code en conséquence pour fermer la fenêtre contextuelle. L'une des solutions consiste à récupérer l'identifiant de la fenêtre contextuelle et à utiliser

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

méthode pour le supprimer. L'API Windows de l'extension Chrome se trouve sur chrome.windows .

En fait, mon extension Chrome MarkView faisait face à ce problème et j'ai dû mettre à jour mon code pour qu'il fonctionne pour cette mise à jour Chrome. À propos, MarkView est un outil pour lire et écrire des fichiers Awesome Markdown, il fournit des fonctionnalités telles que le contour du contenu, les tableaux triables et la mise en évidence de la syntaxe du bloc de code avec le numéro de ligne.

J'ai également créé ce post , tous les commentaires sont les bienvenus.

swcool
la source
2
Le hack correct est open(location, '_self').close();- notez l'utilisation de la valeur de retour de open(). Cela fonctionne toujours sur Chrome36.0.1985.125 m
Brock Adams
Dans mon cas, je viens de tester à nouveau avec open(location, '_self').close();, j'ai eu une erreur "Non autorisé" à ce sujet. Cette erreur est différente avec 'window.close () (warning on this"Scripts may close only the windows that were opened by it."). It looked like open (location,' _self '). Close (); `a avancé un peu, mais cela ne peut pas se terminer dans mon cas. Merci @ brock-adams pour le commentaire.
swcool
J'ai dactylographié et quand je l'ai mis, chrome.windows.removeil dit que je ne trouve pas le symbole chrome. Comment puis-je résoudre ça? dois-je ajouter une sorte de référence?
DevT
@devt chrome.windows.remove est l'API d'extension Chrome, votre javascript doit être reconnu par votre programme d'extension Chrome. Vous pouvez l'essayer dans background.js, dans votre extension chrome manifest.json, vous devez avoir: "background": {"scripts": ["background.js"], ...},
swcool
J'avais supprimé la fonction de connexion MarkView pour que les utilisateurs puissent y accéder librement. Ainsi, l'exemple que j'ai mentionné ci-dessus n'est pas disponible pour le moment.
swcool
21

Dans Tampermonkey, vous pouvez maintenant utiliser

// @grant        window.close

Et puis appelez simplement

window.close();
balping
la source
J'ai confirmé que cela fonctionne dans de nombreux cas, mais encore parfois des obstinés, mais mieux que rien, merci. Je vais l'ajouter au message.
GµårÐïåñ
2
Juste une note: ne fonctionne pas pour moi dans Greasemonkey 3.10
mt025
17

J'utilise la méthode publiée par Brock Adams et cela fonctionne même dans Firefox, si elle est initiée par l'utilisateur.

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

Je l'appelle en appuyant sur un bouton, il est donc lancé par l'utilisateur , et il fonctionne toujours bien avec Chrome 35-40, Internet Explorer 11, Safari 7-8 et AUSSI Firefox 29-35. J'ai testé en utilisant la version 8.1 de Windows et Mac OS X 10.6, 10.9 et 10.10 si cela est différent.


Code de la fenêtre à fermeture automatique (sur la page qui se ferme)

Le code complet à utiliser sur la fenêtre ouverte par l'utilisateur qui peut se fermer:

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

Essayez cette page de test: (maintenant testée dans Chrome 40 et Firefox 35)

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


Code d'ouverture de fenêtre (sur une page qui ouvre la page ci-dessus)

Pour que cela fonctionne, la compatibilité croisée des navigateurs imposée par la sécurité nécessite que la fenêtre à fermer ait déjà été ouverte par l'utilisateur qui clique sur un bouton dans le même domaine de site.

Par exemple, la fenêtre qui utilise la méthode ci-dessus pour se fermer, peut être ouverte à partir d'une page en utilisant ce code (code fourni à partir de mon exemple de page lié ci-dessus):

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
la source
Oublié les exceptions initiées par l'utilisateur; bonne prise. Je pense que la plupart des utilisateurs veulent un fonctionnement entièrement automatique. Ils ont déjà un mécanisme de fermeture pratique, initié par l'utilisateur - ce petit X en haut à droite. (^_^)
Brock Adams
1
D'une manière ou d'une autre, cela ne fonctionne pas pour moi. Ni sur Firefox 30 ni sur Chrome 37. Il ne fait que rendre la page vierge (comportement vraiment bizarre). Mon code est <button onclick="open(location,'_self').close()" >Close Window</button>. Est-ce que je fais manifestement quelque chose de mal? Il me semble que cela est également lancé par l'utilisateur. Notez que j'obtiens le même résultat si j'utilise un <button>ou un <input type="button">.
LordOfThePigs
Ajout d'une page de test ci-dessus dans la réponse pour vous.
Jeff Clayton
@YumYumYum merci pour le message, bitbucket.org a récemment changé le lien vers bitbucket.io - corrigé dans la réponse maintenant
Jeff Clayton
Cela fonctionne pour moi (avoir un bouton sur la page pour fermer la fenêtre). Ce qui n'a pas fonctionné était: window.open('', '_self', ''); window.close(); mais cela a fonctionné avec open(location, '_self').close();
krystonen
10

De nombreuses personnes essaient encore de trouver un moyen de fermer le navigateur Chrome à l'aide de javascript. La méthode suivante ne fonctionne que lorsque vous utilisez Chrome comme lanceur d'applications - kiosque par exemple!

J'ai testé les éléments suivants:

J'utilise l'extension suivante: Fermer le kiosque

Je suis les instructions d'utilisation et cela semble fonctionner très bien (assurez-vous de vider le cache tout en faisant les tests). Le javascript que j'utilise est (attaché à l'événement de clic):

window.location.href = '/closekiosk';

J'espère que cela aide quelqu'un, car c'est la seule solution efficace que j'ai trouvée.

Remarque: il semble que l'extension s'exécute en arrière-plan et ajoute une icône de la barre d'état Chrome. L'option suivante est cochée: "Laisser Chrome s'exécuter en arrière-plan" (ou texte similaire). Vous devrez peut-être jouer avec, jusqu'à ce que cela fonctionne pour vous. Je l'ai décoché et maintenant cela fonctionne très bien!

Ministre
la source
9

Même si vous pensez que c'est «manifestement faux», ce que vous dites «semble être une croyance» est en fait correct. La documentation Mozilla pour window.close dit

Cette méthode ne peut être appelée que pour les fenêtres ouvertes par un script à l'aide de la méthode window.open. Si la fenêtre n'a pas été ouverte par un script, l'erreur suivante apparaît dans la console JavaScript: Les scripts peuvent ne pas fermer les fenêtres qui n'ont pas été ouvertes par script

Vous dites qu'il est "censé le faire encore" mais je ne pense pas que vous trouverez une référence qui soutienne cela, peut-être que vous vous êtes mal souvenu de quelque chose?

Gareth
la source
9

J'ai trouvé une nouvelle façon qui fonctionne parfaitement pour moi

var win = window.open("about:blank", "_self");
win.close();
Gerardo Abdo
la source
1
Nous sommes en 2017 et j'obtiens toujours l'erreur "Les scripts peuvent ne pas fermer les fenêtres qui n'ont pas été ouvertes par script."
Rotimi
Bon hack pour le bouton de confirmation d'IE 11.
Gopal00005
Fonctionne sur Chrome et Firefox
Vineeth Pradhan
1
Ce trou semble avoir été rempli. Je ne sais pas quand mais j'utilise la dernière version de développement 84.x. La page vierge se charge mais la fermeture ne se déclenche pas.
Scott Christensen le
4

Le code ci-dessous a fonctionné pour moi -

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

Testé sur Chrome 43.0.2357.81

DfrDkn
la source
Pouvez-vous ajouter votre version de Chrome s'il vous plaît?
Stephan
Ma version chrome est 43.0.2357.81.
DfrDkn
7
Pour moi, cela remplace simplement la fenêtre actuelle, par une fenêtre à / location.
alianos-
@ alianos- pour moi aussi.
RicardoGonzales
1
Ne fonctionne pas dans le dernier chrome - Version 61.0.3163.100 (version officielle) (64 bits)
Subhajit
1

Cela peut être vieux, mais répondons-y.

J'utilise top.close () pour fermer un onglet. window.close () ou autre open ... close n'a pas fonctionné pour moi.

Soley
la source
11
Cela souffre également du "Scripts may not close windows that were not opened by script."problème mentionné dans d'autres réponses.
kad81
1
veuillez donner une solution à votre réponse. Veuillez ne pas discuter du problème uniquement sur votre réponse.
Bimal Das
0

Dans mon cas, la page devait se fermer, mais peut avoir été ouverte par un lien et window.closeéchouerait donc.

La solution que j'ai choisie est d'émettre le window.close, suivi d'un window.setTimeoutqui redirige vers une autre page.

De cette façon, si elle window.closeréussit, l'exécution sur cette page s'arrête, mais si elle échoue, dans une seconde, elle sera redirigée vers une autre page.

window.close();
window.setTimeout(function(){location.href = '/some-page.php';},1000);
user2182349
la source
0

Cette réponse de Brock a fonctionné pour moi. javascript ne doit pas être autorisé à fermer une fenêtre qui n'a pas été ouverte par ce même javascript.

Je ne peux fermer la fenêtre enfant que si je la ferme à partir du javascript parent. donc chez mes parents je peux faire quelque chose comme ça.

var myChildWindow;

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

function closeWindow() {
myChildWindow.close();
}
Crismogramme
la source
-1

Vous pouvez également essayer d'utiliser mon code ci-dessous. Cela vous aidera également à rediriger votre fenêtre parent:

Parent:

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

Apparaitre:

<!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
la source
-2

Ce n'est que si vous ouvrez une nouvelle fenêtre en utilisant window.open () que la nouvelle fenêtre pourra se fermer en utilisant le code comme je l'ai mentionné ci-dessus. Cela fonctionne parfaitement pour moi :) Remarque: n'utilisez jamais href pour ouvrir la page dans un nouvel onglet. Window.close () ne fonctionne pas avec "href". Utilisez plutôt window.open ().

DfrDkn
la source
1
Il ne fait que remplacer la fenêtre actuelle. Pas plus.
RicardoGonzales
-3

Je voulais partager ma «solution» avec ce problème. Il semble que la plupart d'entre nous essayent de fermer une fenêtre de navigateur dans une session de navigateur standard, où un utilisateur visite un site Web ou un autre, après avoir visité d'autres sites Web et avant d'en visiter d'autres.

Cependant, ma situation est que je crée une application Web pour un appareil qui sera essentiellement la seule chose que l'appareil fera. Vous le démarrez, il lance Chrome et accède à notre application. Il n'est même pas connecté à Internet, tous les serveurs auxquels il parle se trouvent sur nos conteneurs Docker locaux. L'utilisateur a besoin d'un moyen de fermer l'application (c'est-à-dire de fermer Chrome) afin de pouvoir accéder au terminal pour effectuer des mises à jour du système.

Alors il démarre, lance Chrome en mode kiosque, déjà à la bonne adresse. Cela se produit pour satisfaire facilement la deuxième option de la spécification:

Un contexte de navigation peut être fermé par script s'il s'agit d'un contexte de navigation auxiliaire créé par un script (par opposition à une action de l'utilisateur), ou s'il s'agit d'un contexte de navigation de niveau supérieur dont l'historique de session ne contient qu'un seul document.

Donc, simplement appeler window.close()depuis mon application de kiosque fonctionne !

Jonathan Tuzman
la source
-5

Essayez quelque chose comme ceci onclick = "return self.close ()"

Ragven
la source