随着Chrome 59的发布,“无头”模式为now available,适用于Linux和macOS的稳定版本(很快就会推出带有Chrome 60的Windows)。这使我们可以在没有任何可见UI的情况下运行功能齐全的Chrome版本,具有自动化测试的强大功能。 Here are examples.
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无头模式下运行?
答案 0 :(得分:29)
用户代理字符串includes HeadlessChrome
instead of Chrome
。这可能是您打算寻找的信号,因此您可以使用:
/\bHeadlessChrome\//.test(navigator.userAgent)
其他有趣的信号包括:
window.chrome
未定义。[innerWidth, innerHeight]
为[800, 600]
(在headless_browser.cc
中硬编码),而[outerWidth, outerHeight]
为[0, 0]
(通常不应发生)。答案 1 :(得分:15)
您可以检查navigator.webdriver
属性,即:
webdriver
界面的navigator
只读属性表示 用户代理是否由自动化控制。...
在以下情况下,
:navigator.webdriver
属性为trueChrome 使用
--enable-automation
或--headless
标志。
Firefox 已通过marionette.enabled
首选项或--marionette
标志。
W3C WebDriver建议describes it如下:
navigator.webdriver
定义了一种标准方法,用于使用户代理协作来通知文档它由WebDriver控制,例如,以便可以在自动化过程中触发备用代码路径。
答案 2 :(得分:7)
请阅读this article by Antoine Vastel,其中提供了几种方法:
/HeadlessChrome/.test(window.navigator.userAgent)
测试用户代理,但这很容易被欺骗navigator.plugins.length == 0
navigator.languages == ""
!Modernizr["hairline"]
。image.width == 0 && image.height == 0
中测试image.onerror
(他们认为这是最强大的)。不能代表谷歌的动机(是无头Chrome只是为了促进网络应用程序的测试?嗯...... ),但这可以看作是一个列表有一天可能会修复的错误,所以我们不得不怀疑这些测试能运行多长时间:)
答案 3 :(得分:4)
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 talk Headless Browser Hide&amp; amp;由Sergey Shekyan和Bei Zhang寻求(video,slides)。
答案 4 :(得分:4)
我到目前为止最好的解决方案就是这个黑客攻击。我不会在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>'