返回知识中心
指纹

活动窗口仿真与页面可见性状态

比较 BotBrowser headless 与 headful 会话中的 focus、blur、visibilityState 和 document.hidden,不把 active 状态当作真人存在。

BotBrowser Team

文档中心

想直接进入 指纹 文档吗?

这篇文章属于知识中心的指南库。若你要步骤化配置、参考说明和持续更新,请直接进入对应 docs 分区。

启用 --bot-always-active 后,BotBrowser 可以让声明的浏览器上下文保持活动窗口行为,例如 document.visibilityState === "visible" 和 document.hidden === false。这项能力不等于桌面前台窗口、真人、身份或物理屏幕一定在前台。活动窗口文档 介绍 flag 和默认值;页面同时给出 focus/blur 与 Page Visibility 的语义区别、headless/headful 对照 fixture 以及最小化隐私证据。更大的指纹边界见浏览器指纹基础。

TL;DR

  • focus 和 blur 描述窗口或元素焦点变化;visibilitychange、document.visibilityState 和 document.hidden 描述文档可见性。
  • --bot-always-active 在 BotBrowser PRO 及以上保持受保护的 active 模式,但 active 不代表真人、唯一身份、可信任或保证前台。
  • 用相同 profile、页面和 fixture 比较 headless 与 headful。只记录状态、事件计数和有界结果,不记录页面内容或账户标识。
  • 普通浏览器可能在后台标签、最小化窗口或不可见文档中报告 hidden,具体事件顺序由浏览器和平台决定。
  • flag 不可用或显式关闭时,应保留普通可见性结果和产品 fallback,不要伪造真人活动结论。

Contents

语言中立的图示把 focus 与 visibility 分开,比较 headless、headful 和未聚焦标签,最后生成有界隐私记录

焦点不是页面可见性

W3C Page Visibility 2 规范 定义可见性模型和 visibilitychange 事件。它回答文档是否对浏览器可见,不回答是否有人在看、窗口是否接收键盘或显示器是否开启。MDN Page Visibility API 也把后台标签和最小化窗口视为生命周期变化。

focus 与 blur 属于另一层。窗口焦点决定输入接收者,元素焦点决定哪个控件接收键盘。窗口失焦不一定让文档隐藏;可见文档也可能没有焦点元素。因此每个事件都只是观察值,不是注意力、身份或授权证明。

需要比较显示上下文时,可把本 fixture 与设备像素比策略及屏幕和视口属性配合使用;前者说明几何配置,当前页面聚焦生命周期状态。

信号浏览器含义不能证明
focus / blur窗口或焦点元素改变焦点真人注意力、身份或物理前台
visibilitychange文档可见性状态发生变化显示器电源、用户意图或阅读行为
document.visibilityState文档当前状态,例如 visible 或 hidden所有浏览器通用的平台状态
document.hidden文档可见性的布尔视图真人存在或可信任

相对活动窗口文档,这里增加了每个信号的含义和可复现验证;文档页面本身仍负责配置说明。

活动窗口仿真改变了什么

启用 --bot-always-active 时,即使宿主窗口失去焦点,BotBrowser 也会维持受保护的活动窗口行为。文档说明 PRO 默认启用,并且 headless、headful 都适用。这是授权上下文的浏览器行为,不是关于真人或桌面的报告。

页面可能看到 visibilityState 保持 visible、hidden 保持 false,且宿主失焦时没有可见性转换。焦点事件仍有自己的时序,所以 fixture 应记录实际读取的值。该 flag 不会补充缺失 API、修复应用状态机,也不保证物理窗口处于前台。Document.visibilityState 是快照;visibilitychange 是变化通知。

构建三模式对照 fixture

准备同源页面和三种声明模式:启用仿真的 headless、启用仿真的 headful、以及关闭 flag 后主动失焦的 headful 标签。固定 profile、浏览器版本和页面 revision。下面脚本只保存有界浏览器观察结果。

const result = {
  fixtureId: 'visibility-boundary-01',
  flag: 'unknown',
  visibilityState: document.visibilityState,
  hidden: document.hidden,
  focusEvents: 0,
  blurEvents: 0,
  visibilityChanges: 0,
  outcome: 'initial',
};

window.addEventListener(
  'focus',
  () => {
    result.focusEvents += 1;
  },
  { passive: true }
);
window.addEventListener(
  'blur',
  () => {
    result.blurEvents += 1;
  },
  { passive: true }
);
document.addEventListener('visibilitychange', () => {
  result.visibilityChanges += 1;
  result.visibilityState = document.visibilityState;
  result.hidden = document.hidden;
});

window.sampleVisibility = flag => ({
  ...result,
  flag,
  visibilityState: document.visibilityState,
  hidden: document.hidden,
  outcome: 'sampled',
});
模式Flag宿主动作预期记录形状
Headlessenabled没有桌面窗口visible、false、有界事件
Headfulenabled让宿主窗口失焦visible、false、有界事件
Headfuldisabled切换到另一个标签按浏览器上下文得到 hidden 或 visible

最后一行故意保留条件:runner 无法执行失焦时,应记录 action-unavailable,不能伪造 hidden。BotBrowser 支持 active-window 仿真 fixture 的回放与比较,但 BotBrowser 不能证明真人存在或物理窗口状态;证据只说明该 profile 和上下文。生命周期问题可另看长时间浏览器上下文韧性。

读取 visibilityState 与 document.hidden

在 visibilitychange 处理器中读取 document.visibilityState;document.hidden 是布尔形式。不要使用页面加载时缓存的值决定是否恢复任务。任务 owner 必须阻止可见转换重新唤醒已经结束的任务。

let taskActive = false;

function readVisibility() {
  return {
    state: document.visibilityState,
    hidden: document.hidden,
  };
}

document.addEventListener('visibilitychange', () => {
  const current = readVisibility();
  if (current.hidden) pauseOwnedTask();
  else if (taskActive) resumeOwnedTask();
});

这段代码表达任务归属,不是所有产品都必须暂停。播放器可以遵循用户偏好,编辑器则应保留本地保存。focusEvents、blurEvents 和 visibilityChanges 必须作为不同计数记录。

Headless、headful 与未聚焦标签

Headless 和 headful 是运行模式,不是有人在场的状态。Headful 窗口可能被遮挡或最小化,未聚焦标签在某些布局中仍然可见。用同一 profile 运行,并记录模式、宿主动作、观测值和结果。visible 不证明有人观看;hidden 也不说明是谁切换了标签。

Page Visibility API 指南 还说明可见性会影响后台任务和定时器。不要把时间差变成身份分类器;测试应用结果和清理路径,而不是假定的人类毫秒数。

有意使用 flag 与备用路径

--bot-always-active=false 是普通可见性控制组。解释差异前先确认 entitlement、实际参数和 profile。分别记录 flagRequested、flagEffective 和 fallback。BotBrowser 可以回放授权 fixture 并观察结果,但不能证明真人存在或物理窗口状态。flag 不可用时,让浏览器管理事件,并保留暂停、保存、重试等正常交互。

高级功能参考记录了受保护模式。这是授权上下文的一致性功能,不是前台渲染或身份连续性的承诺。

最小化证据和隐私主张

保留如下短记录,并删除无界追踪:

{
  "fixtureId": "visibility-boundary-01",
  "browserMode": "headful",
  "flagEffective": true,
  "visibilityState": "visible",
  "hidden": false,
  "focusEvents": 1,
  "blurEvents": 1,
  "visibilityChanges": 0,
  "outcome": "stable-visible"
}

浏览器版本、系统、profile revision 和日期可以放在测试元数据中。不要保存账户、私有路径、DOM 文本、按键或跨站标识。active 不是真人,active 不是身份,active 也不保证前台。BotBrowser 负责使用指南约束授权和保留时间。

定位第一个差异字段

先查配置:flagEffective 为 false 时检查许可证、参数拼写和 profile。flag 生效但 visibilityState 不同,则比较模式和宿主动作。blurEvents 增加而 visibilityChanges 为零,说明只有焦点变化。若发生可见性转换,应在处理器中读取状态,并确认结束的任务没有被恢复。

交接记录应包含 fixtureId、模式、有效 flag、第一个差异字段、预期与实际分支和下一步。不要为了让测试看起来真实而发送凭据或账户数据。

Public sources

Practical conclusion

把活动窗口仿真视为有界一致性控制。用 visibilitychange、document.visibilityState 和 document.hidden处理文档生命周期,把 focus 与 blur留在交互层。比较三种模式,测试 --bot-always-active=false,最小化证据,并明确 active 不能证明真人、身份、同意或保证前台。

#活动窗口仿真#Page Visibility API#visibilityState#Document.hidden#隐私

本文属于指南: 什么是浏览器指纹?原理、风险、信号与隐私边界

让 BotBrowser 从研究走向生产

先用这些指南理解模型,再进入跨平台验证、隔离上下文和面向规模化的浏览器部署。