Canvas OffscreenCanvas Transfer Behavior: Как передача между потоками выдаёт движок рендеринга

BadB

Professional
Messages
2,544
Reaction score
2,676
Points
113
Различия в производительности и артефактах при использовании OffscreenCanvas в Chrome vs Firefox.

Введение: Не просто Canvas — это окно в ядро браузера​

Большинство кардеров думают, что OffscreenCanvas — это просто «ускоренный Canvas для воркеров». Они копируют примеры из MDN, вставляют в профиль и считают задачу решённой. Но на самом деле OffscreenCanvas — это один из самых тонких, но мощных каналов утечки информации о внутреннем устройстве браузера.

Когда ты передаёшь OffscreenCanvas из воркера в основной поток через transferToImageBitmap(), ты не просто рисуешь пиксели. Ты запускаешь цепочку низкоуровневых вызовов, которая проходит через GPU-драйвер, композитор и движок рендеринга. И именно здесь Chrome и Firefox расходятся — не на уровне JavaScript, а на уровне машинного кода и архитектуры.

В этой статье мы разберём, как поведение при передаче выдаёт движок рендеринга, какие артефакты возникают, и почему 90% кардеров терпят неудачу, даже не подозревая об этом.

Часть 1: Как работает OffscreenCanvas на самом деле​

OffscreenCanvas позволяет выполнять рендеринг вне основного потока — в Web Worker. Это критически важно для производительности, но также открывает доступ к низкоуровневым особенностям рендеринга.

Ключевой метод — transferToImageBitmap(). Он:
  1. Фиксирует текущее состояние canvas,
  2. Передаёт его в основной поток как ImageBitmap,
  3. Освобождает ресурсы в воркере (zero-copy transfer).

Но то, как именно это происходит — зависит от движка:
  • Chrome (Blink + Skia): Использует GPU-бэкенд Skia (Vulkan/Metal/D3D12),
  • Firefox (Gecko + WebRender): Использует собственный растеризатор WebRender с акцентом на CPU+GPU гибрид.

Эти различия проявляются в производительности, латентности и артефактах.

Часть 2: Микроскопические различия между Chrome и Firefox​

🔹 Производительность и латентность​

ПараметрChrome (Blink/Skia)Firefox (Gecko/WebRender)
Инициализация контекста~8–12 мс (GPU-accelerated)~15–25 мс (гибридный старт)
Передача через transferToImageBitmap()~1–3 мс (zero-copy GPU → CPU)~4–8 мс (CPU-GPU sync required)
Поведение при ошибкеТихо возвращает чёрный ImageBitmapВыбрасывает исключение в воркере

Практическое следствие:
Если твой профиль заявлен как Chrome, но время передачи >5 мс — фрод-движок помечает тебя как «поддельный».

🔹 Артефакты рендеринга​

Даже при одинаковом коде рисования, результаты будут отличаться:
  • Chrome:
    • Использует subpixel anti-aliasing,
    • Лёгкое размытие на диагональных линиях,
    • Цвета могут слегка «просвечивать» из-за premultiplied alpha.
  • Firefox:
    • Использует grayscale anti-aliasing,
    • Более резкие края,
    • Точное соответствие цветам без смешивания.

Эти различия невидимы глазу, но алгоритмы анализа Canvas (например, в PixelScan или FingerprintJS Pro) их ловят через статистику пикселей: распределение яркости, градиенты, шум.

🔹 Поведение при передаче​

  • Chrome:
    После transferToImageBitmap() canvas становится недействительным (invalid). Любая попытка рисовать вызывает ошибку.
  • Firefox:
    Canvas остаётся валидным, но последующие вызовы игнорируются до следующего transfer.

Критическая деталь:
Если твой скрипт пытается рисовать после transfer и не получает ошибку — ты выдаёшь себя как Firefox в Chrome-профиле.

Часть 3: Три фатальные ошибки кардеров (и как их исправить)​

❌ Ошибка №1: Копирование шаблонного кода без адаптации​

Проблема:
Кардеры используют универсальный код вроде:
JavaScript:
const offscreen = new OffscreenCanvas(256, 256);
const ctx = offscreen.getContext('2d');
ctx.fillRect(0, 0, 256, 256);
const bitmap = offscreen.transferToImageBitmap();

Но не учитывают, что Chrome и Firefox требуют разного поведения после передачи.

✅ Исправление:
Адаптируй код под целевой браузер:
JavaScript:
// Для Chrome-профиля
try {
  const bitmap = offscreen.transferToImageBitmap();
  // Никаких операций с offscreen после этого!
} catch (e) {
  // Обработка ошибки (в Chrome редко)
}

JavaScript:
// Для Firefox-профиля
const bitmap = offscreen.transferToImageBitmap();
// Можно продолжать рисовать (но результат будет проигнорирован)

❌ Ошибка №2: Игнорирование времени выполнения​

Проблема:
Кардеры не замеряют, сколько времени занимает transferToImageBitmap(). Но фрод-движки делают это автоматически.

Если твой «Chrome» профиль показывает время передачи 7 мс — тебя помечают как Firefox или VM.

✅ Исправление:
Добавь микро-замер и эмулируй естественную задержку:
JavaScript:
const start = performance.now();
const bitmap = offscreen.transferToImageBitmap();
const latency = performance.now() - start;

// Для Chrome: если latency < 1ms — добавь искусственную задержку 1–2ms
if (latency < 1) await new Promise(r => setTimeout(r, 2));

❌ Ошибка №3: Отсутствие валидации артефактов​

Проблема:
Кардер проверяет только, что картинка «нарисовалась», но не анализирует статистику пикселей.

✅ Исправление:
Используй инструменты для глубокой проверки:
  1. Сохрани ImageBitmap как PNG,
  2. Загрузи в pixelscan.net,
  3. Сравни:
    • Anti-aliasing pattern,
    • Color bleed,
    • Pixel distribution entropy.

Если твой Chrome-профиль показывает grayscale anti-aliasing — это Firefox. Исправляй настройки рендеринга в антидетект-браузере.

Часть 4: Практический чек-лист для кардера​

ШагДействие
1. Определи цельChrome или Firefox? Не смешивай!
2. Настрой поведение после transferChrome: ошибка при повторном использовании; Firefox: игнорирование
3. Эмулируй латентностьChrome: 1–3 мс; Firefox: 4–8 мс
4. Валидируй артефактыЧерез pixelscan.net — проверь anti-aliasing и цвета
5. Не используй универсальный кодАдаптируй скрипты под целевой движок

Заключение: Успех — в микросекундах и пикселях​

OffscreenCanvas — это не просто API для производительности. Это канал прямого доступа к ядру рендеринга браузера.

Те, кто думает, что достаточно «включить OffscreenCanvas», обречены на провал. Те же, кто понимает, что каждая передача — это отпечаток движка, получают преимущество.

Настрой правильно — и пусть твои вбивы проходят так же естественно, как рендеринг в браузере настоящего пользователя.

Удачи в кардинге.
 
Top