Skip to content

Commit

Permalink
fix: added webdriver hidding to chromium based browsers (#74)
Browse files Browse the repository at this point in the history
Co-authored-by: Martin Adámek <[email protected]>
  • Loading branch information
petrpatek and B4nan authored May 5, 2022
1 parent 7d78d77 commit dd4d143
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 20 deletions.
29 changes: 28 additions & 1 deletion src/abstract-classes/browser-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,15 +140,36 @@ export abstract class BrowserPlugin<
async launch(
launchContext: LaunchContext<Library, LibraryOptions, LaunchResult, NewPageOptions, NewPageResult> = this.createLaunchContext(),
): Promise<LaunchResult> {
const { proxyUrl } = launchContext;
const { proxyUrl, launchOptions }: { proxyUrl?: string; launchOptions: Record<string, any> } = launchContext;

if (proxyUrl) {
await this._addProxyToLaunchOptions(launchContext);
}

if (this._isChromiumBasedBrowser(launchContext)) {
// This will set the args for chromium based browsers to hide the webdriver.
launchOptions.args = this._mergeArgsToHideWebdriver(launchOptions.args);
}

return this._launch(launchContext);
}

private _mergeArgsToHideWebdriver(originalArgs: string[]): string[] {
if (!originalArgs?.length) {
return ['--disable-blink-features=AutomationControlled'];
}

const argumentIndex = originalArgs.findIndex((arg: string) => arg.startsWith('--disable-blink-features='));

if (argumentIndex !== -1) {
originalArgs[argumentIndex] += ',AutomationControlled';
} else {
originalArgs.push('--disable-blink-features=AutomationControlled');
}

return originalArgs;
};

/**
* @private
*/
Expand All @@ -158,6 +179,12 @@ export abstract class BrowserPlugin<
throwImplementationNeeded('_addProxyToLaunchOptions');
}

// @ts-expect-error Give runtime error as well as compile time
// eslint-disable-next-line space-before-function-paren, @typescript-eslint/no-unused-vars, max-len
protected abstract _isChromiumBasedBrowser(launchContext: LaunchContext<Library, LibraryOptions, LaunchResult, NewPageOptions, NewPageResult>): boolean {
throwImplementationNeeded('_isChromiumBasedBrowser');
}

/**
* @private
*/
Expand Down
4 changes: 1 addition & 3 deletions src/fingerprinting/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { FingerprintInjector } from 'fingerprint-injector';
import { BrowserPool, PlaywrightPlugin, PuppeteerPlugin } from '..';
import { BrowserController } from '../abstract-classes/browser-controller';
import { LaunchContext } from '../launch-context';
import { getGeneratorDefaultOptions, mergeArgsToHideWebdriver } from './utils';
import { getGeneratorDefaultOptions } from './utils';

export function createFingerprintPreLaunchHook(browserPool: BrowserPool<any, any, any, any, any>) {
const {
Expand Down Expand Up @@ -31,8 +31,6 @@ export function createFingerprintPreLaunchHook(browserPool: BrowserPool<any, any
}

launchContext.extend({ fingerprint });
// hide webdriver with arg.
launchOptions.args = mergeArgsToHideWebdriver(launchOptions.args);

if (useIncognitoPages) {
return;
Expand Down
16 changes: 0 additions & 16 deletions src/fingerprinting/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,6 @@ export const getGeneratorDefaultOptions = (launchContext: LaunchContext): Finger
return options;
};

export const mergeArgsToHideWebdriver = (originalArgs: string[]): string[] => {
if (!originalArgs?.length) {
return ['--disable-blink-features=AutomationControlled'];
}

const argumentIndex = originalArgs.findIndex((arg: string) => arg.startsWith('--disable-blink-features='));

if (argumentIndex !== -1) {
originalArgs[argumentIndex] += ',AutomationControlled';
} else {
originalArgs.push('--disable-blink-features=AutomationControlled');
}

return originalArgs;
};

const getBrowserName = (browserPlugin: BrowserPlugin, launchOptions: any): BrowserName => {
const { library } = browserPlugin;
let browserName;
Expand Down
5 changes: 5 additions & 0 deletions src/playwright/playwright-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,9 @@ export class PlaywrightPlugin extends BrowserPlugin<BrowserType, Parameters<Brow
};
}
}

protected _isChromiumBasedBrowser(): boolean {
const name = this.library.name();
return name === 'chromium';
}
}
7 changes: 7 additions & 0 deletions src/puppeteer/puppeteer-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,4 +163,11 @@ export class PuppeteerPlugin extends BrowserPlugin<typeof Puppeteer> {
}
*/
}

protected _isChromiumBasedBrowser(launchContext: LaunchContext<any, unknown, any, unknown, any>): boolean {
const { launchOptions } = launchContext as any;
// @ts-expect-error cannot find .product on this.library
const browserName = launchOptions.product || this.library.product!;
return browserName === 'chrome';
}
}
30 changes: 30 additions & 0 deletions test/browser-pool.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -637,6 +637,36 @@ describe('BrowserPool', () => {
});
});

describe('default browser automation masking', () => {
describe.each(fingerprintingMatrix)('%s', (_name, plugin) => {
let browserPoolWithDefaults: BrowserPool;
let page: any;

beforeEach(async () => {
browserPoolWithDefaults = new BrowserPool({
browserPlugins: [plugin],
closeInactiveBrowserAfterSecs: 2,
});
page = await browserPoolWithDefaults.newPage();
});

afterEach(async () => {
if (page) await page.close();

await browserPoolWithDefaults.destroy();
});

test('should hide webdriver', async () => {
await page.goto(`file://${__dirname}/test.html`);
const webdriver = await page.evaluate(() => {
return navigator.webdriver;
});
// Can be undefined or false, depending on the chrome version.
expect(webdriver).toBeFalsy();
});
});
});

describe('fingerprinting', () => {
describe.each(fingerprintingMatrix)('%s', (_name, plugin) => {
let browserPoolWithFP: BrowserPool;
Expand Down

0 comments on commit dd4d143

Please sign in to comment.