Skip to content

Commit

Permalink
feat: add the slim mode for disabling performance-heavy evasions (#263)
Browse files Browse the repository at this point in the history
* feat: add the slim mode for disabling performance-heavy evasions

* chore: naming conventions
  • Loading branch information
barjin authored Jan 24, 2024
1 parent 7e37117 commit 1c8b0f5
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 6 deletions.
10 changes: 10 additions & 0 deletions packages/fingerprint-generator/src/fingerprint-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ export type Fingerprint = {
multimediaDevices: string[];
fonts: string[];
mockWebRTC: boolean;
slim?: boolean;
}

export type BrowserFingerprintWithHeaders = {
Expand All @@ -82,6 +83,13 @@ export interface FingerprintGeneratorOptions extends HeaderGeneratorOptions {
maxHeight?: number;
};
mockWebRTC?: boolean;
/**
* Enables the slim mode for the fingerprint injection.
* This disables some performance-heavy evasions, but might decrease benchmark scores.
*
* Try enabling this if you are experiencing performance issues with the fingerprint injection.
*/
slim?: boolean;
}

/**
Expand All @@ -99,6 +107,7 @@ export class FingerprintGenerator extends HeaderGenerator {
this.fingerprintGlobalOptions = {
screen: options.screen,
mockWebRTC: options.mockWebRTC,
slim: options.slim,
};
this.fingerprintGeneratorNetwork = new BayesianNetwork({ path: `${__dirname}/data_files/fingerprint-network-definition.zip` });
}
Expand Down Expand Up @@ -181,6 +190,7 @@ export class FingerprintGenerator extends HeaderGenerator {
fingerprint: {
...this.transformFingerprint(fingerprint),
mockWebRTC: options.mockWebRTC ?? this.fingerprintGlobalOptions.mockWebRTC ?? false,
slim: options.slim ?? this.fingerprintGlobalOptions.slim ?? false,
},
headers,
};
Expand Down
7 changes: 7 additions & 0 deletions packages/fingerprint-injector/src/fingerprint-injector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ export class FingerprintInjector {
audioCodecs,
videoCodecs,
mockWebRTC,
slim,
// @ts-expect-error internal browser code
} = fp as EnhancedFingerprint;

Expand Down Expand Up @@ -203,6 +204,12 @@ export class FingerprintInjector {

if (mockWebRTC) blockWebRTC();

if (slim) {
// @ts-expect-error internal browser code
// eslint-disable-next-line dot-notation
window['slim'] = true;
}

overrideIntlAPI(navigatorProps.language);
overrideStatic();

Expand Down
37 changes: 31 additions & 6 deletions packages/fingerprint-injector/src/utils.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
const isHeadlessChromium = () => /headless/i.test(navigator.userAgent) && navigator.plugins.length === 0;
const isChrome = () => navigator.userAgent.includes("Chrome");
const isFirefox = () => navigator.userAgent.includes("Firefox");
const isSafari = () => navigator.userAgent.includes("Safari") && !navigator.userAgent.includes("Chrome");
const isHeadlessChromium = /headless/i.test(navigator.userAgent) && navigator.plugins.length === 0;
const isChrome = navigator.userAgent.includes("Chrome");
const isFirefox = navigator.userAgent.includes("Firefox");
const isSafari = navigator.userAgent.includes("Safari") && !navigator.userAgent.includes("Chrome");

let slim = null;
function getSlim() {
if(slim === null) {
slim = window.slim || false;
if(typeof window.slim !== 'undefined') {
delete window.slim;
}
}

return slim;
}

// This file contains utils that are build and included on the window object with some randomized prefix.

Expand Down Expand Up @@ -102,7 +114,14 @@ function overrideInstancePrototype(instance, overrideObj) {
}
}

/**
* Updates the .toString method in Function.prototype to return a native string representation of the function.
* @param {*} proxyObj
* @param {*} originalObj
*/
function redirectToString(proxyObj, originalObj) {
if(getSlim()) return;

const handler = {
setPrototypeOf: (target, newProto) => {
try {
Expand Down Expand Up @@ -131,6 +150,7 @@ function redirectToString(proxyObj, originalObj) {
const hasSameProto = Object.getPrototypeOf(
Function.prototype.toString,
).isPrototypeOf(ctx.toString); // eslint-disable-line no-prototype-builtins

if (!hasSameProto) {
// Pass the call on to the local Function.prototype.toString instead
return ctx.toString();
Expand Down Expand Up @@ -194,6 +214,11 @@ function redefineProperty(masterObject, propertyName, descriptorOverrides = {})
});
}

/**
* For all the traps in the passed proxy handler, we wrap them in a try/catch and modify the error stack if they throw.
* @param {*} handler A proxy handler object
* @returns A new proxy handler object with error stack modifications
*/
function stripProxyFromErrors(handler) {
const newHandler = {};
// We wrap each trap in the handler in a try/catch and modify the error stack if they throw
Expand Down Expand Up @@ -535,7 +560,7 @@ function overrideUserAgentData(userAgentData) {
};

function fixWindowChrome(){
if( isChrome() && !window.chrome ){
if(isChrome && !window.chrome){
Object.defineProperty(window, 'chrome', {
writable: true,
enumerable: true,
Expand Down Expand Up @@ -704,7 +729,7 @@ function fixPluginArray() {

function runHeadlessFixes(){
try {
if( isHeadlessChromium() ){
if( isHeadlessChromium ){
fixWindowChrome();
fixPermissions();
fixIframeContentWindow();
Expand Down

0 comments on commit 1c8b0f5

Please sign in to comment.