【问题标题】:Can you determine if Chrome is in incognito mode via a script?您能否通过脚本确定 Chrome 是否处于隐身模式?
【发布时间】:2011-02-23 23:03:00
【问题描述】:

是否可以通过脚本确定谷歌浏览器是否处于隐身模式?

编辑: 我实际上的意思是它可能通过用户脚本,但答案假设 JavaScript 在网页上运行。关于用户脚本,我已经重新问了here 的问题。

【问题讨论】:

  • 并且您必须记住,用户必须允许扩展手册的隐身模式。默认情况下,一切都是真的。
  • @Mohamed:必须允许的用户是我,所以这不是问题 :)
  • 等等,我刚刚意识到我没有说清楚 - 我的意思是使用用户脚本。我会保留这个问题,因为它有一些有用的答案(谢谢),但我会问另一个问题,需要额外说明。
  • @PeteAlvin 否则该网站可能会通过检测隐身来降低价值。 Boston Globe 的网站不会以隐身方式显示其文章,从而防止用户绕过他们的免费文章配额。一般来说,我更喜欢对我了解较少的网站。

标签: javascript google-chrome incognito-mode


【解决方案1】:

此答案的功能取决于 Chrome 版本。最近的评论是这个作品在v90

是的。 FileSystem 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"));
    }

【讨论】:

  • 这是最少的黑客方式,应该在顶部。干净优雅。
  • @user2718671 jsfiddle.net/w49x9f1a 在 mac osx 上的最新 Chrome 中对我来说仍然可以正常工作。奇怪...
  • 我在 Chrome 上试过。行得通,但逻辑是倒退的。
  • 感谢these commits,这很快就会消失
  • chrome v 77.0.3865.90 失败
【解决方案2】:

在 Chrome 74 到 84.0.4147.135 中,您可以通过 estimating the available file system storage space 确定这一点

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')
}

【讨论】:

  • 这是正确的答案。接受的答案应该随之更新,或者接受的答案应该改变。不要拿走最初接受的答案,因为它是当时正确的解决方案。
  • 不幸的是,这现在不起作用:例如,在最新的 MS EDGE 中,我在所谓的私有模式下有 224053418 个字节。在 Chrome 中,我在隐身模式下看到 234549212 个字节。
【解决方案3】:

一种方法是访问一个唯一的 URL,然后检查指向该 URL 的链接是否被 CSS 视为已访问。

你可以在“Detecting Incognito”中看到一个例子(死链接)

Research paper by same author to replace Detecting Incognito link above

main.html添加一个iframe,

 <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 中:

<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”。它 但是,将通过网络服务器提供服务。

【讨论】:

  • 这很酷,我没有意识到隐身模式不会突出显示访问过的链接。这需要用户点击链接。
  • 不,它没有,iframe“点击”链接。
  • 这实际上不起作用,因为大多数浏览器不会通过 javascript 公开 :visited 样式信息。 CSS 界面会说好像链接具有未访问的颜色。这是至少自 2010 年以来一直在 WebKit 和 Gecko 浏览器中的一种安全措施。这是为了保护用户的历史记录(例如,可以尝试所有可能的 URL,并将访问过的 URL 发送给第三方。这样可以获得访问 url 中的令牌等等)。
  • Mozilla 官方文章解释了有关:visited 的隐私更改:hacks.mozilla.org/2010/03/…
【解决方案4】:

您可以在 JavaScript 中查看 JHurrah 的 answer。除了不突出显示链接外,所有隐身模式都不会保存浏览历史记录和 cookie。来自谷歌help page

  • 您在隐身状态下打开的网页和下载的文件 不会记录在您的浏览中,并且 下载历史记录。
  • 关闭所有隐身窗口后,所有新的 cookie 都会被删除 你已经打开了。

正如您所见,正常浏览和隐身浏览之间的区别发生在您访问网页之后,因此在此模式下浏览器不会与服务器进行任何通信。

您可以使用许多 HTTP 请求分析器之一(例如 this one here)查看浏览器向服务器发送的确切内容。比较普通会话和隐身会话的标题,你会发现没有区别。

【讨论】:

  • 最近,它禁用了所有扩展,除了那些被用户特别标记为隐身安全的扩展。
【解决方案5】:

如果您正在开发扩展,那么您可以使用标签 API 来确定窗口/标签是否隐身。

更多信息可以在here找到。

如果您只是使用网页,这并不容易,而且它就是这样设计的。但是,我注意到在隐身模式下打开数据库(window.database)的所有尝试都失败了,这是因为在隐身模式下,不允许在用户计算机上留下任何数据痕迹。

我还没有测试过,但我怀疑对 localStorage 的所有调用也会失败。

【讨论】:

    【解决方案6】:

    更新这似乎不再起作用了


    这使用了一个promise来等待异步代码设置一个标志,所以我们可以在之后同步使用它。

    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');
    

    【讨论】:

    • 这看起来很有趣,是一种我不熟悉的 Javascript 形式,并且似乎不受我在 Windows 10 中的 Netbeans 8.2 IDE 的支持。但如果我能让它工作,我也很好奇:如果我想让isIncognito 成为一个只有真或假的布尔值,我可以用resolve(false) 替换reject('Check incognito failed') 吗?谢谢。
    • 我看到Syntax Error: await is a reserved word,我认为await 总是需要在async 函数内。所以我认为这段代码行不通。
    • reject 如果被调用会引发异常,并且不会返回值,因此isIncognito 将始终为truefalse 编写代码的方式。但是,如果您想要返回一个值,您也可以在那里使用“解决”。它可能取决于环境如何处理全局范围内的等待?它适用于全局范围内的 chrome 控制台,但您可以尝试将所有内容包装在 (async function() { 'everything here' })(); 中,以便在异步函数中运行
    • 或者,您可以将承诺保存到 isIncognito 而不是结果,然后在异步函数中运行它:let isIncognito = new Promise( ...etc 然后在其他地方您将拥有像 (async function() { if( !(await isIncognito) ) {alert('not incognito') } })(); 这样的函数
    • 这个答案在 chrome 76+ 中失效
    【解决方案7】:

    对于那些正在寻找解决方案的人,这里简要介绍了截至 2021 年 10 月在各种浏览器中检测隐私浏览模式的当前方法:

    • Chromium:类似于 Vinnie James 的回答,调用 navigator.storage.estimate(),获取 quota 属性并将其与 performance.memory.jsHeapSizeLimit 进行比较。如果 quota 属性小于 jsHeapSizeLimit,则为隐身。如果 jsHeapSizeLimit 未定义,请使用 1073741824 (1 GiB)。

    • macOS 版 Safari:在不存在的推送服务器上使用 safari.pushNotification.requestPermission 并获取错误。如果错误中没有出现“手势”,则处于私密模式。

    • iOS 版 Safari:创建 iframe 并在 iframe 上使用 contentWindow.applicationCache 添加错误事件侦听器。如果错误发生,则它处于私有模式。

    • Firefox:navigator.serviceWorker 将在私有窗口中未定义。

    • Internet Explorer:window.indexedDB 在 InPrivate 模式下将未定义。

    您可以在我在 GitHub 上提供的 detectIncognito 脚本中看到这些方法的实现。

    【讨论】:

    • 适用于 chrome 96。正如作者所述,脚本需要在服务器端加载
    【解决方案8】:

    这是用 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)
    

    【讨论】:

      【解决方案9】:

      基于Alok's Answer的快速函数(注意:这是异步的)

      更新 - 不再工作了

      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') });
      

      【讨论】:

      • 这不再起作用(也许它在过去起作用)
      • 刚刚更新了我的 chrome,它仍然可以工作。我看到您在上面发布了相同的内容,然后说您错了,只是为将来的观众指出这一点(请随时删除您的评论,如果您这样做,我将删除此评论)。
      【解决方案10】:

      此作品于 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.");  }
      

      【讨论】:

      • 你的小提琴对我有用,但在隐身模式下在 localhost 上测试告诉我我不在隐身模式
      • @S.Ramjit 该脚本必须在网页中执行,该网页位于 iframe 中
      猜你喜欢
      • 2011-02-24
      • 2013-05-15
      • 1970-01-01
      • 2014-01-10
      • 1970-01-01
      • 1970-01-01
      • 2012-10-01
      • 2017-07-28
      • 1970-01-01
      相关资源
      最近更新 更多