jumpy-lion 0.0.16 → 0.0.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser-controller.d.ts +18 -1
- package/dist/browser-controller.d.ts.map +1 -1
- package/dist/browser-controller.js +131 -26
- package/dist/browser-controller.js.map +1 -1
- package/dist/browser-plugin.d.ts +32 -7
- package/dist/browser-plugin.d.ts.map +1 -1
- package/dist/browser-plugin.js +47 -97
- package/dist/browser-plugin.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -10,24 +10,41 @@ LaunchReturn, // LaunchResult (CDP client)
|
|
|
10
10
|
{}, // NewPageOptions (empty as there are no specific options)
|
|
11
11
|
NewPageResult> {
|
|
12
12
|
private client?;
|
|
13
|
+
private reconnectAttempts;
|
|
14
|
+
private hasDisconnectListener;
|
|
13
15
|
initialize(): Promise<void>;
|
|
14
16
|
/**
|
|
17
|
+
* Attach a listener to handle WebSocket disconnections.
|
|
18
|
+
* @private
|
|
19
|
+
*/
|
|
20
|
+
private _attachDisconnectListener;
|
|
21
|
+
/**
|
|
22
|
+
* Attempt to reconnect if WebSocket connection is lost.
|
|
23
|
+
* @private
|
|
24
|
+
*/
|
|
25
|
+
private _attemptReconnect;
|
|
26
|
+
/**
|
|
27
|
+
* Gracefully closes the browser and associated process.
|
|
15
28
|
* @private
|
|
16
29
|
*/
|
|
17
30
|
protected _close(): Promise<void>;
|
|
18
31
|
/**
|
|
32
|
+
* Force kills the browser process without any grace period.
|
|
19
33
|
* @private
|
|
20
34
|
*/
|
|
21
35
|
protected _kill(): Promise<void>;
|
|
22
36
|
/**
|
|
37
|
+
* Creates a new page in the browser. Implements retry logic to handle potential errors.
|
|
23
38
|
* @private
|
|
24
39
|
*/
|
|
25
|
-
protected _newPage(): Promise<NewPageResult>;
|
|
40
|
+
protected _newPage(maxRetries?: number): Promise<NewPageResult>;
|
|
26
41
|
/**
|
|
42
|
+
* Sets cookies on the given page.
|
|
27
43
|
* @private
|
|
28
44
|
*/
|
|
29
45
|
protected _setCookies(page: NewPageResult, cookies: Cookie[]): Promise<void>;
|
|
30
46
|
/**
|
|
47
|
+
* Gets cookies from the given page.
|
|
31
48
|
* @private
|
|
32
49
|
*/
|
|
33
50
|
protected _getCookies(page: NewPageResult): Promise<Cookie[]>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser-controller.d.ts","sourceRoot":"","sources":["../src/browser-controller.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAEvD,OAAO,EAAE,iBAAiB,EAAc,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"browser-controller.d.ts","sourceRoot":"","sources":["../src/browser-controller.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAEvD,OAAO,EAAE,iBAAiB,EAAc,MAAM,SAAS,CAAC;AAExD,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACpE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,OAAO,MAAM,WAAW,CAAC;AAEhC,MAAM,MAAM,aAAa,GAAG,OAAO,CAAC;AAEpC,MAAM,CAAC,OAAO,OAAO,oBAAqB,SAAQ,iBAAiB,CAC/D,WAAW,EAAE,6CAA6C;AAC1D,OAAO,EAAE,gBAAgB;AACzB,YAAY,EAAE,4BAA4B;AAC1C,EAAE,EAAE,0DAA0D;AAC9D,aAAa,CAChB;IACG,OAAO,CAAC,MAAM,CAAC,CAAa;IAC5B,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,qBAAqB,CAAS;IAEhC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAgBjC;;;OAGG;IACH,OAAO,CAAC,yBAAyB;IAWjC;;;OAGG;YACW,iBAAiB;IAqC/B;;;OAGG;cACa,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAqBvC;;;OAGG;cACa,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAYtC;;;OAGG;cACa,QAAQ,CAAC,UAAU,SAAI,GAAG,OAAO,CAAC,aAAa,CAAC;IAgDhE;;;OAGG;cACa,WAAW,CAAC,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAQlF;;;OAGG;cACa,WAAW,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAQ1D,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE,YAAY,EAAE,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAI5G"}
|
|
@@ -11,63 +11,166 @@ export default class CDPBrowserController extends BrowserController {
|
|
|
11
11
|
writable: true,
|
|
12
12
|
value: void 0
|
|
13
13
|
});
|
|
14
|
+
Object.defineProperty(this, "reconnectAttempts", {
|
|
15
|
+
enumerable: true,
|
|
16
|
+
configurable: true,
|
|
17
|
+
writable: true,
|
|
18
|
+
value: 0
|
|
19
|
+
});
|
|
20
|
+
Object.defineProperty(this, "hasDisconnectListener", {
|
|
21
|
+
enumerable: true,
|
|
22
|
+
configurable: true,
|
|
23
|
+
writable: true,
|
|
24
|
+
value: false
|
|
25
|
+
}); // Flag to track disconnect listener
|
|
14
26
|
}
|
|
15
27
|
async initialize() {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
28
|
+
try {
|
|
29
|
+
this.client = await CDP({ port: this.launchContext.debuggingPort });
|
|
30
|
+
const { Network, Page } = this.client;
|
|
31
|
+
await Network.enable();
|
|
32
|
+
await Page.enable();
|
|
33
|
+
// Access the internal WebSocket and add event listeners for disconnects
|
|
34
|
+
this._attachDisconnectListener();
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
log.error('Failed to initialize CDP client', error);
|
|
38
|
+
throw error;
|
|
39
|
+
}
|
|
20
40
|
}
|
|
21
41
|
/**
|
|
42
|
+
* Attach a listener to handle WebSocket disconnections.
|
|
43
|
+
* @private
|
|
44
|
+
*/
|
|
45
|
+
_attachDisconnectListener() {
|
|
46
|
+
if (!this.client || this.hasDisconnectListener)
|
|
47
|
+
return;
|
|
48
|
+
this.client.on('disconnect', () => {
|
|
49
|
+
log.error('WebSocket disconnected, attempting to reconnect...');
|
|
50
|
+
this._attemptReconnect();
|
|
51
|
+
});
|
|
52
|
+
this.hasDisconnectListener = true; // Mark that we have a disconnect listener attached
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Attempt to reconnect if WebSocket connection is lost.
|
|
56
|
+
* @private
|
|
57
|
+
*/
|
|
58
|
+
async _attemptReconnect(maxAttempts = 5, delayMs = 2000) {
|
|
59
|
+
this.reconnectAttempts = 0;
|
|
60
|
+
while (this.reconnectAttempts < maxAttempts) {
|
|
61
|
+
try {
|
|
62
|
+
log.info(`Reconnect attempt ${this.reconnectAttempts + 1} of ${maxAttempts}`);
|
|
63
|
+
this.client = await CDP({ port: this.launchContext.debuggingPort });
|
|
64
|
+
const { Network, Page } = this.client;
|
|
65
|
+
await Network.enable();
|
|
66
|
+
await Page.enable();
|
|
67
|
+
// Reset reconnect attempts on success
|
|
68
|
+
this.reconnectAttempts = 0;
|
|
69
|
+
log.info('Reconnected to browser successfully.');
|
|
70
|
+
// Reattach the disconnect listener after a successful reconnection
|
|
71
|
+
this.hasDisconnectListener = false; // Reset flag to allow attaching again
|
|
72
|
+
this._attachDisconnectListener();
|
|
73
|
+
return; // Successfully reconnected
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
this.reconnectAttempts++;
|
|
77
|
+
log.error(`Reconnect attempt ${this.reconnectAttempts} failed.`, error);
|
|
78
|
+
if (this.reconnectAttempts === maxAttempts) {
|
|
79
|
+
log.error('Max reconnect attempts reached. Closing the browser.');
|
|
80
|
+
await this._close(); // Close the browser if reconnecting fails
|
|
81
|
+
throw new Error('Failed to reconnect after multiple attempts.');
|
|
82
|
+
}
|
|
83
|
+
// Wait before the next reconnection attempt
|
|
84
|
+
await utils.sleep(delayMs);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Gracefully closes the browser and associated process.
|
|
22
90
|
* @private
|
|
23
91
|
*/
|
|
24
92
|
async _close() {
|
|
25
93
|
try {
|
|
26
|
-
|
|
94
|
+
if (this.client) {
|
|
95
|
+
await this.client.close();
|
|
96
|
+
}
|
|
97
|
+
// Gracefully close the browser process
|
|
27
98
|
// @ts-expect-error Fix types
|
|
28
99
|
await this.launchContext.process.close();
|
|
29
100
|
await utils.sleep(5000);
|
|
101
|
+
// Force kill the browser process in case it's still hanging
|
|
30
102
|
// @ts-expect-error Fix types
|
|
31
103
|
await this.launchContext.process.kill();
|
|
32
|
-
|
|
104
|
+
log.info('Browser process closed successfully');
|
|
33
105
|
}
|
|
34
106
|
catch (e) {
|
|
35
|
-
log.error(
|
|
107
|
+
log.error('Could not close browser client or process', e);
|
|
108
|
+
// Attempt to force kill the process in case it wasn't closed properly
|
|
36
109
|
// @ts-expect-error Fix types
|
|
37
110
|
this.launchContext.process.kill();
|
|
38
111
|
}
|
|
39
|
-
// @TODO:
|
|
40
112
|
}
|
|
41
113
|
/**
|
|
114
|
+
* Force kills the browser process without any grace period.
|
|
42
115
|
* @private
|
|
43
116
|
*/
|
|
44
117
|
async _kill() {
|
|
45
|
-
|
|
118
|
+
try {
|
|
119
|
+
if (this.client) {
|
|
120
|
+
await this.client.close();
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
catch (e) {
|
|
124
|
+
log.error('Error closing client before kill', e);
|
|
125
|
+
}
|
|
46
126
|
// @ts-expect-error Fix types
|
|
47
127
|
this.launchContext.process.kill();
|
|
48
128
|
}
|
|
49
129
|
/**
|
|
130
|
+
* Creates a new page in the browser. Implements retry logic to handle potential errors.
|
|
50
131
|
* @private
|
|
51
132
|
*/
|
|
52
|
-
async _newPage() {
|
|
53
|
-
|
|
54
|
-
|
|
133
|
+
async _newPage(maxRetries = 3) {
|
|
134
|
+
let retries = 0;
|
|
135
|
+
while (retries < maxRetries) {
|
|
136
|
+
try {
|
|
137
|
+
if (!this.client) {
|
|
138
|
+
await this.initialize();
|
|
139
|
+
}
|
|
140
|
+
const { Target } = this.client;
|
|
141
|
+
// Create a new page target
|
|
142
|
+
const { targetId } = await Target.createTarget({ url: 'about:blank' });
|
|
143
|
+
const session = await CDP({ target: targetId, port: this.launchContext.debuggingPort });
|
|
144
|
+
// Enable necessary domains
|
|
145
|
+
await session.Network.enable();
|
|
146
|
+
await session.Page.enable();
|
|
147
|
+
// Activate the target
|
|
148
|
+
const { targetInfos } = await Target.getTargets();
|
|
149
|
+
const pages = targetInfos.filter((target) => target.type === 'page' && !target.url.includes('chrome://'));
|
|
150
|
+
await Target.activateTarget({ targetId: pages[pages.length - 1].targetId });
|
|
151
|
+
// Create and return the new page
|
|
152
|
+
const page = new CdpPage(session);
|
|
153
|
+
page.once(PAGE_CLOSED, () => {
|
|
154
|
+
this.activePages -= 1;
|
|
155
|
+
});
|
|
156
|
+
return page;
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
retries++;
|
|
160
|
+
log.error(`Failed to create new page. Attempt ${retries} of ${maxRetries}`, error);
|
|
161
|
+
if (retries === maxRetries) {
|
|
162
|
+
log.error('Max retries reached. Closing the browser.');
|
|
163
|
+
await this._close(); // Close the browser if new page cannot be opened
|
|
164
|
+
throw new Error('Failed to create a new page after multiple attempts.');
|
|
165
|
+
}
|
|
166
|
+
// Optional delay before retrying
|
|
167
|
+
await utils.sleep(1000 * retries);
|
|
168
|
+
}
|
|
55
169
|
}
|
|
56
|
-
|
|
57
|
-
const { targetId } = await Target.createTarget({ url: 'about:blank' });
|
|
58
|
-
const session = await CDP({ target: targetId, port: this.launchContext.debuggingPort });
|
|
59
|
-
await session.Network.enable();
|
|
60
|
-
await session.Page.enable();
|
|
61
|
-
const { targetInfos } = await Target.getTargets();
|
|
62
|
-
const pages = targetInfos.filter((target) => target.type === 'page' && !target.url.includes('chrome://'));
|
|
63
|
-
await Target.activateTarget({ targetId: pages[pages.length - 1].targetId });
|
|
64
|
-
const page = new CdpPage(session);
|
|
65
|
-
page.once(PAGE_CLOSED, () => {
|
|
66
|
-
this.activePages -= 1;
|
|
67
|
-
});
|
|
68
|
-
return page;
|
|
170
|
+
throw new Error('Failed to create a new page after maximum retry attempts.');
|
|
69
171
|
}
|
|
70
172
|
/**
|
|
173
|
+
* Sets cookies on the given page.
|
|
71
174
|
* @private
|
|
72
175
|
*/
|
|
73
176
|
async _setCookies(page, cookies) {
|
|
@@ -79,6 +182,7 @@ export default class CDPBrowserController extends BrowserController {
|
|
|
79
182
|
}
|
|
80
183
|
}
|
|
81
184
|
/**
|
|
185
|
+
* Gets cookies from the given page.
|
|
82
186
|
* @private
|
|
83
187
|
*/
|
|
84
188
|
async _getCookies(page) {
|
|
@@ -88,8 +192,9 @@ export default class CDPBrowserController extends BrowserController {
|
|
|
88
192
|
const cookies = await page?.getCookies();
|
|
89
193
|
return cookies || [];
|
|
90
194
|
}
|
|
91
|
-
// @ts-expect-error
|
|
92
195
|
normalizeProxyOptions(_proxyUrl, _pageOptions) {
|
|
196
|
+
// You can implement custom proxy normalization here if needed
|
|
197
|
+
return {};
|
|
93
198
|
}
|
|
94
199
|
}
|
|
95
200
|
//# sourceMappingURL=browser-controller.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser-controller.js","sourceRoot":"","sources":["../src/browser-controller.ts"],"names":[],"mappings":"AACA,OAAO,GAAG,MAAM,yBAAyB,CAAC;AAC1C,OAAO,EAAE,iBAAiB,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"browser-controller.js","sourceRoot":"","sources":["../src/browser-controller.ts"],"names":[],"mappings":"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"}
|
package/dist/browser-plugin.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ type LaunchResult = LaunchReturn;
|
|
|
8
8
|
interface NewPageOptions {
|
|
9
9
|
}
|
|
10
10
|
interface LaunchBrowserOptions {
|
|
11
|
-
browserType:
|
|
11
|
+
browserType: "chrome" | "firefox";
|
|
12
12
|
useIncognitoPages: boolean;
|
|
13
13
|
proxyUrl?: string;
|
|
14
14
|
ignoreHttpsErrors: boolean;
|
|
@@ -17,12 +17,19 @@ interface LaunchBrowserOptions {
|
|
|
17
17
|
}
|
|
18
18
|
export default class CDPBrowserPlugin extends BrowserPlugin<Library, LaunchBrowserOptions, LaunchResult, NewPageOptions, NewPageResult> {
|
|
19
19
|
/**
|
|
20
|
-
|
|
20
|
+
*/
|
|
21
21
|
protected _addProxyToLaunchOptions(): Promise<void>;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Determines if the browser is Chromium-based.
|
|
24
|
+
*
|
|
25
|
+
* @private
|
|
26
|
+
*/
|
|
25
27
|
protected _isChromiumBasedBrowser(launchContext: LaunchContext<Library, LaunchBrowserOptions, LaunchResult, NewPageOptions, NewPageResult>): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Launches the browser using Chrome Remote Interface (CDP).
|
|
30
|
+
*
|
|
31
|
+
* @private
|
|
32
|
+
*/
|
|
26
33
|
protected _launch(launchContext: LaunchContext<Library, LaunchBrowserOptions, LaunchResult, NewPageOptions, NewPageResult>): Promise<LaunchResult>;
|
|
27
34
|
/**
|
|
28
35
|
* Creates a new browser controller.
|
|
@@ -30,11 +37,29 @@ export default class CDPBrowserPlugin extends BrowserPlugin<Library, LaunchBrows
|
|
|
30
37
|
* @private
|
|
31
38
|
*/
|
|
32
39
|
protected _createController(): CDPBrowserController;
|
|
40
|
+
/**
|
|
41
|
+
* Launches a browser with a new profile.
|
|
42
|
+
*
|
|
43
|
+
* @private
|
|
44
|
+
*/
|
|
33
45
|
private _launchBrowser;
|
|
34
|
-
|
|
35
|
-
|
|
46
|
+
/**
|
|
47
|
+
* Waits for a port to be available.
|
|
48
|
+
*
|
|
49
|
+
* @private
|
|
50
|
+
*/
|
|
36
51
|
private _waitForPort;
|
|
52
|
+
/**
|
|
53
|
+
* Finds a free port to use.
|
|
54
|
+
*
|
|
55
|
+
* @private
|
|
56
|
+
*/
|
|
37
57
|
private _findFreePort;
|
|
58
|
+
/**
|
|
59
|
+
* Tries to connect to the browser using CDP with retries.
|
|
60
|
+
*
|
|
61
|
+
* @private
|
|
62
|
+
*/
|
|
38
63
|
private _connectWithRetry;
|
|
39
64
|
}
|
|
40
65
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser-plugin.d.ts","sourceRoot":"","sources":["../src/browser-plugin.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"browser-plugin.d.ts","sourceRoot":"","sources":["../src/browser-plugin.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAO,KAAK,aAAa,EAAE,MAAM,SAAS,CAAC;AAEjE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,oBAAoB,MAAM,yBAAyB,CAAC;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAMjD,KAAK,OAAO,GAAG,WAAW,CAAC;AAC3B,KAAK,YAAY,GAAG,YAAY,CAAC;AACjC,UAAU,cAAc;CAAI;AAC5B,UAAU,oBAAoB;IAC1B,WAAW,EAAE,QAAQ,GAAG,SAAS,CAAC;IAClC,iBAAiB,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,aAAa,CACvD,OAAO,EACP,oBAAoB,EACpB,YAAY,EACZ,cAAc,EACd,aAAa,CAChB;IACG;OACG;cACa,wBAAwB,IAAI,OAAO,CAAC,IAAI,CAAC;IAIzD;;;;OAIG;IACH,SAAS,CAAC,uBAAuB,CAC7B,aAAa,EAAE,aAAa,CAAC,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,cAAc,EAAE,aAAa,CAAC,GACzG,OAAO;IAKV;;;;OAIG;cACa,OAAO,CACnB,aAAa,EAAE,aAAa,CAAC,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,cAAc,EAAE,aAAa,CAAC,GACzG,OAAO,CAAC,YAAY,CAAC;IAwCxB;;;;OAIG;IAGH,SAAS,CAAC,iBAAiB,IAAI,oBAAoB;IAMnD;;;;OAIG;YACW,cAAc;IA4B5B;;;;OAIG;YACW,YAAY;IAmB1B;;;;OAIG;YACW,aAAa;IAuB3B;;;;OAIG;YACW,iBAAiB;CAuBlC"}
|
package/dist/browser-plugin.js
CHANGED
|
@@ -1,79 +1,50 @@
|
|
|
1
1
|
import net from 'net';
|
|
2
|
-
import { exec } from 'child_process';
|
|
3
2
|
import { BrowserPlugin, log } from 'crawlee';
|
|
4
3
|
import CDPBrowserController from './browser-controller.js';
|
|
5
4
|
import { CdpLauncher } from './launcher-wrap.js';
|
|
6
5
|
import { anonymizeProxySugar } from './proxy/anonymize-proxy.js';
|
|
7
6
|
import { launchChromeBrowserWithNewProfile } from './browser-process/browser.js';
|
|
8
7
|
export default class CDPBrowserPlugin extends BrowserPlugin {
|
|
9
|
-
constructor() {
|
|
10
|
-
super(...arguments);
|
|
11
|
-
Object.defineProperty(this, "browserProcessMap", {
|
|
12
|
-
enumerable: true,
|
|
13
|
-
configurable: true,
|
|
14
|
-
writable: true,
|
|
15
|
-
value: new WeakMap()
|
|
16
|
-
});
|
|
17
|
-
Object.defineProperty(this, "activeProcessPIDs", {
|
|
18
|
-
enumerable: true,
|
|
19
|
-
configurable: true,
|
|
20
|
-
writable: true,
|
|
21
|
-
value: new Set()
|
|
22
|
-
});
|
|
23
|
-
Object.defineProperty(this, "zombieProcessCheckInterval", {
|
|
24
|
-
enumerable: true,
|
|
25
|
-
configurable: true,
|
|
26
|
-
writable: true,
|
|
27
|
-
value: null
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
8
|
/**
|
|
31
|
-
|
|
9
|
+
*/
|
|
32
10
|
async _addProxyToLaunchOptions() {
|
|
33
11
|
// Do nothing; we use proxy launch arg
|
|
34
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* Determines if the browser is Chromium-based.
|
|
15
|
+
*
|
|
16
|
+
* @private
|
|
17
|
+
*/
|
|
35
18
|
_isChromiumBasedBrowser(launchContext) {
|
|
36
19
|
const { browserType } = launchContext.launchOptions;
|
|
37
|
-
return browserType !==
|
|
20
|
+
return browserType !== "firefox"; // Assume non-Firefox is Chromium-based
|
|
38
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Launches the browser using Chrome Remote Interface (CDP).
|
|
24
|
+
*
|
|
25
|
+
* @private
|
|
26
|
+
*/
|
|
39
27
|
async _launch(launchContext) {
|
|
40
28
|
const { launchOptions, useIncognitoPages, proxyUrl } = launchContext;
|
|
41
29
|
if (!launchOptions.browserType) {
|
|
42
|
-
launchOptions.browserType =
|
|
30
|
+
launchOptions.browserType = "chrome";
|
|
43
31
|
}
|
|
44
32
|
let browser;
|
|
45
33
|
launchOptions.useIncognitoPages = useIncognitoPages;
|
|
46
|
-
log.debug(
|
|
34
|
+
log.debug("Launch options", launchOptions);
|
|
47
35
|
const [anonymizedProxyUrl, close] = await anonymizeProxySugar(proxyUrl);
|
|
48
36
|
if (anonymizedProxyUrl) {
|
|
49
37
|
launchOptions.proxyUrl = anonymizedProxyUrl;
|
|
50
38
|
}
|
|
51
39
|
const debuggingPort = await this._findFreePort(9233);
|
|
52
40
|
const browserProcess = await this._launchBrowser(debuggingPort, launchOptions);
|
|
53
|
-
log.debug(
|
|
41
|
+
log.debug("browserProcess", browserProcess);
|
|
54
42
|
try {
|
|
55
43
|
browser = await this._connectWithRetry(debuggingPort, 10, 4000);
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
// Add the process PID to the Set
|
|
59
|
-
if (browserProcess.pid) {
|
|
60
|
-
this.activeProcessPIDs.add(browserProcess.pid);
|
|
61
|
-
}
|
|
62
|
-
// Listen for the "close" event on the Chrome Remote Interface connection
|
|
63
|
-
browser.on('close', async () => {
|
|
64
|
-
this.browserProcessMap.delete(browser);
|
|
65
|
-
if (browserProcess.pid) {
|
|
66
|
-
this.activeProcessPIDs.delete(browserProcess.pid);
|
|
67
|
-
}
|
|
68
|
-
await browserProcess.close(); // Close the browser process gracefully
|
|
69
|
-
if (anonymizedProxyUrl) {
|
|
44
|
+
if (anonymizedProxyUrl) {
|
|
45
|
+
browser.on('close', async () => {
|
|
70
46
|
await close();
|
|
71
|
-
}
|
|
72
|
-
log.info(`Browser on port ${debuggingPort} has been closed and cleaned up.`);
|
|
73
|
-
});
|
|
74
|
-
// Start zombie process killer if not already started
|
|
75
|
-
if (!this.zombieProcessCheckInterval) {
|
|
76
|
-
this._startZombieProcessKiller();
|
|
47
|
+
});
|
|
77
48
|
}
|
|
78
49
|
}
|
|
79
50
|
catch (error) {
|
|
@@ -92,21 +63,21 @@ export default class CDPBrowserPlugin extends BrowserPlugin {
|
|
|
92
63
|
// @TODO:
|
|
93
64
|
// @ts-expect-error Fix types
|
|
94
65
|
_createController() {
|
|
66
|
+
// @TODO:
|
|
95
67
|
// @ts-expect-error Fix types
|
|
96
68
|
return new CDPBrowserController(this);
|
|
97
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* Launches a browser with a new profile.
|
|
72
|
+
*
|
|
73
|
+
* @private
|
|
74
|
+
*/
|
|
98
75
|
async _launchBrowser(debuggingPort, launchOptions) {
|
|
99
76
|
const { proxyUrl, browserType, ignoreHttpsErrors = true, headless, executablePath } = launchOptions;
|
|
100
77
|
let browserProcess;
|
|
101
78
|
switch (browserType) {
|
|
102
|
-
case
|
|
103
|
-
browserProcess = await launchChromeBrowserWithNewProfile({
|
|
104
|
-
debuggingPort,
|
|
105
|
-
anonymizedProxyUrl: proxyUrl,
|
|
106
|
-
ignoreHttpsErrors,
|
|
107
|
-
headless,
|
|
108
|
-
executablePath,
|
|
109
|
-
});
|
|
79
|
+
case "chrome": {
|
|
80
|
+
browserProcess = await launchChromeBrowserWithNewProfile({ debuggingPort, anonymizedProxyUrl: proxyUrl, ignoreHttpsErrors, headless, executablePath });
|
|
110
81
|
break;
|
|
111
82
|
}
|
|
112
83
|
default: {
|
|
@@ -125,67 +96,41 @@ export default class CDPBrowserPlugin extends BrowserPlugin {
|
|
|
125
96
|
});
|
|
126
97
|
});
|
|
127
98
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
async _killZombieProcesses() {
|
|
134
|
-
log.debug("Checking for zombie processes...");
|
|
135
|
-
// List all Chrome processes and filter potential zombie processes.
|
|
136
|
-
exec('ps aux | grep "[c]hrome"', (error, stdout) => {
|
|
137
|
-
if (error) {
|
|
138
|
-
log.error('Error while checking for Chrome processes:', error);
|
|
139
|
-
return;
|
|
140
|
-
}
|
|
141
|
-
const chromeProcesses = stdout.split('\n').filter(line => line.includes('--remote-debugging-port'));
|
|
142
|
-
chromeProcesses.forEach((processLine) => {
|
|
143
|
-
const match = processLine.match(/(\S+)\s+(\d+)/);
|
|
144
|
-
if (match) {
|
|
145
|
-
const pid = parseInt(match[2]);
|
|
146
|
-
// Check if this process is in our Set of active PIDs, if not, it's likely a zombie.
|
|
147
|
-
if (!this.activeProcessPIDs.has(pid)) {
|
|
148
|
-
log.info(`Killing zombie Chrome process with PID: ${pid}`);
|
|
149
|
-
exec(`kill -9 ${pid}`, (killError) => {
|
|
150
|
-
if (killError) {
|
|
151
|
-
log.error(`Failed to kill process ${pid}:`, killError);
|
|
152
|
-
}
|
|
153
|
-
else {
|
|
154
|
-
log.info(`Successfully killed zombie process with PID: ${pid}`);
|
|
155
|
-
}
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
});
|
|
160
|
-
});
|
|
161
|
-
}
|
|
99
|
+
/**
|
|
100
|
+
* Waits for a port to be available.
|
|
101
|
+
*
|
|
102
|
+
* @private
|
|
103
|
+
*/
|
|
162
104
|
async _waitForPort(port, timeout = 30000, retryDelay = 500) {
|
|
163
105
|
const startTime = Date.now();
|
|
164
106
|
return new Promise((resolve, reject) => {
|
|
165
107
|
(function tryConnect() {
|
|
166
108
|
const socket = net.createConnection(port, '127.0.0.1');
|
|
167
|
-
socket
|
|
168
|
-
.on('connect', () => {
|
|
109
|
+
socket.on('connect', () => {
|
|
169
110
|
socket.end();
|
|
170
111
|
resolve(true);
|
|
171
|
-
})
|
|
172
|
-
.on('error', (_err) => {
|
|
112
|
+
}).on('error', (_err) => {
|
|
173
113
|
if (Date.now() - startTime > timeout) {
|
|
174
114
|
reject(new Error(`Timeout waiting for port ${port}`));
|
|
175
115
|
}
|
|
176
116
|
else {
|
|
177
|
-
setTimeout(tryConnect, retryDelay);
|
|
117
|
+
setTimeout(tryConnect, retryDelay); // Retry after a delay
|
|
178
118
|
}
|
|
179
119
|
});
|
|
180
|
-
}
|
|
120
|
+
}());
|
|
181
121
|
});
|
|
182
122
|
}
|
|
123
|
+
/**
|
|
124
|
+
* Finds a free port to use.
|
|
125
|
+
*
|
|
126
|
+
* @private
|
|
127
|
+
*/
|
|
183
128
|
async _findFreePort(startingPort) {
|
|
184
129
|
return new Promise((resolve, reject) => {
|
|
185
130
|
const server = net.createServer();
|
|
186
131
|
server.on('error', (err) => {
|
|
187
132
|
if (err.code === 'EADDRINUSE') {
|
|
188
|
-
this._findFreePort(startingPort + 1).then(resolve).catch(reject);
|
|
133
|
+
this._findFreePort(startingPort + 1).then(resolve).catch(reject); // Port is in use, try the next one
|
|
189
134
|
}
|
|
190
135
|
else {
|
|
191
136
|
reject(err);
|
|
@@ -200,6 +145,11 @@ export default class CDPBrowserPlugin extends BrowserPlugin {
|
|
|
200
145
|
server.listen(startingPort, '127.0.0.1');
|
|
201
146
|
});
|
|
202
147
|
}
|
|
148
|
+
/**
|
|
149
|
+
* Tries to connect to the browser using CDP with retries.
|
|
150
|
+
*
|
|
151
|
+
* @private
|
|
152
|
+
*/
|
|
203
153
|
async _connectWithRetry(port, maxRetries, retryDelay) {
|
|
204
154
|
let attempt = 0;
|
|
205
155
|
let lastError = null;
|
|
@@ -215,7 +165,7 @@ export default class CDPBrowserPlugin extends BrowserPlugin {
|
|
|
215
165
|
lastError = error;
|
|
216
166
|
log.warning(`Failed to connect to browser on attempt ${attempt}. Retrying in ${retryDelay}ms...`);
|
|
217
167
|
if (attempt < maxRetries) {
|
|
218
|
-
await new Promise(
|
|
168
|
+
await new Promise(resolve => setTimeout(resolve, retryDelay)); // Wait before retrying
|
|
219
169
|
}
|
|
220
170
|
}
|
|
221
171
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser-plugin.js","sourceRoot":"","sources":["../src/browser-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"browser-plugin.js","sourceRoot":"","sources":["../src/browser-plugin.ts"],"names":[],"mappings":"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"}
|