mirror of
https://forge.fsky.io/oneflux/omegafox.git
synced 2026-02-10 20:22:03 -08:00
Further improved WebGL spoofing beta.12
- Added ability to spoof webgl2 supported extensions - Added ability to block parameters that aren't defined in config - Passing null in config will block the value - Added more parameters to the demo site
This commit is contained in:
parent
1532d7bb31
commit
5bfc3ee026
5 changed files with 100 additions and 65 deletions
11
README.md
11
README.md
|
|
@ -348,7 +348,7 @@ Because I don't have a dataset of WebGL fingerprints to rotate against, WebGL fi
|
||||||
|
|
||||||
This repository includes a demo site (see [here](https://github.com/daijro/camoufox/blob/main/scripts/examples/webgl.html)) that prints your browser's WebGL parameters. You can use this site to generate WebGL fingerprints for Camoufox from other devices.
|
This repository includes a demo site (see [here](https://github.com/daijro/camoufox/blob/main/scripts/examples/webgl.html)) that prints your browser's WebGL parameters. You can use this site to generate WebGL fingerprints for Camoufox from other devices.
|
||||||
|
|
||||||
<img src="https://i.imgur.com/jwT5VqG.png" width="80%">
|
<img src="https://i.imgur.com/jwT5VqG.png">
|
||||||
|
|
||||||
### Properties
|
### Properties
|
||||||
|
|
||||||
|
|
@ -357,18 +357,21 @@ Camoufox supports spoofing WebGL parameters, supported extensions, context attri
|
||||||
**Note**: Do NOT randomly assign values to these properties. WAFs hash your WebGL fingerprint and compare it against a dataset. Randomly assigning values will lead to detection as an unknown device.
|
**Note**: Do NOT randomly assign values to these properties. WAFs hash your WebGL fingerprint and compare it against a dataset. Randomly assigning values will lead to detection as an unknown device.
|
||||||
|
|
||||||
| Property | Description | Example |
|
| Property | Description | Example |
|
||||||
| ----------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
|
| ----------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
|
||||||
| webgl:renderer | Spoofs the name of the unmasked WebGL renderer. | `"NVIDIA GeForce GTX 980, or similar"` |
|
| webgl:renderer | Spoofs the name of the unmasked WebGL renderer. | `"NVIDIA GeForce GTX 980, or similar"` |
|
||||||
| webgl:vendor | Spoofs the name of the unmasked WebGL vendor. | `"NVIDIA Corporation"` |
|
| webgl:vendor | Spoofs the name of the unmasked WebGL vendor. | `"NVIDIA Corporation"` |
|
||||||
| webgl:supportedExtensions | An array of supported WebGL extensions ([full list](https://registry.khronos.org/webgl/extensions/)). | `["ANGLE_instanced_arrays", "EXT_color_buffer_float", "EXT_disjoint_timer_query", ...]` |
|
| webgl:supportedExtensions | An array of supported WebGL extensions ([full list](https://registry.khronos.org/webgl/extensions/)). | `["ANGLE_instanced_arrays", "EXT_color_buffer_float", "EXT_disjoint_timer_query", ...]` |
|
||||||
|
| webgl2:supportedExtensions | The same as `webgl:supportedExtensions`, but for WebGL2. | `["ANGLE_instanced_arrays", "EXT_color_buffer_float", "EXT_disjoint_timer_query", ...]` |
|
||||||
| webgl:contextAttributes | A dictionary of WebGL context attributes. | `{"alpha": true, "antialias": true, "depth": true, ...}` |
|
| webgl:contextAttributes | A dictionary of WebGL context attributes. | `{"alpha": true, "antialias": true, "depth": true, ...}` |
|
||||||
| webgl2:contextAttributes | The same as `webgl:contextAttributes`, but for WebGL2. | `{"alpha": true, "antialias": true, "depth": true, ...}` |
|
| webgl2:contextAttributes | The same as `webgl:contextAttributes`, but for WebGL2. | `{"alpha": true, "antialias": true, "depth": true, ...}` |
|
||||||
| webgl:parameters | A dictionary of WebGL parameters. Keys must be GL enums, and values are the values to spoof them as. | `{"2849": 1, "2884": false, "2928": [0, 1], ...}` |
|
| webgl:parameters | A dictionary of WebGL parameters. Keys must be GL enums, and values are the values to spoof them as. | `{"2849": 1, "2884": false, "2928": [0, 1], ...}` |
|
||||||
| webgl2:parameters | The same as `webgl:parameters`, but for WebGL2. | `{"2849": 1, "2884": false, "2928": [0, 1], ...}` |
|
| webgl2:parameters | The same as `webgl:parameters`, but for WebGL2. | `{"2849": 1, "2884": false, "2928": [0, 1], ...}` |
|
||||||
|
| webgl:parameters:blockIfNotDefined | If set to `true`, only the parameters in `webgl:parameters` will be allowed. Can be dangerous if not used correctly. | `true`/`false` |
|
||||||
|
| webgl2:parameters:blockIfNotDefined | If set to `true`, only the parameters in `webgl2:parameters` will be allowed. Can be dangerous if not used correctly. | `true`/`false` |
|
||||||
| webgl:shaderPrecisionFormats | A dictionary of WebGL shader precision formats. Keys are formatted as `"<shaderType>,<precisionType>"`. | `{"35633,36336": {"rangeMin": 127, "rangeMax": 127, "precision": 23}, ...}` |
|
| webgl:shaderPrecisionFormats | A dictionary of WebGL shader precision formats. Keys are formatted as `"<shaderType>,<precisionType>"`. | `{"35633,36336": {"rangeMin": 127, "rangeMax": 127, "precision": 23}, ...}` |
|
||||||
| webgl2:shaderPrecisionFormats | The same as `webGL:shaderPrecisionFormats`, but for WebGL2. | `{"35633,36336": {"rangeMin": 127, "rangeMax": 127, "precision": 23}, ...}` |
|
| webgl2:shaderPrecisionFormats | The same as `webGL:shaderPrecisionFormats`, but for WebGL2. | `{"35633,36336": {"rangeMin": 127, "rangeMax": 127, "precision": 23}, ...}` |
|
||||||
| webgl:shaderPrecisionFormats:blockIfNotDefined | If set to `true`, only the shader percisions in `webgl:shaderPrecisionFormats` will be passed. Everything else will be blocked. | `true` |
|
| webgl:shaderPrecisionFormats:blockIfNotDefined | If set to `true`, only the shader percisions in `webgl:shaderPrecisionFormats` will be allowed. | `true`/`false` |
|
||||||
| webgl2:shaderPrecisionFormats:blockIfNotDefined | If set to `true`, only the shader percisions in `webgl2:shaderPrecisionFormats` will be passed. Everything else will be blocked. | `true` |
|
| webgl2:shaderPrecisionFormats:blockIfNotDefined | If set to `true`, only the shader percisions in `webgl2:shaderPrecisionFormats` will be allowed. | `true`/`false` |
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ Written by daijro.
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
# include <windows.h>
|
# include <windows.h>
|
||||||
|
|
@ -217,14 +218,15 @@ inline std::optional<T> GetAttribute(const std::string attrib, bool isWebGL2) {
|
||||||
return value.value().get<T>();
|
return value.value().get<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::optional<std::variant<int64_t, bool, double, std::string>> GLParam(
|
inline std::optional<
|
||||||
uint32_t pname, bool isWebGL2) {
|
std::variant<int64_t, bool, double, std::string, std::nullptr_t>>
|
||||||
|
GLParam(uint32_t pname, bool isWebGL2) {
|
||||||
auto value =
|
auto value =
|
||||||
MaskConfig::GetNested(isWebGL2 ? "webgl2:parameters" : "webgl:parameters",
|
MaskConfig::GetNested(isWebGL2 ? "webgl2:parameters" : "webgl:parameters",
|
||||||
std::to_string(pname));
|
std::to_string(pname));
|
||||||
if (!value) return std::nullopt;
|
if (!value) return std::nullopt;
|
||||||
auto data = value.value();
|
auto data = value.value();
|
||||||
// cast the data and return
|
if (data.is_null()) return std::nullptr_t();
|
||||||
if (data.is_number_integer()) return data.get<int64_t>();
|
if (data.is_number_integer()) return data.get<int64_t>();
|
||||||
if (data.is_boolean()) return data.get<bool>();
|
if (data.is_boolean()) return data.get<bool>();
|
||||||
if (data.is_number_float()) return data.get<double>();
|
if (data.is_number_float()) return data.get<double>();
|
||||||
|
|
@ -249,7 +251,8 @@ inline std::vector<T> MParamGLVector(uint32_t pname,
|
||||||
bool isWebGL2) {
|
bool isWebGL2) {
|
||||||
if (auto value = MaskConfig::GetNested(
|
if (auto value = MaskConfig::GetNested(
|
||||||
isWebGL2 ? "webgl2:parameters" : "webgl:parameters",
|
isWebGL2 ? "webgl2:parameters" : "webgl:parameters",
|
||||||
std::to_string(pname)); value.has_value()) {
|
std::to_string(pname));
|
||||||
|
value.has_value()) {
|
||||||
if (value.value().is_array()) {
|
if (value.value().is_array()) {
|
||||||
std::array<T, 4UL> result = value.value().get<std::array<T, 4UL>>();
|
std::array<T, 4UL> result = value.value().get<std::array<T, 4UL>>();
|
||||||
return std::vector<T>(result.begin(), result.end());
|
return std::vector<T>(result.begin(), result.end());
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,18 @@
|
||||||
diff --git a/dom/canvas/ClientWebGLContext.cpp b/dom/canvas/ClientWebGLContext.cpp
|
diff --git a/dom/canvas/ClientWebGLContext.cpp b/dom/canvas/ClientWebGLContext.cpp
|
||||||
index db60868f65..afed6eeb7c 100644
|
index db60868f65..7361f0fc9c 100644
|
||||||
--- a/dom/canvas/ClientWebGLContext.cpp
|
--- a/dom/canvas/ClientWebGLContext.cpp
|
||||||
+++ b/dom/canvas/ClientWebGLContext.cpp
|
+++ b/dom/canvas/ClientWebGLContext.cpp
|
||||||
@@ -4,6 +4,8 @@
|
@@ -4,6 +4,9 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "ClientWebGLContext.h"
|
#include "ClientWebGLContext.h"
|
||||||
+#include "MaskConfig.hpp"
|
+#include "MaskConfig.hpp"
|
||||||
+#include <algorithm>
|
+#include <algorithm>
|
||||||
|
+#include <cstddef>
|
||||||
|
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
|
|
||||||
@@ -744,6 +746,13 @@ void ClientWebGLContext::SetDrawingBufferColorSpace(
|
@@ -744,6 +747,13 @@ void ClientWebGLContext::SetDrawingBufferColorSpace(
|
||||||
Run<RPROC(SetDrawingBufferColorSpace)>(*mDrawingBufferColorSpace);
|
Run<RPROC(SetDrawingBufferColorSpace)>(*mDrawingBufferColorSpace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -25,7 +26,7 @@ index db60868f65..afed6eeb7c 100644
|
||||||
void ClientWebGLContext::GetContextAttributes(
|
void ClientWebGLContext::GetContextAttributes(
|
||||||
dom::Nullable<dom::WebGLContextAttributes>& retval) {
|
dom::Nullable<dom::WebGLContextAttributes>& retval) {
|
||||||
retval.SetNull();
|
retval.SetNull();
|
||||||
@@ -754,14 +763,38 @@ void ClientWebGLContext::GetContextAttributes(
|
@@ -754,14 +764,38 @@ void ClientWebGLContext::GetContextAttributes(
|
||||||
|
|
||||||
const auto& options = mNotLost->info.options;
|
const auto& options = mNotLost->info.options;
|
||||||
|
|
||||||
|
|
@ -72,7 +73,7 @@ index db60868f65..afed6eeb7c 100644
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------
|
// -----------------------
|
||||||
@@ -979,18 +1012,28 @@ bool ClientWebGLContext::CreateHostContext(const uvec2& requestedSize) {
|
@@ -979,18 +1013,28 @@ bool ClientWebGLContext::CreateHostContext(const uvec2& requestedSize) {
|
||||||
std::unordered_map<GLenum, bool> webgl::MakeIsEnabledMap(const bool webgl2) {
|
std::unordered_map<GLenum, bool> webgl::MakeIsEnabledMap(const bool webgl2) {
|
||||||
auto ret = std::unordered_map<GLenum, bool>{};
|
auto ret = std::unordered_map<GLenum, bool>{};
|
||||||
|
|
||||||
|
|
@ -111,11 +112,13 @@ index db60868f65..afed6eeb7c 100644
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@@ -2058,6 +2101,28 @@ void ClientWebGLContext::GetParameter(JSContext* cx, GLenum pname,
|
@@ -2058,6 +2102,57 @@ void ClientWebGLContext::GetParameter(JSContext* cx, GLenum pname,
|
||||||
const auto& state = State();
|
const auto& state = State();
|
||||||
|
|
||||||
// -
|
// -
|
||||||
+ std::optional<std::variant<int64_t, bool, double, std::string>> data;
|
+ std::optional<
|
||||||
|
+ std::variant<int64_t, bool, double, std::string, std::nullptr_t>>
|
||||||
|
+ data;
|
||||||
+ data = MaskConfig::GLParam(pname, mIsWebGL2);
|
+ data = MaskConfig::GLParam(pname, mIsWebGL2);
|
||||||
+
|
+
|
||||||
+ if (data.has_value()) {
|
+ if (data.has_value()) {
|
||||||
|
|
@ -136,11 +139,38 @@ index db60868f65..afed6eeb7c 100644
|
||||||
+ retval.set(StringValue(cx, std::get<std::string>(value), rv));
|
+ retval.set(StringValue(cx, std::get<std::string>(value), rv));
|
||||||
+ return;
|
+ return;
|
||||||
+ }
|
+ }
|
||||||
|
+ if (std::holds_alternative<std::nullptr_t>(value)) {
|
||||||
|
+ retval.set(JS::NullValue());
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ // If the value is not array (we will handle those later),
|
||||||
|
+ // then check if it should be blocked.
|
||||||
|
+ switch (pname) {
|
||||||
|
+ case LOCAL_GL_DEPTH_RANGE:
|
||||||
|
+ case LOCAL_GL_ALIASED_POINT_SIZE_RANGE:
|
||||||
|
+ case LOCAL_GL_ALIASED_LINE_WIDTH_RANGE:
|
||||||
|
+ case LOCAL_GL_COLOR_CLEAR_VALUE:
|
||||||
|
+ case LOCAL_GL_BLEND_COLOR:
|
||||||
|
+ case LOCAL_GL_MAX_VIEWPORT_DIMS:
|
||||||
|
+ case LOCAL_GL_SCISSOR_BOX:
|
||||||
|
+ case LOCAL_GL_VIEWPORT:
|
||||||
|
+ case LOCAL_GL_COMPRESSED_TEXTURE_FORMATS:
|
||||||
|
+ case LOCAL_GL_COLOR_WRITEMASK:
|
||||||
|
+ case dom::WEBGL_debug_renderer_info_Binding::UNMASKED_RENDERER_WEBGL:
|
||||||
|
+ case dom::WEBGL_debug_renderer_info_Binding::UNMASKED_VENDOR_WEBGL:
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ if (MaskConfig::GetBool(mIsWebGL2 ? "webgl2:parameters:blockIfNotDefined"
|
||||||
|
+ : "webgl:parameters:blockIfNotDefined")) {
|
||||||
|
+ retval.set(JS::NullValue());
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
+ }
|
+ }
|
||||||
|
|
||||||
const auto fnSetRetval_Buffer = [&](const GLenum target) {
|
const auto fnSetRetval_Buffer = [&](const GLenum target) {
|
||||||
const auto buffer = *MaybeFind(state.mBoundBufferByTarget, target);
|
const auto buffer = *MaybeFind(state.mBoundBufferByTarget, target);
|
||||||
@@ -2163,49 +2228,84 @@ void ClientWebGLContext::GetParameter(JSContext* cx, GLenum pname,
|
@@ -2163,49 +2258,84 @@ void ClientWebGLContext::GetParameter(JSContext* cx, GLenum pname,
|
||||||
|
|
||||||
// 2 floats
|
// 2 floats
|
||||||
case LOCAL_GL_DEPTH_RANGE:
|
case LOCAL_GL_DEPTH_RANGE:
|
||||||
|
|
@ -238,7 +268,7 @@ index db60868f65..afed6eeb7c 100644
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2385,6 +2485,10 @@ void ClientWebGLContext::GetParameter(JSContext* cx, GLenum pname,
|
@@ -2385,6 +2515,10 @@ void ClientWebGLContext::GetParameter(JSContext* cx, GLenum pname,
|
||||||
|
|
||||||
switch (pname) {
|
switch (pname) {
|
||||||
case dom::WEBGL_debug_renderer_info_Binding::UNMASKED_RENDERER_WEBGL:
|
case dom::WEBGL_debug_renderer_info_Binding::UNMASKED_RENDERER_WEBGL:
|
||||||
|
|
@ -249,7 +279,7 @@ index db60868f65..afed6eeb7c 100644
|
||||||
ret = GetUnmaskedRenderer();
|
ret = GetUnmaskedRenderer();
|
||||||
if (ret && StaticPrefs::webgl_sanitize_unmasked_renderer()) {
|
if (ret && StaticPrefs::webgl_sanitize_unmasked_renderer()) {
|
||||||
*ret = webgl::SanitizeRenderer(*ret);
|
*ret = webgl::SanitizeRenderer(*ret);
|
||||||
@@ -2392,6 +2496,10 @@ void ClientWebGLContext::GetParameter(JSContext* cx, GLenum pname,
|
@@ -2392,6 +2526,10 @@ void ClientWebGLContext::GetParameter(JSContext* cx, GLenum pname,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case dom::WEBGL_debug_renderer_info_Binding::UNMASKED_VENDOR_WEBGL:
|
case dom::WEBGL_debug_renderer_info_Binding::UNMASKED_VENDOR_WEBGL:
|
||||||
|
|
@ -260,7 +290,7 @@ index db60868f65..afed6eeb7c 100644
|
||||||
ret = GetUnmaskedVendor();
|
ret = GetUnmaskedVendor();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -2482,7 +2590,9 @@ void ClientWebGLContext::GetParameter(JSContext* cx, GLenum pname,
|
@@ -2482,7 +2620,9 @@ void ClientWebGLContext::GetParameter(JSContext* cx, GLenum pname,
|
||||||
case LOCAL_GL_COLOR_WRITEMASK: {
|
case LOCAL_GL_COLOR_WRITEMASK: {
|
||||||
const auto mask = uint8_t(*maybe);
|
const auto mask = uint8_t(*maybe);
|
||||||
const auto bs = std::bitset<4>(mask);
|
const auto bs = std::bitset<4>(mask);
|
||||||
|
|
@ -271,7 +301,7 @@ index db60868f65..afed6eeb7c 100644
|
||||||
JS::Rooted<JS::Value> arr(cx);
|
JS::Rooted<JS::Value> arr(cx);
|
||||||
if (!dom::ToJSValue(cx, src.data(), src.size(), &arr)) {
|
if (!dom::ToJSValue(cx, src.data(), src.size(), &arr)) {
|
||||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||||
@@ -2865,6 +2975,24 @@ ClientWebGLContext::GetShaderPrecisionFormat(const GLenum shadertype,
|
@@ -2865,6 +3005,24 @@ ClientWebGLContext::GetShaderPrecisionFormat(const GLenum shadertype,
|
||||||
const GLenum precisiontype) {
|
const GLenum precisiontype) {
|
||||||
if (IsContextLost()) return nullptr;
|
if (IsContextLost()) return nullptr;
|
||||||
const auto info = [&]() {
|
const auto info = [&]() {
|
||||||
|
|
@ -296,7 +326,7 @@ index db60868f65..afed6eeb7c 100644
|
||||||
const auto& inProcess = mNotLost->inProcess;
|
const auto& inProcess = mNotLost->inProcess;
|
||||||
if (inProcess) {
|
if (inProcess) {
|
||||||
return inProcess->GetShaderPrecisionFormat(shadertype, precisiontype);
|
return inProcess->GetShaderPrecisionFormat(shadertype, precisiontype);
|
||||||
@@ -5822,6 +5950,17 @@ bool ClientWebGLContext::IsSupported(const WebGLExtensionID ext,
|
@@ -5822,6 +5980,17 @@ bool ClientWebGLContext::IsSupported(const WebGLExtensionID ext,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -314,14 +344,15 @@ index db60868f65..afed6eeb7c 100644
|
||||||
const auto& limits = Limits();
|
const auto& limits = Limits();
|
||||||
return limits.supportedExtensions[ext];
|
return limits.supportedExtensions[ext];
|
||||||
}
|
}
|
||||||
@@ -5833,6 +5972,17 @@ void ClientWebGLContext::GetSupportedExtensions(
|
@@ -5833,6 +6002,18 @@ void ClientWebGLContext::GetSupportedExtensions(
|
||||||
if (!mNotLost) return;
|
if (!mNotLost) return;
|
||||||
|
|
||||||
auto& retarr = retval.SetValue();
|
auto& retarr = retval.SetValue();
|
||||||
+
|
+
|
||||||
+ // Implement separately to prevent O(n^2) timing
|
+ // Implement separately to prevent O(n^2) timing
|
||||||
+ if (std::vector<std::string> maskValues =
|
+ if (std::vector<std::string> maskValues =
|
||||||
+ MaskConfig::GetStringList("webgl:supportedExtensions");
|
+ MaskConfig::GetStringList(mIsWebGL2 ? "webgl2:supportedExtensions"
|
||||||
|
+ : "webgl:supportedExtensions");
|
||||||
+ !maskValues.empty()) {
|
+ !maskValues.empty()) {
|
||||||
+ for (const auto& ext : maskValues) {
|
+ for (const auto& ext : maskValues) {
|
||||||
+ retarr.AppendElement(NS_ConvertUTF8toUTF16(ext));
|
+ retarr.AppendElement(NS_ConvertUTF8toUTF16(ext));
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,8 @@
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
display: none;
|
display: none;
|
||||||
position: relative;
|
position: relative;
|
||||||
transition: opacity 0.3s ease-out, max-height 0.3s ease-out, padding 0.3s ease-out;
|
transition: opacity 0.3s ease-out, max-height 0.3s ease-out,
|
||||||
|
padding 0.3s ease-out;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
max-height: 100px;
|
max-height: 100px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
@ -114,7 +115,10 @@
|
||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h1>Your WebGL Information (in Camoufox format)</h1>
|
<h1>Your WebGL Information (in Camoufox format)</h1>
|
||||||
<div id="warning">Warning: This browser is not Firefox. The fingerprint below will not run properly on Camoufox.<button id="close-warning">×</button></div>
|
<div id="warning">
|
||||||
|
Warning: This browser is not Firefox. The fingerprint below will not run
|
||||||
|
properly on Camoufox.<button id="close-warning">×</button>
|
||||||
|
</div>
|
||||||
<div id="hash"></div>
|
<div id="hash"></div>
|
||||||
<pre id="output"></pre>
|
<pre id="output"></pre>
|
||||||
<div class="button-container">
|
<div class="button-container">
|
||||||
|
|
@ -152,33 +156,21 @@
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
function getMaxAnisotropy(ctx) {
|
|
||||||
if (ctx) {
|
|
||||||
const ext =
|
|
||||||
ctx.getExtension("EXT_texture_filter_anisotropic") ||
|
|
||||||
ctx.getExtension("WEBKIT_EXT_texture_filter_anisotropic") ||
|
|
||||||
ctx.getExtension("MOZ_EXT_texture_filter_anisotropic");
|
|
||||||
|
|
||||||
if (ext) {
|
|
||||||
return ctx.getParameter(ext.MAX_TEXTURE_MAX_ANISOTROPY_EXT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const glEnums = [
|
const glEnums = [
|
||||||
2849, 2884, 2885, 2886, 2928, 2929, 2930, 2931, 2932, 2960, 2961,
|
2849, 2884, 2885, 2886, 2928, 2929, 2930, 2931, 2932, 2960, 2961,
|
||||||
2962, 2963, 2964, 2965, 2966, 2967, 2968, 2978, 3024, 3042, 3088,
|
2962, 2963, 2964, 2965, 2966, 2967, 2968, 2978, 3024, 3042, 3074,
|
||||||
3089, 3106, 3107, 3317, 3333, 3379, 3386, 3408, 3410, 3411, 3412,
|
3088, 3089, 3106, 3107, 3314, 3315, 3316, 3317, 3330, 3331, 3332,
|
||||||
3413, 3414, 3415, 7936, 7937, 7938, 10752, 32773, 32777, 32823, 32824,
|
3333, 3379, 3386, 3408, 3410, 3411, 3412, 3413, 3414, 3415, 7936,
|
||||||
32873, 32883, 32936, 32937, 32938, 32939, 32968, 32969, 32970, 32971,
|
7937, 7938, 10752, 32773, 32777, 32823, 32824, 32873, 32877, 32878,
|
||||||
33170, 33901, 33902, 34016, 34024, 34045, 34047, 34068, 34076, 34467,
|
32883, 32926, 32928, 32936, 32937, 32938, 32939, 32968, 32969, 32970,
|
||||||
34816, 34817, 34818, 34819, 34852, 34877, 34921, 34930, 34964, 34965,
|
32971, 33000, 33001, 33170, 33901, 33902, 34016, 34024, 34045, 34047,
|
||||||
35071, 35076, 35077, 35371, 35373, 35374, 35375, 35376, 35377, 35379,
|
34068, 34076, 34467, 34816, 34817, 34818, 34819, 34852, 34853, 34854,
|
||||||
35380, 35657, 35658, 35659, 35660, 35661, 35724, 35725, 35968, 35978,
|
34855, 34856, 34857, 34858, 34859, 34860, 34877, 34921, 34930, 34964,
|
||||||
35979, 36003, 36004, 36005, 36006, 36007, 36063, 36183, 36347, 36348,
|
34965, 35071, 35076, 35077, 35371, 35373, 35374, 35375, 35376, 35377,
|
||||||
36349, 37154, 37157, 37440, 37441, 37443, 37444, 37445, 37446,
|
35379, 35380, 35657, 35658, 35659, 35660, 35661, 35723, 35724, 35725,
|
||||||
|
35738, 35739, 35968, 35977, 35978, 35979, 36003, 36004, 36005, 36006,
|
||||||
|
36007, 36063, 36183, 36203, 36345, 36347, 36348, 36349, 36387, 36388,
|
||||||
|
37137, 37154, 37157, 37440, 37441, 37443, 37444, 37445, 37446, 37447,
|
||||||
];
|
];
|
||||||
|
|
||||||
let rendererInfo = null;
|
let rendererInfo = null;
|
||||||
|
|
@ -300,14 +292,17 @@
|
||||||
"DOMContentLoaded",
|
"DOMContentLoaded",
|
||||||
async () => {
|
async () => {
|
||||||
// Check if the user agent is Firefox
|
// Check if the user agent is Firefox
|
||||||
const isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
|
const isFirefox =
|
||||||
|
navigator.userAgent.toLowerCase().indexOf("firefox") > -1;
|
||||||
if (!isFirefox) {
|
if (!isFirefox) {
|
||||||
document.getElementById('warning').style.display = 'block';
|
document.getElementById("warning").style.display = "block";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add event listener for close button
|
// Add event listener for close button
|
||||||
document.getElementById('close-warning').addEventListener('click', function() {
|
document
|
||||||
document.getElementById('warning').classList.add('hide');
|
.getElementById("close-warning")
|
||||||
|
.addEventListener("click", function () {
|
||||||
|
document.getElementById("warning").classList.add("hide");
|
||||||
});
|
});
|
||||||
|
|
||||||
const [webglDetail, webgl2Detail] = await Promise.all([
|
const [webglDetail, webgl2Detail] = await Promise.all([
|
||||||
|
|
|
||||||
|
|
@ -70,8 +70,11 @@
|
||||||
{ "property": "webgl:renderer", "type": "str" },
|
{ "property": "webgl:renderer", "type": "str" },
|
||||||
{ "property": "webgl:vendor", "type": "str" },
|
{ "property": "webgl:vendor", "type": "str" },
|
||||||
{ "property": "webgl:supportedExtensions", "type": "array" },
|
{ "property": "webgl:supportedExtensions", "type": "array" },
|
||||||
|
{ "property": "webgl2:supportedExtensions", "type": "array" },
|
||||||
{ "property": "webgl:parameters", "type": "dict" },
|
{ "property": "webgl:parameters", "type": "dict" },
|
||||||
|
{ "property": "webgl:parameters:blockIfNotDefined", "type": "bool" },
|
||||||
{ "property": "webgl2:parameters", "type": "dict" },
|
{ "property": "webgl2:parameters", "type": "dict" },
|
||||||
|
{ "property": "webgl2:parameters:blockIfNotDefined", "type": "bool" },
|
||||||
{ "property": "webgl:shaderPrecisionFormats", "type": "dict" },
|
{ "property": "webgl:shaderPrecisionFormats", "type": "dict" },
|
||||||
{ "property": "webgl:shaderPrecisionFormats:blockIfNotDefined", "type": "bool" },
|
{ "property": "webgl:shaderPrecisionFormats:blockIfNotDefined", "type": "bool" },
|
||||||
{ "property": "webgl2:shaderPrecisionFormats", "type": "dict" },
|
{ "property": "webgl2:shaderPrecisionFormats", "type": "dict" },
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue