use serde::{Deserialize, Serialize};
use crate::fingerprint::*;
use crate::seed::PersonaSeed;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Viewport {
pub width: u32,
pub height: u32,
pub device_scale_factor: u32,
}
impl Default for Viewport {
fn default() -> Self {
Self {
width: 1440,
height: 900,
device_scale_factor: 1,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
pub struct ScreenConfig {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub width: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub height: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub avail_width: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub avail_height: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub avail_left: Option<i32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub avail_top: Option<i32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub left: Option<i32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub top: Option<i32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub color_depth: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub pixel_depth: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub is_extended: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub orientation_type: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub orientation_angle: Option<u16>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
pub struct WindowConfig {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub outer_width: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub outer_height: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub screen_x: Option<i32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub screen_y: Option<i32>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
pub struct CssConfig {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub moz_prefix_enabled: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub webkit_prefix_enabled: Option<bool>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
pub struct GraphicsConfig {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub webgl_vendor: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub webgl_renderer: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub webgl_masked_vendor: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub webgl_masked_renderer: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
pub struct NavigatorConfig {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub app_version: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub platform: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub language: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub languages: Option<Vec<String>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub hardware_concurrency: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub device_memory_gb: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub max_touch_points: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub do_not_track: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub global_privacy_control: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub expose_global_privacy_control: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub permissions_enabled: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub bluetooth_enabled: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub bluetooth_available: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub media_devices_enabled: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub webgpu_enabled: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub offscreen_canvas_enabled: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub service_worker_enabled: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub ua_platform_version: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub ua_architecture: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub ua_bitness: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub ua_model: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub vendor: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub product_sub: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub pdf_viewer_enabled: Option<bool>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
pub struct MediaConfig {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub speech_voices: Option<Vec<String>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub audio_inputs: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub video_inputs: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub audio_outputs: Option<u32>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
pub struct FontConfig {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub families: Option<Vec<String>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub seed: Option<PersonaSeed>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
pub struct CanvasConfig {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub noise_enabled: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub noise_amplitude: Option<u8>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub blink_low_entropy_probe: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub seed: Option<PersonaSeed>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
pub struct DomRectConfig {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub enabled: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub quantization_steps_per_px: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub fill_empty_client_rects: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub seed: Option<PersonaSeed>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
pub struct EngineConfig {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub enabled: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub to_fixed_range_error_message: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub array_constructor_source: Option<String>,
}
impl EngineConfig {
pub(crate) fn apply_to(&self, engine: &mut EngineFingerprint) {
if let Some(enabled) = self.enabled {
engine.enabled = enabled;
}
if let Some(message) = self
.to_fixed_range_error_message
.as_ref()
.filter(|value| !value.is_empty())
{
engine.to_fixed_range_error_message = message.clone();
}
if let Some(source) = self
.array_constructor_source
.as_ref()
.filter(|value| !value.is_empty())
{
engine.array_constructor_source = source.clone();
}
}
}
impl DomRectConfig {
pub(crate) fn apply_to(&self, domrect: &mut DomRectFingerprint) {
if let Some(enabled) = self.enabled {
domrect.enabled = enabled;
}
if let Some(quantization_steps_per_px) = self.quantization_steps_per_px {
domrect.quantization_steps_per_px = quantization_steps_per_px;
}
if let Some(fill_empty_client_rects) = self.fill_empty_client_rects {
domrect.fill_empty_client_rects = fill_empty_client_rects;
}
if let Some(seed) = self.seed.as_ref() {
domrect.seed = seed.clone();
}
}
}
impl CanvasConfig {
pub(crate) fn apply_to(&self, canvas: &mut CanvasFingerprint) {
if let Some(noise_enabled) = self.noise_enabled {
canvas.noise_enabled = noise_enabled;
}
if let Some(noise_amplitude) = self.noise_amplitude {
canvas.noise_amplitude = noise_amplitude;
}
if let Some(blink_low_entropy_probe) = self.blink_low_entropy_probe {
canvas.blink_low_entropy_probe = blink_low_entropy_probe;
}
if let Some(seed) = self.seed.as_ref() {
canvas.seed = seed.clone();
}
}
}
impl MediaConfig {
pub(crate) fn apply_to(&self, media: &mut MediaFingerprint) {
if let Some(speech_voices) = self
.speech_voices
.as_ref()
.filter(|voices| !voices.is_empty())
{
media.speech_voices = speech_voices.clone();
}
if let Some(audio_inputs) = self.audio_inputs {
media.audio_inputs = audio_inputs;
}
if let Some(video_inputs) = self.video_inputs {
media.video_inputs = video_inputs;
}
if let Some(audio_outputs) = self.audio_outputs {
media.audio_outputs = audio_outputs;
}
}
}
impl FontConfig {
pub(crate) fn apply_to(&self, fonts: &mut FontFingerprint) {
if let Some(families) = self
.families
.as_ref()
.map(|families| {
families
.iter()
.map(|family| family.trim())
.filter(|family| !family.is_empty())
.map(ToOwned::to_owned)
.collect::<Vec<_>>()
})
.filter(|families| !families.is_empty())
{
fonts.families = families;
}
if let Some(seed) = self.seed.as_ref() {
fonts.seed = seed.clone();
}
}
}
impl NavigatorConfig {
pub(crate) fn apply_to(&self, js: &mut JsFingerprint) {
if let Some(app_version) = self.app_version.as_ref().filter(|value| !value.is_empty()) {
js.app_version = app_version.clone();
}
if let Some(platform) = self.platform.as_ref().filter(|value| !value.is_empty()) {
js.platform = platform.clone();
}
if let Some(language) = self.language.as_ref().filter(|value| !value.is_empty()) {
js.language = language.clone();
}
if let Some(languages) = self.languages.as_ref().filter(|values| !values.is_empty()) {
js.languages = languages.clone();
if self.language.is_none()
&& let Some(language) = js.languages.first()
{
js.language = language.clone();
}
}
if let Some(hardware_concurrency) = self.hardware_concurrency {
js.hardware_concurrency = hardware_concurrency;
}
if let Some(device_memory_gb) = self.device_memory_gb {
js.device_memory_gb = device_memory_gb;
}
if let Some(max_touch_points) = self.max_touch_points {
js.max_touch_points = max_touch_points;
}
if let Some(do_not_track) = self.do_not_track.as_ref() {
js.do_not_track = do_not_track.clone();
}
if let Some(global_privacy_control) = self.global_privacy_control {
js.global_privacy_control = global_privacy_control;
}
if let Some(expose_global_privacy_control) = self.expose_global_privacy_control {
js.expose_global_privacy_control = expose_global_privacy_control;
}
if let Some(permissions_enabled) = self.permissions_enabled {
js.permissions_enabled = permissions_enabled;
}
if let Some(bluetooth_enabled) = self.bluetooth_enabled {
js.bluetooth_enabled = bluetooth_enabled;
}
if let Some(bluetooth_available) = self.bluetooth_available {
js.bluetooth_available = bluetooth_available;
}
if let Some(media_devices_enabled) = self.media_devices_enabled {
js.media_devices_enabled = media_devices_enabled;
}
if let Some(webgpu_enabled) = self.webgpu_enabled {
js.webgpu_enabled = webgpu_enabled;
}
if let Some(offscreen_canvas_enabled) = self.offscreen_canvas_enabled {
js.offscreen_canvas_enabled = offscreen_canvas_enabled;
}
if let Some(service_worker_enabled) = self.service_worker_enabled {
js.service_worker_enabled = service_worker_enabled;
}
if let Some(ua_platform_version) = self
.ua_platform_version
.as_ref()
.filter(|value| !value.is_empty())
{
js.ua_platform_version = ua_platform_version.clone();
}
if let Some(ua_architecture) = self
.ua_architecture
.as_ref()
.filter(|value| !value.is_empty())
{
js.ua_architecture = ua_architecture.clone();
}
if let Some(ua_bitness) = self.ua_bitness.as_ref().filter(|value| !value.is_empty()) {
js.ua_bitness = ua_bitness.clone();
}
if let Some(ua_model) = self.ua_model.as_ref() {
js.ua_model = ua_model.clone();
}
if let Some(vendor) = self.vendor.as_ref().filter(|value| !value.is_empty()) {
js.vendor = vendor.clone();
}
if let Some(product_sub) = self.product_sub.as_ref().filter(|value| !value.is_empty()) {
js.product_sub = product_sub.clone();
}
if let Some(pdf_viewer_enabled) = self.pdf_viewer_enabled {
js.pdf_viewer_enabled = pdf_viewer_enabled;
}
}
}
impl GraphicsConfig {
pub(crate) fn apply_to(&self, graphics: &mut GraphicsFingerprint) {
if let Some(webgl_vendor) = self.webgl_vendor.as_ref().filter(|value| !value.is_empty()) {
graphics.webgl_vendor = webgl_vendor.clone();
}
if let Some(webgl_renderer) = self
.webgl_renderer
.as_ref()
.filter(|value| !value.is_empty())
{
graphics.webgl_renderer = webgl_renderer.clone();
}
if let Some(webgl_masked_vendor) = self
.webgl_masked_vendor
.as_ref()
.filter(|value| !value.is_empty())
{
graphics.webgl_masked_vendor = webgl_masked_vendor.clone();
}
if let Some(webgl_masked_renderer) = self
.webgl_masked_renderer
.as_ref()
.filter(|value| !value.is_empty())
{
graphics.webgl_masked_renderer = webgl_masked_renderer.clone();
}
}
}
impl ScreenConfig {
pub(crate) fn apply_to(&self, screen: &mut ScreenFingerprint) {
if let Some(width) = self.width {
screen.width = width;
}
if let Some(height) = self.height {
screen.height = height;
}
if let Some(avail_width) = self.avail_width {
screen.avail_width = avail_width;
}
if let Some(avail_height) = self.avail_height {
screen.avail_height = avail_height;
}
if let Some(avail_left) = self.avail_left {
screen.avail_left = avail_left;
}
if let Some(avail_top) = self.avail_top {
screen.avail_top = avail_top;
}
if let Some(left) = self.left {
screen.left = left;
}
if let Some(top) = self.top {
screen.top = top;
}
if let Some(color_depth) = self.color_depth {
screen.color_depth = color_depth;
}
if let Some(pixel_depth) = self.pixel_depth {
screen.pixel_depth = pixel_depth;
}
if let Some(is_extended) = self.is_extended {
screen.is_extended = is_extended;
}
if let Some(orientation_type) = self
.orientation_type
.as_ref()
.filter(|value| !value.is_empty())
{
screen.orientation_type = orientation_type.clone();
}
if let Some(orientation_angle) = self.orientation_angle {
screen.orientation_angle = orientation_angle;
}
}
}
impl WindowConfig {
pub(crate) fn apply_to(&self, window: &mut WindowFingerprint) {
if let Some(outer_width) = self.outer_width {
window.outer_width = outer_width;
}
if let Some(outer_height) = self.outer_height {
window.outer_height = outer_height;
}
if let Some(screen_x) = self.screen_x {
window.screen_x = screen_x;
}
if let Some(screen_y) = self.screen_y {
window.screen_y = screen_y;
}
}
}
impl CssConfig {
pub(crate) fn apply_to(&self, css: &mut CssFingerprint) {
if let Some(moz_prefix_enabled) = self.moz_prefix_enabled {
css.moz_prefix_enabled = moz_prefix_enabled;
}
if let Some(webkit_prefix_enabled) = self.webkit_prefix_enabled {
css.webkit_prefix_enabled = webkit_prefix_enabled;
}
}
}