habilitar - instalar javascript
Detecta Chrome en modo sin cabeza desde JavaScript (5)
La cadena de
agente de usuario
incluye
HeadlessChrome
lugar de
Chrome
.
Esta es probablemente la señal que debe buscar, por lo que podría usar:
//bHeadlessChrome///.test(navigator.userAgent)
Otras señales interesantes incluyen:
-
Parece que
window.chrome
no está definido cuando no tiene cabeza. -
[innerWidth, innerHeight]
es[800, 600]
(codificado enheadless_browser.cc
), mientras que[outerWidth, outerHeight]
es[0, 0]
(lo que no suele suceder).
Con el lanzamiento de Chrome 59, el modo "sin cabeza" ahora está disponible en versiones estables para Linux y macOS (y pronto también Windows con Chrome 60). Esto nos permite ejecutar una versión completa de Chrome sin ninguna interfaz de usuario visible, una gran capacidad para realizar pruebas automáticas. Aquí hay ejemplos.
chrome --headless --disable-gpu --dump-dom https://stackoverflow.com/
En mi corredor de prueba de JavaScript, me gusta registrar la mayor cantidad de información posible sobre el navegador que se utiliza, para ayudar a aislar los problemas.
Por ejemplo, registro muchas de las propiedades del
navigator
, incluidos los complementos actuales del navegador:
JSON.stringify(Array.from(navigator.plugins).map(p => p.name))
["Chrome PDF Viewer","Widevine Content Decryption Module","Shockwave Flash","Native Client","Chrome PDF Viewer"]
Tengo entendido que Chrome debería comportarse de manera idéntica en modo sin cabeza, pero tengo suficiente experiencia para ser escéptico de una nueva característica que puede cambiar significativamente la canalización de renderizado.
Por ahora, voy a ejecutar pruebas en ambos modos. Me gustaría que el corredor de prueba registre si se está utilizando el modo sin cabeza. Podría pasar esta información en las configuraciones de prueba, pero prefiero tener una solución de JavaScript pura que pueda incorporar al propio corredor de prueba. Sin embargo, no he podido encontrar ninguna interfaz de navegador que revele si el modo sin cabeza está activo.
¿Hay alguna forma de detectar si Chrome se está ejecutando en modo sin cabeza desde JavaScript?
La mejor solución que tengo hasta ahora es este truco. No lo usaría en código prod, pero podría hacerlo en pruebas.
El bloqueador de ventanas emergentes de Chrome generalmente está habilitado para todos los sitios web, pero está deshabilitado en modo sin cabeza.
Podemos usar la capacidad de abrir ventanas emergentes como un proxy bastante preciso para estar en modo sin cabeza.
La implementación es simple: intente
open(...)
una ventana y verifique si obtenemos
null
(lo que indica que estaba bloqueado) en lugar de un objeto
Window
.
Si abrimos uno, ciérrelo lo más rápido posible.
function canPopUp() {
var w = open("");
if (w !== null) {
w.close();
return true;
} else {
return false;
}
}
var isHeadless = canPopUp;
Para un ejemplo rápido, puede intentar lo siguiente con y sin el indicador
--headless
:
chrome --headless --disable-gpu --dump-dom ''data:text/html,<!doctype html><body><script>document.body.innerHTML = `headless: ${open("") !== null}`;</script>''
Puede verificar la propiedad
navigator.webdriver
que es:
La propiedad de solo lectura
webdriver
de la interfaz delnavigator
indica si el agente de usuario está controlado por automatización....
La propiedad
navigator.webdriver
es verdadera cuando en:Chrome Se
--headless
la--headless
--enable-automation
o--headless
.
Firefox Se--marionette
preferenciamarionette.enabled
o--marionette
flag.
La Recomendación del W3C WebDriver lo describe de la siguiente manera:
navigator.webdriver
Define una forma estándar para que los agentes de usuario que cooperan informen al documento de que está controlado por WebDriver, por ejemplo, para que se puedan activar rutas de código alternativas durante la automatización.
Simplemente lea este artículo de Antoine Vastel que proporciona algunas maneras:
-
prueba de agente de usuario con
/HeadlessChrome/.test(window.navigator.userAgent)
, pero esto se puede suplantar fácilmente -
prueba de complementos con
navigator.plugins.length == 0
-
prueba de idiomas con
navigator.languages == ""
- prueba de la información del proveedor y del procesador de WebGL (consulte el artículo para obtener detalles interesantes)
-
prueba de las funciones admitidas detectadas por Modernizr: parece que las "líneas aéreas" no son compatibles (líneas aéreas hidpi / retina, que son bordes CSS con menos de 1 px de ancho, por ser físicamente 1 px en las pantallas hidpi).
La prueba es
!Modernizr["hairline"]
. -
tamaño de prueba del marcador de posición para la imagen que falta.
Inserte una imagen con una URL no válida y pruebe
image.width == 0 && image.height == 0
enimage.onerror
(encontraron que esta es la más robusta).
No puedo hablar por las motivaciones de Google ( ¿Headless Chrome solo trata de facilitar las pruebas de las aplicaciones web? Hmmm ... ), pero esto podría verse como una lista de errores que podrían solucionarse algún día, por lo que uno tiene que preguntarse por cuánto tiempo las pruebas funcionarán :)
navigator.plugins
debe contener una variedad de complementos presentes en el navegador (como los applets de Flash, ActiveX o Java).
Para el navegador
headless
será anulable.
Como parte del control de seguridad, se puede usar
alert
, para los sin cabeza se ignorará:
var start = Date.now();
alert(''Press OK'');
var elapse = Date.now() - start;
if (elapse < 15) {
console.log("headless environment detected");
}
Sergey Shekyan y Bei Zhang discuten varias técnicas para detectar navegadores sin cabeza en la charla OWASP AppSecUSA 2014 Headless Browser Hide & Seek ( video , slides ).