-
Notifications
You must be signed in to change notification settings - Fork 544
/
hooks.ts
105 lines (89 loc) · 4.16 KB
/
hooks.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import type { BrowserFingerprintWithHeaders } from 'fingerprint-generator';
import type { FingerprintInjector } from 'fingerprint-injector';
import { getGeneratorDefaultOptions } from './utils';
import type { BrowserPool } from '..';
import type { BrowserController } from '../abstract-classes/browser-controller';
import type { LaunchContext } from '../launch-context';
import { PlaywrightPlugin } from '../playwright/playwright-plugin';
import { PuppeteerPlugin } from '../puppeteer/puppeteer-plugin';
/**
* @internal
*/
export function createFingerprintPreLaunchHook(browserPool: BrowserPool<any, any, any, any, any>) {
const {
fingerprintGenerator,
fingerprintCache,
fingerprintOptions: {
fingerprintGeneratorOptions,
},
} = browserPool;
return (_pageId: string, launchContext: LaunchContext) => {
const { useIncognitoPages } = launchContext;
const cacheKey = (launchContext.session as { id: string } | undefined)?.id ?? launchContext.proxyUrl;
const { launchOptions }: { launchOptions: any } = launchContext;
// If no options are passed we try to pass best default options as possible to match browser and OS.
const fingerprintGeneratorFinalOptions = fingerprintGeneratorOptions || getGeneratorDefaultOptions(launchContext);
let fingerprint : BrowserFingerprintWithHeaders;
if (cacheKey && fingerprintCache?.has(cacheKey)) {
fingerprint = fingerprintCache.get(cacheKey)!;
} else if (cacheKey) {
fingerprint = fingerprintGenerator!.getFingerprint(fingerprintGeneratorFinalOptions);
fingerprintCache?.set(cacheKey, fingerprint);
} else {
fingerprint = fingerprintGenerator!.getFingerprint(fingerprintGeneratorFinalOptions);
}
launchContext.extend({ fingerprint });
if (useIncognitoPages) {
return;
}
const { navigator: { userAgent }, screen } = fingerprint.fingerprint!;
launchOptions.userAgent = userAgent;
launchOptions.viewport = {
width: screen.width,
height: screen.height,
};
};
}
/**
* @internal
*/
export function createPrePageCreateHook() {
return (_pageId: string, browserController: BrowserController, pageOptions: any): void => {
const { launchContext, browserPlugin } = browserController;
const { fingerprint } = launchContext.fingerprint!;
if (launchContext.useIncognitoPages && browserPlugin instanceof PlaywrightPlugin && pageOptions) {
pageOptions.userAgent ??= fingerprint.navigator.userAgent;
pageOptions.viewport ??= {
width: fingerprint.screen.width,
height: fingerprint.screen.height,
};
}
};
}
/**
* @internal
*/
export function createPostPageCreateHook(fingerprintInjector: FingerprintInjector) {
return async (page: any, browserController: BrowserController): Promise<void> => {
const { browserPlugin, launchContext } = browserController;
const fingerprint = launchContext.fingerprint!;
// TODO this will require refactoring, we should use common API instead of branching based on plugin type,
// and there should be no public methods specific to some browser.
if (browserPlugin instanceof PlaywrightPlugin) {
const { useIncognitoPages, isFingerprintInjected } = launchContext;
if (isFingerprintInjected) {
// If not incognitoPages are used we would add the injection script over and over which could cause memory leaks.
return;
}
const context = page.context();
await fingerprintInjector.attachFingerprintToPlaywright(context, fingerprint);
if (!useIncognitoPages) {
// There is only one context
// We would add the injection script over and over which could cause memory/cpu leaks.
launchContext.extend({ isFingerprintInjected: true });
}
} else if (browserPlugin instanceof PuppeteerPlugin) {
await fingerprintInjector.attachFingerprintToPuppeteer(page, fingerprint);
}
};
}