@browserbasehq/orca 3.6.0-gemini-cua → 3.7.0-preview.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/cjs/lib/v3/agent/AgentClient.d.ts +2 -2
- package/dist/cjs/lib/v3/agent/AgentClient.js.map +1 -1
- package/dist/cjs/lib/v3/agent/AnthropicCUAClient.d.ts +4 -3
- package/dist/cjs/lib/v3/agent/AnthropicCUAClient.js +11 -9
- package/dist/cjs/lib/v3/agent/AnthropicCUAClient.js.map +1 -1
- package/dist/cjs/lib/v3/agent/GoogleCUAClient.d.ts +12 -3
- package/dist/cjs/lib/v3/agent/GoogleCUAClient.js +107 -22
- package/dist/cjs/lib/v3/agent/GoogleCUAClient.js.map +1 -1
- package/dist/cjs/lib/v3/agent/MicrosoftCUAClient.d.ts +2 -2
- package/dist/cjs/lib/v3/agent/MicrosoftCUAClient.js +2 -2
- package/dist/cjs/lib/v3/agent/MicrosoftCUAClient.js.map +1 -1
- package/dist/cjs/lib/v3/agent/OpenAICUAClient.d.ts +6 -3
- package/dist/cjs/lib/v3/agent/OpenAICUAClient.js +13 -7
- package/dist/cjs/lib/v3/agent/OpenAICUAClient.js.map +1 -1
- package/dist/cjs/lib/v3/agent/utils/handleDoneToolCall.d.ts +1 -0
- package/dist/cjs/lib/v3/agent/utils/handleDoneToolCall.js +40 -2
- package/dist/cjs/lib/v3/agent/utils/handleDoneToolCall.js.map +1 -1
- package/dist/cjs/lib/v3/handlers/v3AgentHandler.js +30 -7
- package/dist/cjs/lib/v3/handlers/v3AgentHandler.js.map +1 -1
- package/dist/cjs/lib/v3/handlers/v3CuaAgentHandler.js +32 -18
- package/dist/cjs/lib/v3/handlers/v3CuaAgentHandler.js.map +1 -1
- package/dist/cjs/lib/v3/index.d.ts +1 -0
- package/dist/cjs/lib/v3/llm/LLMProvider.d.ts +2 -2
- package/dist/cjs/lib/v3/llm/LLMProvider.js.map +1 -1
- package/dist/cjs/lib/v3/types/public/agent.d.ts +9 -0
- package/dist/cjs/lib/v3/types/public/agent.js.map +1 -1
- package/dist/cjs/lib/v3/types/public/context.d.ts +7 -0
- package/dist/cjs/lib/v3/types/public/context.js.map +1 -1
- package/dist/cjs/lib/v3/types/public/sdkErrors.d.ts +4 -0
- package/dist/cjs/lib/v3/types/public/sdkErrors.js +9 -1
- package/dist/cjs/lib/v3/types/public/sdkErrors.js.map +1 -1
- package/dist/cjs/lib/v3/understudy/cdp.d.ts +2 -0
- package/dist/cjs/lib/v3/understudy/cdp.js +26 -12
- package/dist/cjs/lib/v3/understudy/cdp.js.map +1 -1
- package/dist/cjs/lib/v3/understudy/context.d.ts +13 -1
- package/dist/cjs/lib/v3/understudy/context.js +284 -1
- package/dist/cjs/lib/v3/understudy/context.js.map +1 -1
- package/dist/cjs/lib/v3/understudy/domainPolicy.d.ts +25 -0
- package/dist/cjs/lib/v3/understudy/domainPolicy.js +162 -0
- package/dist/cjs/lib/v3/understudy/domainPolicy.js.map +1 -0
- package/dist/cjs/lib/v3/v3.js +4 -1
- package/dist/cjs/lib/v3/v3.js.map +1 -1
- package/dist/esm/lib/v3/agent/AgentClient.d.ts +2 -2
- package/dist/esm/lib/v3/agent/AgentClient.js.map +1 -1
- package/dist/esm/lib/v3/agent/AnthropicCUAClient.d.ts +4 -3
- package/dist/esm/lib/v3/agent/AnthropicCUAClient.js +11 -9
- package/dist/esm/lib/v3/agent/AnthropicCUAClient.js.map +1 -1
- package/dist/esm/lib/v3/agent/GoogleCUAClient.d.ts +12 -3
- package/dist/esm/lib/v3/agent/GoogleCUAClient.js +107 -22
- package/dist/esm/lib/v3/agent/GoogleCUAClient.js.map +1 -1
- package/dist/esm/lib/v3/agent/MicrosoftCUAClient.d.ts +2 -2
- package/dist/esm/lib/v3/agent/MicrosoftCUAClient.js +2 -2
- package/dist/esm/lib/v3/agent/MicrosoftCUAClient.js.map +1 -1
- package/dist/esm/lib/v3/agent/OpenAICUAClient.d.ts +6 -3
- package/dist/esm/lib/v3/agent/OpenAICUAClient.js +13 -7
- package/dist/esm/lib/v3/agent/OpenAICUAClient.js.map +1 -1
- package/dist/esm/lib/v3/agent/utils/handleDoneToolCall.d.ts +1 -0
- package/dist/esm/lib/v3/agent/utils/handleDoneToolCall.js +39 -2
- package/dist/esm/lib/v3/agent/utils/handleDoneToolCall.js.map +1 -1
- package/dist/esm/lib/v3/handlers/v3AgentHandler.js +30 -7
- package/dist/esm/lib/v3/handlers/v3AgentHandler.js.map +1 -1
- package/dist/esm/lib/v3/handlers/v3CuaAgentHandler.js +32 -18
- package/dist/esm/lib/v3/handlers/v3CuaAgentHandler.js.map +1 -1
- package/dist/esm/lib/v3/index.d.ts +1 -0
- package/dist/esm/lib/v3/llm/LLMProvider.d.ts +2 -2
- package/dist/esm/lib/v3/llm/LLMProvider.js.map +1 -1
- package/dist/esm/lib/v3/types/public/agent.d.ts +9 -0
- package/dist/esm/lib/v3/types/public/agent.js.map +1 -1
- package/dist/esm/lib/v3/types/public/context.d.ts +7 -0
- package/dist/esm/lib/v3/types/public/context.js.map +1 -1
- package/dist/esm/lib/v3/types/public/sdkErrors.d.ts +4 -0
- package/dist/esm/lib/v3/types/public/sdkErrors.js +7 -0
- package/dist/esm/lib/v3/types/public/sdkErrors.js.map +1 -1
- package/dist/esm/lib/v3/understudy/cdp.d.ts +2 -0
- package/dist/esm/lib/v3/understudy/cdp.js +26 -12
- package/dist/esm/lib/v3/understudy/cdp.js.map +1 -1
- package/dist/esm/lib/v3/understudy/context.d.ts +13 -1
- package/dist/esm/lib/v3/understudy/context.js +285 -2
- package/dist/esm/lib/v3/understudy/context.js.map +1 -1
- package/dist/esm/lib/v3/understudy/domainPolicy.d.ts +25 -0
- package/dist/esm/lib/v3/understudy/domainPolicy.js +158 -0
- package/dist/esm/lib/v3/understudy/domainPolicy.js.map +1 -0
- package/dist/esm/lib/v3/v3.js +4 -1
- package/dist/esm/lib/v3/v3.js.map +1 -1
- package/package.json +3 -3
|
@@ -12,6 +12,11 @@ const clipboard_js_1 = require("./clipboard.js");
|
|
|
12
12
|
const sdkErrors_js_1 = require("../types/public/sdkErrors.js");
|
|
13
13
|
const timeoutConfig_js_1 = require("../timeoutConfig.js");
|
|
14
14
|
const cookies_js_1 = require("./cookies.js");
|
|
15
|
+
const domainPolicy_js_1 = require("./domainPolicy.js");
|
|
16
|
+
function isMissingTargetError(error) {
|
|
17
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
18
|
+
return /No target with given id found/i.test(message);
|
|
19
|
+
}
|
|
15
20
|
/**
|
|
16
21
|
* Returns true when the target's URL points to a document with a real,
|
|
17
22
|
* pierceable HTML DOM. We allowlist the small set of schemes that carry
|
|
@@ -82,6 +87,7 @@ class V3Context {
|
|
|
82
87
|
// Timestamp for most recent popup/open signal
|
|
83
88
|
_lastPopupSignalAt = 0;
|
|
84
89
|
_targetSessionListeners = new Set();
|
|
90
|
+
_domainPolicySessionListeners = new Map();
|
|
85
91
|
_sessionInit = new Set();
|
|
86
92
|
pagesByTarget = new Map();
|
|
87
93
|
mainFrameToTarget = new Map();
|
|
@@ -92,8 +98,17 @@ class V3Context {
|
|
|
92
98
|
typeByTarget = new Map();
|
|
93
99
|
_pageOrder = [];
|
|
94
100
|
pendingCreatedTargetUrl = new Map();
|
|
101
|
+
pageCreationFailures = new Map();
|
|
102
|
+
// Popup close attempts can race targetCreated, targetInfoChanged, and attached.
|
|
103
|
+
// In-flight promises let attach wait for a close result before deciding whether
|
|
104
|
+
// to skip normal setup. Successful closes stay deduped for the context lifetime
|
|
105
|
+
// because Chrome can emit late targetInfoChanged events after targetDestroyed.
|
|
106
|
+
// Failed closes are not retained so attach can continue and future events may retry.
|
|
107
|
+
domainPolicyClosingTargets = new Set();
|
|
108
|
+
domainPolicyClosePromises = new Map();
|
|
95
109
|
initScripts = [];
|
|
96
110
|
extraHttpHeaders = null;
|
|
111
|
+
domainPolicy = null;
|
|
97
112
|
_clipboard;
|
|
98
113
|
installTargetSessionListeners(session) {
|
|
99
114
|
const sessionId = session.id;
|
|
@@ -332,6 +347,120 @@ class V3Context {
|
|
|
332
347
|
throw new sdkErrors_js_1.StagehandSetExtraHTTPHeadersError(failures);
|
|
333
348
|
}
|
|
334
349
|
}
|
|
350
|
+
getDomainPolicy() {
|
|
351
|
+
if (!this.domainPolicy)
|
|
352
|
+
return null;
|
|
353
|
+
return {
|
|
354
|
+
...(this.domainPolicy.allowedDomains.length
|
|
355
|
+
? { allowedDomains: [...this.domainPolicy.allowedDomains] }
|
|
356
|
+
: {}),
|
|
357
|
+
...(this.domainPolicy.blockedDomains.length
|
|
358
|
+
? { blockedDomains: [...this.domainPolicy.blockedDomains] }
|
|
359
|
+
: {}),
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
async setDomainPolicy(policy) {
|
|
363
|
+
const nextPolicy = (0, domainPolicy_js_1.normalizeDomainPolicy)(policy);
|
|
364
|
+
this.domainPolicy = nextPolicy;
|
|
365
|
+
const sessions = [];
|
|
366
|
+
for (const sessionId of this._sessionInit) {
|
|
367
|
+
const session = this.conn.getSession(sessionId);
|
|
368
|
+
if (session)
|
|
369
|
+
sessions.push(session);
|
|
370
|
+
}
|
|
371
|
+
if (!sessions.length)
|
|
372
|
+
return;
|
|
373
|
+
const results = await Promise.allSettled(sessions.map(async (session) => {
|
|
374
|
+
if (!nextPolicy) {
|
|
375
|
+
try {
|
|
376
|
+
await session.send("Fetch.disable");
|
|
377
|
+
this.uninstallDomainPolicyHandler(session);
|
|
378
|
+
}
|
|
379
|
+
catch (error) {
|
|
380
|
+
throw { action: "disable", error };
|
|
381
|
+
}
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
this.installDomainPolicyHandler(session);
|
|
385
|
+
try {
|
|
386
|
+
await session.send("Fetch.enable", {
|
|
387
|
+
patterns: nextPolicy.fetchPatterns,
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
catch (error) {
|
|
391
|
+
throw { action: "enable", error };
|
|
392
|
+
}
|
|
393
|
+
}));
|
|
394
|
+
const failures = results
|
|
395
|
+
.map((result, index) => ({ result, session: sessions[index] }))
|
|
396
|
+
.filter((entry) => entry.result.status === "rejected")
|
|
397
|
+
.map((entry) => {
|
|
398
|
+
const failure = entry.result.reason;
|
|
399
|
+
if (failure?.action === "enable") {
|
|
400
|
+
this.uninstallDomainPolicyHandler(entry.session);
|
|
401
|
+
}
|
|
402
|
+
const reason = failure?.error ?? entry.result.reason;
|
|
403
|
+
const sid = entry.session.id ?? "unknown";
|
|
404
|
+
const message = reason instanceof Error ? reason.message : String(reason);
|
|
405
|
+
return `session=${sid} error=${message}`;
|
|
406
|
+
});
|
|
407
|
+
if (failures.length) {
|
|
408
|
+
throw new sdkErrors_js_1.StagehandSetDomainPolicyError(failures);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
installDomainPolicyHandler(session) {
|
|
412
|
+
const sessionId = session.id;
|
|
413
|
+
if (!sessionId)
|
|
414
|
+
return;
|
|
415
|
+
if (this._domainPolicySessionListeners.has(sessionId))
|
|
416
|
+
return;
|
|
417
|
+
const handler = (evt) => {
|
|
418
|
+
void this.handleDomainPolicyRequestPaused(session, evt);
|
|
419
|
+
};
|
|
420
|
+
this._domainPolicySessionListeners.set(sessionId, handler);
|
|
421
|
+
session.on("Fetch.requestPaused", handler);
|
|
422
|
+
}
|
|
423
|
+
uninstallDomainPolicyHandler(session) {
|
|
424
|
+
const sessionId = session.id;
|
|
425
|
+
if (!sessionId)
|
|
426
|
+
return;
|
|
427
|
+
const handler = this._domainPolicySessionListeners.get(sessionId);
|
|
428
|
+
if (!handler)
|
|
429
|
+
return;
|
|
430
|
+
session.off("Fetch.requestPaused", handler);
|
|
431
|
+
this._domainPolicySessionListeners.delete(sessionId);
|
|
432
|
+
}
|
|
433
|
+
async handleDomainPolicyRequestPaused(session, evt) {
|
|
434
|
+
const decision = (0, domainPolicy_js_1.getDomainPolicyDecision)(evt.request.url, this.domainPolicy);
|
|
435
|
+
if (decision.action === "continue") {
|
|
436
|
+
await session
|
|
437
|
+
.send("Fetch.continueRequest", { requestId: evt.requestId })
|
|
438
|
+
.catch(() => { });
|
|
439
|
+
return;
|
|
440
|
+
}
|
|
441
|
+
let hostname = "";
|
|
442
|
+
try {
|
|
443
|
+
hostname = new URL(evt.request.url).hostname.toLowerCase();
|
|
444
|
+
}
|
|
445
|
+
catch {
|
|
446
|
+
// ignore malformed URLs for logging
|
|
447
|
+
}
|
|
448
|
+
(0, logger_js_1.v3Logger)({
|
|
449
|
+
category: "network",
|
|
450
|
+
message: "Blocked request by domain policy",
|
|
451
|
+
level: 2,
|
|
452
|
+
auxiliary: {
|
|
453
|
+
hostname: { value: hostname, type: "string" },
|
|
454
|
+
ruleType: { value: decision.reason, type: "string" },
|
|
455
|
+
},
|
|
456
|
+
});
|
|
457
|
+
await session
|
|
458
|
+
.send("Fetch.failRequest", {
|
|
459
|
+
requestId: evt.requestId,
|
|
460
|
+
errorReason: "BlockedByClient",
|
|
461
|
+
})
|
|
462
|
+
.catch(() => { });
|
|
463
|
+
}
|
|
335
464
|
get clipboard() {
|
|
336
465
|
return (this._clipboard ??= new clipboard_js_1.ContextClipboard({
|
|
337
466
|
context: this,
|
|
@@ -400,6 +529,12 @@ class V3Context {
|
|
|
400
529
|
await this.conn.send("Target.activateTarget", { targetId }).catch(() => { });
|
|
401
530
|
const deadline = Date.now() + 5000;
|
|
402
531
|
while (Date.now() < deadline) {
|
|
532
|
+
const failure = this.pageCreationFailures.get(targetId);
|
|
533
|
+
if (failure) {
|
|
534
|
+
this.pageCreationFailures.delete(targetId);
|
|
535
|
+
this.pendingCreatedTargetUrl.delete(targetId);
|
|
536
|
+
throw failure;
|
|
537
|
+
}
|
|
403
538
|
const page = this.pagesByTarget.get(targetId);
|
|
404
539
|
if (page) {
|
|
405
540
|
// we created at about:blank; navigate only after attach so init scripts run
|
|
@@ -415,6 +550,7 @@ class V3Context {
|
|
|
415
550
|
}
|
|
416
551
|
await new Promise((r) => setTimeout(r, 25));
|
|
417
552
|
}
|
|
553
|
+
this.pendingCreatedTargetUrl.delete(targetId);
|
|
418
554
|
throw new sdkErrors_js_1.TimeoutError(`newPage: target not attached (${targetId})`, 5000);
|
|
419
555
|
}
|
|
420
556
|
/**
|
|
@@ -430,6 +566,9 @@ class V3Context {
|
|
|
430
566
|
this.createdAtByTarget.clear();
|
|
431
567
|
this.typeByTarget.clear();
|
|
432
568
|
this.pendingCreatedTargetUrl.clear();
|
|
569
|
+
this.pageCreationFailures.clear();
|
|
570
|
+
this.domainPolicyClosingTargets.clear();
|
|
571
|
+
this.domainPolicyClosePromises.clear();
|
|
433
572
|
}
|
|
434
573
|
/**
|
|
435
574
|
* Bootstrap target lifecycle:
|
|
@@ -456,8 +595,12 @@ class V3Context {
|
|
|
456
595
|
const ti = info;
|
|
457
596
|
if (info.type === "page" && (ti?.openerId || ti?.openerFrameId)) {
|
|
458
597
|
this._notePopupSignal();
|
|
598
|
+
void this.closePopupIfBlockedByDomainPolicy(info, "targetCreated");
|
|
459
599
|
}
|
|
460
600
|
});
|
|
601
|
+
this.conn.on("Target.targetInfoChanged", (evt) => {
|
|
602
|
+
void this.closePopupIfBlockedByDomainPolicy(evt.targetInfo, "targetInfoChanged");
|
|
603
|
+
});
|
|
461
604
|
// Only enable auto-attach after listeners are ready so replayed targets are captured.
|
|
462
605
|
await this.conn.enableAutoAttach();
|
|
463
606
|
const targets = await this.conn.getTargets();
|
|
@@ -485,6 +628,9 @@ class V3Context {
|
|
|
485
628
|
* - Resume the target only after listeners are wired.
|
|
486
629
|
*/
|
|
487
630
|
async onAttachedToTarget(info, sessionId) {
|
|
631
|
+
if (await this.closePopupIfBlockedByDomainPolicy(info, "attached")) {
|
|
632
|
+
return;
|
|
633
|
+
}
|
|
488
634
|
// Skip non-web targets (workers, chrome extensions, background pages, etc.).
|
|
489
635
|
// They still need to be resumed so we don't leave them paused by
|
|
490
636
|
// waitForDebuggerOnStart, but injecting the piercer into these targets
|
|
@@ -536,6 +682,24 @@ class V3Context {
|
|
|
536
682
|
.catch(() => false);
|
|
537
683
|
return { dispatched, response };
|
|
538
684
|
};
|
|
685
|
+
const queueFetchEnablePreResume = (params) => {
|
|
686
|
+
let error;
|
|
687
|
+
const dispatched = this.conn
|
|
688
|
+
.waitForSessionDispatch(sessionId, "Fetch.enable")
|
|
689
|
+
.then(() => true)
|
|
690
|
+
.catch((err) => {
|
|
691
|
+
error = err;
|
|
692
|
+
return false;
|
|
693
|
+
});
|
|
694
|
+
const response = session
|
|
695
|
+
.send("Fetch.enable", params)
|
|
696
|
+
.then(() => true)
|
|
697
|
+
.catch((err) => {
|
|
698
|
+
error = err;
|
|
699
|
+
return false;
|
|
700
|
+
});
|
|
701
|
+
return { dispatched, response, getError: () => error };
|
|
702
|
+
};
|
|
539
703
|
const initScriptOps = [];
|
|
540
704
|
// Pre-resume ordering matters:
|
|
541
705
|
// - enable domains;
|
|
@@ -557,6 +721,13 @@ class V3Context {
|
|
|
557
721
|
headerPreResumeOps.push(queuePreResume("Network.enable"));
|
|
558
722
|
headerPreResumeOps.push(queuePreResume("Network.setExtraHTTPHeaders", { headers }));
|
|
559
723
|
}
|
|
724
|
+
const fetchPreResumeOps = [];
|
|
725
|
+
if (this.domainPolicy) {
|
|
726
|
+
this.installDomainPolicyHandler(session);
|
|
727
|
+
fetchPreResumeOps.push(queueFetchEnablePreResume({
|
|
728
|
+
patterns: this.domainPolicy.fetchPatterns,
|
|
729
|
+
}));
|
|
730
|
+
}
|
|
560
731
|
// Send init scripts only after auto-attach has been queued.
|
|
561
732
|
if (this.initScripts.length) {
|
|
562
733
|
for (const source of this.initScripts) {
|
|
@@ -575,6 +746,7 @@ class V3Context {
|
|
|
575
746
|
const preResumeDispatched = (await Promise.all([
|
|
576
747
|
...corePreResumeOps.map((op) => op.dispatched),
|
|
577
748
|
...headerPreResumeOps.map((op) => op.dispatched),
|
|
749
|
+
...fetchPreResumeOps.map((op) => op.dispatched),
|
|
578
750
|
...initScriptOps.map((op) => op.dispatched),
|
|
579
751
|
piercerPreloadOp.dispatched,
|
|
580
752
|
])).every(Boolean);
|
|
@@ -584,9 +756,10 @@ class V3Context {
|
|
|
584
756
|
resumeOp.dispatched,
|
|
585
757
|
resumeOp.response,
|
|
586
758
|
]);
|
|
587
|
-
const [coreResults, headerResults, initScriptResults, piercerPreRegistered,] = await Promise.all([
|
|
759
|
+
const [coreResults, headerResults, fetchResults, initScriptResults, piercerPreRegistered,] = await Promise.all([
|
|
588
760
|
Promise.all(corePreResumeOps.map((op) => op.response)),
|
|
589
761
|
Promise.all(headerPreResumeOps.map((op) => op.response)),
|
|
762
|
+
Promise.all(fetchPreResumeOps.map((op) => op.response)),
|
|
590
763
|
Promise.all(initScriptOps.map((op) => op.response)),
|
|
591
764
|
piercerPreloadOp.response,
|
|
592
765
|
]);
|
|
@@ -619,6 +792,40 @@ class V3Context {
|
|
|
619
792
|
return;
|
|
620
793
|
}
|
|
621
794
|
resumed = true;
|
|
795
|
+
if (fetchPreResumeOps.length > 0 && !fetchResults.every(Boolean)) {
|
|
796
|
+
this.uninstallDomainPolicyHandler(session);
|
|
797
|
+
const fetchError = fetchPreResumeOps
|
|
798
|
+
.map((op) => op.getError())
|
|
799
|
+
.find((error) => error !== undefined);
|
|
800
|
+
const fetchErrorMessage = fetchError
|
|
801
|
+
? fetchError instanceof Error
|
|
802
|
+
? fetchError.message
|
|
803
|
+
: String(fetchError)
|
|
804
|
+
: "Fetch.enable failed during target attach";
|
|
805
|
+
const policyFailureMessage = "Fetch.enable failed during target attach; closing target because " +
|
|
806
|
+
"Stagehand cannot guarantee domain policy enforcement";
|
|
807
|
+
if (this.pendingCreatedTargetUrl.has(info.targetId)) {
|
|
808
|
+
this.pageCreationFailures.set(info.targetId, new sdkErrors_js_1.StagehandSetDomainPolicyError([
|
|
809
|
+
`session=${sessionId} target=${info.targetId} error=${policyFailureMessage} cdpError=${fetchErrorMessage}`,
|
|
810
|
+
]));
|
|
811
|
+
}
|
|
812
|
+
(0, logger_js_1.v3Logger)({
|
|
813
|
+
category: "ctx",
|
|
814
|
+
message: "Closing target because domain policy could not be guaranteed",
|
|
815
|
+
level: 0,
|
|
816
|
+
auxiliary: {
|
|
817
|
+
targetId: { value: String(info.targetId), type: "string" },
|
|
818
|
+
targetType: { value: String(info.type), type: "string" },
|
|
819
|
+
targetUrl: { value: String(info.url ?? ""), type: "string" },
|
|
820
|
+
sessionId: { value: sessionId, type: "string" },
|
|
821
|
+
cdpError: { value: fetchErrorMessage, type: "string" },
|
|
822
|
+
},
|
|
823
|
+
});
|
|
824
|
+
await this.conn
|
|
825
|
+
.send("Target.closeTarget", { targetId: info.targetId })
|
|
826
|
+
.catch(() => { });
|
|
827
|
+
return;
|
|
828
|
+
}
|
|
622
829
|
const scriptsInstalled = coreResults.every(Boolean) && initScriptResults.every(Boolean);
|
|
623
830
|
try {
|
|
624
831
|
// Best-effort lifecycle events; do not block top-level page registration
|
|
@@ -734,6 +941,74 @@ class V3Context {
|
|
|
734
941
|
await resume();
|
|
735
942
|
}
|
|
736
943
|
}
|
|
944
|
+
async closePopupIfBlockedByDomainPolicy(info, source) {
|
|
945
|
+
if (!this.domainPolicy || !isTopLevelPage(info))
|
|
946
|
+
return false;
|
|
947
|
+
if (!info.openerId && !info.openerFrameId)
|
|
948
|
+
return false;
|
|
949
|
+
if (this.domainPolicyClosingTargets.has(info.targetId))
|
|
950
|
+
return true;
|
|
951
|
+
const existingClose = this.domainPolicyClosePromises.get(info.targetId);
|
|
952
|
+
if (existingClose) {
|
|
953
|
+
return source === "attached" ? await existingClose : true;
|
|
954
|
+
}
|
|
955
|
+
const decision = (0, domainPolicy_js_1.getDomainPolicyDecision)(info.url ?? "", this.domainPolicy);
|
|
956
|
+
if (decision.action === "continue")
|
|
957
|
+
return false;
|
|
958
|
+
(0, logger_js_1.v3Logger)({
|
|
959
|
+
category: "network",
|
|
960
|
+
message: "Popup reached a disallowed domain before it could be intercepted; closing it",
|
|
961
|
+
level: 2,
|
|
962
|
+
auxiliary: {
|
|
963
|
+
targetId: { value: String(info.targetId), type: "string" },
|
|
964
|
+
targetUrl: { value: String(info.url ?? ""), type: "string" },
|
|
965
|
+
openerId: { value: String(info.openerId ?? ""), type: "string" },
|
|
966
|
+
openerFrameId: {
|
|
967
|
+
value: String(info.openerFrameId ?? ""),
|
|
968
|
+
type: "string",
|
|
969
|
+
},
|
|
970
|
+
ruleType: { value: decision.reason, type: "string" },
|
|
971
|
+
source: { value: source, type: "string" },
|
|
972
|
+
},
|
|
973
|
+
});
|
|
974
|
+
const closePromise = this.closeTargetAfterDomainPolicyViolation(info, {
|
|
975
|
+
failureMessage: "Failed to close popup after it reached a disallowed domain",
|
|
976
|
+
}).then((closed) => {
|
|
977
|
+
this.domainPolicyClosePromises.delete(info.targetId);
|
|
978
|
+
if (closed) {
|
|
979
|
+
this.domainPolicyClosingTargets.add(info.targetId);
|
|
980
|
+
}
|
|
981
|
+
return closed;
|
|
982
|
+
});
|
|
983
|
+
this.domainPolicyClosePromises.set(info.targetId, closePromise);
|
|
984
|
+
return await closePromise;
|
|
985
|
+
}
|
|
986
|
+
async closeTargetAfterDomainPolicyViolation(info, opts) {
|
|
987
|
+
try {
|
|
988
|
+
await this.conn.send("Target.closeTarget", { targetId: info.targetId });
|
|
989
|
+
return true;
|
|
990
|
+
}
|
|
991
|
+
catch (error) {
|
|
992
|
+
if (isMissingTargetError(error)) {
|
|
993
|
+
return true;
|
|
994
|
+
}
|
|
995
|
+
(0, logger_js_1.v3Logger)({
|
|
996
|
+
category: "network",
|
|
997
|
+
message: opts.failureMessage,
|
|
998
|
+
level: 0,
|
|
999
|
+
auxiliary: {
|
|
1000
|
+
targetId: { value: String(info.targetId), type: "string" },
|
|
1001
|
+
targetType: { value: String(info.type), type: "string" },
|
|
1002
|
+
targetUrl: { value: String(info.url ?? ""), type: "string" },
|
|
1003
|
+
error: {
|
|
1004
|
+
value: error instanceof Error ? error.message : String(error),
|
|
1005
|
+
type: "string",
|
|
1006
|
+
},
|
|
1007
|
+
},
|
|
1008
|
+
});
|
|
1009
|
+
return false;
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
737
1012
|
/**
|
|
738
1013
|
* Detach handler:
|
|
739
1014
|
* - Remove child session ownership and prune its subtree.
|
|
@@ -754,6 +1029,13 @@ class V3Context {
|
|
|
754
1029
|
this.pendingOopifByMainFrame.delete(fid);
|
|
755
1030
|
}
|
|
756
1031
|
this._targetSessionListeners.delete(sessionId);
|
|
1032
|
+
const session = this.conn.getSession(sessionId);
|
|
1033
|
+
if (session) {
|
|
1034
|
+
this.uninstallDomainPolicyHandler(session);
|
|
1035
|
+
}
|
|
1036
|
+
else {
|
|
1037
|
+
this._domainPolicySessionListeners.delete(sessionId);
|
|
1038
|
+
}
|
|
757
1039
|
this._sessionInit.delete(sessionId);
|
|
758
1040
|
this._piercerInstalled.delete(sessionId);
|
|
759
1041
|
}
|
|
@@ -764,6 +1046,7 @@ class V3Context {
|
|
|
764
1046
|
const page = this.pagesByTarget.get(targetId);
|
|
765
1047
|
if (!page)
|
|
766
1048
|
return;
|
|
1049
|
+
this.pageCreationFailures.delete(targetId);
|
|
767
1050
|
const mainId = page.mainFrameId();
|
|
768
1051
|
this.mainFrameToTarget.delete(mainId);
|
|
769
1052
|
this.frameOwnerPage.delete(mainId);
|