Отчёт CreepJS WebGL: контексты и сигналы
Путь полей WebGL в CreepJS: фиксированный исходный код, сравнение контекстов, renderer, чтение пикселей и границы вывода.
BotBrowser Team
Нужна структурированная документация по теме Отпечатки?
Эта статья относится к редакционной библиотеке. Для пошаговой настройки, справки и постоянных обновлений переходите сразу в соответствующий раздел docs.
Отчёт CreepJS WebGL - это не одно графическое значение и не единая проверка с результатом «успех» или «ошибка». В зафиксированной публичной реализации разные участки кода собирают параметры WebGL и WebGL2, необязательные метаданные renderer, точность шейдеров, данные изображения canvas и производные сводки возможностей. Если читать все поля как один вердикт, теряется понимание того, какая операция создала каждое из них и какая ветка обработки ошибки действительно выполнилась.
BotBrowser документирует настройки WebGL на основе профиля и способы их проверки, но не утверждает, что отчёт CreepJS устанавливает личность физического устройства или предсказывает решение постороннего сайта. Практическая задача уже: проследить конкретную реализацию от исходных полей до условных ветвей отчёта и сохранить границы между наблюдениями.
BotBrowser поддерживает настройку WebGL через профиль и проверку заявленного поведения в разрешённой среде; по одному полю CreepJS он не может установить физическую идентичность устройства или решение другого сайта.
Отдельный сборщик BrowserLeaks разобран в анализе отчёта WebGL: там прослежены выбор контекста, необязательные данные рендерера и проверки пропущенных полей без приписывания результатов CreepJS.
TL;DR
- Источник разбора:
src/webgl/index.tsиз commit CreepJS10aa6724cd33a1015db1574211890518cd04f0cc. Статическая проверка кода не подтверждает текущее поведение сайта и не является измерением BotBrowser. - Функция отдельно создаёт контексты WebGL и WebGL2. Она завершает этот путь, если контекст WebGL отсутствует, но видимая ветка не требует наличия WebGL2, чтобы продолжить.
- Проверка соответствия сравнивает выбранные значения из карты параметров WebGL2 с truthy-значениями карты WebGL. Она пропускает
ALIASED_LINE_WIDTH_RANGE,SHADING_LANGUAGE_VERSIONиVERSION. WEBGL_debug_renderer_info, точность шейдеров, URI данных canvas и результатreadPixels- разные наблюдения. Отсутствие данных в одном канале не объясняет состояние другого.- Производная ветка возможностей может присвоить
LowerEntropy.WEBGL, если значение отсутствует во встроенном списке. Это поведение данной зафиксированной реализации, а не универсальное правило WebGL и не вывод о человеке.
Содержание
- Два контекста запускают отдельные пути сбора
- Проверка соответствия охватывает только заданные случаи
- Поля renderer и точности нельзя считать взаимозаменяемыми
- Экспорт canvas и чтение пикселей могут расходиться
- Сводки возможностей вычисляются отдельно
- При чтении отчёта важно сохранять границы доказательств
- Практический вывод
Два контекста запускают отдельные пути сбора
Код создаёт canvas для контекста webgl и другой для webgl2, затем вызывает getContext с соответствующими именами. Функция проверяет, существует ли первый контекст. Если нет, CreepJS записывает неуспешный результат теста webgl и завершает этот путь. В показанном месте кода нет такого же раннего выхода для gl2; последующие helpers обрабатывают отсутствующий контекст иначе.
Этот порядок важен при чтении сжатого отчёта. Ошибка пути WebGL не означает, что оба типа контекста успешно проверены и вернули совпадающие результаты. Код не объясняет и причину недоступности первого контекста. Создание может зависеть от поддержки браузером, состояния canvas, наличия ресурсов и логики приложения. Поле отчёта не определяет, какое именно объяснение верно.
Различие полезно для диагностической страницы собственного приложения. Сборщик может отдельно записывать webgl_context_created и webgl2_context_created, а исключение при настройке сохранять в отдельном поле. Не следует записывать единственный boolean graphics_supported, пока у каждой попытки не определён собственный результат. Такая схема записи предложена как способ читать поведение приложения; это не формат CreepJS и не стандартный API браузера.
| Событие сбора | Что устанавливает зафиксированный код | Что остаётся неизвестным |
|---|---|---|
| Контекст WebGL отсутствует | Эта функция записывает ошибку теста webgl и прекращает данный путь | Почему запрос не создал контекст и изменился бы результат при повторе |
| WebGL есть, WebGL2 отсутствует | Выполнение проходит первую проверку; helpers с отсутствующим контекстом могут вернуть пустые или неопределённые данные | Сохраняют ли последующие поля это различие для конкретного потребителя отчёта |
| Есть ссылки на оба контекста | Последующие helpers параметров и отрисовки могут получить обе ссылки | Сработают ли все необязательные расширения и операции чтения |
| Настройка выбрасывает исключение до присвоения поля | Внешняя обработка ошибок может вернуть результат в форме ошибки | Какая операция завершилась ошибкой, если этап не сохранён вместе с ней |
Это карта потока управления, а не таблица совместимости. Доступный контекст не означает наличия всех необязательных расширений, а его успешное создание не гарантирует, что буфер рисования удастся прочитать. При сравнении версий браузера приложение должно отдельно указывать запрошенный контекст, результат вызова и результат каждой последующей операции. Так изменение кода сбора видно напрямую и его не принимают за изменение графических возможностей.
Общий разбор WebGL fingerprinting описывает более широкую поверхность раскрытия и настройки профиля BotBrowser. Зафиксированный модуль src/webgl/index.ts отдельно формирует результаты контекстов, сравнения параметров, необязательные данные renderer, точность шейдеров, вывод canvas и пикселей, а также производные поля возможностей. Разбор пропавших значений renderer WebGL посвящён состояниям приложения: поле не запрашивалось, контекст недоступен или потерян, расширение отсутствует. Он не прослеживает формирование выходных данных CreepJS.
Проверка соответствия охватывает только заданные случаи
После создания объектов параметров для двух контекстов реализация задаёт три ключа, исключённых из сравнения: ALIASED_LINE_WIDTH_RANGE, SHADING_LANGUAGE_VERSION и VERSION. Список несовпадений строится по ключам объекта WebGL2. Ключ-кандидат также должен иметь truthy-значение в объекте WebGL, не входить в список исключений и отличаться при строковом представлении в обоих объектах. Ветка отчёта срабатывает только тогда, когда полученный список не пуст.
Условие можно представить без лишних утверждений:
для каждого ключа в объекте параметров WebGL2:
оставить только если WebGL[key] - truthy
пропустить ALIASED_LINE_WIDTH_RANGE, SHADING_LANGUAGE_VERSION, VERSION
сравнить String(WebGL[key]) и String(WebGL2[key])
сообщить о несовпадении, только если остался хотя бы один ключ
Такой разбор полезен тем, что показывает и область проверки, и пропуски. Это не исчерпывающая проверка равенства всех значений обоих контекстов. Свойство, имеющееся только в объекте WebGL, не обходится. Ложное значение со стороны WebGL не проходит проверку truthy. Разница, скрытая строковым преобразованием, может обрабатываться не так, как структурное сравнение массивов или типизированных значений. Три исключённых имени не участвуют в проверке независимо от их значений.
| Пример формы входных данных | Попадёт в список несовпадений? | Причина |
|---|---|---|
| Одинаковое truthy-значение не исключённого ключа в обеих картах | Нет | Строковые представления совпадают |
| Разные truthy-значения не исключённого ключа в обеих картах | Да | Строковые представления различаются |
Значение WebGL равно 0, false, '', null или undefined | Нет | Фильтр требует truthy-значение WebGL |
| Ключа нет в карте WebGL2 | Нет | Реализация обходит ключи WebGL2 |
Ключ - VERSION или одно из двух других исключённых имён | Нет | Его отсекает явная карта исключений |
Эти случаи описывают предикат в зафиксированном исходном коде; они не утверждают, какие значения вернул конкретный браузер. Рассуждение можно повторить по объекту VersionParam, фильтру Object.keys(params2) и условию mismatch.length в указанном commit. Это помогает избежать слишком широкого вывода: «отчёт не показал несовпадений» не означает, что все значения WebGL и WebGL2 были равны. Это означает лишь, что предикат вернул пустой список для полученных данных.
Отчёт также не показывает сопровождающей команде, возникло ли различие из-за дефекта реализации, неподдерживаемого значения, сериализации, отсутствующего контекста или изменения сбора. Это возможные направления исследования, а не выводы, содержащиеся в самой ветке. Если важна причина, диагностическая запись должна сохранять имя поля и этап сбора; агрегированный счётчик «несовпадений WebGL» удаляет как раз те сведения, которые нужны для различения случаев.
Поля renderer и точности нельзя считать взаимозаменяемыми
Сначала исходный код собирает значения параметров каждого контекста. Затем при наличии WEBGL_debug_renderer_info добавляются незамаскированные сведения renderer. Helper запрашивает расширение у контекста; если его нет, возвращается пустой объект. Если расширение доступно, код читает UNMASKED_VENDOR_WEBGL и UNMASKED_RENDERER_WEBGL через getParameter.
Путь необязательного расширения отличается от обычных параметров контекста. Спецификация Khronos для расширения определяет необязательные незамаскированные константы vendor и renderer; справочник MDN getParameter описывает API запроса. Ни один из этих источников не делает отсутствие объекта расширения объяснением причины. Оно не доказывает действие настройки приватности, отсутствие GPU, решение политики или намерение приложения. Оно означает только, что helper не добавил два поля этим путём.
Точность шейдеров - другая категория. Helper запрашивает несколько форматов для vertex- и fragment-шейдеров, включая низкую, среднюю и высокую точность с плавающей точкой, а также высокую целочисленную точность. Затем записываются свойства precision, rangeMax и rangeMin под ключами, связанными с этапом шейдера и форматом. Эти поля описывают результат запроса точности у текущего контекста. Это не имена renderer, не флаги расширений и не доказательство физической идентичности двух устройств.
Итоговый объект параметров также дополняется отдельными атрибутами и ограничениями контекста. Видимая сборка включает атрибут antialias, MAX_VIEWPORT_DIMS, максимальную анизотропию текстур при наличии расширения анизотропии и MAX_DRAW_BUFFERS_WEBGL при наличии соответствующего расширения. Некоторые запросы обёрнуты в helper attempt, а значения, зависящие от расширений, могут отсутствовать. Поэтому потребителю отчёта следует различать состояния «отсутствует», «не запрашивалось» и «запрос вызвал ошибку», если окружающий вывод сохраняет это различие.
| Семейство выходных данных | Операция в исходном коде | Чего не устанавливает отсутствующее значение |
|---|---|---|
| Стандартные параметры | Перебор выбранных имён параметров и вызов getParameter | Отсутствие у браузера всех графических возможностей |
| Незамаскированные vendor/renderer | Запрос WEBGL_debug_renderer_info, затем чтение двух констант | Что отсутствие вызвала настройка приватности |
| Точность шейдеров | Вызов getShaderPrecisionFormat для именованных форматов | Стабильную идентичность устройства или решение сайта |
| Необязательные ограничения | Запрос констант расширения или атрибутов контекста | Успех другого независимого запроса |
Таблица описывает путь исходного кода, а не рекомендуемую схему отслеживания. Строки renderer могут быть идентифицирующими и не всегда нужны для ответа на вопрос поддержки. Продукту следует собирать только данные, необходимые для заявленной задачи, объяснять необязательную диагностику и не использовать необработанную метку как ключ учётной записи. Документация BotBrowser по WebGL описывает собственные настройки BotBrowser на основе профилей; исходный код CreepJS не доказывает, что BotBrowser вернёт конкретное значение на устройстве пользователя.
Экспорт canvas и чтение пикселей могут расходиться
Helper getWebGLData рисует шаблон в контексте и пытается создать два вида выходных данных. Первый - URI данных canvas. Второй - массив байтов, заполненный вызовом readPixels. Код читает размеры буфера рисования, получает меньшую ширину и высоту делением на 15 и 6, выделяет по четыре байта на выбираемый пиксель и запрашивает значения RGBA типа unsigned byte от начала в левом нижнем углу.
Порядок операций создаёт конкретный случай частичного отказа. Сначала функция вызывает toDataURL, затем readPixels. Если внутренний вызов readPixels выбрасывает исключение, обработчик возвращает уже полученный dataURI и устанавливает pixels в undefined. Результат не является атомарным. Если видно изображение, а данные пикселей отсутствуют, нельзя заключать, что весь путь WebGL завершился ошибкой. И наоборот, отсутствие URI данных не доказывает, что чтение пикселей предпринималось: более ранняя ошибка может попасть во внешний catch.
Для OffscreenCanvas helper использует отдельный вариант: для получения URI данных он создаёт обычный canvas и рисует на нём. Чтение пикселей по-прежнему относится к исходному WebGL-контексту. Путь экспорта изображения и путь чтения пикселей связаны операцией рисования, но это не один вызов API и не одно представление результата.
| Место ошибки | Путь URI данных | Путь пикселей | Граница интерпретации |
|---|---|---|---|
| Аргумент контекста отсутствует | Helper возвращает неопределённые поля вывода | Чтение не выполняется | Helper не объясняет отсутствие контекста |
| Ошибка при рисовании или создании URI | Внешняя обработка перехватывает ошибку | До последующего чтения выполнение не доходит | Не классифицируйте это как ошибку readPixels |
readPixels завершился ошибкой после создания URI | Helper может вернуть URI данных | pixels становится undefined | У полей нет единого атомарного индикатора успеха |
| Обе операции возвращают результат | URI данных присутствует | Возвращается массив пикселей | Ни одно значение само по себе не описывает физическое устройство |
Разработчик собственной страницы рендеринга может использовать эту карту для теста поддержки: записать, выполнялось ли рисование, завершилась ли сериализация и завершилось ли чтение пикселей. Раздельные результаты помогают проверить резервный путь и не сохранять больше данных, чем требует задача поддержки. Здесь не утверждается, что сетка выборки является стандартным или уникальным отпечатком либо что один из результатов предсказывает принятие сессии третьей стороной.
Сводки возможностей вычисляются отдельно
После сбора исходных полей модуль строит нормализованный числовой список из значений верхнего уровня, которые проходят проверку truthy в JavaScript и не являются строками. Array.prototype.flat() разворачивает массивы на один уровень; каждый полученный элемент преобразуется через Number, дубликаты удаляются, а результат сортируется по числу. Затем код использует строку renderer для получения марки GPU и рассчитывает две отдельные сводки: компактное значение из марки и вектора параметров и значение возможностей на основе свёртки числового списка.
Модуль сравнивает эти производные значения со встроенными списками. Если значение марки и возможностей есть, но отсутствует в списке марок, условие hasSusGpu истинно. Если производное значение возможностей есть, но не входит в числовой список, истинно hasSusCapabilities. Каждая из этих ветвей может присвоить LowerEntropy.WEBGL и вызвать sendToTrash с соответствующей меткой. Позднее исходный код записывает тест WebGL как пройденный и возвращает собранные данные вместе с полями классификации GPU.
Слово “suspicious” в имени переменной относится к внутренней ветке реализации. Это не стандартизованное определение подозрительного оборудования. Значение может отсутствовать в списке после изменения списка, из-за неучтённой комбинации, отсутствующего или преобразованного параметра либо среды выполнения. Статический разбор не позволяет установить, какая причина описывает браузер, создающий отчёт сейчас.
| Производный элемент | Видимые входы в исходном коде | Чего ветка не доказывает |
|---|---|---|
webglParams | Значения верхнего уровня truthy и нестроковые; массивы развёрнуты на один уровень, значения преобразованы, уникальны и отсортированы | Что присутствуют все параметры WebGL или что вектор стабилен между версиями |
webglBrandCapabilities | Марка из строки renderer плюс строковое представление вектора параметров | Что строка renderer называет физическое оборудование или значение уникально определяет устройство |
webglCapabilities | Числовые значения параметров и их позиции после сортировки в операции свёртки | Что результат является отраслевым идентификатором возможностей |
Ветка LowerEntropy.WEBGL | Проверки вхождения во встроенные массивы марок и возможностей | Универсальный bot-вердикт, идентичность учётной записи или причина политики |
Между необработанными полями и производной сводкой есть важное различие. Поле можно связать с вызовом WebGL API. Сводка может зависеть от нормализации, сортировки, функций компактного значения, списков поиска и проверок truthy после сбора. При изменении итогового отчёта полезно сначала сопоставить ревизию исходного кода и эти преобразования, а не приписывать разницу физическому GPU.
Разбор групп сигналов CreepJS объясняет, как отчёт объединяет независимые поверхности браузера. Разбор перекрёстных проверок и решений между группами посвящён комбинациям и логике решения. Производная ветвь модуля использует собранные поля WebGL и встроенные списки; сама ветвь не описывает объединение данных между группами.
При чтении отчёта важно сохранять границы доказательств
Аккуратный анализ исходного кода начинается с фиксации ревизии. Один и тот же путь в изменяемой ветке по умолчанию может измениться между сохранением отчёта и сегодняшним днём. Фиксация commit 10aa6724cd33a1015db1574211890518cd04f0cc и пути src/webgl/index.ts делает ссылки на строки и описание потока управления воспроизводимыми. Однако она не доказывает, что активный сайт развернул эту ревизию, что конкретный отчёт был создан именно ею или что в конкретном браузере выполнились все ветки.
При разборе отчёта фиксируйте только факты, необходимые для поставленного вопроса:
- Определите видимое поле и семейство выходных данных: контекст, параметр, необязательное расширение, запрос шейдера, URI данных, массив пикселей или производная сводка.
- До назначения причины сопоставьте поле с функцией и веткой зафиксированного исходного кода.
- Если исходный код или отчёт сохраняет эти состояния, отдельно отмечайте отсутствие,
undefined, пустое значение, ошибку и наличие результата. - Проверьте, сравнивалось ли значение напрямую, преобразовывалось в строку, нормализовалось, преобразовывалось другим способом или сопоставлялось со списком.
- Формулируйте узкий вывод, который поддерживает наблюдаемая ветка; оставляйте ненаблюдавшиеся причины без вывода.
Эти шаги полезны для проверки приватности, анализа регрессий и объяснения стороннего отчёта без выдумывания идентичности устройства. Снимок исходного кода показывает, что код сделал бы при определённых входных данных; он не предоставляет эти данные и не подтверждает выполнение ненаблюдавшейся ветки.
Вопросы
Отсутствующий renderer WebGL означает, что WebGL выключен?
Нет. Поля renderer поступают через необязательное расширение WEBGL_debug_renderer_info, а создание контекста проверяется отдельно. Контекст может существовать без добавления незамаскированных значений renderer. Одни отсутствующие поля не указывают причину.
Проверка соответствия сравнивает все значения WebGL?
Нет. Она обходит ключи объекта параметров WebGL2, требует истинное соответствующее значение WebGL, пропускает три названных ключа и сравнивает строки. Пустой список несовпадений относится только к этому предикату и полученным им данным.
LowerEntropy.WEBGL означает, что браузер - bot?
В зафиксированном модуле эта внутренняя метка устанавливается, если производное значение отсутствует во встроенных списках. Код не делает её универсальным стандартом WebGL; само поле не устанавливает решение сайта о посетителе.
Успешный URI данных означает, что readPixels тоже завершился успешно?
Нет. Helper сериализует canvas до чтения пикселей. Внутренний обработчик ошибки чтения может вернуть URI данных вместе с неопределёнными данными пикселей. Эти поля имеют разные состояния завершения.
Источники
- Исходный код WebGL CreepJS, commit
10aa6724cd33a1015db1574211890518cd04f0cc - Спецификация Khronos WebGL 1.0
- Расширение Khronos
WEBGL_debug_renderer_info - MDN:
WebGLRenderingContext.getParameter() - MDN:
HTMLCanvasElement.toDataURL() - Документация BotBrowser по WebGL
- Документация BotBrowser по согласованности автоматизации
Практический вывод
Рассматривайте отчёт как набор наблюдений, зависящих от исходного кода, а не как единственную метку устройства. Фиксируйте ревизию реализации, сохраняйте контекст и операцию, создавшие каждое значение, и не объединяйте необязательные данные renderer, сериализацию изображения, чтение пикселей и производные ветви возможностей. Если поле отсутствует, описывайте отсутствие только на уровне, который поддерживает код; не выводите его причину или решение другого сайта.
Эта статья входит в руководство: Что такое отпечаток браузера?
Похожие статьи
Отчёт BrowserLeaks WebGL: сбор и отсутствующие данные
ОтпечаткиWEBGL_debug_renderer_info: границы приватности и renderer
ОтпечаткиНет рендерера WebGL: приватность или состояние контекста?
Отпечаткиwebgl_debug_renderer_info: что GPU раскрывает страницам
ОтпечаткиПрограммный рендеринг WebGL, откат возможностей и приватность
ОтпечаткиСигналы Math в CreepJS: источники полей
Переведите BotBrowser из исследований в продакшн
Используйте эти руководства, чтобы понять модель, а затем перейти к кроссплатформенной валидации, изолированным контекстам и масштабируемому браузерному развертыванию.