From 8f4b20a19da5dbee8a9ca7bf5036e36e09775b5d Mon Sep 17 00:00:00 2001 From: feder-cr <85809106+feder-cr@users.noreply.github.com> Date: Fri, 19 Jun 2026 03:14:38 +0200 Subject: [PATCH] Pin firefox-12: cross-OS render parity + always-present standard fonts - BINARY_VERSION -> firefox-12 (self-calibrating font widths, per-family canvas distinctness, render-noise that preserves solid reference renders). - font_pool: the standard Windows fonts (Calibri, Franklin Gothic, Gadugi, Javanese Text, Myanmar Text) move from the per-profile optional set to core, so they are always present and the detected font set matches a real Windows install on every host. Defensive dedup in derive_font_prefs. - GPU persona applied on every platform (Linux/macOS present a coherent Windows GPU + WebGL params); pool re-rooted on a real-device GPU mix; render seeds recalibrated. - prefs: emit absolute per-family font widths that the binary self-calibrates. - geoip: always pull the latest mmdb via the releases/latest permalink, checked each launch, offline-safe (no pinned tag that can 404). - tests: per-font canvas distinctness, solid-readback purity under render-noise, always-present standard-font invariant, no duplicate families. --- CHANGELOG.md | 6 +- src/invisible_playwright/_fpforge/_sampler.py | 81 ++- .../_fpforge/data/font_pool.json | 415 ++++++++------ .../_fpforge/data/webgl_gpu_pool.json | 524 ++++++++++++++++++ .../_fpforge/data/win_hw_marginals.json | 469 ++++++++++++++++ src/invisible_playwright/_webgl_personas.py | 103 ++-- src/invisible_playwright/constants.py | 10 +- src/invisible_playwright/download.py | 109 ++-- src/invisible_playwright/prefs.py | 105 ++-- tests/test_canvas_render_stealth.py | 125 +++++ tests/test_geoip_update.py | 165 +++--- tests/test_integration.py | 16 +- tests/test_prefs.py | 50 +- tests/test_sampler.py | 74 +++ tests/test_webgl_noise_active.py | 63 +++ 15 files changed, 1885 insertions(+), 430 deletions(-) create mode 100644 src/invisible_playwright/_fpforge/data/webgl_gpu_pool.json create mode 100644 src/invisible_playwright/_fpforge/data/win_hw_marginals.json create mode 100644 tests/test_canvas_render_stealth.py create mode 100644 tests/test_webgl_noise_active.py diff --git a/CHANGELOG.md b/CHANGELOG.md index f142d90..307383d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,11 +8,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), ### Added - `timezone="auto"`: the browser timezone is auto-derived from the egress IP. By default (no explicit timezone) it ALWAYS resolves — from the proxy egress when a proxy is set, otherwise from the host's own public IP — so the zone can never disagree with the IP (the classic `timezone_mismatch` signal). An explicit `"Area/City"` is the only way to force a specific zone. On failure: with a proxy the launch raises (no silent host-TZ fallback behind a foreign proxy); without a proxy it falls back to the host TZ so a transient lookup can't break the launch. -- The egress IP is mapped to its IANA zone with an offline mmdb (`daijro/geoip-all-in-one`). It auto-updates against the upstream weekly rebuild: cached locally, re-checked after `GEOIP_REFRESH_DAYS` (7), older copies pruned, and a stale cache is reused when offline. `STEALTHFOX_GEOIP_MMDB` points at your own `.mmdb` to skip the download. +- The egress IP is mapped to its IANA zone with an offline mmdb (`daijro/geoip-all-in-one`). It always tracks the upstream weekly rebuild: on every launch the current latest release tag is resolved from the `releases/latest/download` permalink (no GitHub API → no rate limit) and pulled only if newer than the cache, older copies pruned. Offline → the cached copy is reused; never a pinned tag (daijro prunes old releases, so a pin eventually 404s). `STEALTHFOX_GEOIP_MMDB` points at your own `.mmdb` to skip the download. - `resolve_session_timezone(timezone, proxy)` and `ensure_geoip_mmdb()` re-exported at the package root (plus `GeoTimezoneError`) so integrations that own their launch can reproduce the resolution. - `tests/test_geo.py` (37) + `tests/test_geoip_update.py` (freshness / auto-update / offline fallback) unit tests. +- Cross-OS render parity (needs `firefox-12`): the same font/canvas/WebGL fingerprint now renders consistently on Windows, Linux and macOS, so a Windows persona looks identical regardless of the host the binary runs on. Each whitelisted font renders a distinct canvas image (font-detection probes that dedup by rendered image keep every name), the standard Windows fonts (Calibri, Franklin Gothic, Gadugi, Javanese Text, Myanmar Text) are always present so the detected font set matches a real Windows install, and the per-seed render-noise leaves a solid-colour reference render byte-exact while still varying real fingerprint renders. +- GPU persona applied on every platform: Linux/macOS hosts now present a coherent Windows GPU (renderer + WebGL parameters) instead of the host's real adapter; pool re-rooted on a real-device GPU mix. +- `tests/test_canvas_render_stealth.py`, `tests/test_webgl_noise_active.py` and new `tests/test_sampler.py` cases: regression guards for per-font canvas distinctness, solid-readback purity under render-noise, and the always-present standard-font invariant. ### Changed +- Pins `BINARY_VERSION = firefox-12` (the build with the cross-OS render-parity patches). - New runtime dependencies: `requests[socks]` (SOCKS egress lookup), `maxminddb` (mmdb reader), `tzdata` (IANA database for `zoneinfo`, which Windows lacks). ## [0.2.0] - 2026-05-28 diff --git a/src/invisible_playwright/_fpforge/_sampler.py b/src/invisible_playwright/_fpforge/_sampler.py index 195ef0d..b3d7048 100644 --- a/src/invisible_playwright/_fpforge/_sampler.py +++ b/src/invisible_playwright/_fpforge/_sampler.py @@ -76,6 +76,16 @@ _CPT_CODEC = _load("cpt_codec_given_class.json")["table"] _CPT_AUDIO = _load("cpt_audio_given_class.json")["table"] _INDEP = _load("priors_independent.json") _FONT_POOL = _load("font_pool.json") +# hardwareConcurrency: grounded in the REAL Windows marginal (browserforge Windows UAs). +# cores are OS-level, ~independent of GPU given the OS (browserforge confirms), so this is a +# root marginal — NOT conditioned on gpu_class/intra_tier. Fixes the old CPT over-representing +# 6 cores (~28% vs real ~2%). NB: screen size + dpr are intentionally LEFT on their existing +# nodes (user 2026-06-18: "non modificare dpr e le size degli screen, rompono sempre"). +_CORES_MARGINAL = [ + {"value": int(e["value"]), "prob": e["prob"]} + for e in _load("win_hw_marginals.json")["cores"] + if 2 <= int(e["value"]) <= 64 and e["prob"] >= 0.004 +] # Each entry is a dict {"name": "", "factor": float}. # - name: the font family advertised to the page. # - factor: per-family width scale used by the consumer to make the family @@ -83,7 +93,13 @@ _FONT_POOL = _load("font_pool.json") # Core = always-included; Optional = sampled with P(font | gpu_class). _FONT_CORE: list = _FONT_POOL["core"] _FONT_OPTIONAL: list = _FONT_POOL["optional"] -_CPT_FONTS_OPT = _load("cpt_fonts_optional_given_class.json")["table"] +_CPT_FONTS_OPT = _load("cpt_fonts_optional_given_class.json")["table"] # legacy (per-font sampling, superseded by profiles) +# Realistic Windows font PROFILES (2026-06-18): each = a real machine's optional-font set +# (validated to NOT over-claim on FP Pro). Profile-level variation (machines differ in +# Office/extra fonts) instead of per-font random sampling, which produced unrealistic +# combinations (exotic fonts -> FP Pro over-detection -> tampering_ml tell). +_FONT_PROFILES: list = _FONT_POOL.get("profiles", []) +_OPT_BY_NAME = {e["name"]: e for e in _FONT_OPTIONAL} # Browsing-history pool + CPT (per-class probabilities for visited sites). # Drives _recaptcha_seed's cookie pre-seed: each persona ends up with a # coherent list of ~15-30 visited sites whose categories correlate with @@ -213,9 +229,10 @@ _NETWORK = Network([ # larger SSD, higher-res screen than a 'budget' mid_range user. Without # this, hwc/screen/storage would be independent given gpu_class (noisy). Node("intra_tier", parents=["gpu_class"], cpt=_cpt_from_table(_CPT_INTRA_TIER)), - # hwc/screen/storage now jointly coherent via (gpu_class, intra_tier). - Node("hw_concurrency", parents=["gpu_class", "intra_tier"], - cpt=_cpt_from_table(_CPT_HWC)), + # hw_concurrency: REAL Windows marginal (root, OS-level, not GPU-conditioned). screen + + # storage stay jointly coherent via (gpu_class, intra_tier) — screen size deliberately + # unchanged (user: dpr + screen sizes break things; leave them). + Node("hw_concurrency", parents=[], cpt=_CORES_MARGINAL), Node("screen", parents=["gpu_class", "intra_tier"], cpt=_cpt_from_table(_CPT_SCREEN)), # Derive screen_tier from screen for msaa parent lookup. @@ -253,9 +270,10 @@ _NETWORK = Network([ def derive_font_prefs(gpu_class: str, rng) -> Dict[str, str]: """Build COHERENT whitelist + metrics strings for the session. - Sampling: - - Core fonts always included. - - Optional fonts sampled with P(font | gpu_class) from the CPT table. + Profile-based (not per-font random): + - Core fonts always included (OS defaults + CSS-generic backers). + - Optional fonts come from ONE realistic Windows profile picked per seed + (weighted, deterministic). Metrics carry REAL per-family widths. Returns: { @@ -275,20 +293,49 @@ def derive_font_prefs(gpu_class: str, rng) -> Dict[str, str]: Markers & add-new-font: simply add an entry to font_pool.json:core (with a factor at least 4% away from 1.0) — no special-case code needed. """ - cpt = _CPT_FONTS_OPT.get(gpu_class) - if cpt is None: - cpt = _CPT_FONTS_OPT["integrated_modern"] - included: list = list(_FONT_CORE) # always present - for entry in _FONT_OPTIONAL: - name = entry["name"] - p = cpt.get(name, 0.7) # default 0.7 if CPT has no row for this font - if rng.random() < p: - included.append(entry) + # Profile-based (2026-06-18): pick ONE realistic Windows font profile (weighted, + # deterministic per seed). Per-font random sampling is superseded — it produced + # unrealistic optional combinations (exotic fonts) that FP Pro over-detected + # (detected-set 26 vs real 20 -> tampering_ml ~0.72). Profiles are validated subsets + # of a real machine's set, so the detected-set matches a genuine Windows install. + included: list = list(_FONT_CORE) # core: always present (OS defaults + generic backers) + profile = None + if _FONT_PROFILES: + total = sum(p.get("weight", 1) for p in _FONT_PROFILES) + anchor = rng.random() * total + cum = 0.0 + for p in _FONT_PROFILES: + cum += p.get("weight", 1) + if anchor < cum: + profile = p + break + if profile is None: + profile = _FONT_PROFILES[-1] + if profile is not None: + for name in profile.get("optional", []): + entry = _OPT_BY_NAME.get(name) + if entry is not None: + included.append(entry) + else: + included.extend(_FONT_OPTIONAL) # fallback (no profiles defined): all optional + # Dedup by name (a profile may list a font that is also in core, e.g. after a + # standard font is promoted core→always-present) so the whitelist/metrics never + # carry a duplicate family. + _seen: set = set() + _uniq: list = [] + for e in included: + if e["name"] not in _seen: + _seen.add(e["name"]) + _uniq.append(e) + included = _uniq # Deterministic ordering: sort by name included.sort(key=lambda e: e["name"]) whitelist = ",".join(e["name"] for e in included) + # Emit the UNIVERSAL real Windows width per font (host-independent value, same everywhere). + # prefs._font_metrics_for_platform divides by the per-platform collapse base to get the C++ + # factor (measureText = base * factor = the exact Windows width on Windows/Linux/mac). metrics = ",".join( - f'{e["name"]}|{e["factor"]:.3f}' for e in included + f'{e["name"]}|{e["width"]:.1f}' for e in included ) return {"whitelist": whitelist, "metrics": metrics} diff --git a/src/invisible_playwright/_fpforge/data/font_pool.json b/src/invisible_playwright/_fpforge/data/font_pool.json index f36e370..bfa4157 100644 --- a/src/invisible_playwright/_fpforge/data/font_pool.json +++ b/src/invisible_playwright/_fpforge/data/font_pool.json @@ -2,669 +2,722 @@ "core": [ { "name": "arial", - "factor": 0.978 + "width": 2256.7 }, { "name": "arial black", - "factor": 1.168 + "width": 2256.7 }, { "name": "arial narrow", - "factor": 0.854 + "width": 2216.7 }, { "name": "bahnschrift", - "factor": 0.951 + "width": 2231.9 }, { "name": "bahnschrift condensed", - "factor": 1.179 + "width": 2216.7 }, { "name": "bahnschrift light", - "factor": 0.908 + "width": 2216.7 }, { "name": "bahnschrift light condensed", - "factor": 1.053 + "width": 2216.7 }, { "name": "bahnschrift light semicondensed", - "factor": 1.063 + "width": 2216.7 }, { "name": "bahnschrift semibold", - "factor": 0.926 + "width": 2216.7 }, { "name": "bahnschrift semibold condensed", - "factor": 1.131 + "width": 2216.7 }, { "name": "bahnschrift semibold semicondensed", - "factor": 1.043 + "width": 2216.7 }, { "name": "bahnschrift semicondensed", - "factor": 1.098 + "width": 2216.7 }, { "name": "bahnschrift semilight", - "factor": 0.873 + "width": 2216.7 }, { "name": "bahnschrift semilight condensed", - "factor": 0.905 + "width": 2216.7 }, { "name": "bahnschrift semilight semicondensed", - "factor": 1.135 + "width": 2216.7 + }, + { + "name": "calibri", + "width": 2139.5 }, { "name": "calibri light", - "factor": 0.901 + "width": 2139.5 }, { "name": "cambria", - "factor": 1.063 + "width": 2258.2 }, { "name": "cambria math", - "factor": 1.041 + "width": 2258.2 }, { "name": "candara", - "factor": 0.927 + "width": 2187.8 }, { "name": "candara light", - "factor": 0.892 + "width": 2187.8 }, { "name": "cascadia code", - "factor": 1.139 + "width": 2362.3 }, { "name": "cascadia mono", - "factor": 0.95 + "width": 2362.3 }, { "name": "comic sans ms", - "factor": 1.087 + "width": 2361.9 }, { "name": "consolas", - "factor": 1.158 + "width": 2216.7 }, { "name": "constantia", - "factor": 1.052 + "width": 2283.2 }, { "name": "corbel", - "factor": 0.895 + "width": 2129.9 }, { "name": "corbel light", - "factor": 0.876 + "width": 2129.9 }, { "name": "courier new", - "factor": 1.187 + "width": 2419.2 }, { "name": "ebrima", - "factor": 0.962 + "width": 2285.2 + }, + { + "name": "franklin gothic", + "width": 2225.4 }, { "name": "franklin gothic medium", - "factor": 1.031 + "width": 2225.4 }, { "name": "gabriola", - "factor": 1.077 + "width": 1598.5 + }, + { + "name": "gadugi", + "width": 2285.2 }, { "name": "georgia", - "factor": 1.094 + "width": 2338.7 }, { "name": "hololens mdl2 assets", - "factor": 1.145 + "width": 2216.7 }, { "name": "impact", - "factor": 0.862 + "width": 2060.8 }, { "name": "ink free", - "factor": 1.048 + "width": 2122.5 + }, + { + "name": "javanese text", + "width": 2311.9 }, { "name": "leelawadee ui semilight", - "factor": 1.061 + "width": 2283.4 }, { "name": "lucida console", - "factor": 1.131 + "width": 2429.5 }, { "name": "lucida sans unicode", - "factor": 1.014 + "width": 2464.3 }, { "name": "malgun gothic", - "factor": 1.128 + "width": 2351.1 }, { "name": "malgun gothic semilight", - "factor": 1.051 + "width": 2351.1 }, { "name": "marlett", - "factor": 0.855 + "width": 3740.2 }, { "name": "microsoft himalaya", - "factor": 1.022 + "width": 1468.4 }, { "name": "microsoft jhenghei", - "factor": 1.061 + "width": 2440.4 }, { "name": "microsoft jhenghei light", - "factor": 0.94 + "width": 2440.4 }, { "name": "microsoft jhenghei ui", - "factor": 1.136 + "width": 2440.4 }, { "name": "microsoft jhenghei ui light", - "factor": 0.826 + "width": 2440.4 }, { "name": "microsoft new tai lue", - "factor": 0.953 + "width": 2285.2 }, { "name": "microsoft phagspa", - "factor": 0.988 + "width": 2285.2 }, { "name": "microsoft sans serif", - "factor": 0.941 + "width": 2256.6 }, { "name": "microsoft tai le", - "factor": 0.957 + "width": 2285.2 }, { "name": "microsoft yahei", - "factor": 1.076 + "width": 2487.6 }, { "name": "microsoft yahei light", - "factor": 1.043 + "width": 2487.6 }, { "name": "microsoft yahei ui", - "factor": 1.076 + "width": 2487.6 }, { "name": "microsoft yahei ui light", - "factor": 1.094 + "width": 2487.6 }, { "name": "microsoft yi baiti", - "factor": 1.008 + "width": 1830.7 }, { "name": "mingliu-extb", - "factor": 1.173 + "width": 2016 }, { "name": "mingliu_hkscs-extb", - "factor": 1.101 + "width": 2016 }, { "name": "mongolian baiti", - "factor": 1.056 + "width": 2191.7 }, { "name": "ms gothic", - "factor": 1.119 + "width": 2016 }, { "name": "ms pgothic", - "factor": 1.074 + "width": 2031.7 }, { "name": "mv boli", - "factor": 0.932 + "width": 2417.4 + }, + { + "name": "myanmar text", + "width": 2285.2 }, { "name": "nirmala ui", - "factor": 0.916 + "width": 2283.4 }, { "name": "nirmala ui semilight", - "factor": 1.15 + "width": 2283.4 }, { "name": "nsimsun", - "factor": 1.119 + "width": 2016 }, { "name": "palatino linotype", - "factor": 1.067 + "width": 2358.6 }, { "name": "pmingliu-extb", - "factor": 1.16 + "width": 2065.9 }, { "name": "sans serif collection", - "factor": 0.854 + "width": 2361.6 }, { "name": "segoe mdl2 assets", - "factor": 0.858 + "width": 2137.2 }, { "name": "segoe print", - "factor": 1.033 + "width": 2675.2 }, { "name": "segoe script", - "factor": 1.058 + "width": 2830.3 }, { "name": "segoe ui", - "factor": 0.948 + "width": 2285.2 }, { "name": "segoe ui black", - "factor": 1.148 + "width": 2285.2 }, { "name": "segoe ui emoji", - "factor": 0.924 + "width": 2283.4 }, { "name": "segoe ui historic", - "factor": 0.969 + "width": 2283.4 }, { "name": "segoe ui semibold", - "factor": 0.965 + "width": 2216.7 }, { "name": "segoe ui semilight", - "factor": 1.055 + "width": 2216.7 }, { "name": "segoe ui symbol", - "factor": 0.972 + "width": 2283.4 }, { "name": "segoe ui variable", - "factor": 0.907 + "width": 2216.7 }, { "name": "simsun", - "factor": 1.113 + "width": 2016 }, { "name": "simsun-extb", - "factor": 1.095 + "width": 2016 }, { "name": "sitka banner", - "factor": 1.078 + "width": 2007.8 }, { "name": "sitka display", - "factor": 0.838 + "width": 2007.8 }, { "name": "sitka heading", - "factor": 0.843 + "width": 2007.8 }, { "name": "sitka small", - "factor": 1.131 + "width": 2007.8 }, { "name": "sitka subheading", - "factor": 0.942 + "width": 2007.8 }, { "name": "sitka text", - "factor": 1.044 + "width": 2007.8 }, { "name": "sylfaen", - "factor": 0.971 + "width": 2279.6 }, { "name": "symbol", - "factor": 0.866 + "width": 2223.4 }, { "name": "tahoma", - "factor": 0.962 + "width": 2233.1 }, { "name": "times new roman", - "factor": 0.926 + "width": 2191.7 }, { "name": "trebuchet ms", - "factor": 0.912 + "width": 2222.4 }, { "name": "verdana", - "factor": 1.128 + "width": 2529.1 }, { "name": "webdings", - "factor": 0.849 + "width": 3627.5 }, { "name": "wingdings", - "factor": 0.864 + "width": 3539.7 }, { "name": "wingdings 2", - "factor": 1.093 + "width": 3582.1 }, { "name": "wingdings 3", - "factor": 0.861 + "width": 2963.4 }, { "name": "yu gothic", - "factor": 1.069 + "width": 2351.3 }, { "name": "yu gothic light", - "factor": 1.038 + "width": 2351.3 }, { "name": "yu gothic medium", - "factor": 1.161 + "width": 2216.7 }, { "name": "yu gothic ui", - "factor": 0.886 + "width": 2285.2 }, { "name": "yu gothic ui light", - "factor": 1.093 + "width": 2285.2 }, { "name": "yu gothic ui semibold", - "factor": 0.942 + "width": 2216.7 }, { "name": "yu gothic ui semilight", - "factor": 0.923 + "width": 2216.7 } ], "optional": [ { "name": "aparajita", - "factor": 0.94 + "width": 2216.7 }, { "name": "arabic typesetting", - "factor": 1.093 + "width": 2216.7 }, { "name": "arial unicode ms", - "factor": 1.047 + "width": 2216.7 }, { "name": "batang", - "factor": 0.911 - }, - { - "name": "calibri", - "factor": 0.934 + "width": 2216.7 }, { "name": "century", - "factor": 1.078 + "width": 2397.7 }, { "name": "century gothic", - "factor": 0.886 + "width": 2409.1 }, { "name": "dengxian", - "factor": 0.846 + "width": 2216.7 }, { "name": "dfkai-sb", - "factor": 0.946 + "width": 2216.7 }, { "name": "dokchampa", - "factor": 1.162 + "width": 2216.7 }, { "name": "estrangelo edessa", - "factor": 1.095 + "width": 2216.7 }, { "name": "euphemia", - "factor": 1.117 + "width": 2216.7 }, { "name": "fangsong", - "factor": 0.942 - }, - { - "name": "franklin gothic", - "factor": 0.942 - }, - { - "name": "gadugi", - "factor": 0.945 + "width": 2216.7 }, { "name": "gautami", - "factor": 1.134 + "width": 2216.7 }, { "name": "haettenschweiler", - "factor": 0.874 + "width": 1567.6 }, { "name": "helv", - "factor": 0.923 + "width": 2256.6 }, { "name": "iskoola pota", - "factor": 0.857 - }, - { - "name": "javanese text", - "factor": 1.083 + "width": 2216.7 }, { "name": "kaiti", - "factor": 1.145 + "width": 2216.7 }, { "name": "kalinga", - "factor": 0.953 + "width": 2216.7 }, { "name": "kartika", - "factor": 0.882 + "width": 2216.7 }, { "name": "khmer ui", - "factor": 1.137 + "width": 2216.7 }, { "name": "kokila", - "factor": 0.919 + "width": 2216.7 }, { "name": "lao ui", - "factor": 0.904 + "width": 2216.7 }, { "name": "latha", - "factor": 0.839 + "width": 2216.7 }, { "name": "leelawadee", - "factor": 0.982 + "width": 2267.4 }, { "name": "leelawadee ui", - "factor": 0.992 + "width": 2283.4 }, { "name": "levenim mt", - "factor": 1.054 + "width": 2216.7 }, { "name": "mangal", - "factor": 1.154 + "width": 2216.7 }, { "name": "meiryo", - "factor": 1.165 + "width": 2216.7 }, { "name": "meiryo ui", - "factor": 1.081 + "width": 2216.7 }, { "name": "microsoft uighur", - "factor": 0.969 + "width": 1498.1 }, { "name": "monotype corsiva", - "factor": 0.939 + "width": 1929.3 }, { "name": "ms mincho", - "factor": 1.112 + "width": 2216.7 }, { "name": "ms outlook", - "factor": 0.921 + "width": 2361.9 }, { "name": "ms pmincho", - "factor": 0.925 + "width": 2216.7 }, { "name": "ms reference sans serif", - "factor": 0.858 + "width": 2529.0 }, { "name": "ms reference specialty", - "factor": 0.958 + "width": 2976.2 }, { "name": "ms ui gothic", - "factor": 1.097 + "width": 2031.7 }, { "name": "mt extra", - "factor": 0.905 - }, - { - "name": "myanmar text", - "factor": 0.961 + "width": 2183.8 }, { "name": "nyala", - "factor": 1.108 + "width": 2216.7 }, { "name": "plantagenet cherokee", - "factor": 1.115 + "width": 2216.7 }, { "name": "pmingliu", - "factor": 1.125 + "width": 2216.7 }, { "name": "pristina", - "factor": 1.023 + "width": 1829.1 }, { "name": "raavi", - "factor": 0.826 + "width": 2216.7 }, { "name": "segoe fluent icons", - "factor": 1.049 + "width": 2142.7 }, { "name": "segoe ui light", - "factor": 0.918 + "width": 2216.7 }, { "name": "shonar bangla", - "factor": 1.141 + "width": 2216.7 }, { "name": "shruti", - "factor": 1.172 + "width": 2216.7 }, { "name": "simhei", - "factor": 1.141 + "width": 2216.7 }, { "name": "simkai", - "factor": 1.1 + "width": 2216.7 }, { "name": "small fonts", - "factor": 0.849 + "width": 2256.7 }, { "name": "traditional arabic", - "factor": 0.893 + "width": 2216.7 }, { "name": "tunga", - "factor": 0.825 + "width": 2216.7 }, { "name": "urdu typesetting", - "factor": 0.869 + "width": 2216.7 }, { "name": "utsaah", - "factor": 1.144 + "width": 2216.7 }, { "name": "vani", - "factor": 1.078 + "width": 2216.7 }, { "name": "vijaya", - "factor": 0.917 + "width": 2216.7 }, { "name": "vrinda", - "factor": 0.985 + "width": 2216.7 }, { "name": "yu mincho", - "factor": 0.867 + "width": 2216.7 + } + ], + "profiles": [ + { + "name": "win_office", + "weight": 40, + "optional": [ + "century", + "century gothic", + "helv", + "haettenschweiler", + "leelawadee", + "ms outlook", + "ms reference specialty", + "ms ui gothic", + "mt extra", + "microsoft uighur", + "monotype corsiva", + "pristina", + "segoe ui light", + "small fonts" + ] + }, + { + "name": "win_base", + "weight": 35, + "optional": [ + "century", + "century gothic", + "helv", + "haettenschweiler", + "leelawadee", + "ms ui gothic", + "microsoft uighur", + "monotype corsiva", + "pristina", + "segoe ui light", + "small fonts" + ] + }, + { + "name": "win_lean", + "weight": 25, + "optional": [ + "century", + "century gothic", + "helv", + "haettenschweiler", + "leelawadee", + "ms ui gothic", + "segoe ui light", + "small fonts" + ] } ] } \ No newline at end of file diff --git a/src/invisible_playwright/_fpforge/data/webgl_gpu_pool.json b/src/invisible_playwright/_fpforge/data/webgl_gpu_pool.json new file mode 100644 index 0000000..34f757b --- /dev/null +++ b/src/invisible_playwright/_fpforge/data/webgl_gpu_pool.json @@ -0,0 +1,524 @@ +{ + "win": [ + { + "vendor": "Google Inc. (NVIDIA)", + "renderer_out": "ANGLE (NVIDIA, NVIDIA GeForce GTX 980 Direct3D11 vs_5_0 ps_5_0), or similar", + "prob": 0.462396, + "prefs": { + "zoom.stealth.webgl.renderer": "ANGLE (NVIDIA, NVIDIA GeForce GTX 980 Direct3D11 vs_5_0 ps_5_0, D3D11)", + "zoom.stealth.webgl.vendor": "Google Inc. (NVIDIA)", + "zoom.stealth.webgl.extensions": "ANGLE_instanced_arrays,EXT_blend_minmax,EXT_color_buffer_half_float,EXT_float_blend,EXT_frag_depth,EXT_shader_texture_lod,EXT_sRGB,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_element_index_uint,OES_fbo_render_mipmap,OES_standard_derivatives,OES_texture_float,OES_texture_float_linear,OES_texture_half_float,OES_texture_half_float_linear,OES_vertex_array_object,WEBGL_color_buffer_float,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_depth_texture,WEBGL_draw_buffers,WEBGL_lose_context,WEBGL_provoking_vertex", + "zoom.stealth.webgl2.extensions": "EXT_color_buffer_float,EXT_float_blend,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_draw_buffers_indexed,OES_texture_float_linear,OVR_multiview2,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_lose_context,WEBGL_provoking_vertex", + "zoom.stealth.webgl.int_params": "2849|1,2885|1029,2886|2305,2931|1,2932|513,2961|0,2962|519,2963|2147483647,2964|7680,2965|7680,2966|7680,2967|0,2968|2147483647,3074|1029,3314|0,3315|0,3316|0,3317|4,3330|0,3331|0,3332|0,3333|4,3379|16384,3408|4,3410|8,3411|8,3412|8,3413|8,3414|24,3415|0,10752|0,32777|32774,32824|0,32877|0,32878|0,32883|2048,32936|1,32937|4,32938|1,32968|0,32969|1,32970|0,32971|1,33000|2147483647,33001|2147483647,33170|4352,34016|33984,34024|16384,34045|2,34076|16384,34816|519,34817|7680,34818|7680,34819|7680,34852|8,34853|1029,34854|0,34855|0,34856|0,34857|0,34858|0,34859|0,34860|0,34877|32774,34921|16,34930|16,35071|2048,35076|-8,35077|7,35371|12,35373|12,35374|24,35375|24,35376|65536,35377|212988,35379|200704,35380|256,35657|4096,35658|16380,35659|120,35660|16,35661|32,35723|4352,35738|5121,35739|6408,35968|4,35978|120,35979|4,36003|0,36004|2147483647,36005|2147483647,36063|8,36183|8,36203|4294967294,36347|4095,36348|30,36349|1024,37137|0,37154|120,37157|120,37443|37444,37447|1000000000", + "zoom.stealth.webgl.int2_params": "2928|0:1,3386|32767:32767,33901|1:1024,33902|1:1", + "zoom.stealth.webgl.float_params": "", + "zoom.stealth.webgl.shader_precisions": "35633*36336|127:127:23,35633*36337|127:127:23,35633*36338|127:127:23,35633*36339|31:30:0,35633*36340|31:30:0,35633*36341|31:30:0,35632*36336|127:127:23,35632*36337|127:127:23,35632*36338|127:127:23,35632*36339|31:30:0,35632*36340|31:30:0,35632*36341|31:30:0", + "zoom.stealth.webgl2.enabled": true + } + }, + { + "vendor": "Google Inc. (Intel)", + "renderer_out": "ANGLE (Intel, Intel(R) HD Graphics Direct3D11 vs_5_0 ps_5_0), or similar", + "prob": 0.192201, + "prefs": { + "zoom.stealth.webgl.renderer": "ANGLE (Intel, Intel(R) HD Graphics Direct3D11 vs_5_0 ps_5_0, D3D11)", + "zoom.stealth.webgl.vendor": "Google Inc. (Intel)", + "zoom.stealth.webgl.extensions": "ANGLE_instanced_arrays,EXT_blend_minmax,EXT_color_buffer_half_float,EXT_float_blend,EXT_frag_depth,EXT_shader_texture_lod,EXT_sRGB,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_element_index_uint,OES_fbo_render_mipmap,OES_standard_derivatives,OES_texture_float,OES_texture_float_linear,OES_texture_half_float,OES_texture_half_float_linear,OES_vertex_array_object,WEBGL_color_buffer_float,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_depth_texture,WEBGL_draw_buffers,WEBGL_lose_context,WEBGL_provoking_vertex", + "zoom.stealth.webgl2.extensions": "EXT_color_buffer_float,EXT_float_blend,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_draw_buffers_indexed,OES_texture_float_linear,OVR_multiview2,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_lose_context,WEBGL_provoking_vertex", + "zoom.stealth.webgl.int_params": "2849|1,2885|1029,2886|2305,2931|1,2932|513,2961|0,2962|519,2963|2147483647,2964|7680,2965|7680,2966|7680,2967|0,2968|2147483647,3074|1029,3314|0,3315|0,3316|0,3317|4,3330|0,3331|0,3332|0,3333|4,3379|16384,3408|4,3410|8,3411|8,3412|8,3413|8,3414|24,3415|0,10752|0,32777|32774,32824|0,32877|0,32878|0,32883|2048,32936|1,32937|4,32938|1,32968|0,32969|1,32970|0,32971|1,33000|2147483647,33001|2147483647,33170|4352,34016|33984,34024|16384,34045|2,34076|16384,34816|519,34817|7680,34818|7680,34819|7680,34852|8,34853|1029,34854|0,34855|0,34856|0,34857|0,34858|0,34859|0,34860|0,34877|32774,34921|16,34930|16,35071|2048,35076|-8,35077|7,35371|12,35373|12,35374|24,35375|24,35376|65536,35377|212992,35379|200704,35380|256,35657|4096,35658|16384,35659|120,35660|16,35661|32,35723|4352,35738|5121,35739|6408,35968|4,35978|120,35979|4,36003|0,36004|2147483647,36005|2147483647,36063|8,36183|8,36203|4294967294,36347|4096,36348|30,36349|1024,37137|0,37154|120,37157|120,37443|37444,37447|1000000000", + "zoom.stealth.webgl.int2_params": "2928|0:1,3386|32767:32767,33901|1:1024,33902|1:1", + "zoom.stealth.webgl.float_params": "", + "zoom.stealth.webgl.shader_precisions": "35633*36336|127:127:23,35633*36337|127:127:23,35633*36338|127:127:23,35633*36339|31:30:0,35633*36340|31:30:0,35633*36341|31:30:0,35632*36336|127:127:23,35632*36337|127:127:23,35632*36338|127:127:23,35632*36339|31:30:0,35632*36340|31:30:0,35632*36341|31:30:0", + "zoom.stealth.webgl2.enabled": true + } + }, + { + "vendor": "Google Inc. (Intel)", + "renderer_out": "ANGLE (Intel, Intel(R) HD Graphics 400 Direct3D11 vs_5_0 ps_5_0), or similar", + "prob": 0.157382, + "prefs": { + "zoom.stealth.webgl.renderer": "ANGLE (Intel, Intel(R) HD Graphics 400 Direct3D11 vs_5_0 ps_5_0, D3D11)", + "zoom.stealth.webgl.vendor": "Google Inc. (Intel)", + "zoom.stealth.webgl.extensions": "ANGLE_instanced_arrays,EXT_blend_minmax,EXT_color_buffer_half_float,EXT_float_blend,EXT_frag_depth,EXT_shader_texture_lod,EXT_sRGB,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_element_index_uint,OES_fbo_render_mipmap,OES_standard_derivatives,OES_texture_float,OES_texture_float_linear,OES_texture_half_float,OES_texture_half_float_linear,OES_vertex_array_object,WEBGL_color_buffer_float,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_depth_texture,WEBGL_draw_buffers,WEBGL_lose_context,WEBGL_provoking_vertex", + "zoom.stealth.webgl2.extensions": "EXT_color_buffer_float,EXT_float_blend,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_draw_buffers_indexed,OES_texture_float_linear,OVR_multiview2,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_lose_context,WEBGL_provoking_vertex", + "zoom.stealth.webgl.int_params": "2849|1,2885|1029,2886|2305,2931|1,2932|513,2961|0,2962|519,2963|2147483647,2964|7680,2965|7680,2966|7680,2967|0,2968|2147483647,3074|1029,3314|0,3315|0,3316|0,3317|4,3330|0,3331|0,3332|0,3333|4,3379|16384,3408|4,3410|8,3411|8,3412|8,3413|8,3414|24,3415|0,10752|0,32777|32774,32824|0,32877|0,32878|0,32883|2048,32936|1,32937|4,32938|1,32968|0,32969|1,32970|0,32971|1,33000|2147483647,33001|2147483647,33170|4352,34016|33984,34024|16384,34045|2,34076|16384,34816|519,34817|7680,34818|7680,34819|7680,34852|8,34853|1029,34854|0,34855|0,34856|0,34857|0,34858|0,34859|0,34860|0,34877|32774,34921|16,34930|16,35071|2048,35076|-8,35077|7,35371|12,35373|12,35374|24,35375|24,35376|65536,35377|212992,35379|200704,35380|256,35657|4096,35658|16384,35659|120,35660|16,35661|32,35723|4352,35738|5121,35739|6408,35968|4,35978|120,35979|4,36003|0,36004|2147483647,36005|2147483647,36063|8,36183|16,36203|4294967294,36347|4096,36348|30,36349|1024,37137|0,37154|120,37157|120,37443|37444,37447|1000000000", + "zoom.stealth.webgl.int2_params": "2928|0:1,3386|32767:32767,33901|1:1024,33902|1:1", + "zoom.stealth.webgl.float_params": "", + "zoom.stealth.webgl.shader_precisions": "35633*36336|127:127:23,35633*36337|127:127:23,35633*36338|127:127:23,35633*36339|31:30:0,35633*36340|31:30:0,35633*36341|31:30:0,35632*36336|127:127:23,35632*36337|127:127:23,35632*36338|127:127:23,35632*36339|31:30:0,35632*36340|31:30:0,35632*36341|31:30:0", + "zoom.stealth.webgl2.enabled": true + } + }, + { + "vendor": "Google Inc. (AMD)", + "renderer_out": "ANGLE (AMD, Radeon HD 3200 Graphics Direct3D11 vs_5_0 ps_5_0), or similar", + "prob": 0.084958, + "prefs": { + "zoom.stealth.webgl.renderer": "ANGLE (AMD, Radeon HD 3200 Graphics Direct3D11 vs_5_0 ps_5_0, D3D11)", + "zoom.stealth.webgl.vendor": "Google Inc. (AMD)", + "zoom.stealth.webgl.extensions": "ANGLE_instanced_arrays,EXT_blend_minmax,EXT_color_buffer_half_float,EXT_float_blend,EXT_frag_depth,EXT_shader_texture_lod,EXT_sRGB,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_element_index_uint,OES_fbo_render_mipmap,OES_standard_derivatives,OES_texture_float,OES_texture_float_linear,OES_texture_half_float,OES_texture_half_float_linear,OES_vertex_array_object,WEBGL_color_buffer_float,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_depth_texture,WEBGL_draw_buffers,WEBGL_lose_context,WEBGL_provoking_vertex", + "zoom.stealth.webgl2.extensions": "EXT_color_buffer_float,EXT_float_blend,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_draw_buffers_indexed,OES_texture_float_linear,OVR_multiview2,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_lose_context,WEBGL_provoking_vertex", + "zoom.stealth.webgl.int_params": "2849|1,2885|1029,2886|2305,2931|1,2932|513,2961|0,2962|519,2963|2147483647,2964|7680,2965|7680,2966|7680,2967|0,2968|2147483647,3074|1029,3314|0,3315|0,3316|0,3317|4,3330|0,3331|0,3332|0,3333|4,3379|16384,3408|4,3410|8,3411|8,3412|8,3413|8,3414|24,3415|0,10752|0,32777|32774,32824|0,32877|0,32878|0,32883|2048,32936|1,32937|4,32938|1,32968|0,32969|1,32970|0,32971|1,33000|2147483647,33001|2147483647,33170|4352,34016|33984,34024|16384,34045|2,34076|16384,34816|519,34817|7680,34818|7680,34819|7680,34852|8,34853|1029,34854|0,34855|0,34856|0,34857|0,34858|0,34859|0,34860|0,34877|32774,34921|16,34930|16,35071|2048,35076|-8,35077|7,35371|12,35373|12,35374|24,35375|24,35376|65536,35377|212992,35379|200704,35380|256,35657|4096,35658|16384,35659|120,35660|16,35661|32,35723|4352,35738|5121,35739|6408,35968|4,35978|120,35979|4,36003|0,36004|2147483647,36005|2147483647,36063|8,36183|8,36203|4294967294,36347|4096,36348|30,36349|1024,37137|0,37154|120,37157|120,37443|37444,37447|1000000000", + "zoom.stealth.webgl.int2_params": "2928|0:1,3386|32767:32767,33901|1:1024,33902|1:1", + "zoom.stealth.webgl.float_params": "", + "zoom.stealth.webgl.shader_precisions": "35633*36336|127:127:23,35633*36337|127:127:23,35633*36338|127:127:23,35633*36339|31:30:0,35633*36340|31:30:0,35633*36341|31:30:0,35632*36336|127:127:23,35632*36337|127:127:23,35632*36338|127:127:23,35632*36339|31:30:0,35632*36340|31:30:0,35632*36341|31:30:0", + "zoom.stealth.webgl2.enabled": true + } + }, + { + "vendor": "Google Inc. (AMD)", + "renderer_out": "ANGLE (AMD, Radeon R9 200 Series Direct3D11 vs_5_0 ps_5_0), or similar", + "prob": 0.052925, + "prefs": { + "zoom.stealth.webgl.renderer": "ANGLE (AMD, Radeon R9 200 Series Direct3D11 vs_5_0 ps_5_0, D3D11)", + "zoom.stealth.webgl.vendor": "Google Inc. (AMD)", + "zoom.stealth.webgl.extensions": "ANGLE_instanced_arrays,EXT_blend_minmax,EXT_color_buffer_half_float,EXT_float_blend,EXT_frag_depth,EXT_shader_texture_lod,EXT_sRGB,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_element_index_uint,OES_fbo_render_mipmap,OES_standard_derivatives,OES_texture_float,OES_texture_float_linear,OES_texture_half_float,OES_texture_half_float_linear,OES_vertex_array_object,WEBGL_color_buffer_float,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_depth_texture,WEBGL_draw_buffers,WEBGL_lose_context,WEBGL_provoking_vertex", + "zoom.stealth.webgl2.extensions": "EXT_color_buffer_float,EXT_float_blend,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_draw_buffers_indexed,OES_texture_float_linear,OVR_multiview2,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_lose_context,WEBGL_provoking_vertex", + "zoom.stealth.webgl.int_params": "2849|1,2885|1029,2886|2305,2931|1,2932|513,2961|0,2962|519,2963|2147483647,2964|7680,2965|7680,2966|7680,2967|0,2968|2147483647,3074|1029,3314|0,3315|0,3316|0,3317|4,3330|0,3331|0,3332|0,3333|4,3379|16384,3408|4,3410|8,3411|8,3412|8,3413|8,3414|24,3415|0,10752|0,32777|32774,32824|0,32877|0,32878|0,32883|2048,32936|1,32937|4,32938|1,32968|0,32969|1,32970|0,32971|1,33000|2147483647,33001|2147483647,33170|4352,34016|33984,34024|16384,34045|2,34076|16384,34816|519,34817|7680,34818|7680,34819|7680,34852|8,34853|1029,34854|0,34855|0,34856|0,34857|0,34858|0,34859|0,34860|0,34877|32774,34921|16,34930|16,35071|2048,35076|-8,35077|7,35371|12,35373|12,35374|24,35375|24,35376|65536,35377|212992,35379|200704,35380|256,35657|4096,35658|16384,35659|120,35660|16,35661|32,35723|4352,35738|5121,35739|6408,35968|4,35978|120,35979|4,36003|0,36004|2147483647,36005|2147483647,36063|8,36183|8,36203|4294967294,36347|4096,36348|30,36349|1024,37137|0,37154|120,37157|120,37443|37444,37447|1000000000", + "zoom.stealth.webgl.int2_params": "2928|0:1,3386|32767:32767,33901|1:1024,33902|1:1", + "zoom.stealth.webgl.float_params": "", + "zoom.stealth.webgl.shader_precisions": "35633*36336|127:127:23,35633*36337|127:127:23,35633*36338|127:127:23,35633*36339|31:30:0,35633*36340|31:30:0,35633*36341|31:30:0,35632*36336|127:127:23,35632*36337|127:127:23,35632*36338|127:127:23,35632*36339|31:30:0,35632*36340|31:30:0,35632*36341|31:30:0", + "zoom.stealth.webgl2.enabled": true + } + }, + { + "vendor": "Google Inc. (NVIDIA)", + "renderer_out": "ANGLE (NVIDIA, NVIDIA GeForce GTX 480 Direct3D11 vs_5_0 ps_5_0), or similar", + "prob": 0.013928, + "prefs": { + "zoom.stealth.webgl.renderer": "ANGLE (NVIDIA, NVIDIA GeForce GTX 480 Direct3D11 vs_5_0 ps_5_0, D3D11)", + "zoom.stealth.webgl.vendor": "Google Inc. (NVIDIA)", + "zoom.stealth.webgl.extensions": "ANGLE_instanced_arrays,EXT_blend_minmax,EXT_color_buffer_half_float,EXT_float_blend,EXT_frag_depth,EXT_shader_texture_lod,EXT_sRGB,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_element_index_uint,OES_fbo_render_mipmap,OES_standard_derivatives,OES_texture_float,OES_texture_float_linear,OES_texture_half_float,OES_texture_half_float_linear,OES_vertex_array_object,WEBGL_color_buffer_float,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_depth_texture,WEBGL_draw_buffers,WEBGL_lose_context,WEBGL_provoking_vertex", + "zoom.stealth.webgl2.extensions": "EXT_color_buffer_float,EXT_float_blend,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_draw_buffers_indexed,OES_texture_float_linear,OVR_multiview2,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_lose_context,WEBGL_provoking_vertex", + "zoom.stealth.webgl.int_params": "2849|1,2885|1029,2886|2305,2931|1,2932|513,2961|0,2962|519,2963|2147483647,2964|7680,2965|7680,2966|7680,2967|0,2968|2147483647,3074|1029,3314|0,3315|0,3316|0,3317|4,3330|0,3331|0,3332|0,3333|4,3379|16384,3408|4,3410|8,3411|8,3412|8,3413|8,3414|24,3415|0,10752|0,32777|32774,32824|0,32877|0,32878|0,32883|2048,32936|1,32937|4,32938|1,32968|0,32969|1,32970|0,32971|1,33000|2147483647,33001|2147483647,33170|4352,34016|33984,34024|16384,34045|2,34076|16384,34816|519,34817|7680,34818|7680,34819|7680,34852|8,34853|1029,34854|0,34855|0,34856|0,34857|0,34858|0,34859|0,34860|0,34877|32774,34921|16,34930|16,35071|2048,35076|-8,35077|7,35371|12,35373|12,35374|24,35375|24,35376|65536,35377|212988,35379|200704,35380|256,35657|4096,35658|16380,35659|120,35660|16,35661|32,35723|4352,35738|5121,35739|6408,35968|4,35978|120,35979|4,36003|0,36004|2147483647,36005|2147483647,36063|8,36183|8,36203|4294967294,36347|4095,36348|30,36349|1024,37137|0,37154|120,37157|120,37443|37444,37447|1000000000", + "zoom.stealth.webgl.int2_params": "2928|0:1,3386|32767:32767,33901|1:1024,33902|1:1", + "zoom.stealth.webgl.float_params": "", + "zoom.stealth.webgl.shader_precisions": "35633*36336|127:127:23,35633*36337|127:127:23,35633*36338|127:127:23,35633*36339|31:30:0,35633*36340|31:30:0,35633*36341|31:30:0,35632*36336|127:127:23,35632*36337|127:127:23,35632*36338|127:127:23,35632*36339|31:30:0,35632*36340|31:30:0,35632*36341|31:30:0", + "zoom.stealth.webgl2.enabled": true + } + }, + { + "vendor": "Google Inc. (Microsoft)", + "renderer_out": "ANGLE (Microsoft, Microsoft Basic Render Driver Direct3D11 vs_5_0 ps_5_0), or similar", + "prob": 0.012535, + "prefs": { + "zoom.stealth.webgl.renderer": "ANGLE (Microsoft, Microsoft Basic Render Driver Direct3D11 vs_5_0 ps_5_0, D3D11)", + "zoom.stealth.webgl.vendor": "Google Inc. (Microsoft)", + "zoom.stealth.webgl.extensions": "ANGLE_instanced_arrays,EXT_blend_minmax,EXT_color_buffer_half_float,EXT_float_blend,EXT_frag_depth,EXT_shader_texture_lod,EXT_sRGB,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_element_index_uint,OES_fbo_render_mipmap,OES_standard_derivatives,OES_texture_float,OES_texture_float_linear,OES_texture_half_float,OES_texture_half_float_linear,OES_vertex_array_object,WEBGL_color_buffer_float,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_depth_texture,WEBGL_draw_buffers,WEBGL_lose_context,WEBGL_provoking_vertex", + "zoom.stealth.webgl2.extensions": "EXT_color_buffer_float,EXT_float_blend,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_draw_buffers_indexed,OES_texture_float_linear,OVR_multiview2,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_lose_context,WEBGL_provoking_vertex", + "zoom.stealth.webgl.int_params": "2849|1,2885|1029,2886|2305,2931|1,2932|513,2961|0,2962|519,2963|2147483647,2964|7680,2965|7680,2966|7680,2967|0,2968|2147483647,3074|1029,3314|0,3315|0,3316|0,3317|4,3330|0,3331|0,3332|0,3333|4,3379|16384,3408|4,3410|8,3411|8,3412|8,3413|8,3414|24,3415|0,10752|0,32777|32774,32824|0,32877|0,32878|0,32883|2048,32936|0,32937|0,32938|1,32968|0,32969|1,32970|0,32971|1,33000|2147483647,33001|2147483647,33170|4352,34016|33984,34024|16384,34045|2,34076|16384,34816|519,34817|7680,34818|7680,34819|7680,34852|8,34853|1029,34854|0,34855|0,34856|0,34857|0,34858|0,34859|0,34860|0,34877|32774,34921|16,34930|16,35071|2048,35076|-8,35077|7,35371|12,35373|12,35374|24,35375|24,35376|65536,35377|212992,35379|200704,35380|256,35657|4096,35658|16384,35659|120,35660|16,35661|32,35723|4352,35738|5121,35739|6408,35968|4,35978|120,35979|4,36003|0,36004|2147483647,36005|2147483647,36063|8,36183|16,36203|4294967294,36347|4096,36348|30,36349|1024,37137|0,37154|120,37157|120,37443|37444,37447|1000000000", + "zoom.stealth.webgl.int2_params": "2928|0:1,3386|32767:32767,33901|1:1024,33902|1:1", + "zoom.stealth.webgl.float_params": "", + "zoom.stealth.webgl.shader_precisions": "35633*36336|127:127:23,35633*36337|127:127:23,35633*36338|127:127:23,35633*36339|31:30:0,35633*36340|31:30:0,35633*36341|31:30:0,35632*36336|127:127:23,35632*36337|127:127:23,35632*36338|127:127:23,35632*36339|31:30:0,35632*36340|31:30:0,35632*36341|31:30:0", + "zoom.stealth.webgl2.enabled": true + } + }, + { + "vendor": "Google Inc. (Intel)", + "renderer_out": "ANGLE (Intel, Intel(R) HD Graphics Direct3D11 vs_5_0 ps_5_0)", + "prob": 0.006964, + "prefs": { + "zoom.stealth.webgl.renderer": "ANGLE (Intel, Intel(R) HD Graphics Direct3D11 vs_5_0 ps_5_0)", + "zoom.stealth.webgl.vendor": "Google Inc. (Intel)", + "zoom.stealth.webgl.extensions": "ANGLE_instanced_arrays,EXT_blend_minmax,EXT_color_buffer_half_float,EXT_float_blend,EXT_frag_depth,EXT_shader_texture_lod,EXT_sRGB,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_element_index_uint,OES_fbo_render_mipmap,OES_standard_derivatives,OES_texture_float,OES_texture_float_linear,OES_texture_half_float,OES_texture_half_float_linear,OES_vertex_array_object,WEBGL_color_buffer_float,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_depth_texture,WEBGL_draw_buffers,WEBGL_lose_context,WEBGL_provoking_vertex", + "zoom.stealth.webgl2.extensions": "EXT_color_buffer_float,EXT_float_blend,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_draw_buffers_indexed,OES_texture_float_linear,OVR_multiview2,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_lose_context,WEBGL_provoking_vertex", + "zoom.stealth.webgl.int_params": "2849|1,2885|1029,2886|2305,2931|1,2932|513,2961|0,2962|519,2963|2147483647,2964|7680,2965|7680,2966|7680,2967|0,2968|2147483647,3074|1029,3314|0,3315|0,3316|0,3317|4,3330|0,3331|0,3332|0,3333|4,3379|16384,3408|4,3410|8,3411|8,3412|8,3413|8,3414|24,3415|0,10752|0,32777|32774,32824|0,32877|0,32878|0,32883|2048,32936|1,32937|4,32938|1,32968|0,32969|1,32970|0,32971|1,33000|2147483647,33001|2147483647,33170|4352,34016|33984,34024|16384,34045|2,34076|16384,34816|519,34817|7680,34818|7680,34819|7680,34852|8,34853|1029,34854|0,34855|0,34856|0,34857|0,34858|0,34859|0,34860|0,34877|32774,34921|16,34930|16,35071|2048,35076|-8,35077|7,35371|12,35373|12,35374|24,35375|24,35376|65536,35377|212992,35379|200704,35380|256,35657|4096,35658|16384,35659|120,35660|16,35661|32,35723|4352,35738|5121,35739|6408,35968|4,35978|120,35979|4,36003|0,36004|2147483647,36005|2147483647,36063|8,36183|8,36203|4294967294,36347|4096,36348|30,36349|1024,37137|0,37154|120,37157|120,37443|37444,37447|1000000000", + "zoom.stealth.webgl.int2_params": "2928|0:1,3386|32767:32767,33901|1:1024,33902|1:1", + "zoom.stealth.webgl.float_params": "", + "zoom.stealth.webgl.shader_precisions": "35633*36336|127:127:23,35633*36337|127:127:23,35633*36338|127:127:23,35633*36339|31:30:0,35633*36340|31:30:0,35633*36341|31:30:0,35632*36336|127:127:23,35632*36337|127:127:23,35632*36338|127:127:23,35632*36339|31:30:0,35632*36340|31:30:0,35632*36341|31:30:0", + "zoom.stealth.webgl2.enabled": true + } + }, + { + "vendor": "Google Inc. (Intel)", + "renderer_out": "ANGLE (Intel, Intel(R) HD Graphics Direct3D11 vs_4_1 ps_4_1), or similar", + "prob": 0.004178, + "prefs": { + "zoom.stealth.webgl.renderer": "ANGLE (Intel, Intel(R) HD Graphics Direct3D11 vs_4_1 ps_4_1, D3D11)", + "zoom.stealth.webgl.vendor": "Google Inc. (Intel)", + "zoom.stealth.webgl.extensions": "ANGLE_instanced_arrays,EXT_blend_minmax,EXT_color_buffer_half_float,EXT_float_blend,EXT_frag_depth,EXT_shader_texture_lod,EXT_sRGB,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_element_index_uint,OES_fbo_render_mipmap,OES_standard_derivatives,OES_texture_float,OES_texture_float_linear,OES_texture_half_float,OES_texture_half_float_linear,OES_vertex_array_object,WEBGL_color_buffer_float,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_depth_texture,WEBGL_draw_buffers,WEBGL_lose_context,WEBGL_provoking_vertex", + "zoom.stealth.webgl2.extensions": "EXT_color_buffer_float,EXT_float_blend,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_draw_buffers_indexed,OES_texture_float_linear,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_lose_context,WEBGL_provoking_vertex", + "zoom.stealth.webgl.int_params": "2849|1,2885|1029,2886|2305,2931|1,2932|513,2961|0,2962|519,2963|2147483647,2964|7680,2965|7680,2966|7680,2967|0,2968|2147483647,3074|1029,3314|0,3315|0,3316|0,3317|4,3330|0,3331|0,3332|0,3333|4,3379|8192,3408|4,3410|8,3411|8,3412|8,3413|8,3414|24,3415|0,10752|0,32777|32774,32824|0,32877|0,32878|0,32883|2048,32936|1,32937|4,32938|1,32968|0,32969|1,32970|0,32971|1,33000|2147483647,33001|2147483647,33170|4352,34016|33984,34024|8192,34045|2,34076|8192,34816|519,34817|7680,34818|7680,34819|7680,34852|8,34853|1029,34854|0,34855|0,34856|0,34857|0,34858|0,34859|0,34860|0,34877|32774,34921|16,34930|16,35071|512,35076|-8,35077|7,35371|12,35373|12,35374|24,35375|24,35376|65536,35377|212992,35379|200704,35380|256,35657|4096,35658|16384,35659|120,35660|16,35661|32,35723|4352,35738|5121,35739|6408,35968|4,35978|120,35979|4,36003|0,36004|2147483647,36005|2147483647,36063|8,36183|4,36203|4294967294,36347|4096,36348|30,36349|1024,37137|0,37154|120,37157|120,37443|37444,37447|1000000000", + "zoom.stealth.webgl.int2_params": "2928|0:1,3386|16383:16383,33901|1:1024,33902|1:1", + "zoom.stealth.webgl.float_params": "", + "zoom.stealth.webgl.shader_precisions": "35633*36336|127:127:23,35633*36337|127:127:23,35633*36338|127:127:23,35633*36339|31:30:0,35633*36340|31:30:0,35633*36341|31:30:0,35632*36336|127:127:23,35632*36337|127:127:23,35632*36338|127:127:23,35632*36339|31:30:0,35632*36340|31:30:0,35632*36341|31:30:0", + "zoom.stealth.webgl2.enabled": true + } + }, + { + "vendor": "Google Inc. (Google)", + "renderer_out": "ANGLE (Google, Vulkan 1.3.0 (SwiftShader Device (Subzero) (0x0000C0DE)), SwiftShader driver)", + "prob": 0.002786, + "prefs": { + "zoom.stealth.webgl.renderer": "ANGLE (Google, Vulkan 1.3.0 (SwiftShader Device (Subzero) (0x0000C0DE)), SwiftShader driver)", + "zoom.stealth.webgl.vendor": "Google Inc. (Google)", + "zoom.stealth.webgl.extensions": "ANGLE_instanced_arrays,EXT_blend_minmax,EXT_color_buffer_half_float,EXT_float_blend,EXT_frag_depth,EXT_shader_texture_lod,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,EXT_sRGB,OES_element_index_uint,OES_fbo_render_mipmap,OES_standard_derivatives,OES_texture_float,OES_texture_float_linear,OES_texture_half_float,OES_texture_half_float_linear,OES_vertex_array_object,WEBGL_color_buffer_float,WEBGL_compressed_texture_astc,WEBGL_compressed_texture_etc,WEBGL_compressed_texture_etc1,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_depth_texture,WEBGL_draw_buffers,WEBGL_lose_context,WEBGL_multi_draw", + "zoom.stealth.webgl2.extensions": "EXT_color_buffer_float,EXT_color_buffer_half_float,EXT_float_blend,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,EXT_texture_norm16,OES_draw_buffers_indexed,OES_texture_float_linear,OVR_multiview2,WEBGL_clip_cull_distance,WEBGL_compressed_texture_astc,WEBGL_compressed_texture_etc,WEBGL_compressed_texture_etc1,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_lose_context,WEBGL_multi_draw", + "zoom.stealth.webgl.int_params": "2849|1,2885|1029,2886|2305,2931|1,2932|513,2961|0,2962|519,2963|2147483647,2964|7680,2965|7680,2966|7680,2967|0,2968|2147483647,3074|1029,3314|0,3315|0,3316|0,3317|4,3330|0,3331|0,3332|0,3333|4,3379|8192,3408|4,3410|8,3411|8,3412|8,3413|8,3414|24,3415|0,10752|0,32777|32774,32824|0,32877|0,32878|0,32883|2048,32936|1,32937|4,32938|1,32968|0,32969|1,32970|0,32971|1,33000|2147483647,33001|2147483647,33170|4352,34016|33984,34024|8192,34045|15,34076|16384,34816|519,34817|7680,34818|7680,34819|7680,34852|8,34853|1029,34854|1029,34855|1029,34856|1029,34857|1029,34858|1029,34859|1029,34860|1029,34877|32774,34921|16,34930|32,35071|2048,35076|-8,35077|7,35371|14,35373|14,35374|60,35375|72,35376|65536,35377|245760,35379|245760,35380|256,35657|16384,35658|16384,35659|124,35660|32,35661|64,35723|4352,35738|5121,35739|6408,35968|4,35978|128,35979|4,36003|0,36004|2147483647,36005|2147483647,36063|8,36183|4,36203|4294967294,36345|1,36347|4096,36348|31,36349|4096,37137|0,37154|128,37157|128,37443|37444,37447|0", + "zoom.stealth.webgl.int2_params": "2928|0:1,3386|8192:8192,33901|1:1023,33902|1:1", + "zoom.stealth.webgl.float_params": "", + "zoom.stealth.webgl.shader_precisions": "35633*36336|15:15:10,35633*36337|15:15:10,35633*36338|127:127:23,35633*36339|15:14:0,35633*36340|15:14:0,35633*36341|31:30:0,35632*36336|15:15:10,35632*36337|15:15:10,35632*36338|127:127:23,35632*36339|15:14:0,35632*36340|15:14:0,35632*36341|31:30:0", + "zoom.stealth.webgl2.enabled": true + } + }, + { + "vendor": "Google Inc. (AMD)", + "renderer_out": "ANGLE (AMD, Radeon R9 200 Series Direct3D11 vs_5_0 ps_5_0)", + "prob": 0.001393, + "prefs": { + "zoom.stealth.webgl.renderer": "ANGLE (AMD, Radeon R9 200 Series Direct3D11 vs_5_0 ps_5_0)", + "zoom.stealth.webgl.vendor": "Google Inc. (AMD)", + "zoom.stealth.webgl.extensions": "ANGLE_instanced_arrays,EXT_blend_minmax,EXT_color_buffer_half_float,EXT_float_blend,EXT_frag_depth,EXT_shader_texture_lod,EXT_sRGB,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_element_index_uint,OES_fbo_render_mipmap,OES_standard_derivatives,OES_texture_float,OES_texture_float_linear,OES_texture_half_float,OES_texture_half_float_linear,OES_vertex_array_object,WEBGL_color_buffer_float,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_depth_texture,WEBGL_draw_buffers,WEBGL_lose_context,WEBGL_provoking_vertex", + "zoom.stealth.webgl2.extensions": "EXT_color_buffer_float,EXT_float_blend,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_draw_buffers_indexed,OES_texture_float_linear,OVR_multiview2,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_lose_context,WEBGL_provoking_vertex", + "zoom.stealth.webgl.int_params": "2849|1,2885|1029,2886|2305,2931|1,2932|513,2961|0,2962|519,2963|2147483647,2964|7680,2965|7680,2966|7680,2967|0,2968|2147483647,3074|1029,3314|0,3315|0,3316|0,3317|4,3330|0,3331|0,3332|0,3333|4,3379|16384,3408|4,3410|8,3411|8,3412|8,3413|8,3414|24,3415|0,10752|0,32777|32774,32824|0,32877|0,32878|0,32883|2048,32936|1,32937|4,32938|1,32968|0,32969|1,32970|0,32971|1,33000|2147483647,33001|2147483647,33170|4352,34016|33984,34024|16384,34045|2,34076|16384,34816|519,34817|7680,34818|7680,34819|7680,34852|8,34853|1029,34854|0,34855|0,34856|0,34857|0,34858|0,34859|0,34860|0,34877|32774,34921|16,34930|16,35071|2048,35076|-8,35077|7,35371|12,35373|12,35374|24,35375|24,35376|65536,35377|212992,35379|200704,35380|256,35657|4096,35658|16384,35659|120,35660|16,35661|32,35723|4352,35738|5121,35739|6408,35968|4,35978|120,35979|4,36003|0,36004|2147483647,36005|2147483647,36063|8,36183|8,36203|4294967294,36347|4096,36348|30,36349|1024,37137|0,37154|120,37157|120,37443|37444,37447|1000000000", + "zoom.stealth.webgl.int2_params": "2928|0:1,3386|32767:32767,33901|1:1024,33902|1:1", + "zoom.stealth.webgl.float_params": "", + "zoom.stealth.webgl.shader_precisions": "35633*36336|127:127:23,35633*36337|127:127:23,35633*36338|127:127:23,35633*36339|31:30:0,35633*36340|31:30:0,35633*36341|31:30:0,35632*36336|127:127:23,35632*36337|127:127:23,35632*36338|127:127:23,35632*36339|31:30:0,35632*36340|31:30:0,35632*36341|31:30:0", + "zoom.stealth.webgl2.enabled": true + } + }, + { + "vendor": "Google Inc. (Intel)", + "renderer_out": "ANGLE (Intel, Intel(R) HD Graphics Direct3D11 vs_4_0 ps_4_0)", + "prob": 0.001393, + "prefs": { + "zoom.stealth.webgl.renderer": "ANGLE (Intel, Intel(R) HD Graphics Direct3D11 vs_4_0 ps_4_0)", + "zoom.stealth.webgl.vendor": "Google Inc. (Intel)", + "zoom.stealth.webgl.extensions": "ANGLE_instanced_arrays,EXT_blend_minmax,EXT_color_buffer_half_float,EXT_float_blend,EXT_frag_depth,EXT_shader_texture_lod,EXT_sRGB,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_element_index_uint,OES_fbo_render_mipmap,OES_standard_derivatives,OES_texture_float,OES_texture_float_linear,OES_texture_half_float,OES_texture_half_float_linear,OES_vertex_array_object,WEBGL_color_buffer_float,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_depth_texture,WEBGL_draw_buffers,WEBGL_lose_context,WEBGL_provoking_vertex", + "zoom.stealth.webgl2.extensions": "", + "zoom.stealth.webgl.int_params": "2849|1,2885|1029,2886|2305,2931|1,2932|513,2961|0,2962|519,2963|2147483647,2964|7680,2965|7680,2966|7680,2967|0,2968|2147483647,3317|4,3333|4,3379|8192,3408|4,3410|8,3411|8,3412|8,3413|8,3414|24,3415|0,10752|0,32777|32774,32824|0,32936|0,32937|0,32938|1,32968|0,32969|1,32970|0,32971|1,33170|4352,34016|33984,34024|8192,34076|8192,34816|519,34817|7680,34818|7680,34819|7680,34877|32774,34921|16,34930|16,35660|16,35661|32,35738|5121,35739|6408,36003|0,36004|2147483647,36005|2147483647,36347|4096,36348|14,36349|1024,37443|37444", + "zoom.stealth.webgl.int2_params": "2928|0:1,3386|16383:16383,33901|1:1024,33902|1:1", + "zoom.stealth.webgl.float_params": "", + "zoom.stealth.webgl.shader_precisions": "35633*36336|127:127:23,35633*36337|127:127:23,35633*36338|127:127:23,35633*36339|31:30:0,35633*36340|31:30:0,35633*36341|31:30:0,35632*36336|127:127:23,35632*36337|127:127:23,35632*36338|127:127:23,35632*36339|31:30:0,35632*36340|31:30:0,35632*36341|31:30:0", + "zoom.stealth.webgl2.enabled": false + } + }, + { + "vendor": "Google Inc. (NVIDIA)", + "renderer_out": "ANGLE (NVIDIA, NVIDIA GeForce 8800 GTX Direct3D11 vs_4_0 ps_4_0)", + "prob": 0.001393, + "prefs": { + "zoom.stealth.webgl.renderer": "ANGLE (NVIDIA, NVIDIA GeForce 8800 GTX Direct3D11 vs_4_0 ps_4_0)", + "zoom.stealth.webgl.vendor": "Google Inc. (NVIDIA)", + "zoom.stealth.webgl.extensions": "ANGLE_instanced_arrays,EXT_blend_minmax,EXT_color_buffer_half_float,EXT_float_blend,EXT_frag_depth,EXT_shader_texture_lod,EXT_sRGB,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_element_index_uint,OES_fbo_render_mipmap,OES_standard_derivatives,OES_texture_float,OES_texture_float_linear,OES_texture_half_float,OES_texture_half_float_linear,OES_vertex_array_object,WEBGL_color_buffer_float,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_depth_texture,WEBGL_draw_buffers,WEBGL_lose_context,WEBGL_provoking_vertex", + "zoom.stealth.webgl2.extensions": "", + "zoom.stealth.webgl.int_params": "2849|1,2885|1029,2886|2305,2931|1,2932|513,2961|0,2962|519,2963|2147483647,2964|7680,2965|7680,2966|7680,2967|0,2968|2147483647,3317|4,3333|4,3379|8192,3408|4,3410|8,3411|8,3412|8,3413|8,3414|24,3415|0,10752|0,32777|32774,32824|0,32936|1,32937|4,32938|1,32968|0,32969|1,32970|0,32971|1,33170|4352,34016|33984,34024|8192,34076|8192,34816|519,34817|7680,34818|7680,34819|7680,34877|32774,34921|16,34930|16,35660|16,35661|32,35738|5121,35739|6408,36003|0,36004|2147483647,36005|2147483647,36347|4095,36348|14,36349|1024,37443|37444", + "zoom.stealth.webgl.int2_params": "2928|0:1,3386|16383:16383,33901|1:1024,33902|1:1", + "zoom.stealth.webgl.float_params": "", + "zoom.stealth.webgl.shader_precisions": "35633*36336|127:127:23,35633*36337|127:127:23,35633*36338|127:127:23,35633*36339|31:30:0,35633*36340|31:30:0,35633*36341|31:30:0,35632*36336|127:127:23,35632*36337|127:127:23,35632*36338|127:127:23,35632*36339|31:30:0,35632*36340|31:30:0,35632*36341|31:30:0", + "zoom.stealth.webgl2.enabled": false + } + }, + { + "vendor": "Google Inc. (Intel)", + "renderer_out": "ANGLE (Intel, Intel 945GM Direct3D11 vs_4_0 ps_4_0)", + "prob": 0.001393, + "prefs": { + "zoom.stealth.webgl.renderer": "ANGLE (Intel, Intel 945GM Direct3D11 vs_4_0 ps_4_0)", + "zoom.stealth.webgl.vendor": "Google Inc. (Intel)", + "zoom.stealth.webgl.extensions": "ANGLE_instanced_arrays,EXT_blend_minmax,EXT_color_buffer_half_float,EXT_float_blend,EXT_frag_depth,EXT_shader_texture_lod,EXT_sRGB,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_element_index_uint,OES_fbo_render_mipmap,OES_standard_derivatives,OES_texture_float,OES_texture_half_float,OES_texture_half_float_linear,OES_vertex_array_object,WEBGL_color_buffer_float,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_depth_texture,WEBGL_draw_buffers,WEBGL_lose_context,WEBGL_provoking_vertex", + "zoom.stealth.webgl2.extensions": "", + "zoom.stealth.webgl.int_params": "2849|1,2885|1029,2886|2305,2931|1,2932|513,2961|0,2962|519,2963|2147483647,2964|7680,2965|7680,2966|7680,2967|0,2968|2147483647,3317|4,3333|4,3379|8192,3408|4,3410|8,3411|8,3412|8,3413|8,3414|24,3415|0,10752|0,32777|32774,32824|0,32936|0,32937|0,32938|1,32968|0,32969|1,32970|0,32971|1,33170|4352,34016|33984,34024|8192,34076|8192,34816|519,34817|7680,34818|7680,34819|7680,34877|32774,34921|16,34930|16,35660|16,35661|32,35738|5121,35739|6408,36003|0,36004|2147483647,36005|2147483647,36347|4096,36348|14,36349|1024,37443|37444", + "zoom.stealth.webgl.int2_params": "2928|0:1,3386|16383:16383,33901|1:1024,33902|1:1", + "zoom.stealth.webgl.float_params": "", + "zoom.stealth.webgl.shader_precisions": "35633*36336|127:127:23,35633*36337|127:127:23,35633*36338|127:127:23,35633*36339|31:30:0,35633*36340|31:30:0,35633*36341|31:30:0,35632*36336|127:127:23,35632*36337|127:127:23,35632*36338|127:127:23,35632*36339|31:30:0,35632*36340|31:30:0,35632*36341|31:30:0", + "zoom.stealth.webgl2.enabled": false + } + }, + { + "vendor": "Google Inc. (Intel)", + "renderer_out": "ANGLE (Intel, Intel(R) HD Graphics Direct3D11 vs_4_1 ps_4_1)", + "prob": 0.001393, + "prefs": { + "zoom.stealth.webgl.renderer": "ANGLE (Intel, Intel(R) HD Graphics Direct3D11 vs_4_1 ps_4_1)", + "zoom.stealth.webgl.vendor": "Google Inc. (Intel)", + "zoom.stealth.webgl.extensions": "ANGLE_instanced_arrays,EXT_blend_minmax,EXT_color_buffer_half_float,EXT_float_blend,EXT_frag_depth,EXT_shader_texture_lod,EXT_sRGB,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_element_index_uint,OES_fbo_render_mipmap,OES_standard_derivatives,OES_texture_float,OES_texture_float_linear,OES_texture_half_float,OES_texture_half_float_linear,OES_vertex_array_object,WEBGL_color_buffer_float,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_depth_texture,WEBGL_draw_buffers,WEBGL_lose_context,WEBGL_provoking_vertex", + "zoom.stealth.webgl2.extensions": "EXT_color_buffer_float,EXT_float_blend,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_draw_buffers_indexed,OES_texture_float_linear,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_lose_context,WEBGL_provoking_vertex", + "zoom.stealth.webgl.int_params": "2849|1,2885|1029,2886|2305,2931|1,2932|513,2961|0,2962|519,2963|2147483647,2964|7680,2965|7680,2966|7680,2967|0,2968|2147483647,3074|1029,3314|0,3315|0,3316|0,3317|4,3330|0,3331|0,3332|0,3333|4,3379|8192,3408|4,3410|8,3411|8,3412|8,3413|8,3414|24,3415|0,10752|0,32777|32774,32824|0,32877|0,32878|0,32883|2048,32936|1,32937|4,32938|1,32968|0,32969|1,32970|0,32971|1,33000|2147483647,33001|2147483647,33170|4352,34016|33984,34024|8192,34045|2,34076|8192,34816|519,34817|7680,34818|7680,34819|7680,34852|8,34853|1029,34854|0,34855|0,34856|0,34857|0,34858|0,34859|0,34860|0,34877|32774,34921|16,34930|16,35071|512,35076|-8,35077|7,35371|12,35373|12,35374|24,35375|24,35376|65536,35377|212992,35379|200704,35380|256,35657|4096,35658|16384,35659|120,35660|16,35661|32,35723|4352,35738|5121,35739|6408,35968|4,35978|120,35979|4,36003|0,36004|2147483647,36005|2147483647,36063|8,36183|4,36203|4294967294,36347|4096,36348|30,36349|1024,37137|0,37154|120,37157|120,37443|37444,37447|1000000000", + "zoom.stealth.webgl.int2_params": "2928|0:1,3386|16383:16383,33901|1:1024,33902|1:1", + "zoom.stealth.webgl.float_params": "", + "zoom.stealth.webgl.shader_precisions": "35633*36336|127:127:23,35633*36337|127:127:23,35633*36338|127:127:23,35633*36339|31:30:0,35633*36340|31:30:0,35633*36341|31:30:0,35632*36336|127:127:23,35632*36337|127:127:23,35632*36338|127:127:23,35632*36339|31:30:0,35632*36340|31:30:0,35632*36341|31:30:0", + "zoom.stealth.webgl2.enabled": true + } + }, + { + "vendor": "Google Inc. (NVIDIA)", + "renderer_out": "ANGLE (NVIDIA, NVIDIA GeForce GTX 980 Direct3D11 vs_5_0 ps_5_0)", + "prob": 0.001393, + "prefs": { + "zoom.stealth.webgl.renderer": "ANGLE (NVIDIA, NVIDIA GeForce GTX 980 Direct3D11 vs_5_0 ps_5_0)", + "zoom.stealth.webgl.vendor": "Google Inc. (NVIDIA)", + "zoom.stealth.webgl.extensions": "ANGLE_instanced_arrays,EXT_blend_minmax,EXT_color_buffer_half_float,EXT_float_blend,EXT_frag_depth,EXT_shader_texture_lod,EXT_sRGB,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_element_index_uint,OES_fbo_render_mipmap,OES_standard_derivatives,OES_texture_float,OES_texture_float_linear,OES_texture_half_float,OES_texture_half_float_linear,OES_vertex_array_object,WEBGL_color_buffer_float,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_depth_texture,WEBGL_draw_buffers,WEBGL_lose_context,WEBGL_provoking_vertex", + "zoom.stealth.webgl2.extensions": "EXT_color_buffer_float,EXT_float_blend,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_draw_buffers_indexed,OES_texture_float_linear,OVR_multiview2,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_lose_context,WEBGL_provoking_vertex", + "zoom.stealth.webgl.int_params": "2849|1,2885|1029,2886|2305,2931|1,2932|513,2961|0,2962|519,2963|2147483647,2964|7680,2965|7680,2966|7680,2967|0,2968|2147483647,3074|1029,3314|0,3315|0,3316|0,3317|4,3330|0,3331|0,3332|0,3333|4,3379|16384,3408|4,3410|8,3411|8,3412|8,3413|8,3414|24,3415|0,10752|0,32777|32774,32824|0,32877|0,32878|0,32883|2048,32936|1,32937|4,32938|1,32968|0,32969|1,32970|0,32971|1,33000|2147483647,33001|2147483647,33170|4352,34016|33984,34024|16384,34045|2,34076|16384,34816|519,34817|7680,34818|7680,34819|7680,34852|8,34853|1029,34854|0,34855|0,34856|0,34857|0,34858|0,34859|0,34860|0,34877|32774,34921|16,34930|16,35071|2048,35076|-8,35077|7,35371|12,35373|12,35374|24,35375|24,35376|65536,35377|212988,35379|200704,35380|256,35657|4096,35658|16380,35659|120,35660|16,35661|32,35723|4352,35738|5121,35739|6408,35968|4,35978|120,35979|4,36003|0,36004|2147483647,36005|2147483647,36063|8,36183|8,36203|4294967294,36347|4095,36348|30,36349|1024,37137|0,37154|120,37157|120,37443|37444,37447|1000000000", + "zoom.stealth.webgl.int2_params": "2928|0:1,3386|32767:32767,33901|1:1024,33902|1:1", + "zoom.stealth.webgl.float_params": "", + "zoom.stealth.webgl.shader_precisions": "35633*36336|127:127:23,35633*36337|127:127:23,35633*36338|127:127:23,35633*36339|31:30:0,35633*36340|31:30:0,35633*36341|31:30:0,35632*36336|127:127:23,35632*36337|127:127:23,35632*36338|127:127:23,35632*36339|31:30:0,35632*36340|31:30:0,35632*36341|31:30:0", + "zoom.stealth.webgl2.enabled": true + } + }, + { + "vendor": "Google Inc. (NVIDIA)", + "renderer_out": "ANGLE (NVIDIA, NVIDIA GeForce GTX 480 Direct3D11 vs_5_0 ps_5_0)", + "prob": 0.001393, + "prefs": { + "zoom.stealth.webgl.renderer": "ANGLE (NVIDIA, NVIDIA GeForce GTX 480 Direct3D11 vs_5_0 ps_5_0)", + "zoom.stealth.webgl.vendor": "Google Inc. (NVIDIA)", + "zoom.stealth.webgl.extensions": "ANGLE_instanced_arrays,EXT_blend_minmax,EXT_color_buffer_half_float,EXT_float_blend,EXT_frag_depth,EXT_shader_texture_lod,EXT_sRGB,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_element_index_uint,OES_fbo_render_mipmap,OES_standard_derivatives,OES_texture_float,OES_texture_float_linear,OES_texture_half_float,OES_texture_half_float_linear,OES_vertex_array_object,WEBGL_color_buffer_float,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_depth_texture,WEBGL_draw_buffers,WEBGL_lose_context,WEBGL_provoking_vertex", + "zoom.stealth.webgl2.extensions": "EXT_color_buffer_float,EXT_float_blend,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_draw_buffers_indexed,OES_texture_float_linear,OVR_multiview2,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_lose_context,WEBGL_provoking_vertex", + "zoom.stealth.webgl.int_params": "2849|1,2885|1029,2886|2305,2931|1,2932|513,2961|0,2962|519,2963|2147483647,2964|7680,2965|7680,2966|7680,2967|0,2968|2147483647,3074|1029,3314|0,3315|0,3316|0,3317|4,3330|0,3331|0,3332|0,3333|4,3379|16384,3408|4,3410|8,3411|8,3412|8,3413|8,3414|24,3415|0,10752|0,32777|32774,32824|0,32877|0,32878|0,32883|2048,32936|1,32937|4,32938|1,32968|0,32969|1,32970|0,32971|1,33000|2147483647,33001|2147483647,33170|4352,34016|33984,34024|16384,34045|2,34076|16384,34816|519,34817|7680,34818|7680,34819|7680,34852|8,34853|1029,34854|0,34855|0,34856|0,34857|0,34858|0,34859|0,34860|0,34877|32774,34921|16,34930|16,35071|2048,35076|-8,35077|7,35371|12,35373|12,35374|24,35375|24,35376|65536,35377|212988,35379|200704,35380|256,35657|4096,35658|16380,35659|120,35660|16,35661|32,35723|4352,35738|5121,35739|6408,35968|4,35978|120,35979|4,36003|0,36004|2147483647,36005|2147483647,36063|8,36183|8,36203|4294967294,36347|4095,36348|30,36349|1024,37137|0,37154|120,37157|120,37443|37444,37447|1000000000", + "zoom.stealth.webgl.int2_params": "2928|0:1,3386|32767:32767,33901|1:1024,33902|1:1", + "zoom.stealth.webgl.float_params": "", + "zoom.stealth.webgl.shader_precisions": "35633*36336|127:127:23,35633*36337|127:127:23,35633*36338|127:127:23,35633*36339|31:30:0,35633*36340|31:30:0,35633*36341|31:30:0,35632*36336|127:127:23,35632*36337|127:127:23,35632*36338|127:127:23,35632*36339|31:30:0,35632*36340|31:30:0,35632*36341|31:30:0", + "zoom.stealth.webgl2.enabled": true + } + } + ], + "mac": [ + { + "vendor": "Apple", + "renderer_out": "Apple M1, or similar", + "prob": 0.84322, + "prefs": { + "zoom.stealth.webgl.renderer": "Apple M1, or similar", + "zoom.stealth.webgl.vendor": "Apple", + "zoom.stealth.webgl.extensions": "ANGLE_instanced_arrays,EXT_blend_minmax,EXT_color_buffer_half_float,EXT_depth_clamp,EXT_float_blend,EXT_frag_depth,EXT_shader_texture_lod,EXT_sRGB,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_element_index_uint,OES_fbo_render_mipmap,OES_standard_derivatives,OES_texture_float,OES_texture_float_linear,OES_texture_half_float,OES_texture_half_float_linear,OES_vertex_array_object,WEBGL_color_buffer_float,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_depth_texture,WEBGL_draw_buffers,WEBGL_lose_context,WEBGL_provoking_vertex", + "zoom.stealth.webgl2.extensions": "EXT_color_buffer_float,EXT_depth_clamp,EXT_float_blend,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_draw_buffers_indexed,OES_texture_float_linear,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_lose_context,WEBGL_provoking_vertex", + "zoom.stealth.webgl.int_params": "2849|1,2885|1029,2886|2305,2931|1,2932|513,2961|0,2962|519,2963|4294967295,2964|7680,2965|7680,2966|7680,2967|0,2968|4294967295,3074|1029,3314|0,3315|0,3316|0,3317|4,3330|0,3331|0,3332|0,3333|4,3379|8192,3408|4,3410|8,3411|8,3412|8,3413|8,3414|24,3415|0,10752|0,32777|32774,32824|0,32877|0,32878|0,32883|2048,32936|1,32937|4,32938|1,32968|0,32969|1,32970|0,32971|1,33000|1048575,33001|150000,33170|4352,34016|33984,34024|8192,34045|16,34076|8192,34816|519,34817|7680,34818|7680,34819|7680,34852|8,34853|1029,34854|0,34855|0,34856|0,34857|0,34858|0,34859|0,34860|0,34877|32774,34921|16,34930|16,35071|2048,35076|-8,35077|7,35371|16,35373|16,35374|80,35375|80,35376|65536,35377|266240,35379|266240,35380|256,35657|4096,35658|4096,35659|124,35660|16,35661|80,35723|4352,35738|5121,35739|6408,35968|4,35978|64,35979|4,36003|0,36004|4294967295,36005|4294967295,36063|8,36183|4,36203|4294967295,36347|1024,36348|32,36349|1024,37137|18446744073709552000,37154|64,37157|128,37443|37444,37447|1000000000", + "zoom.stealth.webgl.int2_params": "2928|0:1,3386|16384:16384,33901|1:64,33902|1:1", + "zoom.stealth.webgl.float_params": "", + "zoom.stealth.webgl.shader_precisions": "35633*36336|127:127:23,35633*36337|127:127:23,35633*36338|127:127:23,35633*36339|24:24:0,35633*36340|24:24:0,35633*36341|24:24:0,35632*36336|127:127:23,35632*36337|127:127:23,35632*36338|127:127:23,35632*36339|24:24:0,35632*36340|24:24:0,35632*36341|24:24:0", + "zoom.stealth.webgl2.enabled": true + } + }, + { + "vendor": "Intel Inc.", + "renderer_out": "Intel(R) HD Graphics 400, or similar", + "prob": 0.076271, + "prefs": { + "zoom.stealth.webgl.renderer": "Intel(R) HD Graphics 400, or similar", + "zoom.stealth.webgl.vendor": "Intel Inc.", + "zoom.stealth.webgl.extensions": "ANGLE_instanced_arrays,EXT_blend_minmax,EXT_color_buffer_half_float,EXT_depth_clamp,EXT_float_blend,EXT_frag_depth,EXT_shader_texture_lod,EXT_sRGB,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_element_index_uint,OES_fbo_render_mipmap,OES_standard_derivatives,OES_texture_float,OES_texture_float_linear,OES_texture_half_float,OES_texture_half_float_linear,OES_vertex_array_object,WEBGL_color_buffer_float,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_depth_texture,WEBGL_draw_buffers,WEBGL_lose_context,WEBGL_provoking_vertex", + "zoom.stealth.webgl2.extensions": "EXT_color_buffer_float,EXT_depth_clamp,EXT_float_blend,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_draw_buffers_indexed,OES_texture_float_linear,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_lose_context,WEBGL_provoking_vertex", + "zoom.stealth.webgl.int_params": "2849|1,2885|1029,2886|2305,2931|1,2932|513,2961|0,2962|519,2963|4294967295,2964|7680,2965|7680,2966|7680,2967|0,2968|4294967295,3074|1029,3314|0,3315|0,3316|0,3317|4,3330|0,3331|0,3332|0,3333|4,3379|8192,3408|8,3410|8,3411|8,3412|8,3413|8,3414|24,3415|0,10752|0,32777|32774,32824|0,32877|0,32878|0,32883|2048,32936|1,32937|4,32938|1,32968|0,32969|1,32970|0,32971|1,33000|1048575,33001|150000,33170|4352,34016|33984,34024|8192,34045|16,34076|8192,34816|519,34817|7680,34818|7680,34819|7680,34852|8,34853|1029,34854|0,34855|0,34856|0,34857|0,34858|0,34859|0,34860|0,34877|32774,34921|16,34930|16,35071|2048,35076|-8,35077|7,35371|15,35373|15,35374|75,35375|75,35376|65536,35377|249856,35379|249856,35380|256,35657|4096,35658|4096,35659|60,35660|16,35661|80,35723|4352,35738|5121,35739|6408,35968|4,35978|64,35979|4,36003|0,36004|4294967295,36005|4294967295,36063|8,36183|16,36203|4294967295,36347|1024,36348|32,36349|1024,37137|18446744073709552000,37154|128,37157|128,37443|37444,37447|1000000000", + "zoom.stealth.webgl.int2_params": "2928|0:1,3386|16384:16384,33902|1:1", + "zoom.stealth.webgl.float_params": "33901|1:255.875", + "zoom.stealth.webgl.shader_precisions": "35633*36336|127:127:23,35633*36337|127:127:23,35633*36338|127:127:23,35633*36339|24:24:0,35633*36340|24:24:0,35633*36341|24:24:0,35632*36336|127:127:23,35632*36337|127:127:23,35632*36338|127:127:23,35632*36339|24:24:0,35632*36340|24:24:0,35632*36341|24:24:0", + "zoom.stealth.webgl2.enabled": true + } + }, + { + "vendor": "ATI Technologies Inc.", + "renderer_out": "Radeon R9 200 Series, or similar", + "prob": 0.038136, + "prefs": { + "zoom.stealth.webgl.renderer": "Radeon R9 200 Series, or similar", + "zoom.stealth.webgl.vendor": "ATI Technologies Inc.", + "zoom.stealth.webgl.extensions": "ANGLE_instanced_arrays,EXT_blend_minmax,EXT_color_buffer_half_float,EXT_depth_clamp,EXT_float_blend,EXT_frag_depth,EXT_shader_texture_lod,EXT_sRGB,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_element_index_uint,OES_fbo_render_mipmap,OES_standard_derivatives,OES_texture_float,OES_texture_float_linear,OES_texture_half_float,OES_texture_half_float_linear,OES_vertex_array_object,WEBGL_color_buffer_float,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_depth_texture,WEBGL_draw_buffers,WEBGL_lose_context,WEBGL_provoking_vertex", + "zoom.stealth.webgl2.extensions": "EXT_color_buffer_float,EXT_depth_clamp,EXT_float_blend,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_draw_buffers_indexed,OES_texture_float_linear,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_lose_context,WEBGL_provoking_vertex", + "zoom.stealth.webgl.int_params": "2849|1,2885|1029,2886|2305,2931|1,2932|513,2961|0,2962|519,2963|4294967295,2964|7680,2965|7680,2966|7680,2967|0,2968|4294967295,3074|1029,3314|0,3315|0,3316|0,3317|4,3330|0,3331|0,3332|0,3333|4,3379|8192,3408|8,3410|8,3411|8,3412|8,3413|8,3414|24,3415|0,10752|0,32777|32774,32824|0,32877|0,32878|0,32883|16384,32936|1,32937|4,32938|1,32968|0,32969|1,32970|0,32971|1,33000|1048575,33001|150000,33170|4352,34016|33984,34024|8192,34045|16,34076|8192,34816|519,34817|7680,34818|7680,34819|7680,34852|8,34853|1029,34854|0,34855|0,34856|0,34857|0,34858|0,34859|0,34860|0,34877|32774,34921|16,34930|16,35071|2048,35076|-8,35077|7,35371|16,35373|16,35374|80,35375|80,35376|65536,35377|266240,35379|266240,35380|256,35657|4096,35658|4096,35659|128,35660|16,35661|80,35723|4352,35738|5121,35739|6408,35968|4,35978|64,35979|4,36003|0,36004|4294967295,36005|4294967295,36063|8,36183|8,36203|4294967295,36347|1024,36348|32,36349|1024,37137|18446744073709552000,37154|128,37157|128,37443|37444,37447|1000000000", + "zoom.stealth.webgl.int2_params": "2928|0:1,3386|16384:16384,33901|1:8191,33902|1:1", + "zoom.stealth.webgl.float_params": "", + "zoom.stealth.webgl.shader_precisions": "35633*36336|127:127:23,35633*36337|127:127:23,35633*36338|127:127:23,35633*36339|24:24:0,35633*36340|24:24:0,35633*36341|24:24:0,35632*36336|127:127:23,35632*36337|127:127:23,35632*36338|127:127:23,35632*36339|24:24:0,35632*36340|24:24:0,35632*36341|24:24:0", + "zoom.stealth.webgl2.enabled": true + } + }, + { + "vendor": "Intel Inc.", + "renderer_out": "Intel(R) HD Graphics, or similar", + "prob": 0.033898, + "prefs": { + "zoom.stealth.webgl.renderer": "Intel(R) HD Graphics, or similar", + "zoom.stealth.webgl.vendor": "Intel Inc.", + "zoom.stealth.webgl.extensions": "ANGLE_instanced_arrays,EXT_blend_minmax,EXT_color_buffer_half_float,EXT_depth_clamp,EXT_float_blend,EXT_frag_depth,EXT_shader_texture_lod,EXT_sRGB,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_element_index_uint,OES_fbo_render_mipmap,OES_standard_derivatives,OES_texture_float,OES_texture_float_linear,OES_texture_half_float,OES_texture_half_float_linear,OES_vertex_array_object,WEBGL_color_buffer_float,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_depth_texture,WEBGL_draw_buffers,WEBGL_lose_context,WEBGL_provoking_vertex", + "zoom.stealth.webgl2.extensions": "EXT_color_buffer_float,EXT_depth_clamp,EXT_float_blend,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_draw_buffers_indexed,OES_texture_float_linear,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_lose_context,WEBGL_provoking_vertex", + "zoom.stealth.webgl.int_params": "2849|1,2885|1029,2886|2305,2931|1,2932|513,2961|0,2962|519,2963|4294967295,2964|7680,2965|7680,2966|7680,2967|0,2968|4294967295,3074|1029,3314|0,3315|0,3316|0,3317|4,3330|0,3331|0,3332|0,3333|4,3379|8192,3408|8,3410|8,3411|8,3412|8,3413|8,3414|24,3415|0,10752|0,32777|32774,32824|0,32877|0,32878|0,32883|2048,32936|1,32937|4,32938|1,32968|0,32969|1,32970|0,32971|1,33000|1048575,33001|150000,33170|4352,34016|33984,34024|8192,34045|16,34076|8192,34816|519,34817|7680,34818|7680,34819|7680,34852|8,34853|1029,34854|0,34855|0,34856|0,34857|0,34858|0,34859|0,34860|0,34877|32774,34921|16,34930|16,35071|2048,35076|-8,35077|7,35371|15,35373|15,35374|75,35375|75,35376|65536,35377|249856,35379|249856,35380|256,35657|4096,35658|4096,35659|60,35660|16,35661|80,35723|4352,35738|5121,35739|6408,35968|4,35978|64,35979|4,36003|0,36004|4294967295,36005|4294967295,36063|8,36183|16,36203|4294967295,36347|1024,36348|32,36349|1024,37137|18446744073709552000,37154|128,37157|128,37443|37444,37447|1000000000", + "zoom.stealth.webgl.int2_params": "2928|0:1,3386|16384:16384,33902|1:1", + "zoom.stealth.webgl.float_params": "33901|1:255.875", + "zoom.stealth.webgl.shader_precisions": "35633*36336|127:127:23,35633*36337|127:127:23,35633*36338|127:127:23,35633*36339|24:24:0,35633*36340|24:24:0,35633*36341|24:24:0,35632*36336|127:127:23,35632*36337|127:127:23,35632*36338|127:127:23,35632*36339|24:24:0,35632*36340|24:24:0,35632*36341|24:24:0", + "zoom.stealth.webgl2.enabled": true + } + }, + { + "vendor": "Google Inc. (NVIDIA)", + "renderer_out": "ANGLE (NVIDIA, NVIDIA GeForce GTX 980 Direct3D11 vs_5_0 ps_5_0), or similar", + "prob": 0.008475, + "prefs": { + "zoom.stealth.webgl.renderer": "ANGLE (NVIDIA, NVIDIA GeForce GTX 980 Direct3D11 vs_5_0 ps_5_0, D3D11)", + "zoom.stealth.webgl.vendor": "Google Inc. (NVIDIA)", + "zoom.stealth.webgl.extensions": "ANGLE_instanced_arrays,EXT_blend_minmax,EXT_color_buffer_half_float,EXT_float_blend,EXT_frag_depth,EXT_shader_texture_lod,EXT_sRGB,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_element_index_uint,OES_fbo_render_mipmap,OES_standard_derivatives,OES_texture_float,OES_texture_float_linear,OES_texture_half_float,OES_texture_half_float_linear,OES_vertex_array_object,WEBGL_color_buffer_float,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_depth_texture,WEBGL_draw_buffers,WEBGL_lose_context,WEBGL_provoking_vertex", + "zoom.stealth.webgl2.extensions": "EXT_color_buffer_float,EXT_float_blend,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_draw_buffers_indexed,OES_texture_float_linear,OVR_multiview2,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_lose_context,WEBGL_provoking_vertex", + "zoom.stealth.webgl.int_params": "2849|1,2885|1029,2886|2305,2931|1,2932|513,2961|0,2962|519,2963|2147483647,2964|7680,2965|7680,2966|7680,2967|0,2968|2147483647,3074|1029,3314|0,3315|0,3316|0,3317|4,3330|0,3331|0,3332|0,3333|4,3379|16384,3408|4,3410|8,3411|8,3412|8,3413|8,3414|24,3415|0,10752|0,32777|32774,32824|0,32877|0,32878|0,32883|2048,32936|1,32937|4,32938|1,32968|0,32969|1,32970|0,32971|1,33000|2147483647,33001|2147483647,33170|4352,34016|33984,34024|16384,34045|2,34076|16384,34816|519,34817|7680,34818|7680,34819|7680,34852|8,34853|1029,34854|0,34855|0,34856|0,34857|0,34858|0,34859|0,34860|0,34877|32774,34921|16,34930|16,35071|2048,35076|-8,35077|7,35371|12,35373|12,35374|24,35375|24,35376|65536,35377|212988,35379|200704,35380|256,35657|4096,35658|16380,35659|120,35660|16,35661|32,35723|4352,35738|5121,35739|6408,35968|4,35978|120,35979|4,36003|0,36004|2147483647,36005|2147483647,36063|8,36183|8,36203|4294967294,36347|4095,36348|30,36349|1024,37137|0,37154|120,37157|120,37443|37444,37447|1000000000", + "zoom.stealth.webgl.int2_params": "2928|0:1,3386|32767:32767,33901|1:1024,33902|1:1", + "zoom.stealth.webgl.float_params": "", + "zoom.stealth.webgl.shader_precisions": "35633*36336|127:127:23,35633*36337|127:127:23,35633*36338|127:127:23,35633*36339|31:30:0,35633*36340|31:30:0,35633*36341|31:30:0,35632*36336|127:127:23,35632*36337|127:127:23,35632*36338|127:127:23,35632*36339|31:30:0,35632*36340|31:30:0,35632*36341|31:30:0", + "zoom.stealth.webgl2.enabled": true + } + } + ], + "lin": [ + { + "vendor": "Intel", + "renderer_out": "Intel(R) HD Graphics, or similar", + "prob": 0.282051, + "prefs": { + "zoom.stealth.webgl.renderer": "Intel(R) HD Graphics, or similar", + "zoom.stealth.webgl.vendor": "Intel", + "zoom.stealth.webgl.extensions": "ANGLE_instanced_arrays,EXT_blend_minmax,EXT_color_buffer_half_float,EXT_depth_clamp,EXT_float_blend,EXT_frag_depth,EXT_shader_texture_lod,EXT_sRGB,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_element_index_uint,OES_fbo_render_mipmap,OES_standard_derivatives,OES_texture_float,OES_texture_float_linear,OES_texture_half_float,OES_texture_half_float_linear,OES_vertex_array_object,WEBGL_color_buffer_float,WEBGL_compressed_texture_astc,WEBGL_compressed_texture_etc,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_depth_texture,WEBGL_draw_buffers,WEBGL_lose_context", + "zoom.stealth.webgl2.extensions": "EXT_color_buffer_float,EXT_depth_clamp,EXT_float_blend,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_draw_buffers_indexed,OES_texture_float_linear,WEBGL_compressed_texture_astc,WEBGL_compressed_texture_etc,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_lose_context", + "zoom.stealth.webgl.int_params": "2849|1,2885|1029,2886|2305,2931|1,2932|513,2961|0,2962|519,2963|255,2964|7680,2965|7680,2966|7680,2967|0,2968|255,3074|1029,3314|0,3315|0,3316|0,3317|4,3330|0,3331|0,3332|0,3333|4,3379|8192,3408|4,3410|8,3411|8,3412|8,3413|8,3414|24,3415|0,10752|0,32777|32774,32824|0,32877|0,32878|0,32883|2048,32936|1,32937|4,32938|1,32968|0,32969|1,32970|0,32971|1,33000|3000,33001|3000,33170|4352,34016|33984,34024|8192,34045|15,34076|8192,34816|519,34817|7680,34818|7680,34819|7680,34852|8,34853|1029,34854|0,34855|0,34856|0,34857|0,34858|0,34859|0,34860|0,34877|32774,34921|16,34930|32,35071|2048,35076|-8,35077|7,35371|15,35373|15,35374|90,35375|90,35376|65536,35377|262144,35379|262144,35380|32,35657|16384,35658|16384,35659|128,35660|32,35661|192,35723|4352,35738|5121,35739|6408,35968|16,35978|64,35979|4,36003|0,36004|255,36005|255,36063|8,36183|16,36203|4294967295,36347|4096,36348|32,36349|4096,37137|9223372034707292000,37154|128,37157|128,37443|37444,37447|1000000000", + "zoom.stealth.webgl.int2_params": "2928|0:1,3386|16384:16384,33901|1:255,33902|1:1", + "zoom.stealth.webgl.float_params": "", + "zoom.stealth.webgl.shader_precisions": "35633*36336|127:127:23,35633*36337|127:127:23,35633*36338|127:127:23,35633*36339|24:24:0,35633*36340|24:24:0,35633*36341|24:24:0,35632*36336|127:127:23,35632*36337|127:127:23,35632*36338|127:127:23,35632*36339|24:24:0,35632*36340|24:24:0,35632*36341|24:24:0", + "zoom.stealth.webgl2.enabled": true + } + }, + { + "vendor": "NVIDIA Corporation", + "renderer_out": "NVIDIA GeForce GTX 980, or similar", + "prob": 0.25641, + "prefs": { + "zoom.stealth.webgl.renderer": "NVIDIA GeForce GTX 980, or similar", + "zoom.stealth.webgl.vendor": "NVIDIA Corporation", + "zoom.stealth.webgl.extensions": "ANGLE_instanced_arrays,EXT_blend_minmax,EXT_color_buffer_half_float,EXT_depth_clamp,EXT_float_blend,EXT_frag_depth,EXT_shader_texture_lod,EXT_sRGB,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_element_index_uint,OES_fbo_render_mipmap,OES_standard_derivatives,OES_texture_float,OES_texture_float_linear,OES_texture_half_float,OES_texture_half_float_linear,OES_vertex_array_object,WEBGL_color_buffer_float,WEBGL_compressed_texture_etc,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_depth_texture,WEBGL_draw_buffers,WEBGL_lose_context", + "zoom.stealth.webgl2.extensions": "EXT_color_buffer_float,EXT_depth_clamp,EXT_float_blend,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_draw_buffers_indexed,OES_texture_float_linear,OVR_multiview2,WEBGL_compressed_texture_etc,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_lose_context", + "zoom.stealth.webgl.int_params": "2849|1,2885|1029,2886|2305,2931|1,2932|513,2961|0,2962|519,2963|4294967295,2964|7680,2965|7680,2966|7680,2967|0,2968|4294967295,3074|1029,3314|0,3315|0,3316|0,3317|4,3330|0,3331|0,3332|0,3333|4,3379|32768,3408|8,3410|8,3411|8,3412|8,3413|8,3414|24,3415|0,10752|0,32777|32774,32824|0,32877|0,32878|0,32883|16384,32936|1,32937|4,32938|1,32968|0,32969|1,32970|0,32971|1,33000|1048576,33001|1048576,33170|4352,34016|33984,34024|32768,34045|15,34076|32768,34816|519,34817|7680,34818|7680,34819|7680,34852|8,34853|1029,34854|0,34855|0,34856|0,34857|0,34858|0,34859|0,34860|0,34877|32774,34921|16,34930|32,35071|2048,35076|-8,35077|7,35371|14,35373|14,35374|84,35375|84,35376|65536,35377|233472,35379|233472,35380|256,35657|4096,35658|4096,35659|124,35660|32,35661|192,35723|4352,35738|5121,35739|6408,35968|4,35978|128,35979|4,36003|0,36004|4294967295,36005|4294967295,36063|8,36183|32,36203|4294967295,36347|1024,36348|32,36349|1024,37137|18446744073709552000,37154|128,37157|128,37443|37444,37447|1000000000", + "zoom.stealth.webgl.int2_params": "2928|0:1,3386|32768:32768,33901|1:2047,33902|1:1", + "zoom.stealth.webgl.float_params": "", + "zoom.stealth.webgl.shader_precisions": "35633*36336|127:127:23,35633*36337|127:127:23,35633*36338|127:127:23,35633*36339|24:24:0,35633*36340|24:24:0,35633*36341|24:24:0,35632*36336|127:127:23,35632*36337|127:127:23,35632*36338|127:127:23,35632*36339|24:24:0,35632*36340|24:24:0,35632*36341|24:24:0", + "zoom.stealth.webgl2.enabled": true + } + }, + { + "vendor": "Intel", + "renderer_out": "Intel(R) HD Graphics 400, or similar", + "prob": 0.153846, + "prefs": { + "zoom.stealth.webgl.renderer": "Intel(R) HD Graphics 400, or similar", + "zoom.stealth.webgl.vendor": "Intel", + "zoom.stealth.webgl.extensions": "ANGLE_instanced_arrays,EXT_blend_minmax,EXT_color_buffer_half_float,EXT_depth_clamp,EXT_float_blend,EXT_frag_depth,EXT_shader_texture_lod,EXT_sRGB,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_element_index_uint,OES_fbo_render_mipmap,OES_standard_derivatives,OES_texture_float,OES_texture_float_linear,OES_texture_half_float,OES_texture_half_float_linear,OES_vertex_array_object,WEBGL_color_buffer_float,WEBGL_compressed_texture_astc,WEBGL_compressed_texture_etc,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_depth_texture,WEBGL_draw_buffers,WEBGL_lose_context", + "zoom.stealth.webgl2.extensions": "EXT_color_buffer_float,EXT_depth_clamp,EXT_float_blend,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_draw_buffers_indexed,OES_texture_float_linear,WEBGL_compressed_texture_astc,WEBGL_compressed_texture_etc,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_lose_context", + "zoom.stealth.webgl.int_params": "2849|1,2885|1029,2886|2305,2931|1,2932|513,2961|0,2962|519,2963|255,2964|7680,2965|7680,2966|7680,2967|0,2968|255,3074|1029,3314|0,3315|0,3316|0,3317|4,3330|0,3331|0,3332|0,3333|4,3379|8192,3408|4,3410|8,3411|8,3412|8,3413|8,3414|24,3415|0,10752|0,32777|32774,32824|0,32877|0,32878|0,32883|2048,32936|1,32937|4,32938|1,32968|0,32969|1,32970|0,32971|1,33000|3000,33001|3000,33170|4352,34016|33984,34024|8192,34045|15,34076|8192,34816|519,34817|7680,34818|7680,34819|7680,34852|8,34853|1029,34854|0,34855|0,34856|0,34857|0,34858|0,34859|0,34860|0,34877|32774,34921|16,34930|32,35071|2048,35076|-8,35077|7,35371|15,35373|15,35374|90,35375|90,35376|65536,35377|262144,35379|262144,35380|32,35657|16384,35658|16384,35659|128,35660|32,35661|192,35723|4352,35738|5121,35739|6408,35968|16,35978|64,35979|4,36003|0,36004|255,36005|255,36063|8,36183|8,36203|4294967295,36347|4096,36348|32,36349|4096,37137|9223372034707292000,37154|128,37157|128,37443|37444,37447|1000000000", + "zoom.stealth.webgl.int2_params": "2928|0:1,3386|16384:16384,33901|1:255,33902|1:1", + "zoom.stealth.webgl.float_params": "", + "zoom.stealth.webgl.shader_precisions": "35633*36336|127:127:23,35633*36337|127:127:23,35633*36338|127:127:23,35633*36339|24:24:0,35633*36340|24:24:0,35633*36341|24:24:0,35632*36336|127:127:23,35632*36337|127:127:23,35632*36338|127:127:23,35632*36339|24:24:0,35632*36340|24:24:0,35632*36341|24:24:0", + "zoom.stealth.webgl2.enabled": true + } + }, + { + "vendor": "AMD", + "renderer_out": "Radeon R9 200 Series, or similar", + "prob": 0.102564, + "prefs": { + "zoom.stealth.webgl.renderer": "Radeon R9 200 Series, or similar", + "zoom.stealth.webgl.vendor": "AMD", + "zoom.stealth.webgl.extensions": "ANGLE_instanced_arrays,EXT_blend_minmax,EXT_color_buffer_half_float,EXT_depth_clamp,EXT_float_blend,EXT_frag_depth,EXT_shader_texture_lod,EXT_sRGB,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_element_index_uint,OES_fbo_render_mipmap,OES_standard_derivatives,OES_texture_float,OES_texture_float_linear,OES_texture_half_float,OES_texture_half_float_linear,OES_vertex_array_object,WEBGL_color_buffer_float,WEBGL_compressed_texture_astc,WEBGL_compressed_texture_etc,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_depth_texture,WEBGL_draw_buffers,WEBGL_lose_context", + "zoom.stealth.webgl2.extensions": "EXT_color_buffer_float,EXT_depth_clamp,EXT_float_blend,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_draw_buffers_indexed,OES_texture_float_linear,WEBGL_compressed_texture_astc,WEBGL_compressed_texture_etc,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_lose_context", + "zoom.stealth.webgl.int_params": "2849|1,2885|1029,2886|2305,2931|1,2932|513,2961|0,2962|519,2963|255,2964|7680,2965|7680,2966|7680,2967|0,2968|255,3074|1029,3314|0,3315|0,3316|0,3317|4,3330|0,3331|0,3332|0,3333|4,3379|16384,3408|8,3410|8,3411|8,3412|8,3413|8,3414|24,3415|0,10752|0,32777|32774,32824|0,32877|0,32878|0,32883|2048,32936|1,32937|4,32938|1,32968|0,32969|1,32970|0,32971|1,33000|3000,33001|3000,33170|4352,34016|33984,34024|16384,34045|16,34076|16384,34816|519,34817|7680,34818|7680,34819|7680,34852|8,34853|1029,34854|0,34855|0,34856|0,34857|0,34858|0,34859|0,34860|0,34877|32774,34921|16,34930|32,35071|2048,35076|-32,35077|31,35371|15,35373|15,35374|90,35375|90,35376|4294967292,35377|16106143729,35379|16106143729,35380|4,35657|16384,35658|16384,35659|128,35660|32,35661|192,35723|4352,35738|5121,35739|6408,35968|128,35978|128,35979|4,36003|0,36004|255,36005|255,36063|8,36183|8,36203|4294967295,36347|4096,36348|32,36349|4096,37137|9223372034707292000,37154|128,37157|128,37443|37444,37447|1000000000", + "zoom.stealth.webgl.int2_params": "2928|0:1,3386|16384:16384,33902|1:1", + "zoom.stealth.webgl.float_params": "33901|0.125:2048", + "zoom.stealth.webgl.shader_precisions": "35633*36336|127:127:23,35633*36337|127:127:23,35633*36338|127:127:23,35633*36339|24:24:0,35633*36340|24:24:0,35633*36341|24:24:0,35632*36336|127:127:23,35632*36337|127:127:23,35632*36338|127:127:23,35632*36339|24:24:0,35632*36340|24:24:0,35632*36341|24:24:0", + "zoom.stealth.webgl2.enabled": true + } + }, + { + "vendor": "AMD", + "renderer_out": "Radeon HD 3200 Graphics, or similar", + "prob": 0.083333, + "prefs": { + "zoom.stealth.webgl.renderer": "Radeon HD 3200 Graphics, or similar", + "zoom.stealth.webgl.vendor": "AMD", + "zoom.stealth.webgl.extensions": "ANGLE_instanced_arrays,EXT_blend_minmax,EXT_color_buffer_half_float,EXT_depth_clamp,EXT_float_blend,EXT_frag_depth,EXT_shader_texture_lod,EXT_sRGB,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_element_index_uint,OES_fbo_render_mipmap,OES_standard_derivatives,OES_texture_float,OES_texture_float_linear,OES_texture_half_float,OES_texture_half_float_linear,OES_vertex_array_object,WEBGL_color_buffer_float,WEBGL_compressed_texture_astc,WEBGL_compressed_texture_etc,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_depth_texture,WEBGL_draw_buffers,WEBGL_lose_context", + "zoom.stealth.webgl2.extensions": "EXT_color_buffer_float,EXT_depth_clamp,EXT_float_blend,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_draw_buffers_indexed,OES_texture_float_linear,WEBGL_compressed_texture_astc,WEBGL_compressed_texture_etc,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_lose_context", + "zoom.stealth.webgl.int_params": "2849|1,2885|1029,2886|2305,2931|1,2932|513,2961|0,2962|519,2963|255,2964|7680,2965|7680,2966|7680,2967|0,2968|255,3074|1029,3314|0,3315|0,3316|0,3317|4,3330|0,3331|0,3332|0,3333|4,3379|16384,3408|8,3410|8,3411|8,3412|8,3413|8,3414|24,3415|0,10752|0,32777|32774,32824|0,32877|0,32878|0,32883|2048,32936|1,32937|4,32938|1,32968|0,32969|1,32970|0,32971|1,33000|3000,33001|3000,33170|4352,34016|33984,34024|16384,34045|16,34076|16384,34816|519,34817|7680,34818|7680,34819|7680,34852|8,34853|1029,34854|0,34855|0,34856|0,34857|0,34858|0,34859|0,34860|0,34877|32774,34921|16,34930|32,35071|2048,35076|-32,35077|31,35371|15,35373|15,35374|90,35375|90,35376|4051211264,35377|15192058624,35379|15192058624,35380|4,35657|16384,35658|16384,35659|128,35660|32,35661|192,35723|4352,35738|5121,35739|6408,35968|128,35978|128,35979|4,36003|0,36004|255,36005|255,36063|8,36183|8,36203|4294967295,36347|4096,36348|32,36349|4096,37137|9223372034707292000,37154|128,37157|128,37443|37444,37447|1000000000", + "zoom.stealth.webgl.int2_params": "2928|0:1,3386|16384:16384,33902|1:1", + "zoom.stealth.webgl.float_params": "33901|0.125:2048", + "zoom.stealth.webgl.shader_precisions": "35633*36336|127:127:23,35633*36337|127:127:23,35633*36338|127:127:23,35633*36339|24:24:0,35633*36340|24:24:0,35633*36341|24:24:0,35632*36336|127:127:23,35632*36337|127:127:23,35632*36338|127:127:23,35632*36339|24:24:0,35632*36340|24:24:0,35632*36341|24:24:0", + "zoom.stealth.webgl2.enabled": true + } + }, + { + "vendor": "Mesa", + "renderer_out": "llvmpipe, or similar", + "prob": 0.070513, + "prefs": { + "zoom.stealth.webgl.renderer": "llvmpipe, or similar", + "zoom.stealth.webgl.vendor": "Mesa", + "zoom.stealth.webgl.extensions": "ANGLE_instanced_arrays,EXT_blend_minmax,EXT_color_buffer_half_float,EXT_depth_clamp,EXT_float_blend,EXT_frag_depth,EXT_shader_texture_lod,EXT_sRGB,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_element_index_uint,OES_fbo_render_mipmap,OES_standard_derivatives,OES_texture_float,OES_texture_float_linear,OES_texture_half_float,OES_texture_half_float_linear,OES_vertex_array_object,WEBGL_color_buffer_float,WEBGL_compressed_texture_astc,WEBGL_compressed_texture_etc,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_depth_texture,WEBGL_draw_buffers,WEBGL_lose_context", + "zoom.stealth.webgl2.extensions": "EXT_color_buffer_float,EXT_depth_clamp,EXT_float_blend,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_draw_buffers_indexed,OES_texture_float_linear,WEBGL_compressed_texture_astc,WEBGL_compressed_texture_etc,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_lose_context", + "zoom.stealth.webgl.int_params": "2849|1,2885|1029,2886|2305,2931|1,2932|513,2961|0,2962|519,2963|255,2964|7680,2965|7680,2966|7680,2967|0,2968|255,3074|1029,3314|0,3315|0,3316|0,3317|4,3330|0,3331|0,3332|0,3333|4,3379|16384,3408|8,3410|8,3411|8,3412|8,3413|8,3414|24,3415|0,10752|0,32777|32774,32824|0,32877|0,32878|0,32883|2048,32936|1,32937|4,32938|1,32968|0,32969|1,32970|0,32971|1,33000|3000,33001|3000,33170|4352,34016|33984,34024|16384,34045|16,34076|16384,34816|519,34817|7680,34818|7680,34819|7680,34852|8,34853|1029,34854|0,34855|0,34856|0,34857|0,34858|0,34859|0,34860|0,34877|32774,34921|16,34930|32,35071|2048,35076|-32,35077|31,35371|15,35373|15,35374|90,35375|90,35376|65536,35377|262144,35379|262144,35380|16,35657|16384,35658|16384,35659|128,35660|32,35661|192,35723|4352,35738|5121,35739|6408,35968|64,35978|64,35979|4,36003|0,36004|255,36005|255,36063|8,36183|4,36203|4294967295,36347|4096,36348|32,36349|4096,37137|9223372034707292000,37154|128,37157|128,37443|37444,37447|1000000000", + "zoom.stealth.webgl.int2_params": "2928|0:1,3386|16384:16384,33901|1:255,33902|1:1", + "zoom.stealth.webgl.float_params": "", + "zoom.stealth.webgl.shader_precisions": "35633*36336|127:127:23,35633*36337|127:127:23,35633*36338|127:127:23,35633*36339|24:24:0,35633*36340|24:24:0,35633*36341|24:24:0,35632*36336|127:127:23,35632*36337|127:127:23,35632*36338|127:127:23,35632*36339|24:24:0,35632*36340|24:24:0,35632*36341|24:24:0", + "zoom.stealth.webgl2.enabled": true + } + }, + { + "vendor": "Intel", + "renderer_out": "Intel(R) HD Graphics 400", + "prob": 0.019231, + "prefs": { + "zoom.stealth.webgl.renderer": "Intel(R) HD Graphics 400", + "zoom.stealth.webgl.vendor": "Intel", + "zoom.stealth.webgl.extensions": "ANGLE_instanced_arrays,EXT_blend_minmax,EXT_color_buffer_half_float,EXT_float_blend,EXT_frag_depth,EXT_shader_texture_lod,EXT_sRGB,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_element_index_uint,OES_fbo_render_mipmap,OES_standard_derivatives,OES_texture_float,OES_texture_float_linear,OES_texture_half_float,OES_texture_half_float_linear,OES_vertex_array_object,WEBGL_color_buffer_float,WEBGL_compressed_texture_astc,WEBGL_compressed_texture_etc,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_depth_texture,WEBGL_draw_buffers,WEBGL_lose_context", + "zoom.stealth.webgl2.extensions": "EXT_color_buffer_float,EXT_float_blend,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_draw_buffers_indexed,OES_texture_float_linear,WEBGL_compressed_texture_astc,WEBGL_compressed_texture_etc,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_lose_context", + "zoom.stealth.webgl.int_params": "2849|1,2885|1029,2886|2305,2931|1,2932|513,2961|0,2962|519,2963|255,2964|7680,2965|7680,2966|7680,2967|0,2968|255,3074|1029,3314|0,3315|0,3316|0,3317|4,3330|0,3331|0,3332|0,3333|4,3379|8192,3408|4,3410|8,3411|8,3412|8,3413|8,3414|24,3415|0,10752|0,32777|32774,32824|0,32877|0,32878|0,32883|2048,32936|1,32937|4,32938|1,32968|0,32969|1,32970|0,32971|1,33000|3000,33001|3000,33170|4352,34016|33984,34024|8192,34045|15,34076|8192,34816|519,34817|7680,34818|7680,34819|7680,34852|8,34853|1029,34854|0,34855|0,34856|0,34857|0,34858|0,34859|0,34860|0,34877|32774,34921|16,34930|32,35071|2048,35076|-8,35077|7,35371|15,35373|15,35374|90,35375|90,35376|65536,35377|262144,35379|262144,35380|32,35657|16384,35658|16384,35659|128,35660|32,35661|192,35723|4352,35738|5121,35739|6408,35968|16,35978|64,35979|4,36003|0,36004|255,36005|255,36063|8,36183|8,36203|4294967295,36347|4096,36348|32,36349|4096,37137|9223372034707292000,37154|128,37157|128,37443|37444,37447|1000000000", + "zoom.stealth.webgl.int2_params": "2928|0:1,3386|16384:16384,33901|1:255,33902|1:1", + "zoom.stealth.webgl.float_params": "", + "zoom.stealth.webgl.shader_precisions": "35633*36336|127:127:23,35633*36337|127:127:23,35633*36338|127:127:23,35633*36339|24:24:0,35633*36340|24:24:0,35633*36341|24:24:0,35632*36336|127:127:23,35632*36337|127:127:23,35632*36338|127:127:23,35632*36339|24:24:0,35632*36340|24:24:0,35632*36341|24:24:0", + "zoom.stealth.webgl2.enabled": true + } + }, + { + "vendor": "Mesa", + "renderer_out": "llvmpipe", + "prob": 0.019231, + "prefs": { + "zoom.stealth.webgl.renderer": "llvmpipe", + "zoom.stealth.webgl.vendor": "Mesa", + "zoom.stealth.webgl.extensions": "ANGLE_instanced_arrays,EXT_blend_minmax,EXT_color_buffer_half_float,EXT_float_blend,EXT_frag_depth,EXT_shader_texture_lod,EXT_sRGB,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_element_index_uint,OES_fbo_render_mipmap,OES_standard_derivatives,OES_texture_float,OES_texture_float_linear,OES_texture_half_float,OES_texture_half_float_linear,OES_vertex_array_object,WEBGL_color_buffer_float,WEBGL_compressed_texture_astc,WEBGL_compressed_texture_etc,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_depth_texture,WEBGL_draw_buffers,WEBGL_lose_context", + "zoom.stealth.webgl2.extensions": "EXT_color_buffer_float,EXT_float_blend,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_draw_buffers_indexed,OES_texture_float_linear,WEBGL_compressed_texture_astc,WEBGL_compressed_texture_etc,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_lose_context", + "zoom.stealth.webgl.int_params": "2849|1,2885|1029,2886|2305,2931|1,2932|513,2961|0,2962|519,2963|255,2964|7680,2965|7680,2966|7680,2967|0,2968|255,3074|1029,3314|0,3315|0,3316|0,3317|4,3330|0,3331|0,3332|0,3333|4,3379|16384,3408|8,3410|8,3411|8,3412|8,3413|8,3414|24,3415|0,10752|0,32777|32774,32824|0,32877|0,32878|0,32883|2048,32936|1,32937|4,32938|1,32968|0,32969|1,32970|0,32971|1,33000|3000,33001|3000,33170|4352,34016|33984,34024|16384,34045|16,34076|16384,34816|519,34817|7680,34818|7680,34819|7680,34852|8,34853|1029,34854|0,34855|0,34856|0,34857|0,34858|0,34859|0,34860|0,34877|32774,34921|16,34930|32,35071|2048,35076|-32,35077|31,35371|15,35373|15,35374|90,35375|90,35376|65536,35377|262144,35379|262144,35380|16,35657|16384,35658|16384,35659|128,35660|32,35661|192,35723|4352,35738|5121,35739|6408,35968|64,35978|64,35979|4,36003|0,36004|255,36005|255,36063|8,36183|4,36203|4294967295,36347|4096,36348|32,36349|4096,37137|9223372034707292000,37154|128,37157|128,37443|37444,37447|1000000000", + "zoom.stealth.webgl.int2_params": "2928|0:1,3386|16384:16384,33901|1:255,33902|1:1", + "zoom.stealth.webgl.float_params": "", + "zoom.stealth.webgl.shader_precisions": "35633*36336|127:127:23,35633*36337|127:127:23,35633*36338|127:127:23,35633*36339|24:24:0,35633*36340|24:24:0,35633*36341|24:24:0,35632*36336|127:127:23,35632*36337|127:127:23,35632*36338|127:127:23,35632*36339|24:24:0,35632*36340|24:24:0,35632*36341|24:24:0", + "zoom.stealth.webgl2.enabled": true + } + }, + { + "vendor": "NVIDIA Corporation", + "renderer_out": "NVIDIA GeForce GTX 980/PCIe/SSE2", + "prob": 0.00641, + "prefs": { + "zoom.stealth.webgl.renderer": "NVIDIA GeForce GTX 980/PCIe/SSE2", + "zoom.stealth.webgl.vendor": "NVIDIA Corporation", + "zoom.stealth.webgl.extensions": "ANGLE_instanced_arrays,EXT_blend_minmax,EXT_color_buffer_half_float,EXT_float_blend,EXT_frag_depth,EXT_shader_texture_lod,EXT_sRGB,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_element_index_uint,OES_fbo_render_mipmap,OES_standard_derivatives,OES_texture_float,OES_texture_float_linear,OES_texture_half_float,OES_texture_half_float_linear,OES_vertex_array_object,WEBGL_color_buffer_float,WEBGL_compressed_texture_etc,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_depth_texture,WEBGL_draw_buffers,WEBGL_lose_context", + "zoom.stealth.webgl2.extensions": "EXT_color_buffer_float,EXT_float_blend,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_draw_buffers_indexed,OES_texture_float_linear,OVR_multiview2,WEBGL_compressed_texture_etc,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_lose_context", + "zoom.stealth.webgl.int_params": "2849|1,2885|1029,2886|2305,2931|1,2932|513,2961|0,2962|519,2963|4294967295,2964|7680,2965|7680,2966|7680,2967|0,2968|4294967295,3074|1029,3314|0,3315|0,3316|0,3317|4,3330|0,3331|0,3332|0,3333|4,3379|32768,3408|8,3410|8,3411|8,3412|8,3413|8,3414|24,3415|0,10752|0,32777|32774,32824|0,32877|0,32878|0,32883|16384,32936|1,32937|4,32938|1,32968|0,32969|1,32970|0,32971|1,33000|1048576,33001|1048576,33170|4352,34016|33984,34024|32768,34045|15,34076|32768,34816|519,34817|7680,34818|7680,34819|7680,34852|8,34853|1029,34854|0,34855|0,34856|0,34857|0,34858|0,34859|0,34860|0,34877|32774,34921|16,34930|32,35071|2048,35076|-8,35077|7,35371|14,35373|14,35374|84,35375|84,35376|65536,35377|233472,35379|233472,35380|256,35657|4096,35658|4096,35659|124,35660|32,35661|192,35723|4352,35738|5121,35739|6408,35968|4,35978|128,35979|4,36003|0,36004|4294967295,36005|4294967295,36063|8,36183|32,36203|4294967295,36347|1024,36348|32,36349|1024,37137|18446744073709552000,37154|128,37157|128,37443|37444,37447|1000000000", + "zoom.stealth.webgl.int2_params": "2928|0:1,3386|32768:32768,33901|1:2047,33902|1:1", + "zoom.stealth.webgl.float_params": "", + "zoom.stealth.webgl.shader_precisions": "35633*36336|127:127:23,35633*36337|127:127:23,35633*36338|127:127:23,35633*36339|24:24:0,35633*36340|24:24:0,35633*36341|24:24:0,35632*36336|127:127:23,35632*36337|127:127:23,35632*36338|127:127:23,35632*36339|24:24:0,35632*36340|24:24:0,35632*36341|24:24:0", + "zoom.stealth.webgl2.enabled": true + } + }, + { + "vendor": "Mesa", + "renderer_out": "GeForce GTX 980, or similar", + "prob": 0.00641, + "prefs": { + "zoom.stealth.webgl.renderer": "GeForce GTX 980, or similar", + "zoom.stealth.webgl.vendor": "Mesa", + "zoom.stealth.webgl.extensions": "ANGLE_instanced_arrays,EXT_blend_minmax,EXT_color_buffer_half_float,EXT_depth_clamp,EXT_float_blend,EXT_frag_depth,EXT_shader_texture_lod,EXT_sRGB,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_element_index_uint,OES_fbo_render_mipmap,OES_standard_derivatives,OES_texture_float,OES_texture_float_linear,OES_texture_half_float,OES_texture_half_float_linear,OES_vertex_array_object,WEBGL_color_buffer_float,WEBGL_compressed_texture_astc,WEBGL_compressed_texture_etc,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_depth_texture,WEBGL_draw_buffers,WEBGL_lose_context", + "zoom.stealth.webgl2.extensions": "EXT_color_buffer_float,EXT_depth_clamp,EXT_float_blend,EXT_texture_compression_bptc,EXT_texture_compression_rgtc,EXT_texture_filter_anisotropic,OES_draw_buffers_indexed,OES_texture_float_linear,WEBGL_compressed_texture_astc,WEBGL_compressed_texture_etc,WEBGL_compressed_texture_s3tc,WEBGL_compressed_texture_s3tc_srgb,WEBGL_debug_renderer_info,WEBGL_debug_shaders,WEBGL_lose_context", + "zoom.stealth.webgl.int_params": "2849|1,2885|1029,2886|2305,2931|1,2932|513,2961|0,2962|519,2963|255,2964|7680,2965|7680,2966|7680,2967|0,2968|255,3074|1029,3314|0,3315|0,3316|0,3317|4,3330|0,3331|0,3332|0,3333|4,3379|16384,3408|8,3410|8,3411|8,3412|8,3413|8,3414|24,3415|0,10752|0,32777|32774,32824|0,32877|0,32878|0,32883|2048,32936|1,32937|4,32938|1,32968|0,32969|1,32970|0,32971|1,33000|3000,33001|3000,33170|4352,34016|33984,34024|16384,34045|15,34076|16384,34816|519,34817|7680,34818|7680,34819|7680,34852|8,34853|1029,34854|0,34855|0,34856|0,34857|0,34858|0,34859|0,34860|0,34877|32774,34921|16,34930|32,35071|2048,35076|-8,35077|7,35371|14,35373|14,35374|84,35375|84,35376|65536,35377|245760,35379|245760,35380|256,35657|16384,35658|16384,35659|124,35660|32,35661|192,35723|4352,35738|5121,35739|6408,35968|128,35978|128,35979|4,36003|0,36004|255,36005|255,36063|8,36183|8,36203|4294967295,36347|4096,36348|32,36349|4096,37137|9223372034707292000,37154|128,37157|128,37443|37444,37447|1000000000", + "zoom.stealth.webgl.int2_params": "2928|0:1,3386|16384:16384,33902|1:1", + "zoom.stealth.webgl.float_params": "33901|1:63.375", + "zoom.stealth.webgl.shader_precisions": "35633*36336|127:127:23,35633*36337|127:127:23,35633*36338|127:127:23,35633*36339|24:24:0,35633*36340|24:24:0,35633*36341|24:24:0,35632*36336|127:127:23,35632*36337|127:127:23,35632*36338|127:127:23,35632*36339|24:24:0,35632*36340|24:24:0,35632*36341|24:24:0", + "zoom.stealth.webgl2.enabled": true + } + } + ], + "_meta": { + "source": "camoufox webgl_data.db (offline extract; real Firefox WebGL telemetry)", + "note": "prefs are zoom.stealth.webgl.* override values; prob normalized per-OS" + } +} \ No newline at end of file diff --git a/src/invisible_playwright/_fpforge/data/win_hw_marginals.json b/src/invisible_playwright/_fpforge/data/win_hw_marginals.json new file mode 100644 index 0000000..9d1d71b --- /dev/null +++ b/src/invisible_playwright/_fpforge/data/win_hw_marginals.json @@ -0,0 +1,469 @@ +{ + "_meta": { + "source": "browserforge Windows UAs (offline; OS-level screen/cores marginal)" + }, + "screens": [ + { + "w": 1536, + "h": 864, + "availW": 1536, + "availH": 816, + "dpr": 1.25, + "prob": 0.264935 + }, + { + "w": 1920, + "h": 1080, + "availW": 1920, + "availH": 1032, + "dpr": 1, + "prob": 0.161965 + }, + { + "w": 1280, + "h": 720, + "availW": 1280, + "availH": 672, + "dpr": 1.5, + "prob": 0.07915 + }, + { + "w": 1920, + "h": 1080, + "availW": 1920, + "availH": 1040, + "dpr": 1, + "prob": 0.06376 + }, + { + "w": 1366, + "h": 768, + "availW": 1366, + "availH": 728, + "dpr": 1, + "prob": 0.054416 + }, + { + "w": 1366, + "h": 768, + "availW": 1366, + "availH": 720, + "dpr": 1, + "prob": 0.046171 + }, + { + "w": 1536, + "h": 864, + "availW": 1536, + "availH": 824, + "dpr": 1.25, + "prob": 0.036644 + }, + { + "w": 1536, + "h": 960, + "availW": 1536, + "availH": 912, + "dpr": 1.25, + "prob": 0.029681 + }, + { + "w": 2560, + "h": 1440, + "availW": 2560, + "availH": 1392, + "dpr": 1, + "prob": 0.029133 + }, + { + "w": 1280, + "h": 800, + "availW": 1280, + "availH": 752, + "dpr": 1.5, + "prob": 0.024917 + }, + { + "w": 1536, + "h": 864, + "availW": 1536, + "availH": 864, + "dpr": 1.25, + "prob": 0.024733 + }, + { + "w": 1920, + "h": 1080, + "availW": 1920, + "availH": 1080, + "dpr": 1, + "prob": 0.013742 + }, + { + "w": 1280, + "h": 720, + "availW": 1280, + "availH": 680, + "dpr": 1.5, + "prob": 0.012643 + }, + { + "w": 1280, + "h": 720, + "availW": 1280, + "availH": 720, + "dpr": 1.5, + "prob": 0.01081 + }, + { + "w": 1920, + "h": 1080, + "availW": 1920, + "availH": 1032, + "dpr": 1, + "prob": 0.009527 + }, + { + "w": 1707, + "h": 1067, + "availW": 1707, + "availH": 1019, + "dpr": 1.5, + "prob": 0.009344 + }, + { + "w": 1440, + "h": 900, + "availW": 1440, + "availH": 852, + "dpr": 2, + "prob": 0.008795 + }, + { + "w": 1920, + "h": 1080, + "availW": 1920, + "availH": 1032, + "dpr": 1, + "prob": 0.008795 + }, + { + "w": 1920, + "h": 1200, + "availW": 1920, + "availH": 1152, + "dpr": 1, + "prob": 0.007513 + }, + { + "w": 1920, + "h": 1080, + "availW": 1920, + "availH": 1032, + "dpr": 1, + "prob": 0.007146 + }, + { + "w": 1920, + "h": 1080, + "availW": 1920, + "availH": 1032, + "dpr": 1, + "prob": 0.006596 + }, + { + "w": 1600, + "h": 900, + "availW": 1600, + "availH": 860, + "dpr": 1, + "prob": 0.006229 + }, + { + "w": 2048, + "h": 1152, + "availW": 2048, + "availH": 1104, + "dpr": 1.25, + "prob": 0.006045 + }, + { + "w": 1920, + "h": 1080, + "availW": 1920, + "availH": 1032, + "dpr": 1, + "prob": 0.005864 + }, + { + "w": 1536, + "h": 864, + "availW": 1536, + "availH": 816, + "dpr": 1.25, + "prob": 0.005864 + }, + { + "w": 1366, + "h": 768, + "availW": 1366, + "availH": 768, + "dpr": 1, + "prob": 0.00568 + }, + { + "w": 2560, + "h": 1440, + "availW": 2560, + "availH": 1392, + "dpr": 1.5, + "prob": 0.00513 + }, + { + "w": 1707, + "h": 960, + "availW": 1707, + "availH": 912, + "dpr": 1.5, + "prob": 0.004946 + }, + { + "w": 1920, + "h": 1080, + "availW": 1920, + "availH": 1040, + "dpr": 1, + "prob": 0.004946 + }, + { + "w": 3440, + "h": 1440, + "availW": 3440, + "availH": 1392, + "dpr": 1, + "prob": 0.00458 + }, + { + "w": 1504, + "h": 1003, + "availW": 1504, + "availH": 955, + "dpr": 1.5, + "prob": 0.004396 + }, + { + "w": 1920, + "h": 1080, + "availW": 1920, + "availH": 1032, + "dpr": 1, + "prob": 0.004396 + }, + { + "w": 1280, + "h": 800, + "availW": 1280, + "availH": 752, + "dpr": 2, + "prob": 0.004396 + }, + { + "w": 1536, + "h": 864, + "availW": 1536, + "availH": 816, + "dpr": 1.25, + "prob": 0.004396 + }, + { + "w": 1920, + "h": 1080, + "availW": 1920, + "availH": 1040, + "dpr": 1, + "prob": 0.004031 + }, + { + "w": 1920, + "h": 1080, + "availW": 1920, + "availH": 1050, + "dpr": 1, + "prob": 0.003847 + }, + { + "w": 2560, + "h": 1440, + "availW": 2560, + "availH": 1400, + "dpr": 1, + "prob": 0.003847 + }, + { + "w": 1366, + "h": 768, + "availW": 1366, + "availH": 728, + "dpr": 1, + "prob": 0.003664 + }, + { + "w": 1920, + "h": 1080, + "availW": 1920, + "availH": 1032, + "dpr": 1, + "prob": 0.003664 + }, + { + "w": 1600, + "h": 900, + "availW": 1600, + "availH": 852, + "dpr": 1, + "prob": 0.003664 + } + ], + "cores": [ + { + "value": 8, + "prob": 0.271311 + }, + { + "value": 12, + "prob": 0.21567 + }, + { + "value": 4, + "prob": 0.157888 + }, + { + "value": 16, + "prob": 0.136607 + }, + { + "value": 20, + "prob": 0.03971 + }, + { + "value": 2, + "prob": 0.025086 + }, + { + "value": 24, + "prob": 0.023184 + }, + { + "value": 6, + "prob": 0.022233 + }, + { + "value": 32, + "prob": 0.021876 + }, + { + "value": 14, + "prob": 0.015575 + }, + { + "value": 3, + "prob": 0.011651 + }, + { + "value": 28, + "prob": 0.010462 + }, + { + "value": 22, + "prob": 0.010225 + }, + { + "value": 5, + "prob": 0.008441 + }, + { + "value": 10, + "prob": 0.005588 + }, + { + "value": 7, + "prob": 0.005469 + }, + { + "value": 9, + "prob": 0.004042 + }, + { + "value": 11, + "prob": 0.003923 + }, + { + "value": 18, + "prob": 0.003567 + }, + { + "value": 15, + "prob": 0.001189 + }, + { + "value": 13, + "prob": 0.000951 + }, + { + "value": 36, + "prob": 0.000713 + }, + { + "value": 64, + "prob": 0.000594 + }, + { + "value": 44, + "prob": 0.000594 + }, + { + "value": 19, + "prob": 0.000476 + }, + { + "value": 17, + "prob": 0.000357 + }, + { + "value": 23, + "prob": 0.000357 + }, + { + "value": 40, + "prob": 0.000357 + }, + { + "value": 21, + "prob": 0.000357 + }, + { + "value": 48, + "prob": 0.000357 + }, + { + "value": 640, + "prob": 0.000357 + }, + { + "value": 56, + "prob": 0.000357 + }, + { + "value": 26, + "prob": 0.000238 + }, + { + "value": 27, + "prob": 0.000119 + }, + { + "value": 25, + "prob": 0.000119 + } + ] +} \ No newline at end of file diff --git a/src/invisible_playwright/_webgl_personas.py b/src/invisible_playwright/_webgl_personas.py index d743eea..3381b6c 100644 --- a/src/invisible_playwright/_webgl_personas.py +++ b/src/invisible_playwright/_webgl_personas.py @@ -85,53 +85,79 @@ _EXT2 = ( ) -def _p(key, renderer, vendor, gpu_class, weight): - return {"key": key, "renderer": renderer, "vendor": vendor, - "gpu_class": gpu_class, "weight": weight, "ext1": _EXT1, "ext2": _EXT2} - - -# Only the two robustly-clean Windows buckets (calibration sweep 2026-06-14). Both discrete, -# so gpu_class=mid_range keeps cores/screen coherent with the declared GPU for OTHER detectors -# (gpu_class does NOT affect tampering_ml). Weights ~ real-world prevalence of the BUCKET: -# "Radeon R9 200 Series" represents ALL modern AMD (large real slice); "Arc A750" = Intel -# discrete (rarer). Cross-vendor => the fleet is not a single-GPU cluster. -_PERSONAS: List[Dict] = [ - _p("amd_radeon_r9", "ANGLE (AMD, AMD Radeon R9 200 Series Direct3D11 vs_5_0 ps_5_0, D3D11)", - "Google Inc. (AMD)", "mid_range", 70), # -> bucket "Radeon R9 200 Series"; tml 0.03-0.35 - _p("intel_arc_a750", "ANGLE (Intel, Intel(R) Arc(TM) A750 Graphics Direct3D11 vs_5_0 ps_5_0, D3D11)", - "Google Inc. (Intel)", "mid_range", 30), # -> bucket "Intel(R) Arc(TM) A750 Graphics"; tml 0.02-0.38 -] - -_TOTAL_W = sum(p["weight"] for p in _PERSONAS) - -# ENABLED: we falsify the GPU on Windows/mac. Validated clean on an Intel Arc host (see the -# HOST-INDEPENDENCE caveat in the module docstring — unvalidated on non-Arc hosts). On Linux -# select_persona returns None: there prefs.py spoofs profile.gpu.renderer directly. +# ── Real-Firefox GPU pool (2026-06-18, supersedes the 2-bucket sweep above) ─────────────── +# The personas are now sourced from `_fpforge/data/webgl_gpu_pool.json` — an OFFLINE extract +# of camoufox's real-Firefox WebGL telemetry DB (17 Windows GPUs with their REAL per-OS +# prevalence AND the full coherent WebGL fingerprint: renderer + vendor + extensions + +# ~100 getParameter values + shader-precision formats). prefs.py applies ALL of these, not +# just the renderer string. The linchpin A/B (2026-06-18) proved that the OLD "NVIDIA 0/10" +# verdict was an artifact of spoofing the renderer string over the host's REAL (Arc) params: +# FP Pro cross-checks renderer<->params, so a GTX 980 string over Arc params mismatched +# (~0.7-0.85). Injecting camoufox's REAL GTX 980 params makes it coherent (tml median 0.333, +# flags clean). So the params are NOT vendor-independent (the old assumption) and per-GPU +# real data is what unlocks the full real GPU mix — including NVIDIA (~47% of real FF-Win), +# which we no longer gate. _ENABLED = True +_POOL_PATH = __import__("pathlib").Path(__file__).parent / "_fpforge" / "data" / "webgl_gpu_pool.json" +_GPU_POOL_CACHE: Optional[List[Dict]] = None + + +def _gpu_pool() -> List[Dict]: + """Lazy-load the Windows GPU pool (we always claim Windows). Each entry: + {key, renderer (input form), vendor, gpu_class (via classify_gpu), prefs (full + zoom.stealth.webgl.* override dict), weight (real per-OS prevalence)}.""" + global _GPU_POOL_CACHE + if _GPU_POOL_CACHE is not None: + return _GPU_POOL_CACHE + import json + from ._fpforge._sampler import classify_gpu # lazy import → no module cycle + raw = json.loads(_POOL_PATH.read_text(encoding="utf-8")) + pool: List[Dict] = [] + for e in raw.get("win", []): + prefs = e["prefs"] + rend_in = prefs["zoom.stealth.webgl.renderer"] + cls = classify_gpu({"renderer": rend_in, + "vendor": prefs.get("zoom.stealth.webgl.vendor", "")}) + pool.append({ + "key": e.get("renderer_out", rend_in)[:48], + "renderer": rend_in, + "vendor": prefs["zoom.stealth.webgl.vendor"], + "gpu_class": cls, + "prefs": prefs, + "weight": float(e["prob"]), + }) + _GPU_POOL_CACHE = pool + return pool def select_persona(seed: int) -> Optional[Dict]: - """Deterministic, prevalence-weighted persona for this seed (None on Linux). + """Deterministic, prevalence-weighted GPU persona for this seed — on EVERY host. Same seed -> same persona (fppro_consistency: identity stable per seed). Different seeds - spread across the persona mix by weight. None on Linux (the sampled profile.gpu.renderer - is spoofed directly there). - """ - if not _ENABLED or sys.platform.startswith("linux") or not _PERSONAS: + spread across the REAL Windows GPU mix by prevalence. Returns the Windows-ANGLE persona on + Linux/Mac too: we must always look Windows, and the C++ WebGL override (SanitizeRenderer + + pref-driven params/extensions) is platform-independent, so the same Windows GPU is presented + on any host without consulting the real GL backend (no more Linux "Generic Renderer").""" + if not _ENABLED: return None - h = (int(seed) * 2654435761) % _TOTAL_W - cum = 0 - for p in _PERSONAS: + pool = _gpu_pool() + if not pool: + return None + total = sum(p["weight"] for p in pool) or 1.0 + h = ((int(seed) * 2654435761) % 1_000_003) / 1_000_003.0 * total + cum = 0.0 + for p in pool: cum += p["weight"] if h < cum: return p - return _PERSONAS[-1] + return pool[-1] def forced_gpu_class(seed: int) -> Optional[str]: - """The gpu_class the forge conditions the WHOLE bundle on (== the selected persona's class), - so cores/screen/fonts stay coherent with the GPU we expose. Does NOT affect FP Pro - tampering_ml (proven) but matters for detectors that cross-check hardware tier. None on Linux.""" + """The gpu_class the forge conditions the bundle on (== the selected GPU's class via + classify_gpu), so cores/screen/fonts stay coherent with the GPU we expose. Does NOT + affect FP Pro tampering_ml (proven) but matters for detectors that cross-check hardware + tier. None on Linux.""" p = select_persona(seed) return p["gpu_class"] if p else None @@ -152,7 +178,14 @@ def forced_gpu_class(seed: int) -> Optional[str]: # the Intel-Arc host. On other GPUs the clean set may differ (host-independence open, # same as the personas) — Option B (substitution = GPU-independent render hash) would # remove that dependency. Validate per-host or move to B before trusting fleet-wide. -CLEAN_RENDER_SEEDS = [19, 10, 28, 24, 23, 16, 11, 30, 17, 22, 3, 9, 12, 26] +# RECALIBRATED 2026-06-18 for the real-Firefox GPU mix (incl NVIDIA, which is more +# consistency-sensitive than the old amd/arc personas). Swept hw_seed 0..30 on the hottest +# persona (NVIDIA GTX 980) through a residential exit: these 9 stayed well within the clean +# band with a wide margin to the rest. The old pool's picks scored dirty on NVIDIA (clean +# only on the retired amd/arc mix) → dropped. NVIDIA is the worst case, so these are clean on +# amd/intel too. hw_seed = the canvas/WebGL gamma render hash (the dominant consistency-score +# driver); host-calibrated. +CLEAN_RENDER_SEEDS = [0, 5, 6, 9, 11, 16, 19, 20, 28] def render_noise_seed(seed: int) -> int: diff --git a/src/invisible_playwright/constants.py b/src/invisible_playwright/constants.py index 3844bca..731d7ce 100644 --- a/src/invisible_playwright/constants.py +++ b/src/invisible_playwright/constants.py @@ -7,7 +7,7 @@ bugfixes don't force a multi-hour Firefox rebuild. from __future__ import annotations # Bump this when a new patched Firefox build is released on GitHub. -BINARY_VERSION: str = "firefox-11" +BINARY_VERSION: str = "firefox-12" # Releases known to be broken — ensure_binary() refuses them with a clear error # instead of handing the user an unusable binary. firefox-8 was packaged without @@ -68,11 +68,11 @@ RELEASE_URL_TEMPLATE = ( # single mmdb (country ISO + coordinates + IANA timezone via tzfpy), rebuilt # weekly. GPL-3.0, so we DOWNLOAD it at runtime into the user cache (like the # Firefox binary) rather than bundling it into this MIT package. The `-all` -# variant covers IPv4+IPv6. download.py tracks the LATEST release and refreshes -# weekly; GEOIP_MMDB_VERSION is only the cold-cache fallback when the GitHub -# API is unreachable on a machine that has never downloaded the DB. +# variant covers IPv4+IPv6. download.py NEVER pins a tag (daijro prunes old +# releases, so a pinned tag eventually 404s): on every launch it resolves the +# CURRENT latest tag from the `releases/latest/download` permalink (no GitHub +# API, no rate limit) and pulls it if newer than the cache. GEOIP_REPO: str = "daijro/geoip-all-in-one" -GEOIP_MMDB_VERSION: str = "2026.06.03" GEOIP_ASSET: str = "geoip-aio-all.mmdb.zip" GEOIP_MMDB_NAME: str = "geoip-aio-all.mmdb" GEOIP_RELEASE_URL_TEMPLATE: str = ( diff --git a/src/invisible_playwright/download.py b/src/invisible_playwright/download.py index acb5d49..4e07b8f 100644 --- a/src/invisible_playwright/download.py +++ b/src/invisible_playwright/download.py @@ -24,7 +24,7 @@ from .constants import ( BROKEN_VERSIONS, GEOIP_ASSET, GEOIP_MMDB_NAME, - GEOIP_MMDB_VERSION, + GEOIP_REPO, GEOIP_RELEASE_URL_TEMPLATE, RELEASE_URL_TEMPLATE, ) @@ -198,26 +198,23 @@ def ensure_binary(version: str = BINARY_VERSION) -> Path: # ───────────────────────────────────────────────────────────────────────── # GeoIP mmdb (timezone="auto" → map egress IP → IANA zone) # -# daijro/geoip-all-in-one is rebuilt WEEKLY, so we don't pin a tag. We cache -# the latest mmdb and, once it's older than GEOIP_REFRESH_DAYS, re-check the -# latest release and pull a newer build if one exists. Net effect: no download -# (not even an API call) on a launch within the window; auto-refresh after it; -# a stale cache is reused when offline rather than breaking the launch. +# daijro/geoip-all-in-one is rebuilt weekly and KEEPS ONLY the latest ~2 +# releases — older tags are pruned and 404. So we NEVER pin a tag: on every +# launch we resolve the CURRENT latest tag from the `releases/latest/download` +# permalink (its 302 Location carries the tag — a plain CDN request, NOT the +# rate-limited GitHub API) and download it if it differs from the cached one. +# Offline → reuse the cached mmdb; cold cache + offline → raise (the caller can +# then fall back off timezone="auto"). No stale pinned tag to rot. # ───────────────────────────────────────────────────────────────────────── -GEOIP_REFRESH_DAYS = 7 # matches daijro's weekly rebuild cadence def _geoip_root() -> Path: return cache_root() / "geoip" -def _geoip_check_marker() -> Path: - return _geoip_root() / ".last_check" - - def _cached_geoip_mmdb() -> Path | None: """Newest cached mmdb across tag dirs, or None. Tag dirs are date strings - (e.g. ``2026.06.03``) so a lexical sort is chronological.""" + (e.g. ``2026.06.17``) so a lexical sort is chronological.""" root = _geoip_root() if not root.exists(): return None @@ -225,21 +222,14 @@ def _cached_geoip_mmdb() -> Path | None: return cands[-1] if cands else None -def _geoip_cache_fresh(max_age_days: int) -> bool: - marker = _geoip_check_marker() - if not marker.exists(): - return False - return (time.time() - marker.stat().st_mtime) < max_age_days * 86400 +def _geoip_latest_url() -> str: + return f"https://github.com/{GEOIP_REPO}/releases/latest/download/{GEOIP_ASSET}" -def _touch_geoip_marker() -> None: - m = _geoip_check_marker() - m.parent.mkdir(parents=True, exist_ok=True) - m.touch() - - -def _latest_geoip_tag() -> str: - """Latest ``daijro/geoip-all-in-one`` release tag via the GitHub API.""" +def _latest_geoip_tag_api() -> str: + """Latest ``daijro/geoip-all-in-one`` release tag via the GitHub API + (fallback for :func:`_resolve_latest_geoip_tag` when the permalink HEAD + can't be parsed).""" headers = {"Accept": "application/vnd.github+json"} token = _github_token() if token: @@ -255,6 +245,25 @@ def _latest_geoip_tag() -> str: return tag +def _resolve_latest_geoip_tag() -> str | None: + """Current latest release tag WITHOUT the rate-limited API: HEAD the + ``releases/latest/download`` permalink — GitHub answers 302 with + ``Location: …/releases/download//``. Falls back to the API, + then to ``None`` (offline / unparseable).""" + try: + r = requests.head(_geoip_latest_url(), allow_redirects=False, timeout=10) + loc = r.headers.get("Location") or r.headers.get("location") or "" + m = re.search(r"/releases/download/([^/]+)/", loc) + if m: + return m.group(1) + except Exception: + pass + try: + return _latest_geoip_tag_api() + except Exception: + return None + + def _download_geoip_tag(tag: str) -> Path: """Download + extract a specific tag's mmdb if not already cached.""" dst_dir = _geoip_root() / tag @@ -290,18 +299,17 @@ def geoip_mmdb_path() -> Path | None: return _cached_geoip_mmdb() -def ensure_geoip_mmdb(max_age_days: int = GEOIP_REFRESH_DAYS) -> Path: - """Return a geoip mmdb, kept fresh against daijro's weekly rebuild. +def ensure_geoip_mmdb() -> Path: + """Return the geoip mmdb, always the latest daijro build. Checked on EVERY + call — a single cheap permalink HEAD (no GitHub API, so no rate limit). Resolution order: 1. ``STEALTHFOX_GEOIP_MMDB`` env → use that file (user-supplied / test). - 2. A cached mmdb younger than ``max_age_days`` → use it (no network). - 3. Else ask GitHub for the latest tag, download it if not already cached, - prune older tags, and reset the freshness timer. - 4. If the API/download is unreachable but a cached mmdb exists → use it - (and reset the timer so we don't hammer the API while offline). - 5. Cold cache + no network → fall back to the pinned ``GEOIP_MMDB_VERSION``; - if that download also fails, raise. + 2. Resolve the CURRENT latest tag. If it differs from the newest cached + tag (or nothing is cached) → download it, prune older tags, return it. + 3. Latest tag == newest cached tag → use the cache (no download). + 4. Couldn't resolve the tag (offline / unparseable): cached mmdb → use it; + cold cache → raise (caller can then drop timezone="auto"). """ override = os.environ.get("STEALTHFOX_GEOIP_MMDB") if override: @@ -311,18 +319,25 @@ def ensure_geoip_mmdb(max_age_days: int = GEOIP_REFRESH_DAYS) -> Path: return p cached = _cached_geoip_mmdb() - if cached and _geoip_cache_fresh(max_age_days): - return cached + cached_tag = cached.parent.name if cached else None - try: - tag = _latest_geoip_tag() - except Exception: - if cached: - _touch_geoip_marker() # recheck after the window; don't hammer - return cached - tag = GEOIP_MMDB_VERSION # cold cache + API down → pinned fallback + latest = _resolve_latest_geoip_tag() + if latest and latest != cached_tag: + # newer build available (or nothing cached) → fetch it + try: + mmdb = _download_geoip_tag(latest) + _prune_old_geoip_tags(mmdb.parent.name) + return mmdb + except Exception: + if cached: + return cached # transient download failure → keep using the cache + raise - mmdb = _download_geoip_tag(tag) - _prune_old_geoip_tags(mmdb.parent.name) - _touch_geoip_marker() - return mmdb + if cached: + return cached # cache is already the latest, or we're offline + + raise RuntimeError( + "geoip mmdb unavailable: no cached copy and GitHub is unreachable. " + "Connect once to download it, or set STEALTHFOX_GEOIP_MMDB to a local " + "geoip-aio-all.mmdb file." + ) diff --git a/src/invisible_playwright/prefs.py b/src/invisible_playwright/prefs.py index 529b01f..d50bd2d 100644 --- a/src/invisible_playwright/prefs.py +++ b/src/invisible_playwright/prefs.py @@ -180,17 +180,28 @@ _WIN_VOICES = ",".join([ # ────────────────────────────────────────────────────────────────────── _LINUX_GENERIC_FONT_FACTORS = ( - # Calibrated to bring DejaVu/Liberation widths in line with what Windows - # FP Pro probes report for native Segoe/Times. Linux base measurements - # (font_preferences) and Windows targets: - # serif: 162 → 149 factor 0.920 - # sans: 162 → 144 factor 0.889 - # monospace:121 → 121 factor 1.000 - # system: 162 → 147 factor 0.910 + # GENERIC factors are calibrated to FP Pro's font_preferences probe (NOT the 72px named-probe + # scale — verified 2026-06-18: recalibrating to the named-probe scale broke them, mono 121.55 + # -> 112.4; the original values are correct for font_preferences). DejaVu/Liberation generics + # vs Windows targets: serif 0.920, sans 0.889, monospace 1.000, system-ui 0.910. "serif|0.920,sans-serif|0.889,monospace|1.000," "system-ui|0.910,cursive|0.932,fantasy|0.812," ) +# Calibration reference string for the C++ self-calibrating absolute-width path. +# MUST be byte-identical to the probe the font_pool widths were measured with +# (72px canvas measureText) and to the binary's zoom.stealth.font.calib_ref +# default. Set explicitly so correctness never depends on the binary default. +_FONT_CALIB_REF = "mmmmwwwwiiiillloooMMMMWWWW0123456789 The quick brown fox" +# NOTE: there is intentionally NO per-OS collapse-base table here anymore. +# The C++ font hook self-calibrates: `font_pool` stores the UNIVERSAL real +# Windows measureText width per font and the binary divides it by the host's +# own collapse base (gfxTextRun::StealthCollapseBase, summed from the list-head +# font's per-glyph advances over zoom.stealth.font.calib_ref). So the SAME +# stored value yields the exact Windows width on Windows, Linux AND macOS with +# nothing to measure per platform. (Was: _COLLAPSE_BASE = {win32:1530, linux:2400} +# + a darwin TODO — removed 2026-06-18 when the self-calibrating C++ landed.) + # ────────────────────────────────────────────────────────────────────── # Baseline — applied to every session regardless of Profile. @@ -478,12 +489,20 @@ def _font_metrics_for_platform(profile_metrics: str) -> str: """ if not profile_metrics: return "" + # profile_metrics arrives as "name|,..." (host-independent + # absolute widths, e.g. "arial|2256.7"). We pass them through UNCHANGED: the C++ + # hook treats a value >= 10 as an ABSOLUTE target measureText width and divides it + # by the host's own collapse base (self-calibrating), so the SAME value yields the + # exact Windows width on Windows, Linux AND macOS. No per-OS division here. + metrics = profile_metrics + # Linux ADDITIONALLY needs CSS-generic compensation (DejaVu/Liberation generics + # render wider/narrower than Windows). These are multiplicative FACTORS (< 10), + # calibrated to FP Pro's font_preferences probe; the C++ hook treats values < 10 as + # factors. Generics bypass the whitelist/collapse so they are NOT self-calibrated. + # Windows/mac generics render native -> no compensation. if sys.platform.startswith("linux"): - return _LINUX_GENERIC_FONT_FACTORS + profile_metrics - # Windows / macOS: named-font factors only (the generics render native and - # bypass the whitelist, so no generic compensation — but the named families - # MUST be factored or they all collapse to the list-head width). - return profile_metrics + return _LINUX_GENERIC_FONT_FACTORS + metrics + return metrics def translate_profile_to_prefs( @@ -519,23 +538,30 @@ def translate_profile_to_prefs( # GPU that passes FP Pro host-independently (the host's real GPU never leaks). If no # validated persona exists for the sampled gpu_class yet, fall back to the host-real # renderer (empty → native ANGLE; SanitizeRenderer at ClientWebGLContext.cpp:2592). - _persona = None - if sys.platform.startswith("linux"): - prefs["zoom.stealth.webgl.renderer"] = profile.gpu.renderer - prefs["zoom.stealth.webgl.vendor"] = profile.gpu.vendor - _renderer_lo = (profile.gpu.renderer or "").lower() + # Apply the camoufox-derived real-Firefox GPU persona on EVERY host (Win/Linux/Mac). + # We must ALWAYS look Windows (rule), and the WebGL override is platform-independent: + # SanitizeRenderer (ClientWebGLContext.cpp) is pure string regex, and the param/extension + # overrides are pref-driven, so the C++ presents the SAME Windows ANGLE GPU regardless of + # the host's real GL backend (it never consults it when the pref is set). This is why a + # Windows GPU shows correctly even on a Linux/Mesa host (no more "Generic Renderer"). + _persona = select_persona(profile.seed) + if _persona: + # Apply the FULL coherent WebGL override (renderer + vendor + webgl1/webgl2 extensions + # + ~100 getParameter values + shader-precision formats). Setting ALL of them — not just + # the renderer string — keeps renderer<->params coherent (FP Pro cross-checks them); a + # string-only spoof over the host's real params is the old ~0.85 mismatch. + for _k, _v in _persona["prefs"].items(): + if _k == "zoom.stealth.webgl2.enabled": + prefs["webgl.enable-webgl2"] = bool(_v) + else: + prefs[_k] = _v else: - _persona = select_persona(profile.seed) - if _persona: - prefs["zoom.stealth.webgl.renderer"] = _persona["renderer"] - prefs["zoom.stealth.webgl.vendor"] = _persona["vendor"] - else: - prefs["zoom.stealth.webgl.renderer"] = "" - prefs["zoom.stealth.webgl.vendor"] = "" - # Canvas-noise mask is calibrated to the REAL host GPU's rendering variance — the canvas is - # drawn by real hardware, NOT the persona's claimed GPU, so it must NOT follow the persona - # (a non-Intel persona on an Intel host would over-noise). Deployment host is Intel. - _renderer_lo = "intel" + prefs["zoom.stealth.webgl.renderer"] = "" + prefs["zoom.stealth.webgl.vendor"] = "" + # Canvas-noise mask is calibrated to the REAL host GPU's rendering variance — the canvas is + # drawn by real hardware, NOT the persona's claimed GPU, so it must NOT follow the persona + # (a non-Intel persona on an Intel host would over-noise). Dev/deployment host is Intel. + _renderer_lo = "intel" # MSAA: on Windows, pin to 4 (Firefox default for ANGLE) so gl.SAMPLES is # constant across all sessions. Different MSAA values cause different CN-set @@ -585,6 +611,10 @@ def translate_profile_to_prefs( prefs["zoom.stealth.font.metrics"] = _font_metrics_for_platform( profile._raw.get("font_metrics", "") or "" ) + # Reference string the binary sums the collapsed font's advances over to + # self-calibrate the per-host collapse base (turns the absolute widths in + # `metrics` into the right factor on any OS). See _font_metrics_for_platform. + prefs["zoom.stealth.font.calib_ref"] = _FONT_CALIB_REF # UI / dark mode + Windows colors palette (only when light theme). prefs["ui.systemUsesDarkTheme"] = int(profile.dark_theme) @@ -625,21 +655,14 @@ def translate_profile_to_prefs( prefs["zoom.stealth.webrtc.host_ip"] = _lan_ip # Windows/mac extension list: - # - persona active → FORCE the validated extension list. A non-Intel host's native - # extensions would mismatch the persona's renderer (renderer says AMD/Intel-Arc but - # extensions are the host's), so the persona must carry its own list to stay - # host-independent. + # - persona active → the coherent webgl1/webgl2 extension lists (in the GPU's real + # native order) were ALREADY applied above from the GPU pool's `prefs`, alongside the + # matching renderer + params + shader-precisions. Nothing to do here. # - no persona → clear so the host-real renderer reports its native extension set # (matches real vanilla captures for that host's GPU). - if not sys.platform.startswith("linux"): - if _persona: - # The persona carries its OWN extension lists in EXACT NATIVE ORDER — a - # reordered/foreign list is flagged by FP Pro (verified 2026-06-13). - prefs["zoom.stealth.webgl.extensions"] = _persona["ext1"] - prefs["zoom.stealth.webgl2.extensions"] = _persona["ext2"] - else: - prefs["zoom.stealth.webgl.extensions"] = "" - prefs["zoom.stealth.webgl2.extensions"] = "" + if not sys.platform.startswith("linux") and not _persona: + prefs["zoom.stealth.webgl.extensions"] = "" + prefs["zoom.stealth.webgl2.extensions"] = "" # Linux Xvfb workarounds (no-op on Windows). if sys.platform.startswith("linux"): diff --git a/tests/test_canvas_render_stealth.py b/tests/test_canvas_render_stealth.py new file mode 100644 index 0000000..e0c7ba1 --- /dev/null +++ b/tests/test_canvas_render_stealth.py @@ -0,0 +1,125 @@ +"""Canvas / WebGL render-stealth regression tests (binary-level, 2026-06-18). + +Two patched-binary behaviours that must never regress, both needed for the +fingerprint to look like a real Windows browser to FOSS detectors (CreepJS, +FingerprintJS, BrowserLeaks) and to image-dedup font probes / fixed-hash +reference checks: + + 1. Per-font canvas distinctness — whitelisted named fonts are backed by the + host list-head glyphs (so measureText widths are host-independent), but each + must still rasterise to a DISTINCT image at tiny probe sizes. Otherwise an + image-dedup font probe collapses them to ~1 name and the reported font set + looks fabricated. (C++: per-font sub-pixel draw offset in DrawText.) + 2. Solid WebGL readback purity under render-noise — a fixed solid-colour WebGL + readback (which reference checks hash against a universal constant) must stay + byte-exact even with per-seed render-noise enabled, while high-entropy + renders stay noised. (C++: render-noise skips near-uniform WebGL readbacks.) + +Runs against about:blank, no network/proxy. Part of the e2e release gate. +Run: pytest tests/test_canvas_render_stealth.py -m e2e -v +""" +from __future__ import annotations + +import pytest + +from invisible_playwright import InvisiblePlaywright +from invisible_playwright import prefs as _prefs +from invisible_playwright._fpforge import generate_profile + +# Diverse-codepoint probe string — maximises per-font rendering differences, the +# way an image-dedup font probe drives a tiny canvas. +_PROBE = ("\U0001f6cd1>'`amlρiюदे來˦" + "\U00025578に◌\U0002003eԩԨ") + + +def _named_fonts(limit: int = 30) -> list[str]: + """The whitelisted NAMED fonts (absolute collapse-target width >= 10) for the + test seed — these are the ones the per-font offset must keep distinct.""" + prof = generate_profile(42) + metrics = _prefs._font_metrics_for_platform(prof._raw.get("font_metrics", "") or "") + out: list[str] = [] + for ent in metrics.split(","): + name, _, val = ent.partition("|") + if not val: + continue + try: + if float(val.replace("px", "")) >= 10.0: + out.append(name) + except ValueError: + pass + return out[:limit] + + +_FONTS = _named_fonts() + + +@pytest.fixture(scope="module") +def noised_page(firefox_binary): + """Headless session with render-noise explicitly ON (positive hw_seed) so the + purity / distinctness guards actually exercise the noise path.""" + with InvisiblePlaywright( + seed=42, + binary_path=firefox_binary, + headless=True, + extra_prefs={"zoom.stealth.fpp.hw_seed": 24680}, + ) as browser: + p = browser.new_context().new_page() + p.goto("about:blank", timeout=30_000) + yield p + + +@pytest.mark.e2e +def test_named_fonts_render_distinct_canvas_images(noised_page): + """Each whitelisted named font must produce a DISTINCT tiny-canvas image so an + image-dedup font probe keeps every name. Regression: without the per-font draw + offset all whitelisted fonts share the list-head glyphs -> ~1-2 distinct + images -> degenerate detected-font set.""" + assert len(_FONTS) >= 10, "expected a non-trivial named-font whitelist to probe" + distinct = noised_page.evaluate( + """(args) => { + const [fonts, V] = args; + const c = document.createElement('canvas'); c.width = 90; c.height = 12; + const d = c.getContext('2d'); d.fillStyle = 'red'; + const seen = new Set(); + for (const f of fonts) { + d.clearRect(0, 0, 90, 12); + d.font = 'normal 4px "' + f + '"'; + d.fillText(V, 5, 8); + seen.add(c.toDataURL()); + } + return seen.size; + }""", + [_FONTS, _PROBE], + ) + # broken (offset removed) collapses to ~1-2; require nearly all distinct. + assert distinct >= len(_FONTS) - 2, \ + f"only {distinct}/{len(_FONTS)} distinct font images (per-font offset regressed?)" + + +@pytest.mark.e2e +def test_solid_webgl_readback_stays_pure_under_noise(noised_page): + """A solid-colour WebGL readback must remain byte-exact (only {0,255}) with + render-noise on. Regression: the noise drifted edge pixels 255->254 on some GL + backends (Linux ANGLE-over-GL), breaking fixed-hash reference checks ('oe').""" + res = noised_page.evaluate( + """() => { + const c = document.createElement('canvas'); c.width = 256; c.height = 24; + const gl = c.getContext('webgl', {preserveDrawingBuffer: true}); + if (!gl) return {ok: false, reason: 'no-webgl'}; + gl.clearColor(1, 0, 0, 1); gl.clear(gl.COLOR_BUFFER_BIT); + const buf = new Uint8Array(256 * 24 * 4); + gl.finish(); gl.readPixels(0, 0, 256, 24, gl.RGBA, gl.UNSIGNED_BYTE, buf); + const vals = new Set(); + for (let i = 0; i < buf.length; i++) vals.add(buf[i]); + return {ok: true, vals: Array.from(vals).sort((a, b) => a - b)}; + }""" + ) + if not res["ok"]: + pytest.skip(res.get("reason", "webgl unavailable")) + assert res["vals"] == [0, 255], \ + f"solid WebGL readback not pure under noise: values {res['vals']} (uniform-skip regressed?)" + + +# NOTE: "high-entropy WebGL still noised" is covered by test_webgl_noise_active.py +# (kept separate: it launches its own browsers, so it must not run while this +# module's shared `noised_page` browser is open — the sync API cannot nest). diff --git a/tests/test_geoip_update.py b/tests/test_geoip_update.py index 26632b7..54fa390 100644 --- a/tests/test_geoip_update.py +++ b/tests/test_geoip_update.py @@ -1,13 +1,11 @@ -"""Unit tests for the intelligent geoip mmdb auto-update in `download.py`. +"""Unit tests for the geoip mmdb auto-update in `download.py`. -daijro/geoip-all-in-one rebuilds weekly; `ensure_geoip_mmdb` keeps the cache -fresh without a download (or API call) on every launch. These tests mock the -cache root, the latest-tag API, and the per-tag download so nothing touches the -network. +daijro/geoip-all-in-one rebuilds weekly and keeps only the latest ~2 releases, +so `ensure_geoip_mmdb` never pins a tag: on every call it resolves the CURRENT +latest tag (from the `releases/latest/download` permalink, no GitHub API) and +downloads it only when it differs from the cache. These tests mock the cache +root, the tag resolver, and the per-tag download so nothing touches the network. """ -import os -import time - import pytest import invisible_playwright.download as dl @@ -29,14 +27,6 @@ def _make_cached(root, tag, name=dl.GEOIP_MMDB_NAME): return f -def _set_marker_age(root, days): - m = root / "geoip" / ".last_check" - m.parent.mkdir(parents=True, exist_ok=True) - m.touch() - old = time.time() - days * 86400 - os.utime(m, (old, old)) - - # ────────────────────────────────────────────────────────────────────── # env override # ────────────────────────────────────────────────────────────────────── @@ -56,76 +46,97 @@ def test_env_override_missing_raises(tmp_path, monkeypatch): # ────────────────────────────────────────────────────────────────────── -# freshness window +# every-launch latest check # ────────────────────────────────────────────────────────────────────── @pytest.mark.unit -def test_fresh_cache_no_network(cache, monkeypatch): - f = _make_cached(cache, "2026.06.03") - _set_marker_age(cache, 0) # just checked - - def boom(): - raise AssertionError("latest-tag API must NOT be called within the window") - - monkeypatch.setattr(dl, "_latest_geoip_tag", boom) - assert dl.ensure_geoip_mmdb(max_age_days=7) == f - - -@pytest.mark.unit -def test_stale_same_tag_no_download(cache, monkeypatch): - f = _make_cached(cache, "2026.06.03") - _set_marker_age(cache, 30) # stale → will re-check - monkeypatch.setattr(dl, "_latest_geoip_tag", lambda: "2026.06.03") - # real _download_geoip_tag runs but target exists, so no actual download: +def test_cache_is_latest_no_download(cache, monkeypatch): + f = _make_cached(cache, "2026.06.17") + monkeypatch.setattr(dl, "_resolve_latest_geoip_tag", lambda: "2026.06.17") monkeypatch.setattr(dl, "_download_file", lambda *a, **k: (_ for _ in ()).throw( - AssertionError("must not download when tag already cached"))) - assert dl.ensure_geoip_mmdb(max_age_days=7) == f + AssertionError("must not download when cache already on the latest tag"))) + assert dl.ensure_geoip_mmdb() == f @pytest.mark.unit -def test_stale_new_tag_downloads_and_prunes(cache, monkeypatch): - old = _make_cached(cache, "2026.06.03") - _set_marker_age(cache, 30) - monkeypatch.setattr(dl, "_latest_geoip_tag", lambda: "2026.06.10") - - def fake_download(tag): - return _make_cached(cache, tag) # simulate fetch+extract of the new tag - - monkeypatch.setattr(dl, "_download_geoip_tag", fake_download) - got = dl.ensure_geoip_mmdb(max_age_days=7) - assert got.parent.name == "2026.06.10" +def test_new_tag_downloads_and_prunes(cache, monkeypatch): + old = _make_cached(cache, "2026.06.10") + monkeypatch.setattr(dl, "_resolve_latest_geoip_tag", lambda: "2026.06.17") + monkeypatch.setattr(dl, "_download_geoip_tag", lambda tag: _make_cached(cache, tag)) + got = dl.ensure_geoip_mmdb() + assert got.parent.name == "2026.06.17" assert not old.parent.exists() # old tag pruned assert got.exists() -# ────────────────────────────────────────────────────────────────────── -# offline resilience -# ────────────────────────────────────────────────────────────────────── @pytest.mark.unit -def test_api_down_with_cache_uses_cache(cache, monkeypatch): - f = _make_cached(cache, "2026.06.03") - _set_marker_age(cache, 30) - - def boom(): - raise OSError("offline") - - monkeypatch.setattr(dl, "_latest_geoip_tag", boom) - assert dl.ensure_geoip_mmdb(max_age_days=7) == f # stale cache reused, no raise - - -@pytest.mark.unit -def test_cold_cache_api_down_falls_back_to_pinned(cache, monkeypatch): - # no cache at all + API unreachable → pinned GEOIP_MMDB_VERSION fallback. - def boom(): - raise OSError("offline") - - monkeypatch.setattr(dl, "_latest_geoip_tag", boom) - captured = {} - - def fake_download(tag): - captured["tag"] = tag - return _make_cached(cache, tag) - - monkeypatch.setattr(dl, "_download_geoip_tag", fake_download) - got = dl.ensure_geoip_mmdb(max_age_days=7) - assert captured["tag"] == dl.GEOIP_MMDB_VERSION +def test_cold_cache_downloads_latest(cache, monkeypatch): + monkeypatch.setattr(dl, "_resolve_latest_geoip_tag", lambda: "2026.06.17") + monkeypatch.setattr(dl, "_download_geoip_tag", lambda tag: _make_cached(cache, tag)) + got = dl.ensure_geoip_mmdb() + assert got.parent.name == "2026.06.17" assert got.exists() + + +# ────────────────────────────────────────────────────────────────────── +# offline resilience (no pinned-tag fallback — the pin rots and 404s) +# ────────────────────────────────────────────────────────────────────── +@pytest.mark.unit +def test_offline_with_cache_uses_cache(cache, monkeypatch): + f = _make_cached(cache, "2026.06.10") + monkeypatch.setattr(dl, "_resolve_latest_geoip_tag", lambda: None) # offline + monkeypatch.setattr(dl, "_download_file", lambda *a, **k: (_ for _ in ()).throw( + AssertionError("offline → must not attempt a download"))) + assert dl.ensure_geoip_mmdb() == f # cache reused, no raise + + +@pytest.mark.unit +def test_cold_cache_offline_raises(cache, monkeypatch): + monkeypatch.setattr(dl, "_resolve_latest_geoip_tag", lambda: None) # offline + with pytest.raises(RuntimeError): + dl.ensure_geoip_mmdb() + + +@pytest.mark.unit +def test_download_failure_with_cache_falls_back(cache, monkeypatch): + f = _make_cached(cache, "2026.06.10") + monkeypatch.setattr(dl, "_resolve_latest_geoip_tag", lambda: "2026.06.17") + + def boom(tag): + raise OSError("transient download failure") + + monkeypatch.setattr(dl, "_download_geoip_tag", boom) + assert dl.ensure_geoip_mmdb() == f # keeps the old cache rather than failing + + +# ────────────────────────────────────────────────────────────────────── +# latest-tag resolution via the permalink 302 (no GitHub API) +# ────────────────────────────────────────────────────────────────────── +@pytest.mark.unit +def test_resolve_tag_from_permalink_redirect(monkeypatch): + class _Resp: + headers = {"Location": + "https://github.com/daijro/geoip-all-in-one/releases/download/" + "2026.06.17/geoip-aio-all.mmdb.zip"} + + monkeypatch.setattr(dl.requests, "head", lambda *a, **k: _Resp()) + assert dl._resolve_latest_geoip_tag() == "2026.06.17" + + +@pytest.mark.unit +def test_resolve_tag_permalink_fails_falls_back_to_api(monkeypatch): + def head_boom(*a, **k): + raise OSError("no network for HEAD") + + monkeypatch.setattr(dl.requests, "head", head_boom) + monkeypatch.setattr(dl, "_latest_geoip_tag_api", lambda: "2026.06.17") + assert dl._resolve_latest_geoip_tag() == "2026.06.17" + + +@pytest.mark.unit +def test_resolve_tag_all_fail_returns_none(monkeypatch): + def boom(*a, **k): + raise OSError("offline") + + monkeypatch.setattr(dl.requests, "head", boom) + monkeypatch.setattr(dl, "_latest_geoip_tag_api", boom) + assert dl._resolve_latest_geoip_tag() is None diff --git a/tests/test_integration.py b/tests/test_integration.py index c5c8e91..4ba29c2 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -306,9 +306,9 @@ def test_windows_virtual_display_with_socks_proxy(monkeypatch): @pytest.mark.integration def test_linux_xvfb_workarounds_with_socks_proxy(monkeypatch): """IT11 — Linux + SOCKS5 proxy: Xvfb workarounds applied, GPU renderer - spoofed from profile, SOCKS keys written. virtual_display is a Windows- - only concept so we omit it here; passing ``virtual_display=True`` on - Linux must NOT set ``security.sandbox.gpu.level`` (covered by VD3).""" + spoofed from the validated WebGL persona, SOCKS keys written. virtual_display + is a Windows-only concept so we omit it here; passing ``virtual_display=True`` + on Linux must NOT set ``security.sandbox.gpu.level`` (covered by VD3).""" monkeypatch.setattr(sys, "platform", "linux") profile = generate_profile(seed=42) prefs = translate_profile_to_prefs(profile, virtual_display=True) @@ -323,9 +323,15 @@ def test_linux_xvfb_workarounds_with_socks_proxy(monkeypatch): assert prefs["webgl.force-enabled"] is True # Windows-only sandbox key absent on Linux even with virtual_display=True. assert "security.sandbox.gpu.level" not in prefs - # GPU renderer is spoofed from the profile (not cleared like on Windows). - assert prefs["zoom.stealth.webgl.renderer"] == profile.gpu.renderer + # GPU renderer is spoofed from the validated WebGL persona (a coherent Windows + # ANGLE GPU whose renderer + params cross-check), applied on every host — NOT the + # raw profile.gpu.renderer, which has no coherent param set and is never exposed. + from invisible_playwright._webgl_personas import select_persona + _persona = select_persona(profile.seed) + assert _persona, "expected a validated persona for this seed" + assert prefs["zoom.stealth.webgl.renderer"] == _persona["prefs"]["zoom.stealth.webgl.renderer"] assert prefs["zoom.stealth.webgl.renderer"] # non-empty + assert "ANGLE" in prefs["zoom.stealth.webgl.renderer"] # Windows ANGLE form # SOCKS branch wrote its keys without clobbering the Linux prefs above. assert prefs["network.proxy.type"] == 1 assert prefs["network.proxy.socks"] == "127.0.0.1" diff --git a/tests/test_prefs.py b/tests/test_prefs.py index bab2655..609841b 100644 --- a/tests/test_prefs.py +++ b/tests/test_prefs.py @@ -15,18 +15,18 @@ from invisible_playwright.prefs import ( @pytest.mark.unit def test_translate_includes_gpu_renderer_windows(monkeypatch): - """On Windows we falsify the GPU to one of the calibrated CLEAN buckets (FP Pro - tampering_ml<=0.5 on every seed; sweep 2026-06-14). Only Radeon R9 200 Series and - Intel Arc A750 ship — every NVIDIA/iGPU/945 bucket is penalized. See _webgl_personas.""" + """On Windows we falsify the GPU to a real-Firefox GPU from the camoufox-derived pool + (prevalence-weighted; full coherent renderer+vendor+params+extensions). The chosen GPU's + renderer/vendor are applied verbatim and the renderer is in ANGLE D3D11 wire format.""" monkeypatch.setattr(sys, "platform", "win32") - _CLEAN = { - "ANGLE (AMD, AMD Radeon R9 200 Series Direct3D11 vs_5_0 ps_5_0, D3D11)", - "ANGLE (Intel, Intel(R) Arc(TM) A750 Graphics Direct3D11 vs_5_0 ps_5_0, D3D11)", - } + from invisible_playwright._webgl_personas import select_persona p = generate_profile(seed=42) prefs = translate_profile_to_prefs(p) - assert prefs["zoom.stealth.webgl.renderer"] in _CLEAN - assert prefs["zoom.stealth.webgl.vendor"] in {"Google Inc. (AMD)", "Google Inc. (Intel)"} + persona = select_persona(42) + assert prefs["zoom.stealth.webgl.renderer"] == persona["renderer"] + assert prefs["zoom.stealth.webgl.renderer"].endswith(", D3D11)") + assert prefs["zoom.stealth.webgl.vendor"] == persona["vendor"] + assert "Google Inc." in prefs["zoom.stealth.webgl.vendor"] @pytest.mark.unit @@ -156,15 +156,17 @@ def test_canvas_noise_mask_windows_uses_intel_path(monkeypatch): @pytest.mark.unit def test_webgl_extensions_persona_on_windows(monkeypatch): - # WE2: with a persona active on Windows, extensions are FORCED to the persona's native-order - # list (host-independent), NOT cleared. Order is load-bearing (must match the persona verbatim). + # WE2: with a persona active on Windows, the webgl1/webgl2 extension lists are FORCED to + # the chosen GPU's real native-order lists (carried in the persona's coherent `prefs`), + # NOT cleared. Order is load-bearing (must match the GPU's real capture verbatim). monkeypatch.setattr(sys, "platform", "win32") from invisible_playwright._webgl_personas import select_persona p = generate_profile(seed=42) prefs = translate_profile_to_prefs(p) persona = select_persona(42) - assert prefs["zoom.stealth.webgl.extensions"] == persona["ext1"] - assert prefs["zoom.stealth.webgl2.extensions"] == persona["ext2"] + assert prefs["zoom.stealth.webgl.extensions"] == persona["prefs"]["zoom.stealth.webgl.extensions"] + assert prefs["zoom.stealth.webgl2.extensions"] == persona["prefs"]["zoom.stealth.webgl2.extensions"] + assert prefs["zoom.stealth.webgl.extensions"] # non-empty (a real GPU's ext list) # ────────────────────────────────────────────────────────────────────── @@ -413,14 +415,18 @@ def test_font_metrics_linux2_variant_uses_linux_branch(monkeypatch): @pytest.mark.unit def test_gpu_renderer_set_from_profile_on_linux(monkeypatch): - # PG1: on Linux we spoof to the profile's Windows-ANGLE renderer - # string so cross-platform sessions present a consistent Windows GPU. + # PG1: on Linux (as on EVERY host) we apply the camoufox-derived Windows-ANGLE GPU persona, + # so the page sees a consistent Windows GPU (rule: always look Windows). The C++ WebGL + # override is platform-independent (SanitizeRenderer is pure string regex), so the same + # persona renderer/vendor is presented on Linux too — no more "Generic Renderer". monkeypatch.setattr(sys, "platform", "linux") + from invisible_playwright._webgl_personas import select_persona p = generate_profile(seed=42) prefs = translate_profile_to_prefs(p) - assert prefs["zoom.stealth.webgl.renderer"] == p.gpu.renderer - assert prefs["zoom.stealth.webgl.vendor"] == p.gpu.vendor - assert prefs["zoom.stealth.webgl.renderer"] # non-empty + persona = select_persona(42) + assert prefs["zoom.stealth.webgl.renderer"] == persona["renderer"] + assert prefs["zoom.stealth.webgl.renderer"].endswith(", D3D11)") + assert prefs["zoom.stealth.webgl.vendor"] == persona["vendor"] @pytest.mark.unit @@ -465,8 +471,10 @@ def test_canvas_noise_mask_intel_on_linux(monkeypatch): @pytest.mark.unit def test_canvas_noise_mask_nvidia_on_linux(monkeypatch): - # CN2: NVIDIA/AMD renderer → 1/8 noise (mask=7). The "intel" substring - # check must NOT match here. + # CN2: the canvas-noise mask follows the REAL HOST GPU (the canvas is drawn by real + # hardware, NOT the exposed persona), so it is the Intel-class 1/16 rate (mask=15) on the + # dev/test host even when an NVIDIA persona is exposed — the persona vendor does NOT drive + # the noise rate anymore (would over-noise on an Intel host). monkeypatch.setattr(sys, "platform", "linux") p = generate_profile( seed=42, @@ -476,7 +484,7 @@ def test_canvas_noise_mask_nvidia_on_linux(monkeypatch): }, ) prefs = translate_profile_to_prefs(p) - assert prefs["zoom.stealth.canvas.noise_skip_mask"] == 7 + assert prefs["zoom.stealth.canvas.noise_skip_mask"] == 15 @pytest.mark.unit diff --git a/tests/test_sampler.py b/tests/test_sampler.py index e71c016..b201c7f 100644 --- a/tests/test_sampler.py +++ b/tests/test_sampler.py @@ -275,6 +275,80 @@ def test_derive_font_whitelist_legacy_shim_matches_dict_form(): derive_font_prefs("low_end", rng_b)["whitelist"] +# Standard fonts that ship with every Windows 10/11 install. They MUST be in the +# core (always-present) set, never in the optional/per-profile set: a real Windows +# machine never lacks them, so a session that drops one advertises a font set that +# doesn't match any real Windows profile (image-dedup font probes then report a +# short/degenerate name list → server-side OS-font-set checks fail). Calibri in +# particular sat in `optional` (a bug); these five caused the detected set to come +# up short on some seeds. Regression guard for the 2026-06-18 optional→core move. +_STANDARD_WINDOWS_FONTS = [ + "calibri", "franklin gothic", "gadugi", "javanese text", "myanmar text", +] +_ALL_GPU_CLASSES = [ + "integrated_old", "integrated_modern", "mid_range", "high_end", + "low_end", "workstation", +] + + +@pytest.mark.unit +@pytest.mark.parametrize("gpu_class", _ALL_GPU_CLASSES) +def test_standard_windows_fonts_always_present_every_class_and_seed(gpu_class): + """FP7 [regression]: the standard-Windows fonts appear in BOTH whitelist and + metrics for every gpu_class across many seeds (i.e. they are core, not + profile-optional). Guards against a standard font silently becoming optional.""" + for seed in range(40): + out = derive_font_prefs(gpu_class, random.Random(seed)) + wl = set(out["whitelist"].split(",")) + metrics_names = {s.split("|", 1)[0] for s in out["metrics"].split(",")} + for font in _STANDARD_WINDOWS_FONTS: + assert font in wl, f"{font!r} missing from whitelist (class={gpu_class}, seed={seed})" + assert font in metrics_names, f"{font!r} missing from metrics (class={gpu_class}, seed={seed})" + + +@pytest.mark.unit +def test_standard_windows_fonts_are_in_core_pool(): + """FP8 [regression]: the standard-Windows fonts live in the CORE pool (not + optional) — the structural source of the always-present guarantee above.""" + core_names = {e["name"] for e in _sampler._FONT_CORE} + optional_names = {e["name"] for e in _sampler._FONT_OPTIONAL} + for font in _STANDARD_WINDOWS_FONTS: + assert font in core_names, f"{font!r} must be in core pool" + assert font not in optional_names, f"{font!r} must NOT be in optional pool" + + +@pytest.mark.unit +@pytest.mark.parametrize("gpu_class", _ALL_GPU_CLASSES) +def test_derive_font_prefs_no_duplicate_families(gpu_class): + """FP9 [regression]: no family appears twice in whitelist/metrics, even when a + profile's optional list also names a core font. Guards the dedup in + derive_font_prefs (a duplicate family would emit a malformed pref pair).""" + for seed in range(30): + out = derive_font_prefs(gpu_class, random.Random(seed)) + wl = out["whitelist"].split(",") + metrics_names = [s.split("|", 1)[0] for s in out["metrics"].split(",")] + assert len(wl) == len(set(wl)), f"duplicate in whitelist (class={gpu_class}, seed={seed})" + assert len(metrics_names) == len(set(metrics_names)), \ + f"duplicate in metrics (class={gpu_class}, seed={seed})" + + +@pytest.mark.unit +@pytest.mark.parametrize("gpu_class", _ALL_GPU_CLASSES) +def test_derive_font_prefs_named_fonts_emit_absolute_widths(gpu_class): + """FP10 [regression]: every emitted metrics value is a positive number; named + (non-generic) fonts carry an ABSOLUTE collapse-target width (>= 10), which the + binary self-calibrates per host. A value < 10 here would mean a font slipped + through as a bare multiplicative factor and would render at the wrong width.""" + out = derive_font_prefs(gpu_class, random.Random(3)) + for entry in out["metrics"].split(","): + name, _, val = entry.partition("|") + v = float(val.replace("px", "")) + assert v > 0.0, f"non-positive metrics value for {name!r}" + # the standard named fonts must be absolute (collapse-target) widths + if name in _STANDARD_WINDOWS_FONTS: + assert v >= 10.0, f"{name!r} emitted as factor {v} (<10), expected absolute width" + + # ── Forge / sample ────────────────────────────────────────────────────── # Keys the Forge.sample bundle must always contain. Builds on _LOCKED + diff --git a/tests/test_webgl_noise_active.py b/tests/test_webgl_noise_active.py new file mode 100644 index 0000000..4d460df --- /dev/null +++ b/tests/test_webgl_noise_active.py @@ -0,0 +1,63 @@ +"""Regression guard: render-noise stays ACTIVE on high-entropy WebGL readbacks. + +The near-uniform skip added 2026-06-18 (so fixed-hash reference checks on a solid +WebGL readback pass) must NOT disable noise on real fingerprint renders. A +high-entropy WebGL readback (>16 distinct colours) must still differ between two +seeds — i.e. the per-seed gamma noise is applied. Pairs with +test_canvas_render_stealth.py (solid readback stays pure). + +Kept in its own file: it launches its own short-lived browsers, so it must not run +alongside another module's shared browser (the Playwright sync API cannot nest). + +Run: pytest tests/test_webgl_noise_active.py -m e2e -v +""" +from __future__ import annotations + +import hashlib + +import pytest + +from invisible_playwright import InvisiblePlaywright + +# A high-entropy render: 64 columns, each a distinct colour (>16 distinct → the +# near-uniform skip does NOT apply → noise must run). +_HIGH_ENTROPY_JS = """() => { + const c = document.createElement('canvas'); c.width = 64; c.height = 64; + const gl = c.getContext('webgl', {preserveDrawingBuffer: true}); + if (!gl) return null; + gl.enable(gl.SCISSOR_TEST); + for (let k = 0; k < 64; k++) { + gl.scissor(k, 0, 1, 64); + gl.clearColor(k / 64, (63 - k) / 64, (k * 7 % 64) / 64, 1); + gl.clear(gl.COLOR_BUFFER_BIT); + } + const buf = new Uint8Array(64 * 64 * 4); + gl.finish(); gl.readPixels(0, 0, 64, 64, gl.RGBA, gl.UNSIGNED_BYTE, buf); + return Array.from(buf); +}""" + + +def _render_hash(firefox_binary, seed: int): + with InvisiblePlaywright( + seed=seed, binary_path=firefox_binary, headless=True, + extra_prefs={"zoom.stealth.fpp.hw_seed": 1000 + seed}, + ) as b: + p = b.new_context().new_page() + p.goto("about:blank", timeout=30_000) + arr = p.evaluate(_HIGH_ENTROPY_JS) + if arr is None: + return None + return hashlib.sha256(bytes(arr)).hexdigest() + + +@pytest.mark.e2e +def test_high_entropy_webgl_still_noised_per_seed(firefox_binary): + """Two different seeds → two different per-seed gamma curves → the high-entropy + readback hashes must differ. Identical hashes would mean the noise was skipped + on a real (non-uniform) render — a regression of the uniform-skip scope.""" + h1 = _render_hash(firefox_binary, 1) + h2 = _render_hash(firefox_binary, 2) + if h1 is None or h2 is None: + pytest.skip("webgl unavailable") + assert h1 != h2, \ + "high-entropy WebGL readback identical across seeds → render-noise not applied"