Découvrez si la console Chrome est ouverte


143

J'utilise ce petit script pour savoir si Firebug est ouvert:

if (window.console && window.console.firebug) {
    //is open
};

Et ça marche bien. Maintenant, je cherchais une demi-heure pour trouver un moyen de détecter si la console de développement Web intégrée à Google Chrome était ouverte, mais je n'ai trouvé aucun indice.

Ce:

if (window.console && window.console.chrome) {
    //is open
};

ne fonctionne pas.

ÉDITER:

Il semble donc qu'il n'est pas possible de détecter si la console Chrome est ouverte. Mais il y a un " hack " qui fonctionne, avec quelques inconvénients:

  • ne fonctionnera pas lorsque la console est désancrée
  • ne fonctionnera pas lorsque la console est ouverte lors du chargement de la page

Donc, je vais choisir la réponse de Unsigned pour le moment, mais si quelqu'un a une idée géniale, il est le bienvenu pour toujours répondre et je change la réponse choisie! Merci!



La solution dans la réponse semble fonctionner, mais uniquement si la console est ancrée. De plus, cela ne fonctionne pas si la console est déjà ouverte au chargement de la page, alors que le script Firebug n'a pas ces problèmes et semble toujours fonctionner. Mais je peux vivre avec ça pour le moment! Merci beaucoup @pimvdb !! Je vais quand même garder la question ouverte pour peut-être trouver un moyen similaire au script Firebug, qui fonctionne toujours.
r0skar

J'ai essayé des choses comme lancer une erreur et voir si elle .messageest récupérée (ce qui se produit lorsque le débogueur est ouvert parce que vous voyez le message), mais malheureusement, cela se produit également lorsque le débogueur n'est pas ouvert. Je voudrais connaître un hack pour cela s'il existe ...
pimvdb

4
@Spudley Ce n'est pas pertinent pour la question de savoir pourquoi j'en ai besoin et je ne veux pas commencer à expliquer. Je sais qu'il n'y a aucun moyen d'empêcher some1 de déboguer, mais ce n'est pas ce que j'essaie de faire. J'essaie juste de trouver un moyen de savoir si la console est ouverte ou non. C'est tout :)
r0skar

1
La méthode JFYI console.profiles a été récemment supprimée de l'API de la console src.chromium.org/viewvc/blink?view=revision&revision=151136
loislo

Réponses:


98

requestAnimationFrame (fin 2019)

Laissant ces réponses précédentes ici pour le contexte historique. Actuellement, l'approche de Muhammad Umer fonctionne sur Chrome 78, avec l'avantage supplémentaire de détecter les événements fermés et ouverts.

fonction toString (2019)

Crédit au commentaire d' Overcl9ck sur cette réponse. Le remplacement de l'expression régulière /./par un objet de fonction vide fonctionne toujours.

var devtools = function() {};
devtools.toString = function() {
  if (!this.opened) {
    alert("Opened");
  }
  this.opened = true;
}

console.log('%c', devtools);
// devtools.opened will become true if/when the console is opened

regex toString (2017-2018)

Étant donné que le demandeur d'origine ne semble plus être là et que c'est toujours la réponse acceptée, l'ajout de cette solution pour la visibilité. Le crédit va à Antonin Hildebrand est un commentaire sur zswang 's réponse . Cette solution tire parti du fait qu'elle toString()n'est appelée sur les objets journalisés que si la console est ouverte.

var devtools = /./;
devtools.toString = function() {
  if (!this.opened) {
    alert("Opened");
  }
  this.opened = true;
}

console.log('%c', devtools);
// devtools.opened will become true if/when the console is opened

console.profiles (2013)

Mise à jour: console.profiles a été supprimé de Chrome. Cette solution ne fonctionne plus.

Merci à Paul Irish d' avoir souligné cette solution de Discover DevTools , en utilisant le profileur:

function isInspectOpen() {
  console.profile();
  console.profileEnd();
  if (console.clear) {
    console.clear();
  }
  return console.profiles.length > 0;
}
function showIfInspectIsOpen() {
  alert(isInspectOpen());
}
<button onClick="showIfInspectIsOpen()">Is it open?</button>

window.innerHeight (2011)

Cette autre option peut détecter l' ouverture de l' inspecteur ancré , après le chargement de la page, mais ne pourra pas détecter un inspecteur non ancré, ou si l'inspecteur était déjà ouvert lors du chargement de la page. Il existe également un potentiel de faux positifs.

window.onresize = function() {
  if ((window.outerHeight - window.innerHeight) > 100) {
    alert('Docked inspector was opened');
  }
}


1
Obtenir TypeError: Impossible de lire la propriété 'length' de undefined dans isInspectOpen ()
sandeep

2
Il y a un nouveau meilleur moyen (crédits: @zswang): stackoverflow.com/questions/7798748/…
Vicky Chijwani

3
la solution de 'toString (2017)' ne fonctionne pas dans le chrome
Richard Chan

2
toString semble avoir été corrigé dans chrome. Éditer. En fait, cela fonctionne si vous utilisez une function() {}expression
régulière

1
@ Overcl9ck votre solution fonctionnait jusqu'à la dernière mise à jour de Chrome 77. Pouvez-vous nous indiquer la bonne direction pour une solution de contournement?
Agustin Haller

118

Chrome 65+ (2018)

r = /./
r.toString = function () {
    document.title = '1'
}
console.log('%c', r);

démo: https://jsbin.com/cecuzeb/edit?output (mise à jour le 16/03/2018)

paquet: https://github.com/zswang/jdetects


Lors de l'impression de "Element", les outils de développement Chrome obtiendront son identifiant

var checkStatus;

var element = document.createElement('any');
element.__defineGetter__('id', function() {
    checkStatus = 'on';
});

setInterval(function() {
    checkStatus = 'off';
    console.log(element);
    console.clear();
}, 1000);

Une autre version (à partir des commentaires)

var element = new Image();
Object.defineProperty(element, 'id', {
  get: function () {
    /* TODO */
    alert('囧');
  }
});
console.log('%cHello', element);

Imprimer une variable régulière :

var r = /./;
r.toString = function() {
  document.title = 'on';
};
console.log(r);

3
Très bonne réponse. Une chose à ajouter ... MDN dit __defineGetter__est obsolète, donc j'ai changé pour Object.defineProperty(element, 'id', {get:function() {checkStatus='on';}});... toujours travailler.
denikov

5
De plus, la console `` lira '' l'élément dès que la console s'ouvre, vous pouvez donc imprimer une seule fois et attendre que la fonction dans le getter s'exécute au lieu de définir unsetInterval
xpy

8
Sur la base de cette découverte, j'ai pu trouver une méthode moins intrusive. DevTools appelle toString () sur les fonctions lors de leur impression sur la console. Ainsi, on peut imprimer un objet fonction personnalisé avec la méthode toString () override retournant une chaîne vide. De plus, vous pouvez utiliser la chaîne de formatage de la console% c et définir la couleur: transparent pour vous assurer que le texte potentiellement imprimé s'imprime comme invisible. J'ai utilisé cette technique ici: github.com/binaryage/cljs-devtools/blob/…
Antonin Hildebrand

3
Année 2017 ici. Chrome écrit toujours des éléments sur la console sans que vous l'ouvriez. Et votre hack ne fonctionne plus.
vothaison le

2
Testé sur Firefox ne fonctionne pas avec Inspection Element (Q) et Inspect Element avec Firebug
Asif Ashraf

28

Hack très fiable

En gros, définissez un getter sur la propriété et connectez-le dans la console. Apparemment, la chose n'est accessible que lorsque la console est ouverte.

https://jsfiddle.net/gcdfs3oo/44/

var checkStatus;

var element = new Image();
Object.defineProperty(element, 'id', {
  get: function() {
    checkStatus='on';
    throw new Error("Dev tools checker");
  }
});

requestAnimationFrame(function check() {
  checkStatus = 'off';
  console.dir(element);
  document.querySelector('#devtool-status').className  = checkStatus;
  requestAnimationFrame(check);
});
.on{
  color:limegreen;
}

.off{
  color:red;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.7.1/css/all.css" integrity="sha256-DVK12s61Wqwmj3XI0zZ9MFFmnNH8puF/eRHTB4ftKwk=" crossorigin="anonymous" />

<p>
  <ul>
    <li>
      dev toolbar open: icon is <span class="on">green</span>
    </li>
    <li>
      dev toolbar closed: icon is <span class="off">red</span>
    </li>
  </ul>
</p>
<div id="devtool-status"><i class="fas fa-7x fa-power-off"></i></div>
<br/>
<p><b>Now press F12 to see if this works for your browser!</b></p>


Chrome version 79 ✅
Legends

4
A quoi ça throw new Error("Dev tools checker");sert? Parce que ça marche sans ça.
Legends

cela semble spammer la console (lorsqu'elle est ouverte)? qui, je suppose, commencera à manger une quantité importante de mémoire après quelques jours :)
pythonator

Le seul moyen qui fonctionne à partir de 2020.7
laike9m

24

J'ai créé devtools-detect qui détecte quand DevTools est ouvert:

console.log('is DevTools open?', window.devtools.open);

Vous pouvez également écouter un événement:

window.addEventListener('devtoolschange', function (e) {
    console.log('is DevTools open?', e.detail.open);
});

Cela ne fonctionne pas lorsque DevTools est désancré. Cependant, fonctionne avec Chrome / Safari / Firefox DevTools et Firebug.


@barbushin Je pense que votre devtool ouvert est ancré, il ne peut pas détecter une fenêtre séparée.
Mithril

Malheureusement, il a cessé de fonctionner pour Chrome github.com/sindresorhus/devtools-detect/issues/40
laike9m le

15

J'ai trouvé un moyen de savoir si la console Chrome est ouverte ou non. C'est toujours un hack, mais c'est beaucoup plus précis et fonctionnera si la console n'est pas ancrée ou non.

Fondamentalement, exécuter ce code avec la console fermée prend environ 100 microsecondes et pendant que la console est ouverte, cela prend environ deux fois plus d'environ 200 microsecondes.

console.log(1);
console.clear();

(1 milliseconde = 1000 microseconde)

J'en ai écrit plus ici .

La démo est .


Mettre à jour:

@zswang a trouvé la meilleure solution actuelle - découvrez sa réponse


1
C'est une très mauvaise solution. Google it -> "Race Hazard". Ordinateur plus lent ou plus rapide et ...?
18C

1
"Race Hazard" n'est pas lié ici. Il y a toujours une relative lenteur à l'ouverture de la console.
guya

1
Lenteur relative mais pas toujours 100 ou 200ms. Ainsi Race Hazard. Btw. Si vous jouez à un jeu en même temps, cette «solution» renverra un faux résultat positif.
18C

8

Si votre objectif est de brouiller les outils de développement, essayez ceci (j'en ai trouvé une version plus compliquée à un endroit où le code JS était obscurci, c'est très ennuyeux):

setTimeout(function() {while (true) {eval("debugger");}}, 0);

L'utilisateur peut, dans Chrome, désactiver l'écoute du débogueur.
Jack Giffin

3

Il existe un moyen délicat de vérifier les extensions avec l'autorisation `` onglets '':

chrome.tabs.query({url:'chrome-devtools://*/*'}, function(tabs){
    if (tabs.length > 0){
        //devtools is open
    }
});

Vous pouvez également vérifier s'il est ouvert pour votre page:

chrome.tabs.query({
    url: 'chrome-devtools://*/*',
    title: '*example.com/your/page*'
}, function(tabs){ ... })

3

J'ai écrit un article de blog à ce sujet: http://nepjua.org/check-if-browser-console-is-open/

Il peut détecter s'il est ancré ou non

function isConsoleOpen() {  
  var startTime = new Date();
  debugger;
  var endTime = new Date();

  return endTime - startTime > 100;
}

$(function() {
  $(window).resize(function() {
    if(isConsoleOpen()) {
        alert("You're one sneaky dude, aren't you ?")
    }
  });
});

3
C'est bien, mais la page sera périmée et aucun message ne sera affiché tant que l'utilisateur n'aura pas cliqué sur le bouton de reprise. Ce sera très intrusif pour l'utilisateur.
guya

2
Prochaine solution «Race Hazard». Très mal. BTW. La commande "debugger" peut être désactivée.
18C

3
var div = document.createElement('div');
Object.defineProperty(div,'id',{get:function(){
    document.title = 'xxxxxx'
}});

setTimeout(()=>console.log(div),3000)

Ça n'a pas marché. Et le lien vers test onlinen'a pas fonctionné.
Samuel

2

Les outils de développement Chrome ne sont en réalité qu'une partie de la bibliothèque WebCore de WebKit. Cette question s'applique donc à Safari, Chrome et à tout autre consommateur WebCore.

Si une solution existe, elle sera basée sur une différence dans le DOM lorsque l'inspecteur Web WebKit est ouvert et lorsqu'il est fermé. Malheureusement, c'est une sorte de problème de poule et d'œuf car nous ne pouvons pas utiliser l'inspecteur pour observer le DOM lorsque l'inspecteur est fermé.

Ce que vous pouvez faire est d'écrire un peu de JavaScript pour vider toute l'arborescence DOM. Exécutez-le ensuite une fois lorsque l'inspecteur est ouvert et une fois lorsque l'inspecteur est fermé. Toute différence dans le DOM est probablement un effet secondaire de l'inspecteur Web, et nous pourrons peut-être l'utiliser pour tester si l'utilisateur inspecte ou non.

Ce lien est un bon début pour un script de vidage DOM, mais vous voudrez vider l' DOMWindowobjet entier , pas seulement document.

Mettre à jour:

On dirait qu'il existe un moyen de le faire maintenant. Découvrez Chrome Inspector Detector


Chrome Inspector Detector ne fonctionne plus pour Google Chrome comme mentionné par le développeur
Angelo

1

Vous pouvez également essayer ceci: https://github.com/sindresorhus/devtools-detect

// check if it's open
console.log('is DevTools open?', window.devtools.open);
// check it's orientation, null if not open
console.log('and DevTools orientation?', window.devtools.orientation);

// get notified when it's opened/closed or orientation changes
window.addEventListener('devtoolschange', function (e) {
    console.log('is DevTools open?', e.detail.open);
    console.log('and DevTools orientation?', e.detail.orientation);
});

1
Cela ne fonctionne pas bien. Si un utilisateur utilise un appareil mobile, il tourne son appareil à 90 degrés, l'écran se redimensionnera.
Jack Giffin

fonctionne sur chrome et ff pas ie ou edge à partir du 05/04/2019
SolidSnake

1

L'approche de Muhammad Umer a fonctionné pour moi, et j'utilise React, j'ai donc décidé de créer une solution de hooks:

const useConsoleOpen = () => {
  const [consoleOpen, setConsoleOpen] = useState(true)

  useEffect(() => {
    var checkStatus;

    var element = new Image();
    Object.defineProperty(element, "id", {
      get: function () {
        checkStatus = true;
        throw new Error("Dev tools checker");
      },
    });

    requestAnimationFrame(function check() {
      checkStatus = false;
      console.dir(element); //Don't delete this line!
      setConsoleOpen(checkStatus)
      requestAnimationFrame(check);
    });
  }, []);

  return consoleOpen
}

REMARQUE: quand je l'ai joué, cela n'a pas fonctionné pendant très longtemps et je ne pouvais pas comprendre pourquoi. J'avais suppriméconsole.dir(element); ce qui est essentiel à son fonctionnement. Je supprime la plupart des actions de console non descriptives car elles prennent juste de l'espace et ne sont généralement pas nécessaires à la fonction, c'est pourquoi cela ne fonctionnait pas pour moi.

Pour l'utiliser:

import React from 'react'

const App = () => {
  const consoleOpen = useConsoleOpen()

  return (
    <div className="App">
      <h1>{"Console is " + (consoleOpen ? "Open" : "Closed")}</h1>
    </div>
  );
}

J'espère que cela aidera quiconque utilise React. Si quelqu'un veut développer cela, j'aimerais pouvoir arrêter la boucle infinie à un moment donné (puisque je ne l'utilise pas dans chaque composant) et trouver un moyen de garder la console propre.


0

Si vous êtes des développeurs qui font des choses pendant le développement. Découvrez cette extension Chrome. Il vous aide à détecter quand Chrome Devtoos est ouvert ou fermé.

https://chrome.google.com/webstore/detail/devtools-status-detector/pmbbjdhohceladenbdjjoejcanjijoaa?authuser=1

Cette extension aide les développeurs Javascript à détecter quand Chrome Devtools est ouvert ou fermé sur la page en cours. Lorsque Chrome Devtools se ferme / s'ouvre, l'extension déclenche un événement nommé 'devtoolsStatusChanged' sur l'élément window.document.

Voici un exemple de code:

 function addEventListener(el, eventName, handler) {
    if (el.addEventListener) {
        el.addEventListener(eventName, handler);
    } else {
        el.attachEvent('on' + eventName,
            function() {
                handler.call(el);
            });
    }
}


// Add an event listener.
addEventListener(document, 'devtoolsStatusChanged', function(e) {
    if (e.detail === 'OPENED') {
        // Your code when Devtools opens
    } else {
        // Your code when Devtools Closed
    }
});

0

Certaines réponses ici cesseront de fonctionner dans Chrome 65. Voici une alternative d'attaque temporelle qui fonctionne de manière assez fiable dans Chrome et qui est beaucoup plus difficile à atténuer que la toString()méthode. Malheureusement, ce n'est pas si fiable dans Firefox.

addEventListener("load", () => {

var baseline_measurements = [];
var measurements = 20;
var warmup_runs = 3;

const status = document.documentElement.appendChild(document.createTextNode("DevTools are closed"));
const junk = document.documentElement.insertBefore(document.createElement("div"), document.body);
junk.style.display = "none";
const junk_filler = new Array(1000).join("junk");
const fill_junk = () => {
  var i = 10000;
  while (i--) {
    junk.appendChild(document.createTextNode(junk_filler));
  }
};
const measure = () => {
    if (measurements) {
    const baseline_start = performance.now();
    fill_junk();
    baseline_measurements.push(performance.now() - baseline_start);
    junk.textContent = "";
    measurements--;
    setTimeout(measure, 0);
  } else {
    baseline_measurements = baseline_measurements.slice(warmup_runs); // exclude unoptimized runs
    const baseline = baseline_measurements.reduce((sum, el) => sum + el, 0) / baseline_measurements.length;

    setInterval(() => {
      const start = performance.now();
      fill_junk();
      const time = performance.now() - start;
      // in actual usage you would also check document.hasFocus()
      // as background tabs are throttled and get false positives
      status.data = "DevTools are " + (time > 1.77 * baseline ? "open" : "closed");
      junk.textContent = "";
    }, 1000);
  }
};

setTimeout(measure, 300);

});

0

Quant à Chrome / 77.0.3865.75, une version de 2019 ne fonctionne pas. toString invoque immédiatement sans l'ouverture de l'inspecteur.

const resultEl = document.getElementById('result')
const detector = function () {}

detector.toString = function () {
	resultEl.innerText = 'Triggered'
}

console.log('%c', detector)
<div id="result">Not detected</div>

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.