2017-06-06 161 views
25

隨着Chrome 59的發佈,「無頭」模式爲now available穩定版Linux和macOS(以及即將推出的Windows與Chrome 60)。這使我們能夠運行功能齊全的Chrome版本,而不需要任何可見的用戶界面,這是一種用於自動化測試的強大功能。 Here are examples.檢測Chrome以JavaScript運行在無頭模式下

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

在我的JavaScript測試跑步,我喜歡使用的瀏覽器來記錄儘可能多的信息越好,以幫助隔離問題。例如,我記錄了許多navigator的屬性,包括當前的瀏覽器插件:

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

我的理解是,Chrome的應該行爲相同的無頭模式,但我有足夠的經驗,懷疑可能會顯着改變渲染流水線的新特性。

現在,我要在兩種模式下運行測試。我希望測試運行人員記錄是否正在使用無頭模式。我可以在測試配置中傳遞這些信息,但我寧願有一個純粹的JavaScript解決方案,我可以將其構建到測試運行器本身中。但是,我一直無法找到任何揭示無頭模式是否激活的瀏覽器界面。

有沒有什麼方法可以檢測Chrome是否在JavaScript的無頭模式下運行?

回答

16

用戶代理字符串includes HeadlessChrome instead of Chrome。這可能是你要去找信號,因此您可以使用:

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

其他有趣的信號包括:

  • 看起來window.chrome是不確定的,當無頭。
  • [innerWidth, innerHeight][800, 600](硬編碼在headless_browser.cc),而[outerWidth, outerHeight][0, 0](通常不應該發生)。
+1

[我確認'window.chrome === undefined'似乎工作](https://i.stack.imgur.com/68yHd.png )。 –

+0

我已經瀏覽了無代碼的Chrome代碼,但不知何故錯過了[該用戶代理的最高定義](https://chromium.googlesource.com/chromium/src.git/+/lkgr/headless/public/ headless_browser.cc#19)。感謝您指出。如果有更明確的東西,我會讓賞金流通,但這可能是我將要解決的問題。 –

3

navigator.plugins應包含瀏覽器中存在的插件數組(如Flash,ActiveX或Java小程序)。對於headless瀏覽器,它將爲空。

作爲安全的一部分,檢查它可以用來alert,無頭將被忽略:

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

一些技術用於檢測無頭的瀏覽器在OWASP AppSecUSA 2014通話模擬瀏覽器隱藏&討論通過Sergey Shekyan和Bei Zhang尋找video,slides)。

+0

我確認我在無頭Chrome瀏覽器中看到了'navigator.plugins.length === 0'。測試命令:'chrome --headless --disable-gpu --dump-dom'data:text/html,<!doctype html>'' –

1

到目前爲止,我所擁有的最佳解決方案就是這種破解。我不會在prod代碼中使用它,但可能在測試中。

Chrome的彈出式窗口攔截器通常可用於所有網站,但在無頭模式下禁用。我們可以使用打開彈出窗口的能力作爲處於無頭模式的相當準確的代理。執行很簡單:嘗試到open(...)一個窗口,並檢查我們是否得到null(表示它被阻止)而不是Window對象。如果我們打開一個,儘快關閉它。

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

var isHeadless = canPopUp; 

對於一個簡單的例子,你可以嘗試使用和不使用--headless標誌如下:

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

+0

可能相關:https://crbug.com/696439 –

1

剛看完this article by Antoine Vastel它提供了幾個方法:用/HeadlessChrome/.test(window.navigator.userAgent)

  • 測試用戶代理,但是這是很容易欺騙
  • 測試插件與navigator.plugins.length == 0
  • 測試語言與navigator.languages == ""
  • 測試WebGL供應商和渲染器信息(請參閱有關詳細信息的文章)
  • 測試Modernizr檢測支持的功能:似乎不支持「細線」(hidpi/retina細線,其寬度小於1px的CSS邊界,在hidpi屏幕上物理上爲1px)。測試是!Modernizr["hairline"]
  • 測試丟失圖像佔位符的大小。插入帶有無效網址的圖片,然後在image.onerror中測試image.width == 0 && image.height == 0(他們發現這是最穩健的)。

無法對谷歌的動機發言(是無頭的Chrome只有幫助web應用程序的測試?嗯...),但是這可能被看作是可能會有朝一日修復的bug列表,以便人們不知道這些測試將工作多長時間:)

+0

我在發帖之後注意到Josh Lee在昨天的問題下的評論中提到了這一點。我讀了同一篇文章,並記起了上個月的這個問題......我希望我能在原作者的廣告之間取得平衡,並且不會抄襲。如果這太多,我可以編輯,刪除等(謝謝Jeremy的版本) –

相關問題