add fingerprinting configuration
This commit is contained in:
@@ -0,0 +1,174 @@
|
||||
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];
|
||||
}
|
||||
Reference in New Issue
Block a user