camofox-browser 2.4.6 → 2.4.8
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/CHANGELOG.md +37 -0
- package/README.md +29 -6
- package/THIRD-PARTY-NOTICES.md +49 -0
- package/dist/src/cli/server/manager.d.ts.map +1 -1
- package/dist/src/cli/server/manager.js +1 -4
- package/dist/src/cli/server/manager.js.map +1 -1
- package/dist/src/routes/core.d.ts.map +1 -1
- package/dist/src/routes/core.js +46 -1
- package/dist/src/routes/core.js.map +1 -1
- package/dist/src/routes/openclaw.d.ts.map +1 -1
- package/dist/src/routes/openclaw.js +35 -1
- package/dist/src/routes/openclaw.js.map +1 -1
- package/dist/src/services/context-pool.d.ts +42 -2
- package/dist/src/services/context-pool.d.ts.map +1 -1
- package/dist/src/services/context-pool.js +408 -115
- package/dist/src/services/context-pool.js.map +1 -1
- package/dist/src/services/health.d.ts +57 -6
- package/dist/src/services/health.d.ts.map +1 -1
- package/dist/src/services/health.js +132 -11
- package/dist/src/services/health.js.map +1 -1
- package/dist/src/services/nav-recovery.d.ts +23 -0
- package/dist/src/services/nav-recovery.d.ts.map +1 -0
- package/dist/src/services/nav-recovery.js +63 -0
- package/dist/src/services/nav-recovery.js.map +1 -0
- package/dist/src/services/session.d.ts +84 -0
- package/dist/src/services/session.d.ts.map +1 -1
- package/dist/src/services/session.js +338 -35
- package/dist/src/services/session.js.map +1 -1
- package/dist/src/services/tab.d.ts +5 -1
- package/dist/src/services/tab.d.ts.map +1 -1
- package/dist/src/services/tab.js +133 -54
- package/dist/src/services/tab.js.map +1 -1
- package/dist/src/services/tracing.js +2 -2
- package/dist/src/services/tracing.js.map +1 -1
- package/dist/src/services/vnc.d.ts.map +1 -1
- package/dist/src/services/vnc.js +2 -0
- package/dist/src/services/vnc.js.map +1 -1
- package/dist/src/types.d.ts +2 -0
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/utils/config.d.ts +3 -0
- package/dist/src/utils/config.d.ts.map +1 -1
- package/dist/src/utils/config.js +3 -0
- package/dist/src/utils/config.js.map +1 -1
- package/dist/src/utils/launcher.js +1 -1
- package/dist/src/utils/launcher.js.map +1 -1
- package/dist/src/utils/platform-support.d.ts +17 -0
- package/dist/src/utils/platform-support.d.ts.map +1 -0
- package/dist/src/utils/platform-support.js +57 -0
- package/dist/src/utils/platform-support.js.map +1 -0
- package/dist/src/utils/profile-path.d.ts +9 -0
- package/dist/src/utils/profile-path.d.ts.map +1 -0
- package/dist/src/utils/profile-path.js +105 -0
- package/dist/src/utils/profile-path.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +11 -4
- package/dist/src/cli/utils/api-fallback.d.ts +0 -4
- package/dist/src/cli/utils/api-fallback.d.ts.map +0 -1
- package/dist/src/cli/utils/api-fallback.js +0 -20
- package/dist/src/cli/utils/api-fallback.js.map +0 -1
|
@@ -20,7 +20,11 @@ export interface ValidateUrlOptions {
|
|
|
20
20
|
}
|
|
21
21
|
export declare function throwBlockedNavigationErrorIfPresent(page: Page): void;
|
|
22
22
|
export declare function flushBlockedNavigationError(page: Page): Promise<void>;
|
|
23
|
-
export
|
|
23
|
+
export interface BlockedNavigationTrackingOptions {
|
|
24
|
+
/** Yield once after actions whose DOM event can enqueue navigation after the action promise resolves. */
|
|
25
|
+
settlePostActionNavigation?: boolean;
|
|
26
|
+
}
|
|
27
|
+
export declare function withBlockedNavigationTracking<T>(page: Page, action: () => Promise<T>, options?: BlockedNavigationTrackingOptions): Promise<T>;
|
|
24
28
|
export declare function validateUrl(url: string, options?: ValidateUrlOptions): string | null;
|
|
25
29
|
export declare function validateNavigationUrl(url: string, options?: ValidateUrlOptions): Promise<string | null>;
|
|
26
30
|
export declare function navigateWithSafetyGuard(page: Pick<Page, 'goto' | 'route' | 'unroute' | 'mainFrame'>, targetUrl: string, options?: ValidateUrlOptions & {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tab.d.ts","sourceRoot":"","sources":["../../../src/services/tab.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAMrE,OAAO,KAAK,EAEX,cAAc,EAEd,OAAO,EACP,cAAc,EACd,QAAQ,EACR,uBAAuB,EACvB,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"tab.d.ts","sourceRoot":"","sources":["../../../src/services/tab.ts"],"names":[],"mappings":"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"}
|
package/dist/src/services/tab.js
CHANGED
|
@@ -82,7 +82,12 @@ const DEFAULT_EVAL_EXTENDED_TIMEOUT = 30000;
|
|
|
82
82
|
const MAX_RESULT_SIZE = 1048576; // 1MB
|
|
83
83
|
const CONSOLE_BUFFER_SIZE = CONFIG.consoleBufferSize;
|
|
84
84
|
const POST_ACTION_NAVIGATION_SETTLE_MS = 500;
|
|
85
|
+
const POST_ACTION_NAVIGATION_DRAIN_TIMEOUT_MS = POST_ACTION_NAVIGATION_SETTLE_MS;
|
|
85
86
|
const ACTION_TRACKER_POLL_MS = 10;
|
|
87
|
+
// Perpetual timers or animation frames must not hold the tab lock forever.
|
|
88
|
+
// Only background-work settling is best effort; unresolved navigation guards
|
|
89
|
+
// must fail closed when this budget expires.
|
|
90
|
+
const ACTION_TRACKER_DRAIN_TIMEOUT_MS = 3000;
|
|
86
91
|
const navigationGuardHandlers = new WeakMap();
|
|
87
92
|
const blockedNavigationErrors = new WeakMap();
|
|
88
93
|
const trackedBlockedNavigationErrors = new WeakMap();
|
|
@@ -376,49 +381,50 @@ function installActionTrackerScript() {
|
|
|
376
381
|
const originalQueueMicrotask = typeof browserGlobal.queueMicrotask === 'function'
|
|
377
382
|
? browserGlobal.queueMicrotask.bind(browserGlobal)
|
|
378
383
|
: null;
|
|
384
|
+
// Wrap tokenless callbacks too, so background work restores token 0 while a
|
|
385
|
+
// tracked action is in its bounded post-action attribution window.
|
|
379
386
|
browserGlobal.setTimeout = (handler, delay, ...args) => {
|
|
380
387
|
const token = state.activeToken;
|
|
381
|
-
if (!token) {
|
|
382
|
-
return originalSetTimeout(handler, delay, ...args);
|
|
383
|
-
}
|
|
384
|
-
increment(token);
|
|
385
388
|
let timeoutId;
|
|
386
389
|
const wrapped = (...callbackArgs) => {
|
|
387
|
-
const trackedToken = state.timeoutTokens.get(timeoutId)
|
|
390
|
+
const trackedToken = state.timeoutTokens.get(timeoutId) ?? token;
|
|
388
391
|
state.timeoutTokens.delete(timeoutId);
|
|
389
392
|
try {
|
|
390
393
|
return withToken(trackedToken, () => runHandler(handler, callbackArgs));
|
|
391
394
|
}
|
|
392
395
|
finally {
|
|
393
|
-
|
|
396
|
+
if (trackedToken > 0)
|
|
397
|
+
decrement(trackedToken);
|
|
394
398
|
}
|
|
395
399
|
};
|
|
396
400
|
timeoutId = originalSetTimeout(wrapped, delay, ...args);
|
|
401
|
+
if (token > 0)
|
|
402
|
+
increment(token);
|
|
397
403
|
state.timeoutTokens.set(timeoutId, token);
|
|
398
404
|
return timeoutId;
|
|
399
405
|
};
|
|
400
406
|
browserGlobal.clearTimeout = (timeoutId) => {
|
|
401
407
|
const token = state.timeoutTokens.get(timeoutId);
|
|
402
|
-
if (token) {
|
|
408
|
+
if (token !== undefined) {
|
|
403
409
|
state.timeoutTokens.delete(timeoutId);
|
|
404
|
-
|
|
410
|
+
if (token > 0)
|
|
411
|
+
decrement(token);
|
|
405
412
|
}
|
|
406
413
|
return originalClearTimeout(timeoutId);
|
|
407
414
|
};
|
|
408
415
|
browserGlobal.setInterval = (handler, delay, ...args) => {
|
|
409
416
|
const token = state.activeToken;
|
|
410
|
-
if (!token) {
|
|
411
|
-
return originalSetInterval(handler, delay, ...args);
|
|
412
|
-
}
|
|
413
417
|
let intervalId;
|
|
414
418
|
const wrapped = (...callbackArgs) => {
|
|
415
|
-
const trackedToken = state.intervalTokens.get(intervalId)
|
|
416
|
-
|
|
419
|
+
const trackedToken = state.intervalTokens.get(intervalId) ?? token;
|
|
420
|
+
if (trackedToken > 0)
|
|
421
|
+
increment(trackedToken);
|
|
417
422
|
try {
|
|
418
423
|
return withToken(trackedToken, () => runHandler(handler, callbackArgs));
|
|
419
424
|
}
|
|
420
425
|
finally {
|
|
421
|
-
|
|
426
|
+
if (trackedToken > 0)
|
|
427
|
+
decrement(trackedToken);
|
|
422
428
|
}
|
|
423
429
|
};
|
|
424
430
|
intervalId = originalSetInterval(wrapped, delay, ...args);
|
|
@@ -432,19 +438,18 @@ function installActionTrackerScript() {
|
|
|
432
438
|
if (originalRequestAnimationFrame && originalCancelAnimationFrame) {
|
|
433
439
|
browserGlobal.requestAnimationFrame = (callback) => {
|
|
434
440
|
const token = state.activeToken;
|
|
435
|
-
if (
|
|
436
|
-
|
|
437
|
-
}
|
|
438
|
-
increment(token);
|
|
441
|
+
if (token > 0)
|
|
442
|
+
increment(token);
|
|
439
443
|
let rafId = 0;
|
|
440
444
|
const wrapped = (timestamp) => {
|
|
441
|
-
const trackedToken = state.rafTokens.get(rafId)
|
|
445
|
+
const trackedToken = state.rafTokens.get(rafId) ?? token;
|
|
442
446
|
state.rafTokens.delete(rafId);
|
|
443
447
|
try {
|
|
444
448
|
return withToken(trackedToken, () => callback(timestamp));
|
|
445
449
|
}
|
|
446
450
|
finally {
|
|
447
|
-
|
|
451
|
+
if (trackedToken > 0)
|
|
452
|
+
decrement(trackedToken);
|
|
448
453
|
}
|
|
449
454
|
};
|
|
450
455
|
rafId = originalRequestAnimationFrame(wrapped);
|
|
@@ -453,9 +458,10 @@ function installActionTrackerScript() {
|
|
|
453
458
|
};
|
|
454
459
|
browserGlobal.cancelAnimationFrame = (rafId) => {
|
|
455
460
|
const token = state.rafTokens.get(rafId);
|
|
456
|
-
if (token) {
|
|
461
|
+
if (token !== undefined) {
|
|
457
462
|
state.rafTokens.delete(rafId);
|
|
458
|
-
|
|
463
|
+
if (token > 0)
|
|
464
|
+
decrement(token);
|
|
459
465
|
}
|
|
460
466
|
return originalCancelAnimationFrame(rafId);
|
|
461
467
|
};
|
|
@@ -463,16 +469,15 @@ function installActionTrackerScript() {
|
|
|
463
469
|
if (originalQueueMicrotask) {
|
|
464
470
|
browserGlobal.queueMicrotask = (callback) => {
|
|
465
471
|
const token = state.activeToken;
|
|
466
|
-
if (
|
|
467
|
-
|
|
468
|
-
}
|
|
469
|
-
increment(token);
|
|
472
|
+
if (token > 0)
|
|
473
|
+
increment(token);
|
|
470
474
|
return originalQueueMicrotask(() => {
|
|
471
475
|
try {
|
|
472
476
|
return withToken(token, callback);
|
|
473
477
|
}
|
|
474
478
|
finally {
|
|
475
|
-
|
|
479
|
+
if (token > 0)
|
|
480
|
+
decrement(token);
|
|
476
481
|
}
|
|
477
482
|
});
|
|
478
483
|
};
|
|
@@ -590,8 +595,8 @@ async function getCurrentTrackedActionToken(page) {
|
|
|
590
595
|
const token = await page.evaluate(() => {
|
|
591
596
|
return globalThis.__camofoxActionTracker?.getActiveToken?.() || 0;
|
|
592
597
|
});
|
|
593
|
-
if (typeof token === 'number'
|
|
594
|
-
return token;
|
|
598
|
+
if (typeof token === 'number') {
|
|
599
|
+
return token > 0 ? token : null;
|
|
595
600
|
}
|
|
596
601
|
return activeTrackedActionTokens.get(page) || null;
|
|
597
602
|
}
|
|
@@ -611,6 +616,9 @@ function decrementInFlightGuardCheck(page) {
|
|
|
611
616
|
inFlightGuardChecks.delete(page);
|
|
612
617
|
}
|
|
613
618
|
}
|
|
619
|
+
function getInFlightGuardCheckCount(page) {
|
|
620
|
+
return inFlightGuardChecks.get(page) || 0;
|
|
621
|
+
}
|
|
614
622
|
function incrementTrackedInFlightGuardCheck(page, token) {
|
|
615
623
|
const existing = trackedInFlightGuardChecks.get(page) || new Map();
|
|
616
624
|
existing.set(token, (existing.get(token) || 0) + 1);
|
|
@@ -634,13 +642,56 @@ function decrementTrackedInFlightGuardCheck(page, token) {
|
|
|
634
642
|
function getTrackedInFlightGuardCheckCount(page, token) {
|
|
635
643
|
return trackedInFlightGuardChecks.get(page)?.get(token) || 0;
|
|
636
644
|
}
|
|
645
|
+
async function waitForPostActionNavigationSettle(page) {
|
|
646
|
+
if (typeof page.waitForTimeout === 'function') {
|
|
647
|
+
await page.waitForTimeout(POST_ACTION_NAVIGATION_SETTLE_MS);
|
|
648
|
+
return;
|
|
649
|
+
}
|
|
650
|
+
await new Promise((resolve) => setTimeout(resolve, POST_ACTION_NAVIGATION_SETTLE_MS));
|
|
651
|
+
}
|
|
652
|
+
function createPostActionNavigationTimeoutError() {
|
|
653
|
+
return createNavigationBlockError('Blocked navigation guard did not settle before the action completed');
|
|
654
|
+
}
|
|
655
|
+
async function withPostActionNavigationDeadline(promise, deadline) {
|
|
656
|
+
const remainingMs = deadline - Date.now();
|
|
657
|
+
if (remainingMs <= 0)
|
|
658
|
+
throw createPostActionNavigationTimeoutError();
|
|
659
|
+
try {
|
|
660
|
+
return await withTimeout(promise, remainingMs, 'post-action navigation tracking');
|
|
661
|
+
}
|
|
662
|
+
catch {
|
|
663
|
+
throw createPostActionNavigationTimeoutError();
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
async function drainPostActionNavigation(page, actionToken) {
|
|
667
|
+
// Keep the action token active for the full settle window. DOM event
|
|
668
|
+
// handlers can enqueue navigation after the Playwright action promise has
|
|
669
|
+
// resolved, especially on slower Windows runners. A single event-loop yield
|
|
670
|
+
// can finish tracking before that navigation is attributed to this action.
|
|
671
|
+
await waitForPostActionNavigationSettle(page);
|
|
672
|
+
const deadline = Date.now() + POST_ACTION_NAVIGATION_DRAIN_TIMEOUT_MS;
|
|
673
|
+
while (true) {
|
|
674
|
+
throwTrackedBlockedNavigationErrorIfPresent(page, actionToken);
|
|
675
|
+
const pendingCount = await withPostActionNavigationDeadline(getTrackedPendingCount(page, actionToken), deadline);
|
|
676
|
+
const inFlightGuardCount = getTrackedInFlightGuardCheckCount(page, actionToken);
|
|
677
|
+
const postActionPendingWork = pendingCount > 0 || inFlightGuardCount > 0 || getInFlightGuardCheckCount(page) > 0;
|
|
678
|
+
if (!postActionPendingWork)
|
|
679
|
+
break;
|
|
680
|
+
await withPostActionNavigationDeadline(new Promise((resolve) => setTimeout(resolve, ACTION_TRACKER_POLL_MS)), deadline);
|
|
681
|
+
}
|
|
682
|
+
throwTrackedBlockedNavigationErrorIfPresent(page, actionToken);
|
|
683
|
+
// A tokenless navigation during the settle turn is background work. It was
|
|
684
|
+
// blocked by the guard, but must not become the select action's response or
|
|
685
|
+
// leak into the next operation.
|
|
686
|
+
clearBlockedNavigationError(page);
|
|
687
|
+
}
|
|
637
688
|
async function flushBlockedNavigationError(page) {
|
|
638
689
|
if (typeof page.waitForTimeout === 'function') {
|
|
639
690
|
await page.waitForTimeout(POST_ACTION_NAVIGATION_SETTLE_MS);
|
|
640
691
|
}
|
|
641
692
|
throwBlockedNavigationErrorIfPresent(page);
|
|
642
693
|
}
|
|
643
|
-
async function withBlockedNavigationTracking(page, action) {
|
|
694
|
+
async function withBlockedNavigationTracking(page, action, options = {}) {
|
|
644
695
|
if (CONFIG.allowPrivateNetworkTargets) {
|
|
645
696
|
return action();
|
|
646
697
|
}
|
|
@@ -663,19 +714,31 @@ async function withBlockedNavigationTracking(page, action) {
|
|
|
663
714
|
return result;
|
|
664
715
|
}
|
|
665
716
|
let sawPendingWork = false;
|
|
717
|
+
const drainDeadline = Date.now() + ACTION_TRACKER_DRAIN_TIMEOUT_MS;
|
|
666
718
|
while (true) {
|
|
667
719
|
throwTrackedBlockedNavigationErrorIfPresent(page, actionToken);
|
|
668
720
|
if (sawPendingWork) {
|
|
669
721
|
throwBlockedNavigationErrorIfPresent(page);
|
|
670
722
|
}
|
|
671
|
-
|
|
723
|
+
if (Date.now() >= drainDeadline) {
|
|
724
|
+
// Include guards still resolving their action token, before they
|
|
725
|
+
// appear in the per-action counter.
|
|
726
|
+
if (getInFlightGuardCheckCount(page) > 0) {
|
|
727
|
+
throw createPostActionNavigationTimeoutError();
|
|
728
|
+
}
|
|
729
|
+
(0, logging_1.log)('warn', 'action drain timed out, proceeding without full settle', {
|
|
730
|
+
timeoutMs: ACTION_TRACKER_DRAIN_TIMEOUT_MS,
|
|
731
|
+
});
|
|
732
|
+
break;
|
|
733
|
+
}
|
|
734
|
+
const pendingCount = await withPostActionNavigationDeadline(getTrackedPendingCount(page, actionToken), drainDeadline);
|
|
672
735
|
const inFlightGuardCount = getTrackedInFlightGuardCheckCount(page, actionToken);
|
|
673
736
|
if (pendingCount === 0 && inFlightGuardCount === 0) {
|
|
674
737
|
if (!sawPendingWork) {
|
|
675
738
|
await new Promise((resolve) => setTimeout(resolve, ACTION_TRACKER_POLL_MS));
|
|
676
739
|
throwTrackedBlockedNavigationErrorIfPresent(page, actionToken);
|
|
677
740
|
throwBlockedNavigationErrorIfPresent(page);
|
|
678
|
-
if ((await getTrackedPendingCount(page, actionToken)) === 0 && getTrackedInFlightGuardCheckCount(page, actionToken) === 0) {
|
|
741
|
+
if ((await withPostActionNavigationDeadline(getTrackedPendingCount(page, actionToken), drainDeadline)) === 0 && getTrackedInFlightGuardCheckCount(page, actionToken) === 0) {
|
|
679
742
|
break;
|
|
680
743
|
}
|
|
681
744
|
sawPendingWork = true;
|
|
@@ -684,7 +747,7 @@ async function withBlockedNavigationTracking(page, action) {
|
|
|
684
747
|
await new Promise((resolve) => setTimeout(resolve, ACTION_TRACKER_POLL_MS));
|
|
685
748
|
throwTrackedBlockedNavigationErrorIfPresent(page, actionToken);
|
|
686
749
|
throwBlockedNavigationErrorIfPresent(page);
|
|
687
|
-
if ((await getTrackedPendingCount(page, actionToken)) === 0 && getTrackedInFlightGuardCheckCount(page, actionToken) === 0)
|
|
750
|
+
if ((await withPostActionNavigationDeadline(getTrackedPendingCount(page, actionToken), drainDeadline)) === 0 && getTrackedInFlightGuardCheckCount(page, actionToken) === 0)
|
|
688
751
|
break;
|
|
689
752
|
}
|
|
690
753
|
else {
|
|
@@ -696,6 +759,14 @@ async function withBlockedNavigationTracking(page, action) {
|
|
|
696
759
|
if (sawPendingWork) {
|
|
697
760
|
throwBlockedNavigationErrorIfPresent(page);
|
|
698
761
|
}
|
|
762
|
+
if (options.settlePostActionNavigation) {
|
|
763
|
+
// Some DOM actions (for example selectOption with a synchronous
|
|
764
|
+
// location.href handler) enqueue navigation after the action promise
|
|
765
|
+
// resolves without creating tracked timer work. Yield once while the
|
|
766
|
+
// action token is still active so the route guard can associate that
|
|
767
|
+
// request with this action before the in-flight drain below.
|
|
768
|
+
await drainPostActionNavigation(page, actionToken);
|
|
769
|
+
}
|
|
699
770
|
await finish();
|
|
700
771
|
return result;
|
|
701
772
|
}
|
|
@@ -1043,33 +1114,41 @@ async function ensureNavigationSafetyGuard(page, options = {}) {
|
|
|
1043
1114
|
const requestPage = requestFrame && typeof requestFrame.page === 'function' ? requestFrame.page() : null;
|
|
1044
1115
|
const relatedPages = new Set();
|
|
1045
1116
|
let trackedToken = null;
|
|
1046
|
-
|
|
1047
|
-
relatedPages.
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1117
|
+
const addRelatedPage = (page) => {
|
|
1118
|
+
if (relatedPages.has(page))
|
|
1119
|
+
return;
|
|
1120
|
+
relatedPages.add(page);
|
|
1121
|
+
// Count the route before resolving the action token. The token lookup
|
|
1122
|
+
// itself is asynchronous and the action wrapper must not finish while
|
|
1123
|
+
// a guard check is still being associated with its page.
|
|
1124
|
+
incrementInFlightGuardCheck(page);
|
|
1125
|
+
};
|
|
1126
|
+
try {
|
|
1127
|
+
if (requestPage) {
|
|
1128
|
+
addRelatedPage(requestPage);
|
|
1129
|
+
trackedToken = await getCurrentTrackedActionToken(requestPage);
|
|
1130
|
+
const mappedOpener = popupOpenerPages.get(requestPage);
|
|
1131
|
+
if (mappedOpener) {
|
|
1132
|
+
addRelatedPage(mappedOpener);
|
|
1060
1133
|
if (trackedToken === null) {
|
|
1061
|
-
trackedToken = await getCurrentTrackedActionToken(
|
|
1134
|
+
trackedToken = await getCurrentTrackedActionToken(mappedOpener);
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
else if (typeof requestPage.opener === 'function') {
|
|
1138
|
+
const openerPage = await requestPage.opener().catch(() => null);
|
|
1139
|
+
if (openerPage) {
|
|
1140
|
+
addRelatedPage(openerPage);
|
|
1141
|
+
if (trackedToken === null) {
|
|
1142
|
+
trackedToken = await getCurrentTrackedActionToken(openerPage);
|
|
1143
|
+
}
|
|
1062
1144
|
}
|
|
1063
1145
|
}
|
|
1064
1146
|
}
|
|
1065
|
-
}
|
|
1066
|
-
for (const relatedPage of relatedPages) {
|
|
1067
|
-
incrementInFlightGuardCheck(relatedPage);
|
|
1068
1147
|
if (trackedToken !== null) {
|
|
1069
|
-
|
|
1148
|
+
for (const relatedPage of relatedPages) {
|
|
1149
|
+
incrementTrackedInFlightGuardCheck(relatedPage, trackedToken);
|
|
1150
|
+
}
|
|
1070
1151
|
}
|
|
1071
|
-
}
|
|
1072
|
-
try {
|
|
1073
1152
|
const requestError = await validateNavigationUrl(request.url(), { allowPrivateNetworkTargets: false });
|
|
1074
1153
|
if (requestError) {
|
|
1075
1154
|
for (const relatedPage of relatedPages) {
|