2017-06-06 74 views
25

Wraz z wersją Chrome 59 tryb "bez głowy" to now available w stabilnych kompilacjach dla systemów Linux i macOS (a wkrótce także Windows z Chrome 60). Dzięki temu możemy uruchomić w pełni funkcjonalną wersję przeglądarki Chrome bez widocznego interfejsu użytkownika, co daje ogromne możliwości testowania automatycznego. Here are examples.Wykrywanie Chrome działającego w trybie bezotwartym z JavaScript

chrome --headless --disable-gpu --dump-dom https://stackoverflow.com/ 

W moim testowym JavaScript biegacza, chciałbym nagrać jak najwięcej informacji na temat możliwości używanego przez przeglądarkę, aby ułatwić określenie problemów. Na przykład, mogę nagrywać wiele właściwości navigator, w tym aktualnych wtyczek przeglądarek:

JSON.stringify(Array.from(navigator.plugins).map(p => p.name)) 
["Chrome PDF Viewer","Widevine Content Decryption Module","Shockwave Flash","Native Client","Chrome PDF Viewer"] 

moim rozumieniu jest to, że Chrome powinny zachowują się identycznie w trybie bez głowy, ale mam wystarczająco dużo doświadczenia, aby być sceptyczny nowej funkcji, która może znacząco zmienić potok renderowania.

Na razie mam zamiar uruchomić testy w obu trybach. Chciałbym, aby biegacz testowy zarejestrował, czy używany jest tryb bezgłowy. Mogłabym przekazać te informacje w konfiguracjach testowych, ale wolałbym mieć czyste rozwiązanie JavaScript, które mógłbym wbudować w sam test. Jednak nie udało mi się znaleźć żadnego interfejsu przeglądarki, który ujawniłby, czy tryb bezgłowy jest aktywny.

Czy istnieje sposób sprawdzenia, czy Chrome działa w trybie bezgłowym z JavaScript?

Odpowiedz

16

Środek użytkownik ciąg includes HeadlessChrome instead of Chrome.Prawdopodobnie jest to sygnał, że jesteś przeznaczony do poszukiwania, więc można użyć:

/\bHeadlessChrome\//.test(navigator.userAgent) 

Inne interesujące sygnały to:

  • Wygląda window.chrome jest nieokreślone gdy bezgłowy.
  • [innerWidth, innerHeight] to [800, 600] (na stałe w headless_browser.cc), natomiast [outerWidth, outerHeight] to [0, 0] (co zwykle nie powinno się zdarzyć).
+1

[Potwierdzam, że' window.chrome === undefined' wydaje się działać] (https://i.stack.imgur.com/68yHd.png). –

+0

Przeszukałem bezgłowy kod przeglądarki Chrome, ale w jakiś sposób opuściłem [definicję tego agenta użytkownika blisko samej góry] (https://chromium.googlesource.com/chromium/src.git/+/lkgr/headless/public/ headless_browser.cC# 19). Dziękuję za wskazanie. Pozwolę, aby nagroda przebiegła, na wypadek, gdyby było coś jeszcze bardziej wyraźnego, ale prawdopodobnie to rozwiązanie przyjdzie mi z pomocą. –

3

navigator.plugins powinien zawierać tablicę wtyczek obecnych w przeglądarce (np. Flash, ActiveX lub aplety Java). Dla przeglądarki headless będzie ona null.

W ramach zabezpieczenia sprawdzić może on być stosowany alert dla headless to będzie ignorowane:

var start = Date.now(); 
alert('Press OK'); 
var elapse = Date.now() - start; 
if (elapse < 15) { 
    console.log("headless environment detected"); 
} 

kilku technik do wykrywania bezgłowe przeglądarek są omówione w OWASP AppSecUSA 2014 Dyskusja Headless Browser Ukryj & Poszukać (video, slides) przez Sergey Shekyan i Bei Zhang.

+0

Potwierdzam, że widzę 'navigator.plugins.length === 0' w bezgłowym Chrome. Polecenie testowe: 'chrome --headless --disable-gpu --dump-dom 'data: text/html, '' –

1

Najlepsze do tej pory rozwiązanie to ten hack. Nie użyłbym go w prod code, ale mógłbym w testowaniu.

Blokowanie wyskakujących okienek Chrome jest zwykle włączone dla wszystkich witryn internetowych, ale jest wyłączone w trybie bezgłowym. Możemy korzystać z możliwości otwierania okienek wyskakujących jako dość dokładnego proxy dla trybu bezgłowego. Wdrożenie jest proste: spróbuj otworzyć okno i sprawdź, czy otrzymujemy null (wskazując, że został on zablokowany) zamiast obiektu Window. Jeśli otworzymy jeden, zamknij go tak szybko, jak to możliwe.

function canPopUp() { 
    var w = open(""); 
    if (w !== null) { 
    w.close(); 
    return true; 
    } else { 
    return false; 
    } 
} 

var isHeadless = canPopUp; 

Na szybki przykład, można spróbować następujących zi bez flagi --headless:

chrome --headless --disable-gpu --dump-dom 'data:text/html,<!doctype html><body><script>document.body.innerHTML = `headless: ${open("") !== null}`;</script>'

+0

Prawdopodobnie powiązane: https://crbug.com/696439 –

1

Wystarczy przeczytać this article by Antoine Vastel który zapewnia kilka sposobów:

  • testowania agenta użytkownika z /HeadlessChrome/.test(window.navigator.userAgent), ale to łatwo sfałszowane
  • testowania wtyczek z navigator.plugins.length == 0
  • testowania języków z navigator.languages == ""
  • testów Dostawca WebGL i informacje o rendererach (zobacz artykuł po interesujących szczegółach)
  • testowanie obsługiwanych funkcji wykrytych przez Modernizr: wydaje się, że "hairlines" nie są obsługiwane (hairlines/retina hairlines, które są granicami CSS o szerokości mniejszej niż 1px, ponieważ fizycznie są 1px na ekranach hidpi). Test to !Modernizr["hairline"].
  • testowy rozmiar zastępczy dla brakującego obrazu. Wstaw obraz o nieprawidłowym adresie URL i przetestuj go pod kątem image.width == 0 && image.height == 0 pod numerem image.onerror (uznali go za najbardziej niezawodny).

nie można mówić o motywacji Google (jest Headless Chrome tylko o ułatwienie testów aplikacji internetowych? Hmmm ...), ale może to być postrzegane jako lista błędów, które mogą dostać stałych kiedyś tak trzeba się zastanawiać, jak długo te testy będą działać :)

+0

Właśnie zauważyłem po opublikowaniu tego, że Josh Lee wspomniał o tym w komentarzu pod wczorajszym pytaniem. Przeczytałem ten sam artykuł i zapamiętałem to pytanie z zeszłego miesiąca ... Mam nadzieję, że pogodzę właściwą równowagę między reklamą dla oryginalnego autora i nie będę plagiatować. Jeśli to za dużo, będę mógł edytować, usuwać itp. (Dziękuje Jeremy za wydanie) –