mirror of
https://github.com/feder-cr/invisible_playwright.git
synced 2026-06-28 09:29:37 +02:00
Geo-aware locale, audio noise off, font prefs for the bundled-font binary
locale defaults to "auto" and resolves from the proxy egress country the same way timezone does - it reuses the egress IP, maps the country to a BCP-47 locale with the offline mmdb, and falls back to en-US. prefs emit juggler.locale.override (the full Accept-Language list) so the binary keeps navigator.languages and the Intl default locale in sync. The audio fingerprint noise is off in the baseline. Font prefs match the new binary: the sampled whitelist drives font.system.whitelist, system-ui is Segoe UI, the bundled fonts are activated, and the CSS generics are pinned to Windows defaults so they resolve on a non-Windows host too.
This commit is contained in:
parent
8f4b20a19d
commit
3c0efa2d4f
13 changed files with 353 additions and 1015 deletions
|
|
@ -1,19 +1,17 @@
|
|||
"""Canvas / WebGL render-stealth regression tests (binary-level, 2026-06-18).
|
||||
"""Canvas / WebGL render-stealth regression test (binary-level, 2026-06-18).
|
||||
|
||||
Two patched-binary behaviours that must never regress, both needed for the
|
||||
Guards a patched-binary behaviour that must never regress, 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:
|
||||
FingerprintJS, BrowserLeaks) and 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.)
|
||||
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.)
|
||||
|
||||
(Per-font canvas distinctness is no longer guarded here: the font-collapse +
|
||||
per-font draw offset were removed on 2026-06-20 in favour of real bundled
|
||||
Windows fonts, which rasterise to distinct images by nature.)
|
||||
|
||||
Runs against about:blank, no network/proxy. Part of the e2e release gate.
|
||||
Run: pytest tests/test_canvas_render_stealth.py -m e2e -v
|
||||
|
|
@ -23,34 +21,6 @@ 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")
|
||||
|
|
@ -68,34 +38,6 @@ def noised_page(firefox_binary):
|
|||
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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue