-
Notifications
You must be signed in to change notification settings - Fork 626
/
launch-context.ts
136 lines (124 loc) · 5.06 KB
/
launch-context.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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import type { Dictionary } from '@crawlee/types';
import type { BrowserFingerprintWithHeaders } from 'fingerprint-generator';
import type { BrowserPlugin, CommonBrowser, CommonLibrary } from './abstract-classes/browser-plugin';
import type { UnwrapPromise } from './utils';
/**
* `LaunchContext` holds information about the launched browser. It's useful
* to retrieve the `launchOptions`, the proxy the browser was launched with
* or any other information user chose to add to the `LaunchContext` by calling
* its `extend` function. This is very useful to keep track of browser-scoped
* values, such as session IDs.
*/
export interface LaunchContextOptions<
Library extends CommonLibrary = CommonLibrary,
LibraryOptions extends Dictionary | undefined = Parameters<Library['launch']>[0],
LaunchResult extends CommonBrowser = UnwrapPromise<ReturnType<Library['launch']>>,
NewPageOptions = Parameters<LaunchResult['newPage']>[0],
NewPageResult = UnwrapPromise<ReturnType<LaunchResult['newPage']>>,
> {
/**
* To make identification of `LaunchContext` easier, `BrowserPool` assigns
* the `LaunchContext` an `id` that's equal to the `id` of the page that
* triggered the browser launch. This is useful, because many pages share
* a single launch context (single browser).
*/
id?: string;
/**
* The `BrowserPlugin` instance used to launch the browser.
*/
browserPlugin: BrowserPlugin<Library, LibraryOptions, LaunchResult, NewPageOptions, NewPageResult>;
/**
* The actual options the browser was launched with, after changes.
* Those changes would be typically made in pre-launch hooks.
*/
launchOptions: LibraryOptions;
/**
* By default pages share the same browser context.
* If set to `true` each page uses its own context that is destroyed once the page is closed or crashes.
*/
useIncognitoPages?: boolean;
/**
* @experimental
* Like `useIncognitoPages`, but for persistent contexts, so cache is used for faster loading.
* Works best with Firefox. Unstable on Chromium.
*/
experimentalContainers?: boolean;
/**
* Path to a User Data Directory, which stores browser session data like cookies and local storage.
*/
userDataDir?: string;
proxyUrl?: string;
}
export class LaunchContext<
Library extends CommonLibrary = CommonLibrary,
LibraryOptions extends Dictionary | undefined = Parameters<Library['launch']>[0],
LaunchResult extends CommonBrowser = UnwrapPromise<ReturnType<Library['launch']>>,
NewPageOptions = Parameters<LaunchResult['newPage']>[0],
NewPageResult = UnwrapPromise<ReturnType<LaunchResult['newPage']>>,
> {
id?: string;
browserPlugin: BrowserPlugin<Library, LibraryOptions, LaunchResult, NewPageOptions, NewPageResult>;
launchOptions: LibraryOptions;
useIncognitoPages: boolean;
experimentalContainers: boolean;
userDataDir: string;
private _proxyUrl?: string;
private readonly _reservedFieldNames = [...Reflect.ownKeys(this), 'extend'];
fingerprint?: BrowserFingerprintWithHeaders;
[K: PropertyKey]: unknown;
constructor(options: LaunchContextOptions<Library, LibraryOptions, LaunchResult, NewPageOptions, NewPageResult>) {
const {
id,
browserPlugin,
launchOptions,
proxyUrl,
useIncognitoPages,
experimentalContainers,
userDataDir = '',
} = options;
this.id = id;
this.browserPlugin = browserPlugin;
this.launchOptions = launchOptions;
this.useIncognitoPages = useIncognitoPages ?? false;
this.experimentalContainers = experimentalContainers ?? false;
this.userDataDir = userDataDir;
this._proxyUrl = proxyUrl;
}
/**
* Extend the launch context with any extra fields.
* This is useful to keep state information relevant
* to the browser being launched. It ensures that
* no internal fields are overridden and should be
* used instead of property assignment.
*/
extend<T extends Record<PropertyKey, unknown>>(fields: T): void {
Object.entries(fields).forEach(([key, value]) => {
if (this._reservedFieldNames.includes(key)) {
throw new Error(`Cannot extend LaunchContext with key: ${key}, because it's reserved.`);
} else {
Reflect.set(this, key, value);
}
});
}
/**
* Sets a proxy URL for the browser.
* Use `undefined` to unset existing proxy URL.
*/
set proxyUrl(url: string | undefined) {
if (!url) {
return;
}
const urlInstance = new URL(url);
urlInstance.pathname = '/';
urlInstance.search = '';
urlInstance.hash = '';
// https://www.chromium.org/developers/design-documents/network-settings/#command-line-options-for-proxy-settings
this._proxyUrl = urlInstance.href.slice(0, -1);
}
/**
* Returns the proxy URL of the browser.
*/
get proxyUrl(): string | undefined {
return this._proxyUrl;
}
}