openchrome-mcp 1.10.0 → 1.10.1
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/cdp/client.d.ts +15 -1
- package/dist/cdp/client.d.ts.map +1 -1
- package/dist/cdp/client.js +119 -33
- package/dist/cdp/client.js.map +1 -1
- package/dist/chrome/headed-fallback.d.ts +1 -0
- package/dist/chrome/headed-fallback.d.ts.map +1 -1
- package/dist/chrome/headed-fallback.js +32 -6
- package/dist/chrome/headed-fallback.js.map +1 -1
- package/dist/chrome/launcher.d.ts.map +1 -1
- package/dist/chrome/launcher.js +9 -2
- package/dist/chrome/launcher.js.map +1 -1
- package/dist/dashboard/types.d.ts +1 -1
- package/dist/dashboard/types.d.ts.map +1 -1
- package/dist/desktop/dashboard-state.d.ts +2 -2
- package/dist/desktop/dashboard-state.d.ts.map +1 -1
- package/dist/desktop/dashboard-state.js.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp-server.d.ts.map +1 -1
- package/dist/mcp-server.js +20 -9
- package/dist/mcp-server.js.map +1 -1
- package/dist/metrics/collector.d.ts.map +1 -1
- package/dist/metrics/collector.js +3 -0
- package/dist/metrics/collector.js.map +1 -1
- package/dist/orchestration/workflow-engine.d.ts.map +1 -1
- package/dist/orchestration/workflow-engine.js +6 -3
- package/dist/orchestration/workflow-engine.js.map +1 -1
- package/dist/security/audit-logger.d.ts +4 -0
- package/dist/security/audit-logger.d.ts.map +1 -1
- package/dist/security/audit-logger.js +5 -1
- package/dist/security/audit-logger.js.map +1 -1
- package/dist/session-manager.d.ts +12 -0
- package/dist/session-manager.d.ts.map +1 -1
- package/dist/session-manager.js +42 -4
- package/dist/session-manager.js.map +1 -1
- package/dist/transports/http.d.ts.map +1 -1
- package/dist/transports/http.js +14 -2
- package/dist/transports/http.js.map +1 -1
- package/dist/utils/pid-manager.d.ts +1 -0
- package/dist/utils/pid-manager.d.ts.map +1 -1
- package/dist/utils/pid-manager.js +26 -1
- package/dist/utils/pid-manager.js.map +1 -1
- package/dist/utils/process-guardian.d.ts +11 -0
- package/dist/utils/process-guardian.d.ts.map +1 -0
- package/dist/utils/process-guardian.js +110 -0
- package/dist/utils/process-guardian.js.map +1 -0
- package/dist/utils/safe-listener.d.ts +5 -0
- package/dist/utils/safe-listener.d.ts.map +1 -1
- package/dist/utils/safe-listener.js +42 -0
- package/dist/utils/safe-listener.js.map +1 -1
- package/dist/watchdog/health-endpoint.d.ts +7 -0
- package/dist/watchdog/health-endpoint.d.ts.map +1 -1
- package/dist/watchdog/health-endpoint.js +1 -0
- package/dist/watchdog/health-endpoint.js.map +1 -1
- package/package.json +1 -1
package/dist/cdp/client.d.ts
CHANGED
|
@@ -3,6 +3,15 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { Browser, BrowserContext, Page, Target, CDPSession } from 'puppeteer-core';
|
|
5
5
|
import { Budget } from '../utils/budget';
|
|
6
|
+
export type CookieScanStatus = 'complete' | 'partial' | 'no_candidates' | 'no_cookies';
|
|
7
|
+
export interface CookieScanResult {
|
|
8
|
+
status: CookieScanStatus;
|
|
9
|
+
targetId: string | null;
|
|
10
|
+
scanned: number;
|
|
11
|
+
total: number;
|
|
12
|
+
elapsedMs: number;
|
|
13
|
+
warning?: string;
|
|
14
|
+
}
|
|
6
15
|
export interface CDPClientOptions {
|
|
7
16
|
port?: number;
|
|
8
17
|
maxReconnectAttempts?: number;
|
|
@@ -37,7 +46,9 @@ export declare class CDPClient {
|
|
|
37
46
|
private cookieSourceCache;
|
|
38
47
|
private cookieDataCache;
|
|
39
48
|
private targetIdIndex;
|
|
49
|
+
private targetActivityAt;
|
|
40
50
|
private inFlightCookieScans;
|
|
51
|
+
private lastCookieScanResult;
|
|
41
52
|
/** Coalesces concurrent connect() calls — only one connectInternal() runs at a time. */
|
|
42
53
|
private pendingConnect;
|
|
43
54
|
/** Timestamp of last successful connection verification (heartbeat or active probe). */
|
|
@@ -88,6 +99,8 @@ export declare class CDPClient {
|
|
|
88
99
|
* Handle target destroyed event
|
|
89
100
|
*/
|
|
90
101
|
private onTargetDestroyed;
|
|
102
|
+
private touchTargetActivity;
|
|
103
|
+
getLastCookieScanResult(): CookieScanResult | null;
|
|
91
104
|
/**
|
|
92
105
|
* Emit connection event
|
|
93
106
|
*/
|
|
@@ -228,13 +241,14 @@ export declare class CDPClient {
|
|
|
228
241
|
*
|
|
229
242
|
* @param targetDomain Optional domain to prioritize when selecting cookie source
|
|
230
243
|
*/
|
|
244
|
+
findAuthenticatedPageTarget(targetDomain?: string): Promise<CookieScanResult>;
|
|
231
245
|
findAuthenticatedPageTargetId(targetDomain?: string): Promise<string | null>;
|
|
232
246
|
/**
|
|
233
247
|
* Internal implementation of the authenticated-page probe.
|
|
234
248
|
* Uses Target.attachToTarget (multiplexed CDP) instead of raw WebSocket connections.
|
|
235
249
|
* Uses Target.getTargets result directly instead of /json/list HTTP calls.
|
|
236
250
|
*/
|
|
237
|
-
private
|
|
251
|
+
private _doFindAuthenticatedPageTarget;
|
|
238
252
|
/**
|
|
239
253
|
* Copy all cookies from authenticated page to destination page.
|
|
240
254
|
* Uses Target.attachToTarget (multiplexed CDP) to bypass Puppeteer's context isolation —
|
package/dist/cdp/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/cdp/client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAkB,EAAE,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AA0B9F,OAAO,EAAE,MAAM,EAAsB,MAAM,iBAAiB,CAAC;AAkB7D,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,oEAAoE;IACpE,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,MAAM,eAAe,GAAG,cAAc,GAAG,YAAY,GAAG,WAAW,GAAG,cAAc,CAAC;AAE3F,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,WAAW,GAAG,cAAc,GAAG,cAAc,GAAG,aAAa,GAAG,kBAAkB,CAAC;IACzF,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAkBD,qBAAa,SAAS;IACpB,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,QAAQ,CAAsC;IACtD,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,oBAAoB,CAAS;IACrC,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,mBAAmB,CAAS;IACpC,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,eAAe,CAAmC;IAC1D,OAAO,CAAC,cAAc,CAA4C;IAClE,OAAO,CAAC,wBAAwB,CAAmD;IACnF,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,4BAA4B,CAAK;IACzC,OAAO,CAAC,6BAA6B,CAAK;IAC1C,OAAO,CAAC,uBAAuB,CAAS;IACxC,OAAO,CAAC,UAAU,CAAU;IAC5B,OAAO,CAAC,iBAAiB,CAAmE;IAC5F,OAAO,CAAC,eAAe,CAAyE;IAChG,OAAO,CAAC,aAAa,CAAgC;IACrD,OAAO,CAAC,mBAAmB,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/cdp/client.ts"],"names":[],"mappings":"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"}
|
package/dist/cdp/client.js
CHANGED
|
@@ -89,7 +89,9 @@ class CDPClient {
|
|
|
89
89
|
cookieSourceCache = new Map();
|
|
90
90
|
cookieDataCache = new Map();
|
|
91
91
|
targetIdIndex = new Map();
|
|
92
|
+
targetActivityAt = new Map();
|
|
92
93
|
inFlightCookieScans = new Map();
|
|
94
|
+
lastCookieScanResult = null;
|
|
93
95
|
/** Coalesces concurrent connect() calls — only one connectInternal() runs at a time. */
|
|
94
96
|
pendingConnect = null;
|
|
95
97
|
/** Timestamp of last successful connection verification (heartbeat or active probe). */
|
|
@@ -184,6 +186,7 @@ class CDPClient {
|
|
|
184
186
|
}
|
|
185
187
|
// Clean up cookie data cache for this target
|
|
186
188
|
this.cookieDataCache.delete(targetId);
|
|
189
|
+
this.targetActivityAt.delete(targetId);
|
|
187
190
|
// Look up page BEFORE deleting from index so listeners can use it
|
|
188
191
|
const page = this.targetIdIndex.get(targetId);
|
|
189
192
|
this.targetIdIndex.delete(targetId);
|
|
@@ -196,6 +199,12 @@ class CDPClient {
|
|
|
196
199
|
}
|
|
197
200
|
}
|
|
198
201
|
}
|
|
202
|
+
touchTargetActivity(targetId) {
|
|
203
|
+
this.targetActivityAt.set(targetId, Date.now());
|
|
204
|
+
}
|
|
205
|
+
getLastCookieScanResult() {
|
|
206
|
+
return this.lastCookieScanResult;
|
|
207
|
+
}
|
|
199
208
|
/**
|
|
200
209
|
* Emit connection event
|
|
201
210
|
*/
|
|
@@ -418,6 +427,7 @@ class CDPClient {
|
|
|
418
427
|
if (this.browser) {
|
|
419
428
|
this.browser.removeAllListeners('disconnected');
|
|
420
429
|
this.browser.removeAllListeners('targetdestroyed');
|
|
430
|
+
this.browser.removeAllListeners('targetchanged');
|
|
421
431
|
this.browser.removeAllListeners('targetcreated');
|
|
422
432
|
try {
|
|
423
433
|
this.browser.disconnect();
|
|
@@ -564,6 +574,7 @@ class CDPClient {
|
|
|
564
574
|
if (this.browser) {
|
|
565
575
|
this.browser.removeAllListeners('disconnected');
|
|
566
576
|
this.browser.removeAllListeners('targetdestroyed');
|
|
577
|
+
this.browser.removeAllListeners('targetchanged');
|
|
567
578
|
this.browser.removeAllListeners('targetcreated');
|
|
568
579
|
this.browser.disconnect().catch(() => { });
|
|
569
580
|
this.browser = null;
|
|
@@ -605,11 +616,19 @@ class CDPClient {
|
|
|
605
616
|
});
|
|
606
617
|
});
|
|
607
618
|
// Set up target destroyed handler
|
|
608
|
-
this.browser.on('targetdestroyed', (target) => {
|
|
619
|
+
this.browser.on('targetdestroyed', (0, safe_listener_1.safeAsyncListener)('targetdestroyed', async (target) => {
|
|
609
620
|
const targetId = (0, puppeteer_helpers_1.getTargetId)(target);
|
|
610
621
|
console.error(`[CDPClient] Target destroyed: ${targetId}`);
|
|
611
622
|
this.onTargetDestroyed(targetId);
|
|
612
|
-
});
|
|
623
|
+
}));
|
|
624
|
+
this.browser.on('targetchanged', (0, safe_listener_1.safeAsyncListener)('targetchanged', async (target) => {
|
|
625
|
+
if (target.type() !== 'page')
|
|
626
|
+
return;
|
|
627
|
+
const targetId = (0, puppeteer_helpers_1.getTargetId)(target);
|
|
628
|
+
if (this.targetIdIndex.has(targetId)) {
|
|
629
|
+
console.error(`[CDPClient] Target changed: ${targetId}`);
|
|
630
|
+
}
|
|
631
|
+
}));
|
|
613
632
|
// Note: We intentionally do NOT call target.page() for EVERY targetcreated event.
|
|
614
633
|
// Eagerly calling target.page() on every new target can materialize Chrome's internal
|
|
615
634
|
// targets (prerender, speculative navigation, new-tab-page) as visible about:blank
|
|
@@ -655,6 +674,7 @@ class CDPClient {
|
|
|
655
674
|
const page = await target.page();
|
|
656
675
|
if (page) {
|
|
657
676
|
this.targetIdIndex.set(targetId, page);
|
|
677
|
+
this.touchTargetActivity(targetId);
|
|
658
678
|
this.configurePageDefenses(page);
|
|
659
679
|
console.error(`[CDPClient] Indexed popup target ${targetId} (URL: ${url})`);
|
|
660
680
|
}
|
|
@@ -662,6 +682,17 @@ class CDPClient {
|
|
|
662
682
|
catch {
|
|
663
683
|
// Target may have already closed — expected race, not an error.
|
|
664
684
|
}
|
|
685
|
+
}, (_err, args) => {
|
|
686
|
+
const target = args[0];
|
|
687
|
+
const targetId = (0, puppeteer_helpers_1.getTargetId)(target);
|
|
688
|
+
if (!targetId)
|
|
689
|
+
return;
|
|
690
|
+
Promise.resolve().then(() => __importStar(require('../session-manager'))).then(({ getSessionManager }) => {
|
|
691
|
+
getSessionManager().evictTarget(targetId, 'listener_error');
|
|
692
|
+
})
|
|
693
|
+
.catch(() => {
|
|
694
|
+
// best-effort cleanup only
|
|
695
|
+
});
|
|
665
696
|
}));
|
|
666
697
|
this.connectionState = 'connected';
|
|
667
698
|
this.emitConnectionEvent({
|
|
@@ -757,6 +788,7 @@ class CDPClient {
|
|
|
757
788
|
try {
|
|
758
789
|
this.browser.removeAllListeners('disconnected');
|
|
759
790
|
this.browser.removeAllListeners('targetdestroyed');
|
|
791
|
+
this.browser.removeAllListeners('targetchanged');
|
|
760
792
|
this.browser.removeAllListeners('targetcreated');
|
|
761
793
|
await this.browser.disconnect();
|
|
762
794
|
}
|
|
@@ -766,7 +798,9 @@ class CDPClient {
|
|
|
766
798
|
this.browser = null;
|
|
767
799
|
this.sessions.clear();
|
|
768
800
|
this.targetIdIndex.clear();
|
|
801
|
+
this.targetActivityAt.clear();
|
|
769
802
|
this.inFlightCookieScans.clear();
|
|
803
|
+
this.lastCookieScanResult = null;
|
|
770
804
|
}
|
|
771
805
|
if (this.disconnectRequested) {
|
|
772
806
|
return;
|
|
@@ -846,6 +880,7 @@ class CDPClient {
|
|
|
846
880
|
try {
|
|
847
881
|
this.browser.removeAllListeners('disconnected');
|
|
848
882
|
this.browser.removeAllListeners('targetdestroyed');
|
|
883
|
+
this.browser.removeAllListeners('targetchanged');
|
|
849
884
|
this.browser.removeAllListeners('targetcreated');
|
|
850
885
|
await this.browser.disconnect();
|
|
851
886
|
}
|
|
@@ -950,13 +985,21 @@ class CDPClient {
|
|
|
950
985
|
*
|
|
951
986
|
* @param targetDomain Optional domain to prioritize when selecting cookie source
|
|
952
987
|
*/
|
|
953
|
-
async
|
|
988
|
+
async findAuthenticatedPageTarget(targetDomain) {
|
|
954
989
|
// Check cache first (stale targetId is handled gracefully: copyCookiesViaCDP returns 0)
|
|
955
990
|
const cacheKey = targetDomain || '*';
|
|
956
991
|
const cached = this.cookieSourceCache.get(cacheKey);
|
|
957
992
|
if (cached && Date.now() - cached.timestamp < CDPClient.COOKIE_CACHE_TTL) {
|
|
958
993
|
console.error(`[CDPClient] Cache hit for cookie source (domain: ${cacheKey}): ${cached.targetId.slice(0, 8)}`);
|
|
959
|
-
|
|
994
|
+
const result = {
|
|
995
|
+
status: 'complete',
|
|
996
|
+
targetId: cached.targetId,
|
|
997
|
+
scanned: 0,
|
|
998
|
+
total: 0,
|
|
999
|
+
elapsedMs: 0,
|
|
1000
|
+
};
|
|
1001
|
+
this.lastCookieScanResult = result;
|
|
1002
|
+
return result;
|
|
960
1003
|
}
|
|
961
1004
|
// Promise coalescing: if a scan for this domain is already in-flight, reuse it
|
|
962
1005
|
const existing = this.inFlightCookieScans.get(cacheKey);
|
|
@@ -965,7 +1008,7 @@ class CDPClient {
|
|
|
965
1008
|
return existing;
|
|
966
1009
|
}
|
|
967
1010
|
// Start the scan and register it so concurrent callers share this promise
|
|
968
|
-
const scanPromise = this.
|
|
1011
|
+
const scanPromise = this._doFindAuthenticatedPageTarget(targetDomain, cacheKey);
|
|
969
1012
|
this.inFlightCookieScans.set(cacheKey, scanPromise);
|
|
970
1013
|
try {
|
|
971
1014
|
return await scanPromise;
|
|
@@ -974,31 +1017,44 @@ class CDPClient {
|
|
|
974
1017
|
this.inFlightCookieScans.delete(cacheKey);
|
|
975
1018
|
}
|
|
976
1019
|
}
|
|
1020
|
+
async findAuthenticatedPageTargetId(targetDomain) {
|
|
1021
|
+
const result = await this.findAuthenticatedPageTarget(targetDomain);
|
|
1022
|
+
return result.targetId;
|
|
1023
|
+
}
|
|
977
1024
|
/**
|
|
978
1025
|
* Internal implementation of the authenticated-page probe.
|
|
979
1026
|
* Uses Target.attachToTarget (multiplexed CDP) instead of raw WebSocket connections.
|
|
980
1027
|
* Uses Target.getTargets result directly instead of /json/list HTTP calls.
|
|
981
1028
|
*/
|
|
982
|
-
async
|
|
1029
|
+
async _doFindAuthenticatedPageTarget(targetDomain, cacheKey) {
|
|
983
1030
|
const scanStart = Date.now();
|
|
984
1031
|
const browser = this.getBrowser();
|
|
985
1032
|
const session = await browser.target().createCDPSession();
|
|
986
1033
|
let targetsScanned = 0;
|
|
987
|
-
const
|
|
988
|
-
|
|
1034
|
+
const buildResult = (status, totalCandidates, targetId, warning) => ({
|
|
1035
|
+
status,
|
|
1036
|
+
targetId,
|
|
1037
|
+
scanned: targetsScanned,
|
|
1038
|
+
total: totalCandidates,
|
|
1039
|
+
elapsedMs: Date.now() - scanStart,
|
|
1040
|
+
warning,
|
|
1041
|
+
});
|
|
1042
|
+
const recordOutcome = (result) => {
|
|
1043
|
+
this.lastCookieScanResult = result;
|
|
1044
|
+
const durationSec = result.elapsedMs / 1000;
|
|
989
1045
|
try {
|
|
990
1046
|
const m = (0, collector_1.getMetricsCollector)();
|
|
991
|
-
m.inc('openchrome_cookie_scan_total', { status:
|
|
992
|
-
m.observe('openchrome_cookie_scan_duration_seconds', { status:
|
|
993
|
-
m.observe('openchrome_cookie_scan_targets_scanned', { status:
|
|
1047
|
+
m.inc('openchrome_cookie_scan_total', { status: result.status });
|
|
1048
|
+
m.observe('openchrome_cookie_scan_duration_seconds', { status: result.status }, durationSec);
|
|
1049
|
+
m.observe('openchrome_cookie_scan_targets_scanned', { status: result.status }, targetsScanned);
|
|
994
1050
|
}
|
|
995
1051
|
catch {
|
|
996
1052
|
// Metrics collector unavailable — scan behavior must not depend on it.
|
|
997
1053
|
}
|
|
998
|
-
if (
|
|
999
|
-
console.error(`[CDPClient] Cookie scan partial: scanned ${targetsScanned}/${
|
|
1054
|
+
if (result.status === 'partial' && !result.targetId) {
|
|
1055
|
+
console.error(`[CDPClient] Cookie scan partial: scanned ${targetsScanned}/${result.total} targets ` +
|
|
1000
1056
|
`in ${(durationSec * 1000).toFixed(0)}ms before ${defaults_1.DEFAULT_COOKIE_SCAN_TIMEOUT_MS}ms timeout — ` +
|
|
1001
|
-
`no authenticated tab matched among scanned targets; remaining ${
|
|
1057
|
+
`no authenticated tab matched among scanned targets; remaining ${result.total - targetsScanned} were skipped.`);
|
|
1002
1058
|
}
|
|
1003
1059
|
};
|
|
1004
1060
|
try {
|
|
@@ -1013,8 +1069,9 @@ class CDPClient {
|
|
|
1013
1069
|
!target.url.includes('/auth'));
|
|
1014
1070
|
if (candidates.length === 0) {
|
|
1015
1071
|
console.error('[CDPClient] No candidate pages found for cookie source');
|
|
1016
|
-
|
|
1017
|
-
|
|
1072
|
+
const result = buildResult('no_candidates', 0, null);
|
|
1073
|
+
recordOutcome(result);
|
|
1074
|
+
return result;
|
|
1018
1075
|
}
|
|
1019
1076
|
// If targeting an external domain (not localhost), exclude localhost pages
|
|
1020
1077
|
if (targetDomain && !this.isLocalhost(`https://${targetDomain}`)) {
|
|
@@ -1024,14 +1081,23 @@ class CDPClient {
|
|
|
1024
1081
|
candidates = externalCandidates;
|
|
1025
1082
|
}
|
|
1026
1083
|
}
|
|
1027
|
-
// Sort candidates by domain match score
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1084
|
+
// Sort candidates by domain match score first, then by best-known recent
|
|
1085
|
+
// activity. This makes actively-used OpenChrome pages win ties while still
|
|
1086
|
+
// prioritizing explicit domain affinity for cookie restoration.
|
|
1087
|
+
candidates.sort((a, b) => {
|
|
1088
|
+
const scoreA = targetDomain ? this.domainMatchScore(a.url, targetDomain) : 0;
|
|
1089
|
+
const scoreB = targetDomain ? this.domainMatchScore(b.url, targetDomain) : 0;
|
|
1090
|
+
if (scoreA !== scoreB)
|
|
1032
1091
|
return scoreB - scoreA;
|
|
1033
|
-
|
|
1034
|
-
|
|
1092
|
+
const activityA = this.targetActivityAt.get(a.targetId) ?? 0;
|
|
1093
|
+
const activityB = this.targetActivityAt.get(b.targetId) ?? 0;
|
|
1094
|
+
return activityB - activityA;
|
|
1095
|
+
});
|
|
1096
|
+
if (targetDomain) {
|
|
1097
|
+
console.error(`[CDPClient] Sorted ${candidates.length} candidates by domain match and recent activity for ${targetDomain}`);
|
|
1098
|
+
}
|
|
1099
|
+
else {
|
|
1100
|
+
console.error(`[CDPClient] Sorted ${candidates.length} candidates by recent activity`);
|
|
1035
1101
|
}
|
|
1036
1102
|
// Limit candidates to prevent N×30s cascading timeouts in parallel sessions.
|
|
1037
1103
|
// Best-match candidates are already sorted first, so truncating is safe.
|
|
@@ -1046,8 +1112,11 @@ class CDPClient {
|
|
|
1046
1112
|
// Check overall scan timeout to prevent cascading hangs
|
|
1047
1113
|
if (Date.now() - scanStart > defaults_1.DEFAULT_COOKIE_SCAN_TIMEOUT_MS) {
|
|
1048
1114
|
console.error(`[CDPClient] Cookie scan timed out after ${Date.now() - scanStart}ms`);
|
|
1049
|
-
|
|
1050
|
-
|
|
1115
|
+
const warning = `Cookie scan timed out after scanning ${targetsScanned}/${candidates.length} targets; ` +
|
|
1116
|
+
`a matching authenticated page may still exist in the skipped remainder.`;
|
|
1117
|
+
const result = buildResult('partial', candidates.length, null, warning);
|
|
1118
|
+
recordOutcome(result);
|
|
1119
|
+
return result;
|
|
1051
1120
|
}
|
|
1052
1121
|
targetsScanned += 1;
|
|
1053
1122
|
let attachedSessionId = null;
|
|
@@ -1077,8 +1146,11 @@ class CDPClient {
|
|
|
1077
1146
|
const domainScore = targetDomain ? this.domainMatchScore(candidate.url, targetDomain) : 0;
|
|
1078
1147
|
console.error(`[CDPClient] Found authenticated page ${candidate.targetId.slice(0, 8)} at ${candidate.url.slice(0, 50)} (${cookieCount} cookies, domain score: ${domainScore})`);
|
|
1079
1148
|
this.cookieSourceCache.set(cacheKey, { targetId: candidate.targetId, timestamp: Date.now() });
|
|
1080
|
-
|
|
1081
|
-
|
|
1149
|
+
this.touchTargetActivity(candidate.targetId);
|
|
1150
|
+
const status = targetsScanned < candidates.length ? 'partial' : 'complete';
|
|
1151
|
+
const resultSummary = buildResult(status, candidates.length, candidate.targetId);
|
|
1152
|
+
recordOutcome(resultSummary);
|
|
1153
|
+
return resultSummary;
|
|
1082
1154
|
}
|
|
1083
1155
|
}
|
|
1084
1156
|
catch {
|
|
@@ -1091,8 +1163,9 @@ class CDPClient {
|
|
|
1091
1163
|
}
|
|
1092
1164
|
}
|
|
1093
1165
|
console.error('[CDPClient] No pages with cookies found');
|
|
1094
|
-
|
|
1095
|
-
|
|
1166
|
+
const result = buildResult('no_cookies', candidates.length, null);
|
|
1167
|
+
recordOutcome(result);
|
|
1168
|
+
return result;
|
|
1096
1169
|
}
|
|
1097
1170
|
finally {
|
|
1098
1171
|
await session.detach().catch(() => { });
|
|
@@ -1245,10 +1318,13 @@ class CDPClient {
|
|
|
1245
1318
|
// The global skipCookieBridge flag serves as a manual override escape hatch.
|
|
1246
1319
|
// Overall timeout prevents cascading hangs from unresponsive source tabs.
|
|
1247
1320
|
if (!skipCookieBridge && !(0, global_1.getGlobalConfig)().skipCookieBridge) {
|
|
1248
|
-
const
|
|
1249
|
-
if (
|
|
1321
|
+
const cookieScan = await this.findAuthenticatedPageTarget(targetDomain);
|
|
1322
|
+
if (cookieScan.status === 'partial' && !cookieScan.targetId) {
|
|
1323
|
+
console.error(`[CDPClient] Cookie bridge proceeding without copied cookies: ${cookieScan.warning ?? 'cookie scan incomplete'}`);
|
|
1324
|
+
}
|
|
1325
|
+
if (cookieScan.targetId) {
|
|
1250
1326
|
await Promise.race([
|
|
1251
|
-
this.copyCookiesViaCDP(
|
|
1327
|
+
this.copyCookiesViaCDP(cookieScan.targetId, page),
|
|
1252
1328
|
new Promise((resolve) => setTimeout(() => {
|
|
1253
1329
|
console.error(`[CDPClient] Cookie copy timed out after ${defaults_1.DEFAULT_COOKIE_COPY_TIMEOUT_MS}ms, proceeding without cookies`);
|
|
1254
1330
|
resolve();
|
|
@@ -1258,7 +1334,11 @@ class CDPClient {
|
|
|
1258
1334
|
}
|
|
1259
1335
|
}
|
|
1260
1336
|
// Index page for O(1) target-to-page lookups (replaces eager targetcreated indexing)
|
|
1261
|
-
|
|
1337
|
+
{
|
|
1338
|
+
const pageTargetId = (0, puppeteer_helpers_1.getTargetId)(page.target());
|
|
1339
|
+
this.targetIdIndex.set(pageTargetId, page);
|
|
1340
|
+
this.touchTargetActivity(pageTargetId);
|
|
1341
|
+
}
|
|
1262
1342
|
this.configurePageDefenses(page);
|
|
1263
1343
|
// Set default viewport for consistent debugging experience (non-critical; swallow timeout)
|
|
1264
1344
|
await Promise.race([
|
|
@@ -1362,6 +1442,7 @@ class CDPClient {
|
|
|
1362
1442
|
// evaluateOnNewDocument scripts persist on the CDP session and execute at
|
|
1363
1443
|
// document_start of every new document — before any <script> tag on the page.
|
|
1364
1444
|
this.targetIdIndex.set(targetId, page);
|
|
1445
|
+
this.touchTargetActivity(targetId);
|
|
1365
1446
|
this.configurePageDefenses(page);
|
|
1366
1447
|
// Stealth-only fingerprint defenses (WebGL, Canvas, Audio, hardware, screen, webdriver)
|
|
1367
1448
|
const fpScript = (0, fingerprint_defense_1.getStealthFingerprintDefenseScript)();
|
|
@@ -1679,6 +1760,7 @@ class CDPClient {
|
|
|
1679
1760
|
if (!page.isClosed()) {
|
|
1680
1761
|
const targetId = (0, puppeteer_helpers_1.getTargetId)(page.target());
|
|
1681
1762
|
newIndex.set(targetId, page);
|
|
1763
|
+
this.touchTargetActivity(targetId);
|
|
1682
1764
|
indexed++;
|
|
1683
1765
|
}
|
|
1684
1766
|
}
|
|
@@ -1696,6 +1778,7 @@ class CDPClient {
|
|
|
1696
1778
|
// Fast path: check index first (O(1))
|
|
1697
1779
|
const indexed = this.targetIdIndex.get(targetId);
|
|
1698
1780
|
if (indexed && !indexed.isClosed()) {
|
|
1781
|
+
this.touchTargetActivity(targetId);
|
|
1699
1782
|
return indexed;
|
|
1700
1783
|
}
|
|
1701
1784
|
// Fallback: linear scan (for pages created before indexing started)
|
|
@@ -1710,6 +1793,7 @@ class CDPClient {
|
|
|
1710
1793
|
if (page) {
|
|
1711
1794
|
// Populate index for future lookups
|
|
1712
1795
|
this.targetIdIndex.set(targetId, page);
|
|
1796
|
+
this.touchTargetActivity(targetId);
|
|
1713
1797
|
this.configurePageDefenses(page);
|
|
1714
1798
|
}
|
|
1715
1799
|
return page;
|
|
@@ -1726,9 +1810,11 @@ class CDPClient {
|
|
|
1726
1810
|
*/
|
|
1727
1811
|
indexExternalPage(targetId, page) {
|
|
1728
1812
|
this.targetIdIndex.set(targetId, page);
|
|
1813
|
+
this.touchTargetActivity(targetId);
|
|
1729
1814
|
this.configurePageDefenses(page);
|
|
1730
1815
|
page.once('close', () => {
|
|
1731
1816
|
this.targetIdIndex.delete(targetId);
|
|
1817
|
+
this.targetActivityAt.delete(targetId);
|
|
1732
1818
|
// sessions and cookie cache cleanup handled by onTargetDestroyed via browser targetdestroyed event
|
|
1733
1819
|
});
|
|
1734
1820
|
}
|