是否可以通过脚本确定 Google Chrome 是否处于隐身模式?
编辑: 实际上我的意思是通过用户脚本是否可行,但是答案假设 JavaScript 是在网页上运行的。关于用户脚本,我重新提出了这个问题。
一种方法是访问一个唯一的 URL,然后检查指向该 URL 的链接是否被 CSS 视为访问过。
您可以在“隐姓埋名检测”(死亡链接)中看到这方面的一个例子。
同一作者的研究论文代替了上述隐名链接的检测
在 main.html中添加一个 iframe,
main.html
<iframe id='testFrame' name='testFrame' onload='setUniqueSource(this)' src='' style="width:0; height:0; visibility:hidden;"></iframe>
以及一些 JavaScript 代码:
function checkResult() { var a = frames[0].document.getElementById('test'); if (!a) return; var color; if (a.currentStyle) { color = a.currentStyle.color; } else { color = frames[0].getComputedStyle(a, '').color; } var visited = (color == 'rgb(51, 102, 160)' || color == '#3366a0'); alert('mode is ' + (visited ? 'NOT Private' : 'Private')); } function setUniqueSource(frame) { frame.src = "test.html?" + Math.random(); frame.onload = ''; }
然后在 test.html中加载到 iFrame 中:
test.html
<style> a:link { color: #336699; } a:visited { color: #3366A0; } </style> <script> setTimeout(function() { var a = document.createElement('a'); a.href = location; a.id = 'test'; document.body.appendChild(a); parent.checkResult(); }, 100); </script>
注意: 从文件系统中尝试这个操作可能会让 Chrome 为“不安全的 Javascript”而哭泣 但是,将工作从一个网络服务器。
您可以在 JavaScript 中查看 JHurrah 的 回答。除了没有突出显示链接,所有的隐身模式都没有保存浏览历史记录和 cookie。来自 google 帮助页面:
当你隐姓埋名时打开的网页和下载的文件 没有记录在你的浏览和 下载历史记录。 关闭所有隐身窗口后,所有新 Cookie 将被删除 你打开的那个。
正如你所看到的,正常浏览和匿名浏览之间的区别发生在 之后你访问该网页,因此浏览器在这种模式下没有任何东西与服务器通信。
您可以使用许多 HTTP 请求分析器之一(如 这个)查看浏览器到底向服务器发送了什么。比较标题之间的正常会话和隐姓埋名,你会看到没有区别。
如果您正在开发一个扩展,那么您可以使用选项卡 API 来确定窗口/选项卡是否隐藏。
更多信息可以找到 给你。
如果你只是在使用一个网页,这并不容易,而且它就是这样设计的。然而,我注意到所有尝试打开数据库(window.database)的尝试都会在隐身状态下失败,这是因为隐身状态下不允许在用户机器上留下任何数据痕迹。
我还没有测试它,但我怀疑所有调用本地存储也会失败。
这个答案的功能取决于 Chrome 的版本
是的。文件系统 API 在隐身模式下是禁用的。当您处于和不处于隐身模式时,请查看 https://jsfiddle.net/w49x9f1a/。
示例代码:
var fs = window.RequestFileSystem || window.webkitRequestFileSystem; if (!fs) { console.log("check failed?"); } else { fs(window.TEMPORARY, 100, console.log.bind(console, "not in incognito mode"), console.log.bind(console, "incognito mode")); }
基于 阿洛克的回答的快速函数(注意: 这是异步的)
更新 -不再工作
function ifIncognito(incog,func){ var fs = window.RequestFileSystem || window.webkitRequestFileSystem; if (!fs) console.log("checking incognito failed"); else { if(incog) fs(window.TEMPORARY, 100, ()=>{}, func); else fs(window.TEMPORARY, 100, func, ()=>{}); } }
用途:
ifIncognito(true, ()=>{ alert('in incognito') }); // or ifIncognito(false, ()=>{ alert('not in incognito') });
更新 这似乎不再工作了
这使用了一个等待异步代码设置标志的承诺,这样我们就可以在以后同步地使用它。
let isIncognito = await new Promise((resolve, reject)=>{ var fs = window.RequestFileSystem || window.webkitRequestFileSystem; if (!fs) reject('Check incognito failed'); else fs(window.TEMPORARY, 100, ()=>resolve(false), ()=>resolve(true)); });
然后我们就可以
if(isIncognito) alert('in incognito'); else alert('not in incognito');
注意,要使用 await,您需要位于一个异步函数内部。如果不是,那么可以将所有代码封装在一个代码中
await
下面是用 ES6语法编写的建议答案,稍微整理一下。
const isIncognito = () => new Promise((resolve, reject) => { const fs = window.RequestFileSystem || window.webkitRequestFileSystem; if (!fs) { reject('Cant determine whether browser is running in incognito mode!'); } fs(window.TEMPORARY, 100, resolve.bind(null, false), resolve.bind(null, true)); }); // Usage isIncognito() .then(console.log) .catch(console.error)
在 Chrome74到84.0.4147.135中,你可以通过 估计可用的文件系统存储空间来确定这一点
看看 Jsfiddle
if ('storage' in navigator && 'estimate' in navigator.storage) { const {usage, quota} = await navigator.storage.estimate(); console.log(`Using ${usage} out of ${quota} bytes.`); if(quota < 120000000){ console.log('Incognito') } else { console.log('Not Incognito') } } else { console.log('Can not detect') }
这在2021年5月起作用: https://jsfiddle.net/2b1dk8oa/
该脚本必须在一个网页中执行,该网页位于一个 iframe 中。
try{ var ls = localStorage; alert("You are not in Incognito Mode."); } catch(e) { alert("You are in Incognito Mode."); }
对于那些寻找解决方案的人来说,下面是2021年10月各种浏览器中当前检测私人浏览模式的方法的简要概述:
Chromium: 与 Vinnie James 的回答类似,调用导航器.storage.Estith () ,获取配额属性并将其与 Performance.memy.jsHeapSizelimit 进行比较。如果配额属性小于 jsHeapSizelimit,则为匿名。如果 jsHeapSizelimit 未定义,请使用1073741824(1GiB)。
Safari for macOS: 在不存在的推送服务器上使用 Safari.pushNotification.requestPermission 并获取错误。如果“手势”没有出现在错误中,那么它处于私有模式。
Safari for iOS: 创建一个 iframe 并使用 iframe 上的 contentWindow.applicationCache 添加一个错误事件侦听器。如果出现错误,它将处于私有模式。
在一个私有窗口中没有定义 Firefox: Navator.serviceWorker。
Internet Explorer: window.indexedDB 将不在 InPrivate 模式中定义。
您可以在 GitHub 上的 隐姓埋名脚本中看到这些方法的实现。
其他答案似乎不再有效,在最近的铬版本。
这个想法是找出存储估计,以确定是否标签是隐名或没有。隐名标签的存储空间更小。
在普通和匿名窗口中运行此代码,并记下配额大小。
const {quota} = await navigator.storage.estimate(); console.log(quota);
使用配额大小差异来实现隐身模式检测的逻辑。
Chrome v105的逻辑工作如下:
const { quota } = await navigator.storage.estimate(); if (quota.toString().length === 10) { console.log("gotcha: this is incognito tab"); //quota = 1102885027 } else { console.log("this is a normal tab"); //quota = 296630877388 }
另外,看看这个解决方案获得更广泛的支持(也包括其他浏览器) 探测隐身者
演示: https://detectincognito.com/