Files
MrbWebLibre/app/lib/features/user/domain/entities/fingerprint_overrides.dart
T

175 lines
5.1 KiB
Dart

import 'package:exceptions/exceptions.dart';
import 'package:fast_equatable/fast_equatable.dart';
class FingerprintOverrides with FastEquatable {
static final pattern = RegExp('([+-])([a-zA-Z_][a-zA-Z0-9_]{1,64})');
final bool? allTargets;
final Map<String, bool> targets;
FingerprintOverrides(this.allTargets, this.targets);
//Monitor https://searchfox.org/firefox-main/source/toolkit/components/resistfingerprinting/RFPTargetsDefault.inc
FingerprintOverrides.defaults()
: this(false, {
'CanvasRandomization': true,
'EfficientCanvasRandomization': true,
'FontVisibilityLangPack': true,
'JSMathFdlibm': true,
'ScreenAvailToResolution': true,
'NavigatorHWConcurrencyTiered': true,
'MaxTouchPointsCollapse': true,
});
FingerprintOverrides.hardenedDefaults()
: this(false, {
'TouchEvents': true,
'PointerEvents': true,
'KeyboardEvents': true,
'ScreenOrientation': true,
'SpeechSynthesis': true,
'CSSPrefersReducedMotion': true,
'CSSPrefersContrast': true,
'CanvasRandomization': true,
'CanvasExtractionFromThirdPartiesIsBlocked': true,
'JSLocale': true,
'NavigatorAppVersion': true,
'NavigatorBuildID': true,
'NavigatorHWConcurrency': true,
'NavigatorOscpu': true,
'NavigatorPlatform': true,
'NavigatorUserAgent': true,
'PointerId': true,
'StreamVideoFacingMode': true,
'JSDateTimeUTC': true,
'JSMathFdlibm': true,
'Gamepad': true,
'HttpUserAgent': true,
'WindowOuterSize': true,
'WindowScreenXY': true,
'WindowInnerScreenXY': true,
'ScreenPixelDepth': true,
'ScreenRect': true,
'ScreenAvailRect': true,
'VideoElementMozFrames': true,
'VideoElementMozFrameDelay': true,
'VideoElementPlaybackQuality': true,
'ReduceTimerPrecision': true,
'WidgetEvents': true,
'MediaDevices': true,
'MediaCapabilities': true,
'AudioSampleRate': true,
'NetworkConnection': true,
'WindowDevicePixelRatio': true,
'MouseEventScreenPoint': true,
'FontVisibilityBaseSystem': true,
'FontVisibilityLangPack': true,
'DeviceSensors': true,
'RoundWindowSize': true,
'UseStandinsForNativeColors': true,
'AudioContext': true,
'MediaError': true,
'DOMStyleOsxFontSmoothing': true,
'CSSDeviceSize': true,
'CSSColorInfo': true,
'CSSResolution': true,
'CSSPrefersReducedTransparency': true,
'CSSInvertedColors': true,
'CSSVideoDynamicRange': true,
'CSSPointerCapabilities': true,
'WebGLRenderCapability': true,
'WebGLRenderInfo': true,
'SiteSpecificZoom': true,
'FontVisibilityRestrictGenerics': true,
'WebVTT': true,
'WebGPULimits': true,
'WebGPUIsFallbackAdapter': true,
'WebGPUSubgroupSizes': true,
'JSLocalePrompt': true,
'ScreenAvailToResolution': true,
'UseHardcodedFontSubstitutes': true,
'DiskStorageLimit': true,
'WebCodecs': true,
'MaxTouchPoints': true,
'MaxTouchPointsCollapse': true,
'NavigatorHWConcurrencyTiered': true,
});
static Result<FingerprintOverrides> parse(
String input,
Set<String> availableTargets,
) {
final cleaned = input.replaceAll(RegExp(r'\s'), '');
if (cleaned.isEmpty) return Result.success(FingerprintOverrides(null, {}));
bool? allTargets;
final targets = <String, bool>{};
for (final word in cleaned.split(',')) {
final match = pattern.firstMatch(word);
if (match == null) {
return Result.failure(
const ErrorMessage(source: 'FpParser', message: 'Invalid Override'),
);
}
final enabled = match.group(1) != '-';
final name = match.group(2)!;
if (name == 'AllTargets') {
allTargets = enabled;
continue;
}
if (!availableTargets.contains(name)) {
return Result.failure(
const ErrorMessage(
source: 'FpParser',
message: 'Invalid target name',
),
);
}
targets[name] = enabled;
}
return Result.success(FingerprintOverrides(allTargets, targets));
}
@override
String toString() {
final sb = StringBuffer();
if (allTargets != null) {
sb.write('${allTargets! ? '+' : '-'}AllTargets');
if (targets.isNotEmpty) {
sb.write(',');
}
}
sb.write(
targets.entries.map((e) => (e.value ? '+' : '-') + e.key).join(','),
);
return sb.toString();
}
FingerprintOverrides copyWithAllTargetsEnabled(bool value) {
return FingerprintOverrides(
value,
Map.fromEntries(targets.entries.where((e) => e.value != value)),
);
}
FingerprintOverrides copyWithTarget(String name, bool value) {
if (value && allTargets == true) {
return this;
}
return FingerprintOverrides(allTargets, {...targets, name: value});
}
@override
List<Object?> get hashParameters => [allTargets, targets];
}