rebrowser-playwright-core 1.47.100 → 1.49.0
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/README.md +1 -1
- package/ThirdPartyNotices.txt +70 -384
- package/bin/reinstall_chrome_beta_linux.sh +10 -8
- package/bin/reinstall_chrome_stable_linux.sh +10 -8
- package/bin/reinstall_msedge_beta_linux.sh +11 -9
- package/bin/reinstall_msedge_dev_linux.sh +11 -9
- package/bin/reinstall_msedge_stable_linux.sh +11 -9
- package/browsers.json +24 -12
- package/lib/cli/program.js +49 -19
- package/lib/client/api.js +6 -0
- package/lib/client/browserContext.js +20 -2
- package/lib/client/channelOwner.js +6 -2
- package/lib/client/connection.js +3 -0
- package/lib/client/fetch.js +16 -21
- package/lib/client/jsHandle.js +0 -8
- package/lib/client/localUtils.js +1 -0
- package/lib/client/locator.js +7 -0
- package/lib/client/network.js +180 -17
- package/lib/client/page.js +25 -2
- package/lib/client/playwright.js +6 -3
- package/lib/client/tracing.js +29 -20
- package/lib/client/waiter.js +15 -11
- package/lib/generated/consoleApiSource.js +1 -1
- package/lib/generated/injectedScriptSource.js +1 -1
- package/lib/generated/pollingRecorderSource.js +7 -0
- package/lib/generated/webSocketMockSource.js +7 -0
- package/lib/protocol/validator.js +103 -17
- package/lib/server/ariaSnapshot.js +33 -0
- package/lib/server/bidi/bidiBrowser.js +23 -8
- package/lib/server/bidi/bidiChromium.js +124 -0
- package/lib/server/bidi/bidiConnection.js +1 -3
- package/lib/server/bidi/bidiExecutionContext.js +0 -6
- package/lib/server/bidi/bidiFirefox.js +15 -21
- package/lib/server/bidi/bidiInput.js +16 -32
- package/lib/server/bidi/bidiNetworkManager.js +39 -5
- package/lib/server/bidi/bidiOverCdp.js +103 -0
- package/lib/server/bidi/bidiPage.js +98 -25
- package/lib/server/bidi/bidiPdf.js +140 -0
- package/lib/server/bidi/third_party/firefoxPrefs.js +221 -0
- package/lib/server/browser.js +13 -2
- package/lib/server/browserContext.js +6 -23
- package/lib/server/browserType.js +43 -12
- package/lib/server/chromium/chromium.js +9 -17
- package/lib/server/chromium/chromiumSwitches.js +3 -1
- package/lib/server/chromium/crBrowser.js +4 -3
- package/lib/server/chromium/crConnection.js +153 -0
- package/lib/server/chromium/crExecutionContext.js +0 -20
- package/lib/server/chromium/crPage.js +13 -7
- package/lib/server/chromium/videoRecorder.js +1 -1
- package/lib/server/codegen/csharp.js +12 -17
- package/lib/server/codegen/java.js +5 -8
- package/lib/server/codegen/javascript.js +29 -7
- package/lib/server/codegen/language.js +14 -2
- package/lib/server/codegen/python.js +13 -17
- package/lib/server/cookieStore.js +73 -0
- package/lib/server/debugController.js +10 -7
- package/lib/server/deviceDescriptorsSource.json +127 -127
- package/lib/server/dialog.js +1 -0
- package/lib/server/dispatchers/androidDispatcher.js +13 -2
- package/lib/server/dispatchers/browserContextDispatcher.js +19 -2
- package/lib/server/dispatchers/debugControllerDispatcher.js +1 -1
- package/lib/server/dispatchers/dispatcher.js +1 -1
- package/lib/server/dispatchers/frameDispatcher.js +8 -1
- package/lib/server/dispatchers/jsHandleDispatcher.js +0 -5
- package/lib/server/dispatchers/pageDispatcher.js +9 -0
- package/lib/server/dispatchers/playwrightDispatcher.js +2 -1
- package/lib/server/dispatchers/tracingDispatcher.js +10 -0
- package/lib/server/dispatchers/webSocketRouteDispatcher.js +189 -0
- package/lib/server/dom.js +79 -36
- package/lib/server/download.js +9 -2
- package/lib/server/fetch.js +105 -96
- package/lib/server/firefox/ffBrowser.js +6 -4
- package/lib/server/firefox/ffExecutionContext.js +0 -15
- package/lib/server/firefox/ffNetworkManager.js +1 -1
- package/lib/server/firefox/ffPage.js +6 -3
- package/lib/server/firefox/firefox.js +2 -13
- package/lib/server/frameSelectors.js +1 -1
- package/lib/server/frames.js +68 -67
- package/lib/server/har/harTracer.js +11 -0
- package/lib/server/index.js +0 -6
- package/lib/server/input.js +0 -1
- package/lib/server/javascript.js +0 -13
- package/lib/server/page.js +53 -9
- package/lib/server/playwright.js +5 -2
- package/lib/server/progress.js +0 -3
- package/lib/server/recorder/contextRecorder.js +33 -50
- package/lib/server/recorder/recorderApp.js +22 -25
- package/lib/server/recorder/recorderCollection.js +68 -79
- package/lib/server/recorder/recorderInTraceViewer.js +144 -0
- package/lib/server/recorder/recorderRunner.js +75 -97
- package/lib/server/recorder/recorderUtils.js +48 -6
- package/lib/server/recorder.js +87 -47
- package/lib/server/registry/index.js +154 -26
- package/lib/server/registry/nativeDeps.js +6 -3
- package/lib/server/socksClientCertificatesInterceptor.js +15 -3
- package/lib/server/trace/recorder/snapshotter.js +2 -12
- package/lib/server/trace/recorder/snapshotterInjected.js +21 -3
- package/lib/server/trace/recorder/tracing.js +127 -17
- package/lib/server/trace/test/inMemorySnapshotter.js +4 -4
- package/lib/server/trace/viewer/traceViewer.js +4 -6
- package/lib/server/webkit/webkit.js +1 -1
- package/lib/server/webkit/wkBrowser.js +8 -7
- package/lib/server/webkit/wkExecutionContext.js +0 -16
- package/lib/server/webkit/wkPage.js +11 -4
- package/lib/utils/comparators.js +12 -30
- package/lib/utils/crypto.js +1 -4
- package/lib/utils/happy-eyeballs.js +13 -0
- package/lib/utils/hostPlatform.js +8 -2
- package/lib/utils/httpServer.js +1 -0
- package/lib/utils/isomorphic/ariaSnapshot.js +267 -0
- package/lib/utils/isomorphic/locatorGenerators.js +30 -21
- package/lib/utils/isomorphic/locatorParser.js +2 -2
- package/lib/utils/isomorphic/recorderUtils.js +227 -0
- package/lib/utils/isomorphic/stringUtils.js +30 -0
- package/lib/utils/isomorphic/urlMatch.js +5 -1
- package/lib/utils/network.js +1 -1
- package/lib/utils/sequence.js +64 -0
- package/lib/utils/stackTrace.js +16 -3
- package/lib/utils/zones.js +32 -23
- package/lib/utilsBundle.js +4 -5
- package/lib/utilsBundleImpl/index.js +190 -33
- package/lib/vite/htmlReport/index.html +19 -16
- package/lib/vite/recorder/assets/codeMirrorModule-AFvV6hAs.js +24 -0
- package/lib/vite/recorder/assets/index-_cTWgVuJ.js +184 -0
- package/lib/vite/recorder/assets/{index-B-MT5gKo.css → index-iA1aAGZg.css} +1 -1
- package/lib/vite/recorder/index.html +2 -2
- package/lib/vite/traceViewer/assets/codeMirrorModule-KatbITLF.js +24 -0
- package/lib/vite/traceViewer/assets/inspectorTab-DdpLd2bb.js +68 -0
- package/lib/vite/traceViewer/assets/workbench-CdYbzWFD.js +9 -0
- package/lib/vite/traceViewer/embedded.6m3UZh7r.js +2 -0
- package/lib/vite/traceViewer/embedded.html +5 -3
- package/lib/vite/traceViewer/index.WUV-8boJ.js +2 -0
- package/lib/vite/traceViewer/index.html +24 -5
- package/lib/vite/traceViewer/inspectorTab.DEOUW62d.css +1 -0
- package/lib/vite/traceViewer/recorder.B_SY1GJM.css +0 -0
- package/lib/vite/traceViewer/recorder.OT2tVHgn.js +2 -0
- package/lib/vite/traceViewer/recorder.html +17 -0
- package/lib/vite/traceViewer/sw.bundle.js +3 -3
- package/lib/vite/traceViewer/uiMode.BZBTyvGn.js +5 -0
- package/lib/vite/traceViewer/uiMode.html +6 -4
- package/lib/vite/traceViewer/{uiMode.D3cNFP6u.css → uiMode.voC1ZiOQ.css} +1 -1
- package/lib/vite/traceViewer/workbench.C-zR9ysA.css +1 -0
- package/package.json +1 -1
- package/types/protocol.d.ts +135 -16
- package/types/types.d.ts +2149 -965
- package/lib/generated/recorderSource.js +0 -7
- package/lib/third_party/diff_match_patch.js +0 -2222
- package/lib/vite/recorder/assets/codeMirrorModule-aW6Vz3gf.js +0 -24
- package/lib/vite/recorder/assets/index-DCpXOVIh.js +0 -47
- package/lib/vite/traceViewer/assets/codeMirrorModule-eFKCUIu2.js +0 -24
- package/lib/vite/traceViewer/assets/workbench-D0cirtfA.js +0 -72
- package/lib/vite/traceViewer/embedded.BkuvsLJp.js +0 -2
- package/lib/vite/traceViewer/index.C968kAiC.js +0 -2
- package/lib/vite/traceViewer/uiMode.BkFnr4V0.js +0 -10
- package/lib/vite/traceViewer/workbench.DjbIuxix.css +0 -1
- /package/lib/server/recorder/{recorderActions.js → recorderFrontend.js} +0 -0
package/lib/server/dom.js
CHANGED
|
@@ -225,17 +225,21 @@ class ElementHandle extends js.JSHandle {
|
|
|
225
225
|
// Allow 1x1 elements. Compensate for rounding errors by comparing with 0.99 instead.
|
|
226
226
|
const filtered = quads.map(quad => intersectQuadWithViewport(quad)).filter(quad => computeQuadArea(quad) > 0.99);
|
|
227
227
|
if (!filtered.length) return 'error:notinviewport';
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
228
|
+
if (this._page._browserContext._browser.options.name === 'firefox') {
|
|
229
|
+
// Firefox internally uses integer coordinates, so 8.x is converted to 8 or 9 when clicking.
|
|
230
|
+
//
|
|
231
|
+
// This does not work nicely for small elements. For example, 1x1 square with corners
|
|
232
|
+
// (8;8) and (9;9) is targeted when clicking at (8;8) but not when clicking at (9;9).
|
|
233
|
+
// So, clicking at (8.x;8.y) will sometimes click at (9;9) and miss the target.
|
|
234
|
+
//
|
|
235
|
+
// Therefore, we try to find an integer point within a quad to make sure we click inside the element.
|
|
236
|
+
for (const quad of filtered) {
|
|
237
|
+
const integerPoint = findIntegerPointInsideQuad(quad);
|
|
238
|
+
if (integerPoint) return integerPoint;
|
|
239
|
+
}
|
|
236
240
|
}
|
|
237
|
-
|
|
238
|
-
return
|
|
241
|
+
// Return the middle point of the first quad.
|
|
242
|
+
return quadMiddlePoint(filtered[0]);
|
|
239
243
|
}
|
|
240
244
|
async _offsetPoint(offset) {
|
|
241
245
|
const [box, border] = await Promise.all([this.boundingBox(), this.evaluateInUtility(([injected, node]) => injected.getElementBorderWidth(node), {}).catch(e => {})]);
|
|
@@ -253,7 +257,7 @@ class ElementHandle extends js.JSHandle {
|
|
|
253
257
|
const waitTime = [0, 20, 100, 100, 500];
|
|
254
258
|
while (progress.isRunning()) {
|
|
255
259
|
if (retry) {
|
|
256
|
-
progress.log(`retrying ${actionName} action${options.trial ? ' (trial run)' : ''}
|
|
260
|
+
progress.log(`retrying ${actionName} action${options.trial ? ' (trial run)' : ''}`);
|
|
257
261
|
const timeout = waitTime[Math.min(retry - 1, waitTime.length - 1)];
|
|
258
262
|
if (timeout) {
|
|
259
263
|
progress.log(` waiting ${timeout}ms`);
|
|
@@ -263,7 +267,7 @@ class ElementHandle extends js.JSHandle {
|
|
|
263
267
|
} else {
|
|
264
268
|
progress.log(`attempting ${actionName} action${options.trial ? ' (trial run)' : ''}`);
|
|
265
269
|
}
|
|
266
|
-
if (!options.
|
|
270
|
+
if (!options.skipActionPreChecks && !options.force) await this._frame._page.performActionPreChecks(progress);
|
|
267
271
|
const result = await action(retry);
|
|
268
272
|
++retry;
|
|
269
273
|
if (result === 'error:notvisible') {
|
|
@@ -294,7 +298,7 @@ class ElementHandle extends js.JSHandle {
|
|
|
294
298
|
}
|
|
295
299
|
async _retryPointerAction(progress, actionName, waitForEnabled, action, options) {
|
|
296
300
|
// Note: do not perform locator handlers checkpoint to avoid moving the mouse in the middle of a drag operation.
|
|
297
|
-
const
|
|
301
|
+
const skipActionPreChecks = actionName === 'move and up';
|
|
298
302
|
return await this._retryAction(progress, actionName, async retry => {
|
|
299
303
|
// By default, we scroll with protocol method to reveal the action point.
|
|
300
304
|
// However, that might not work to scroll from under position:sticky elements
|
|
@@ -314,7 +318,7 @@ class ElementHandle extends js.JSHandle {
|
|
|
314
318
|
return await this._performPointerAction(progress, actionName, waitForEnabled, action, forceScrollOptions, options);
|
|
315
319
|
}, {
|
|
316
320
|
...options,
|
|
317
|
-
|
|
321
|
+
skipActionPreChecks
|
|
318
322
|
});
|
|
319
323
|
}
|
|
320
324
|
async _performPointerAction(progress, actionName, waitForEnabled, action, forceScrollOptions, options) {
|
|
@@ -367,7 +371,7 @@ class ElementHandle extends js.JSHandle {
|
|
|
367
371
|
if (typeof maybePoint === 'string') return maybePoint;
|
|
368
372
|
const point = roundPoint(maybePoint);
|
|
369
373
|
progress.metadata.point = point;
|
|
370
|
-
await
|
|
374
|
+
await this.instrumentation.onBeforeInputAction(this, progress.metadata);
|
|
371
375
|
let hitTargetInterceptionHandle;
|
|
372
376
|
if (force) {
|
|
373
377
|
progress.log(` forcing action`);
|
|
@@ -433,9 +437,16 @@ class ElementHandle extends js.JSHandle {
|
|
|
433
437
|
progress.log(' navigations have finished');
|
|
434
438
|
return 'done';
|
|
435
439
|
}
|
|
440
|
+
async _markAsTargetElement(metadata) {
|
|
441
|
+
if (!metadata.id) return;
|
|
442
|
+
await this.evaluateInUtility(([injected, node, callId]) => {
|
|
443
|
+
if (node.nodeType === 1 /* Node.ELEMENT_NODE */) injected.markTargetElements(new Set([node]), callId);
|
|
444
|
+
}, metadata.id);
|
|
445
|
+
}
|
|
436
446
|
async hover(metadata, options) {
|
|
437
447
|
const controller = new _progress.ProgressController(metadata, this);
|
|
438
448
|
return controller.run(async progress => {
|
|
449
|
+
await this._markAsTargetElement(metadata);
|
|
439
450
|
const result = await this._hover(progress, options);
|
|
440
451
|
return assertDone(throwRetargetableDOMError(result));
|
|
441
452
|
}, this._page._timeoutSettings.timeout(options));
|
|
@@ -449,6 +460,7 @@ class ElementHandle extends js.JSHandle {
|
|
|
449
460
|
async click(metadata, options = {}) {
|
|
450
461
|
const controller = new _progress.ProgressController(metadata, this);
|
|
451
462
|
return controller.run(async progress => {
|
|
463
|
+
await this._markAsTargetElement(metadata);
|
|
452
464
|
const result = await this._click(progress, {
|
|
453
465
|
...options,
|
|
454
466
|
waitAfter: !options.noWaitAfter
|
|
@@ -462,6 +474,7 @@ class ElementHandle extends js.JSHandle {
|
|
|
462
474
|
async dblclick(metadata, options) {
|
|
463
475
|
const controller = new _progress.ProgressController(metadata, this);
|
|
464
476
|
return controller.run(async progress => {
|
|
477
|
+
await this._markAsTargetElement(metadata);
|
|
465
478
|
const result = await this._dblclick(progress, options);
|
|
466
479
|
return assertDone(throwRetargetableDOMError(result));
|
|
467
480
|
}, this._page._timeoutSettings.timeout(options));
|
|
@@ -475,6 +488,7 @@ class ElementHandle extends js.JSHandle {
|
|
|
475
488
|
async tap(metadata, options = {}) {
|
|
476
489
|
const controller = new _progress.ProgressController(metadata, this);
|
|
477
490
|
return controller.run(async progress => {
|
|
491
|
+
await this._markAsTargetElement(metadata);
|
|
478
492
|
const result = await this._tap(progress, options);
|
|
479
493
|
return assertDone(throwRetargetableDOMError(result));
|
|
480
494
|
}, this._page._timeoutSettings.timeout(options));
|
|
@@ -488,6 +502,7 @@ class ElementHandle extends js.JSHandle {
|
|
|
488
502
|
async selectOption(metadata, elements, values, options) {
|
|
489
503
|
const controller = new _progress.ProgressController(metadata, this);
|
|
490
504
|
return controller.run(async progress => {
|
|
505
|
+
await this._markAsTargetElement(metadata);
|
|
491
506
|
const result = await this._selectOption(progress, elements, values, options);
|
|
492
507
|
return throwRetargetableDOMError(result);
|
|
493
508
|
}, this._page._timeoutSettings.timeout(options));
|
|
@@ -495,7 +510,7 @@ class ElementHandle extends js.JSHandle {
|
|
|
495
510
|
async _selectOption(progress, elements, values, options) {
|
|
496
511
|
let resultingOptions = [];
|
|
497
512
|
await this._retryAction(progress, 'select option', async () => {
|
|
498
|
-
await
|
|
513
|
+
await this.instrumentation.onBeforeInputAction(this, progress.metadata);
|
|
499
514
|
if (!options.force) progress.log(` waiting for element to be visible and enabled`);
|
|
500
515
|
const optionsToSelect = [...elements, ...values];
|
|
501
516
|
const result = await this.evaluateInUtility(async ([injected, node, {
|
|
@@ -523,6 +538,7 @@ class ElementHandle extends js.JSHandle {
|
|
|
523
538
|
async fill(metadata, value, options = {}) {
|
|
524
539
|
const controller = new _progress.ProgressController(metadata, this);
|
|
525
540
|
return controller.run(async progress => {
|
|
541
|
+
await this._markAsTargetElement(metadata);
|
|
526
542
|
const result = await this._fill(progress, value, options);
|
|
527
543
|
assertDone(throwRetargetableDOMError(result));
|
|
528
544
|
}, this._page._timeoutSettings.timeout(options));
|
|
@@ -530,7 +546,7 @@ class ElementHandle extends js.JSHandle {
|
|
|
530
546
|
async _fill(progress, value, options) {
|
|
531
547
|
progress.log(` fill("${value}")`);
|
|
532
548
|
return await this._retryAction(progress, 'fill', async () => {
|
|
533
|
-
await
|
|
549
|
+
await this.instrumentation.onBeforeInputAction(this, progress.metadata);
|
|
534
550
|
if (!options.force) progress.log(' waiting for element to be visible, enabled and editable');
|
|
535
551
|
const result = await this.evaluateInUtility(async ([injected, node, {
|
|
536
552
|
value,
|
|
@@ -578,6 +594,7 @@ class ElementHandle extends js.JSHandle {
|
|
|
578
594
|
const inputFileItems = await (0, _fileUploadUtils.prepareFilesForUpload)(this._frame, params);
|
|
579
595
|
const controller = new _progress.ProgressController(metadata, this);
|
|
580
596
|
return controller.run(async progress => {
|
|
597
|
+
await this._markAsTargetElement(metadata);
|
|
581
598
|
const result = await this._setInputFiles(progress, inputFileItems);
|
|
582
599
|
return assertDone(throwRetargetableDOMError(result));
|
|
583
600
|
}, this._page._timeoutSettings.timeout(params));
|
|
@@ -607,7 +624,7 @@ class ElementHandle extends js.JSHandle {
|
|
|
607
624
|
});
|
|
608
625
|
if (result === 'error:notconnected' || !result.asElement()) return 'error:notconnected';
|
|
609
626
|
const retargeted = result.asElement();
|
|
610
|
-
await
|
|
627
|
+
await this.instrumentation.onBeforeInputAction(this, progress.metadata);
|
|
611
628
|
progress.throwIfAborted(); // Avoid action that has side-effects.
|
|
612
629
|
if (localPaths || localDirectory) {
|
|
613
630
|
const localPathsOrDirectory = localDirectory ? [localDirectory] : localPaths;
|
|
@@ -628,6 +645,7 @@ class ElementHandle extends js.JSHandle {
|
|
|
628
645
|
async focus(metadata) {
|
|
629
646
|
const controller = new _progress.ProgressController(metadata, this);
|
|
630
647
|
await controller.run(async progress => {
|
|
648
|
+
await this._markAsTargetElement(metadata);
|
|
631
649
|
const result = await this._focus(progress);
|
|
632
650
|
return assertDone(throwRetargetableDOMError(result));
|
|
633
651
|
}, 0);
|
|
@@ -643,13 +661,14 @@ class ElementHandle extends js.JSHandle {
|
|
|
643
661
|
async type(metadata, text, options) {
|
|
644
662
|
const controller = new _progress.ProgressController(metadata, this);
|
|
645
663
|
return controller.run(async progress => {
|
|
664
|
+
await this._markAsTargetElement(metadata);
|
|
646
665
|
const result = await this._type(progress, text, options);
|
|
647
666
|
return assertDone(throwRetargetableDOMError(result));
|
|
648
667
|
}, this._page._timeoutSettings.timeout(options));
|
|
649
668
|
}
|
|
650
669
|
async _type(progress, text, options) {
|
|
651
670
|
progress.log(`elementHandle.type("${text}")`);
|
|
652
|
-
await
|
|
671
|
+
await this.instrumentation.onBeforeInputAction(this, progress.metadata);
|
|
653
672
|
const result = await this._focus(progress, true /* resetSelectionIfNotFocused */);
|
|
654
673
|
if (result !== 'done') return result;
|
|
655
674
|
progress.throwIfAborted(); // Avoid action that has side-effects.
|
|
@@ -659,13 +678,14 @@ class ElementHandle extends js.JSHandle {
|
|
|
659
678
|
async press(metadata, key, options) {
|
|
660
679
|
const controller = new _progress.ProgressController(metadata, this);
|
|
661
680
|
return controller.run(async progress => {
|
|
681
|
+
await this._markAsTargetElement(metadata);
|
|
662
682
|
const result = await this._press(progress, key, options);
|
|
663
683
|
return assertDone(throwRetargetableDOMError(result));
|
|
664
684
|
}, this._page._timeoutSettings.timeout(options));
|
|
665
685
|
}
|
|
666
686
|
async _press(progress, key, options) {
|
|
667
687
|
progress.log(`elementHandle.press("${key}")`);
|
|
668
|
-
await
|
|
688
|
+
await this.instrumentation.onBeforeInputAction(this, progress.metadata);
|
|
669
689
|
return this._page._frameManager.waitForSignalsCreatedBy(progress, !options.noWaitAfter, async () => {
|
|
670
690
|
const result = await this._focus(progress, true /* resetSelectionIfNotFocused */);
|
|
671
691
|
if (result !== 'done') return result;
|
|
@@ -693,6 +713,7 @@ class ElementHandle extends js.JSHandle {
|
|
|
693
713
|
const result = await this.evaluateInUtility(([injected, node]) => injected.elementState(node, 'checked'), {});
|
|
694
714
|
return throwRetargetableDOMError(result);
|
|
695
715
|
};
|
|
716
|
+
await this._markAsTargetElement(progress.metadata);
|
|
696
717
|
if ((await isChecked()) === state) return 'done';
|
|
697
718
|
const result = await this._click(progress, {
|
|
698
719
|
...options,
|
|
@@ -706,6 +727,9 @@ class ElementHandle extends js.JSHandle {
|
|
|
706
727
|
async boundingBox() {
|
|
707
728
|
return this._page._delegate.getBoundingBox(this);
|
|
708
729
|
}
|
|
730
|
+
async ariaSnapshot() {
|
|
731
|
+
return await this.evaluateInUtility(([injected, element]) => injected.ariaSnapshot(element), {});
|
|
732
|
+
}
|
|
709
733
|
async screenshot(metadata, options = {}) {
|
|
710
734
|
const controller = new _progress.ProgressController(metadata, this);
|
|
711
735
|
return controller.run(progress => this._page._screenshotter.screenshotElement(progress, this, options), this._page._timeoutSettings.timeout(options));
|
|
@@ -825,21 +849,40 @@ function roundPoint(point) {
|
|
|
825
849
|
y: (point.y * 100 | 0) / 100
|
|
826
850
|
};
|
|
827
851
|
}
|
|
828
|
-
function
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
852
|
+
function quadMiddlePoint(quad) {
|
|
853
|
+
const result = {
|
|
854
|
+
x: 0,
|
|
855
|
+
y: 0
|
|
856
|
+
};
|
|
857
|
+
for (const point of quad) {
|
|
858
|
+
result.x += point.x / 4;
|
|
859
|
+
result.y += point.y / 4;
|
|
860
|
+
}
|
|
861
|
+
return result;
|
|
862
|
+
}
|
|
863
|
+
function triangleArea(p1, p2, p3) {
|
|
864
|
+
return Math.abs(p1.x * (p2.y - p3.y) + p2.x * (p3.y - p1.y) + p3.x * (p1.y - p2.y)) / 2;
|
|
865
|
+
}
|
|
866
|
+
function isPointInsideQuad(point, quad) {
|
|
867
|
+
const area1 = triangleArea(point, quad[0], quad[1]) + triangleArea(point, quad[1], quad[2]) + triangleArea(point, quad[2], quad[3]) + triangleArea(point, quad[3], quad[0]);
|
|
868
|
+
const area2 = triangleArea(quad[0], quad[1], quad[2]) + triangleArea(quad[1], quad[2], quad[3]);
|
|
869
|
+
// Check that point is inside the quad.
|
|
870
|
+
if (Math.abs(area1 - area2) > 0.1) return false;
|
|
871
|
+
// Check that point is not on the right/bottom edge, because clicking
|
|
872
|
+
// there does not actually click the element.
|
|
873
|
+
return point.x < Math.max(quad[0].x, quad[1].x, quad[2].x, quad[3].x) && point.y < Math.max(quad[0].y, quad[1].y, quad[2].y, quad[3].y);
|
|
874
|
+
}
|
|
875
|
+
function findIntegerPointInsideQuad(quad) {
|
|
876
|
+
// Try all four rounding directions of the middle point.
|
|
877
|
+
const point = quadMiddlePoint(quad);
|
|
878
|
+
point.x = Math.floor(point.x);
|
|
879
|
+
point.y = Math.floor(point.y);
|
|
880
|
+
if (isPointInsideQuad(point, quad)) return point;
|
|
881
|
+
point.x += 1;
|
|
882
|
+
if (isPointInsideQuad(point, quad)) return point;
|
|
883
|
+
point.y += 1;
|
|
884
|
+
if (isPointInsideQuad(point, quad)) return point;
|
|
885
|
+
point.x -= 1;
|
|
886
|
+
if (isPointInsideQuad(point, quad)) return point;
|
|
844
887
|
}
|
|
845
888
|
const kUnableToAdoptErrorMessage = exports.kUnableToAdoptErrorMessage = 'Unable to adopt element handle from a different document';
|
package/lib/server/download.js
CHANGED
|
@@ -39,15 +39,22 @@ class Download {
|
|
|
39
39
|
this.url = url;
|
|
40
40
|
this._suggestedFilename = suggestedFilename;
|
|
41
41
|
page._browserContext._downloads.add(this);
|
|
42
|
-
if (suggestedFilename !== undefined) this.
|
|
42
|
+
if (suggestedFilename !== undefined) this._fireDownloadEvent();
|
|
43
|
+
}
|
|
44
|
+
page() {
|
|
45
|
+
return this._page;
|
|
43
46
|
}
|
|
44
47
|
_filenameSuggested(suggestedFilename) {
|
|
45
48
|
(0, _utils.assert)(this._suggestedFilename === undefined);
|
|
46
49
|
this._suggestedFilename = suggestedFilename;
|
|
47
|
-
this.
|
|
50
|
+
this._fireDownloadEvent();
|
|
48
51
|
}
|
|
49
52
|
suggestedFilename() {
|
|
50
53
|
return this._suggestedFilename;
|
|
51
54
|
}
|
|
55
|
+
_fireDownloadEvent() {
|
|
56
|
+
this._page.instrumentation.onDownload(this._page, this);
|
|
57
|
+
this._page.emit(_page.Page.Events.Download, this);
|
|
58
|
+
}
|
|
52
59
|
}
|
|
53
60
|
exports.Download = Download;
|
package/lib/server/fetch.js
CHANGED
|
@@ -4,10 +4,10 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.GlobalAPIRequestContext = exports.BrowserContextAPIRequestContext = exports.APIRequestContext = void 0;
|
|
7
|
+
exports.createProxyAgent = createProxyAgent;
|
|
7
8
|
var _http = _interopRequireDefault(require("http"));
|
|
8
9
|
var _https = _interopRequireDefault(require("https"));
|
|
9
10
|
var _stream = require("stream");
|
|
10
|
-
var _url = _interopRequireDefault(require("url"));
|
|
11
11
|
var _zlib = _interopRequireDefault(require("zlib"));
|
|
12
12
|
var _timeoutSettings = require("../common/timeoutSettings");
|
|
13
13
|
var _userAgent = require("../utils/userAgent");
|
|
@@ -20,8 +20,8 @@ var _happyEyeballs = require("../utils/happy-eyeballs");
|
|
|
20
20
|
var _instrumentation = require("./instrumentation");
|
|
21
21
|
var _progress = require("./progress");
|
|
22
22
|
var _tracing = require("./trace/recorder/tracing");
|
|
23
|
-
var _network = require("./network");
|
|
24
23
|
var _socksClientCertificatesInterceptor = require("./socksClientCertificatesInterceptor");
|
|
24
|
+
var _tls = require("tls");
|
|
25
25
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
26
26
|
/**
|
|
27
27
|
* Copyright (c) Microsoft Corporation.
|
|
@@ -71,7 +71,7 @@ class APIRequestContext extends _instrumentation.SdkObject {
|
|
|
71
71
|
return uid;
|
|
72
72
|
}
|
|
73
73
|
async fetch(params, metadata) {
|
|
74
|
-
var _params$method
|
|
74
|
+
var _params$method;
|
|
75
75
|
const defaults = this._defaultOptions();
|
|
76
76
|
const headers = {
|
|
77
77
|
'user-agent': defaults.userAgent,
|
|
@@ -90,8 +90,10 @@ class APIRequestContext extends _instrumentation.SdkObject {
|
|
|
90
90
|
value
|
|
91
91
|
} of params.headers) setHeader(headers, name, value);
|
|
92
92
|
}
|
|
93
|
-
const requestUrl = new URL(
|
|
94
|
-
if (params.
|
|
93
|
+
const requestUrl = new URL((0, _utils.constructURLBasedOnBaseURL)(defaults.baseURL, params.url));
|
|
94
|
+
if (params.encodedParams) {
|
|
95
|
+
requestUrl.search = params.encodedParams;
|
|
96
|
+
} else if (params.params) {
|
|
95
97
|
for (const {
|
|
96
98
|
name,
|
|
97
99
|
value
|
|
@@ -102,23 +104,9 @@ class APIRequestContext extends _instrumentation.SdkObject {
|
|
|
102
104
|
const method = ((_params$method = params.method) === null || _params$method === void 0 ? void 0 : _params$method.toUpperCase()) || 'GET';
|
|
103
105
|
const proxy = defaults.proxy;
|
|
104
106
|
let agent;
|
|
105
|
-
//
|
|
106
|
-
//
|
|
107
|
-
|
|
108
|
-
if (proxy && !((_defaults$clientCerti = defaults.clientCertificates) !== null && _defaults$clientCerti !== void 0 && _defaults$clientCerti.length) && proxy.server !== 'per-context' && !shouldBypassProxy(requestUrl, proxy.bypass)) {
|
|
109
|
-
var _proxyOpts$protocol;
|
|
110
|
-
const proxyOpts = _url.default.parse(proxy.server);
|
|
111
|
-
if ((_proxyOpts$protocol = proxyOpts.protocol) !== null && _proxyOpts$protocol !== void 0 && _proxyOpts$protocol.startsWith('socks')) {
|
|
112
|
-
agent = new _utilsBundle.SocksProxyAgent({
|
|
113
|
-
host: proxyOpts.hostname,
|
|
114
|
-
port: proxyOpts.port || undefined
|
|
115
|
-
});
|
|
116
|
-
} else {
|
|
117
|
-
if (proxy.username) proxyOpts.auth = `${proxy.username}:${proxy.password || ''}`;
|
|
118
|
-
// TODO: We should use HttpProxyAgent conditional on proxyOpts.protocol instead of always using CONNECT method.
|
|
119
|
-
agent = new _utilsBundle.HttpsProxyAgent(proxyOpts);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
107
|
+
// We skip 'per-context' in order to not break existing users. 'per-context' was previously used to
|
|
108
|
+
// workaround an upstream Chromium bug. Can be removed in the future.
|
|
109
|
+
if (proxy && proxy.server !== 'per-context' && !shouldBypassProxy(requestUrl, proxy.bypass)) agent = createProxyAgent(proxy);
|
|
122
110
|
const timeout = defaults.timeoutSettings.timeout(params);
|
|
123
111
|
const deadline = timeout && (0, _utils.monotonicTime)() + timeout;
|
|
124
112
|
const options = {
|
|
@@ -190,6 +178,7 @@ class APIRequestContext extends _instrumentation.SdkObject {
|
|
|
190
178
|
try {
|
|
191
179
|
return await this._sendRequest(progress, url, options, postData);
|
|
192
180
|
} catch (e) {
|
|
181
|
+
e = (0, _socksClientCertificatesInterceptor.rewriteOpenSSLErrorIfNeeded)(e);
|
|
193
182
|
if (maxRetries === 0) throw e;
|
|
194
183
|
if (i === maxRetries || options.deadline && (0, _utils.monotonicTime)() + backoff > options.deadline) throw new Error(`Failed after ${i + 1} attempt(s): ${e}`);
|
|
195
184
|
// Retry on connection reset only.
|
|
@@ -227,8 +216,33 @@ class APIRequestContext extends _instrumentation.SdkObject {
|
|
|
227
216
|
...options,
|
|
228
217
|
agent
|
|
229
218
|
};
|
|
219
|
+
const startAt = (0, _utils.monotonicTime)();
|
|
220
|
+
let reusedSocketAt;
|
|
221
|
+
let dnsLookupAt;
|
|
222
|
+
let tcpConnectionAt;
|
|
223
|
+
let tlsHandshakeAt;
|
|
224
|
+
let requestFinishAt;
|
|
225
|
+
let serverIPAddress;
|
|
226
|
+
let serverPort;
|
|
227
|
+
let securityDetails;
|
|
228
|
+
const listeners = [];
|
|
230
229
|
const request = requestConstructor(url, requestOptions, async response => {
|
|
230
|
+
const responseAt = (0, _utils.monotonicTime)();
|
|
231
231
|
const notifyRequestFinished = body => {
|
|
232
|
+
var _tlsHandshakeAt;
|
|
233
|
+
const endAt = (0, _utils.monotonicTime)();
|
|
234
|
+
// spec: http://www.softwareishard.com/blog/har-12-spec/#timings
|
|
235
|
+
const connectEnd = (_tlsHandshakeAt = tlsHandshakeAt) !== null && _tlsHandshakeAt !== void 0 ? _tlsHandshakeAt : tcpConnectionAt;
|
|
236
|
+
const timings = {
|
|
237
|
+
send: requestFinishAt - startAt,
|
|
238
|
+
wait: responseAt - requestFinishAt,
|
|
239
|
+
receive: endAt - responseAt,
|
|
240
|
+
dns: dnsLookupAt ? dnsLookupAt - startAt : -1,
|
|
241
|
+
connect: connectEnd ? connectEnd - startAt : -1,
|
|
242
|
+
// "If [ssl] is defined then the time is also included in the connect field "
|
|
243
|
+
ssl: tlsHandshakeAt ? tlsHandshakeAt - tcpConnectionAt : -1,
|
|
244
|
+
blocked: reusedSocketAt ? reusedSocketAt - startAt : -1
|
|
245
|
+
};
|
|
232
246
|
const requestFinishedEvent = {
|
|
233
247
|
requestEvent,
|
|
234
248
|
httpVersion: response.httpVersion,
|
|
@@ -237,7 +251,11 @@ class APIRequestContext extends _instrumentation.SdkObject {
|
|
|
237
251
|
headers: response.headers,
|
|
238
252
|
rawHeaders: response.rawHeaders,
|
|
239
253
|
cookies,
|
|
240
|
-
body
|
|
254
|
+
body,
|
|
255
|
+
timings,
|
|
256
|
+
serverIPAddress,
|
|
257
|
+
serverPort,
|
|
258
|
+
securityDetails
|
|
241
259
|
};
|
|
242
260
|
this.emit(APIRequestContext.Events.RequestFinished, requestFinishedEvent);
|
|
243
261
|
};
|
|
@@ -363,13 +381,59 @@ class APIRequestContext extends _instrumentation.SdkObject {
|
|
|
363
381
|
body.on('data', chunk => chunks.push(chunk));
|
|
364
382
|
body.on('end', notifyBodyFinished);
|
|
365
383
|
});
|
|
366
|
-
request.on('error',
|
|
367
|
-
|
|
384
|
+
request.on('error', reject);
|
|
385
|
+
listeners.push(_utils.eventsHelper.addEventListener(this, APIRequestContext.Events.Dispose, () => {
|
|
368
386
|
reject(new Error('Request context disposed.'));
|
|
369
387
|
request.destroy();
|
|
370
|
-
};
|
|
371
|
-
|
|
372
|
-
request.on('
|
|
388
|
+
}));
|
|
389
|
+
request.on('close', () => _utils.eventsHelper.removeEventListeners(listeners));
|
|
390
|
+
request.on('socket', socket => {
|
|
391
|
+
var _tcpConnectionAt, _tcpConnectionAt3;
|
|
392
|
+
if (request.reusedSocket) {
|
|
393
|
+
reusedSocketAt = (0, _utils.monotonicTime)();
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// happy eyeballs don't emit lookup and connect events, so we use our custom ones
|
|
398
|
+
const happyEyeBallsTimings = (0, _happyEyeballs.timingForSocket)(socket);
|
|
399
|
+
dnsLookupAt = happyEyeBallsTimings.dnsLookupAt;
|
|
400
|
+
(_tcpConnectionAt = tcpConnectionAt) !== null && _tcpConnectionAt !== void 0 ? _tcpConnectionAt : tcpConnectionAt = happyEyeBallsTimings.tcpConnectionAt;
|
|
401
|
+
|
|
402
|
+
// non-happy-eyeballs sockets
|
|
403
|
+
listeners.push(_utils.eventsHelper.addEventListener(socket, 'lookup', () => {
|
|
404
|
+
dnsLookupAt = (0, _utils.monotonicTime)();
|
|
405
|
+
}), _utils.eventsHelper.addEventListener(socket, 'connect', () => {
|
|
406
|
+
var _tcpConnectionAt2;
|
|
407
|
+
(_tcpConnectionAt2 = tcpConnectionAt) !== null && _tcpConnectionAt2 !== void 0 ? _tcpConnectionAt2 : tcpConnectionAt = (0, _utils.monotonicTime)();
|
|
408
|
+
}), _utils.eventsHelper.addEventListener(socket, 'secureConnect', () => {
|
|
409
|
+
tlsHandshakeAt = (0, _utils.monotonicTime)();
|
|
410
|
+
if (socket instanceof _tls.TLSSocket) {
|
|
411
|
+
var _socket$getProtocol;
|
|
412
|
+
const peerCertificate = socket.getPeerCertificate();
|
|
413
|
+
securityDetails = {
|
|
414
|
+
protocol: (_socket$getProtocol = socket.getProtocol()) !== null && _socket$getProtocol !== void 0 ? _socket$getProtocol : undefined,
|
|
415
|
+
subjectName: peerCertificate.subject.CN,
|
|
416
|
+
validFrom: new Date(peerCertificate.valid_from).getTime() / 1000,
|
|
417
|
+
validTo: new Date(peerCertificate.valid_to).getTime() / 1000,
|
|
418
|
+
issuer: peerCertificate.issuer.CN
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
}));
|
|
422
|
+
|
|
423
|
+
// when using socks proxy, having the socket means the connection got established
|
|
424
|
+
if (agent instanceof _utilsBundle.SocksProxyAgent) (_tcpConnectionAt3 = tcpConnectionAt) !== null && _tcpConnectionAt3 !== void 0 ? _tcpConnectionAt3 : tcpConnectionAt = (0, _utils.monotonicTime)();
|
|
425
|
+
serverIPAddress = socket.remoteAddress;
|
|
426
|
+
serverPort = socket.remotePort;
|
|
427
|
+
});
|
|
428
|
+
request.on('finish', () => {
|
|
429
|
+
requestFinishAt = (0, _utils.monotonicTime)();
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
// http proxy
|
|
433
|
+
request.on('proxyConnect', () => {
|
|
434
|
+
var _tcpConnectionAt4;
|
|
435
|
+
(_tcpConnectionAt4 = tcpConnectionAt) !== null && _tcpConnectionAt4 !== void 0 ? _tcpConnectionAt4 : tcpConnectionAt = (0, _utils.monotonicTime)();
|
|
436
|
+
});
|
|
373
437
|
progress.log(`→ ${options.method} ${url.toString()}`);
|
|
374
438
|
if (options.headers) {
|
|
375
439
|
for (const [name, value] of Object.entries(options.headers)) progress.log(` ${name}: ${value}`);
|
|
@@ -470,7 +534,6 @@ class GlobalAPIRequestContext extends APIRequestContext {
|
|
|
470
534
|
let url = proxy === null || proxy === void 0 ? void 0 : proxy.server.trim();
|
|
471
535
|
if (!/^\w+:\/\//.test(url)) url = 'http://' + url;
|
|
472
536
|
proxy.server = url;
|
|
473
|
-
if (options.clientCertificates) throw new Error('Cannot specify both proxy and clientCertificates');
|
|
474
537
|
}
|
|
475
538
|
if (options.storageState) {
|
|
476
539
|
this._origins = options.storageState.origins;
|
|
@@ -515,6 +578,15 @@ class GlobalAPIRequestContext extends APIRequestContext {
|
|
|
515
578
|
}
|
|
516
579
|
}
|
|
517
580
|
exports.GlobalAPIRequestContext = GlobalAPIRequestContext;
|
|
581
|
+
function createProxyAgent(proxy) {
|
|
582
|
+
var _proxyURL$protocol;
|
|
583
|
+
const proxyURL = new URL(proxy.server);
|
|
584
|
+
if ((_proxyURL$protocol = proxyURL.protocol) !== null && _proxyURL$protocol !== void 0 && _proxyURL$protocol.startsWith('socks')) return new _utilsBundle.SocksProxyAgent(proxyURL);
|
|
585
|
+
if (proxy.username) proxyURL.username = proxy.username;
|
|
586
|
+
if (proxy.password) proxyURL.password = proxy.password;
|
|
587
|
+
// TODO: We should use HttpProxyAgent conditional on proxyURL.protocol instead of always using CONNECT method.
|
|
588
|
+
return new _utilsBundle.HttpsProxyAgent(proxyURL);
|
|
589
|
+
}
|
|
518
590
|
function toHeadersArray(rawHeaders) {
|
|
519
591
|
const result = [];
|
|
520
592
|
for (let i = 0; i < rawHeaders.length; i += 2) result.push({
|
|
@@ -525,26 +597,9 @@ function toHeadersArray(rawHeaders) {
|
|
|
525
597
|
}
|
|
526
598
|
const redirectStatus = [301, 302, 303, 307, 308];
|
|
527
599
|
function parseCookie(header) {
|
|
528
|
-
const
|
|
529
|
-
|
|
530
|
-
let value = '';
|
|
531
|
-
const separatorPos = p.indexOf('=');
|
|
532
|
-
if (separatorPos === -1) {
|
|
533
|
-
// If only a key is specified, the value is left undefined.
|
|
534
|
-
key = p.trim();
|
|
535
|
-
} else {
|
|
536
|
-
// Otherwise we assume that the key is the element before the first `=`
|
|
537
|
-
key = p.slice(0, separatorPos).trim();
|
|
538
|
-
// And the value is the rest of the string.
|
|
539
|
-
value = p.slice(separatorPos + 1).trim();
|
|
540
|
-
}
|
|
541
|
-
return [key, value];
|
|
542
|
-
});
|
|
543
|
-
if (!pairs.length) return null;
|
|
544
|
-
const [name, value] = pairs[0];
|
|
600
|
+
const raw = (0, _cookieStore.parseRawCookie)(header);
|
|
601
|
+
if (!raw) return null;
|
|
545
602
|
const cookie = {
|
|
546
|
-
name,
|
|
547
|
-
value,
|
|
548
603
|
domain: '',
|
|
549
604
|
path: '',
|
|
550
605
|
expires: -1,
|
|
@@ -552,55 +607,9 @@ function parseCookie(header) {
|
|
|
552
607
|
secure: false,
|
|
553
608
|
// From https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite
|
|
554
609
|
// The cookie-sending behavior if SameSite is not specified is SameSite=Lax.
|
|
555
|
-
sameSite: 'Lax'
|
|
610
|
+
sameSite: 'Lax',
|
|
611
|
+
...raw
|
|
556
612
|
};
|
|
557
|
-
for (let i = 1; i < pairs.length; i++) {
|
|
558
|
-
const [name, value] = pairs[i];
|
|
559
|
-
switch (name.toLowerCase()) {
|
|
560
|
-
case 'expires':
|
|
561
|
-
const expiresMs = +new Date(value);
|
|
562
|
-
// https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.1
|
|
563
|
-
if (isFinite(expiresMs)) {
|
|
564
|
-
if (expiresMs <= 0) cookie.expires = 0;else cookie.expires = Math.min(expiresMs / 1000, _network.kMaxCookieExpiresDateInSeconds);
|
|
565
|
-
}
|
|
566
|
-
break;
|
|
567
|
-
case 'max-age':
|
|
568
|
-
const maxAgeSec = parseInt(value, 10);
|
|
569
|
-
if (isFinite(maxAgeSec)) {
|
|
570
|
-
// From https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.2
|
|
571
|
-
// If delta-seconds is less than or equal to zero (0), let expiry-time
|
|
572
|
-
// be the earliest representable date and time.
|
|
573
|
-
if (maxAgeSec <= 0) cookie.expires = 0;else cookie.expires = Math.min(Date.now() / 1000 + maxAgeSec, _network.kMaxCookieExpiresDateInSeconds);
|
|
574
|
-
}
|
|
575
|
-
break;
|
|
576
|
-
case 'domain':
|
|
577
|
-
cookie.domain = value.toLocaleLowerCase() || '';
|
|
578
|
-
if (cookie.domain && !cookie.domain.startsWith('.') && cookie.domain.includes('.')) cookie.domain = '.' + cookie.domain;
|
|
579
|
-
break;
|
|
580
|
-
case 'path':
|
|
581
|
-
cookie.path = value || '';
|
|
582
|
-
break;
|
|
583
|
-
case 'secure':
|
|
584
|
-
cookie.secure = true;
|
|
585
|
-
break;
|
|
586
|
-
case 'httponly':
|
|
587
|
-
cookie.httpOnly = true;
|
|
588
|
-
break;
|
|
589
|
-
case 'samesite':
|
|
590
|
-
switch (value.toLowerCase()) {
|
|
591
|
-
case 'none':
|
|
592
|
-
cookie.sameSite = 'None';
|
|
593
|
-
break;
|
|
594
|
-
case 'lax':
|
|
595
|
-
cookie.sameSite = 'Lax';
|
|
596
|
-
break;
|
|
597
|
-
case 'strict':
|
|
598
|
-
cookie.sameSite = 'Strict';
|
|
599
|
-
break;
|
|
600
|
-
}
|
|
601
|
-
break;
|
|
602
|
-
}
|
|
603
|
-
}
|
|
604
613
|
return cookie;
|
|
605
614
|
}
|
|
606
615
|
function serializePostData(params, headers) {
|
|
@@ -53,7 +53,8 @@ class FFBrowser extends _browser.Browser {
|
|
|
53
53
|
browser._defaultContext = new FFBrowserContext(browser, undefined, options.persistent);
|
|
54
54
|
promises.push(browser._defaultContext._initialize());
|
|
55
55
|
}
|
|
56
|
-
|
|
56
|
+
const proxy = options.originalLaunchOptions.proxyOverride || options.proxy;
|
|
57
|
+
if (proxy) promises.push(browser.session.send('Browser.setBrowserProxy', toJugglerProxyOptions(proxy)));
|
|
57
58
|
await Promise.all(promises);
|
|
58
59
|
return browser;
|
|
59
60
|
}
|
|
@@ -205,7 +206,7 @@ class FFBrowserContext extends _browserContext.BrowserContext {
|
|
|
205
206
|
browserContextId,
|
|
206
207
|
bypassCSP: true
|
|
207
208
|
}));
|
|
208
|
-
if (this._options.ignoreHTTPSErrors) promises.push(this._browser.session.send('Browser.setIgnoreHTTPSErrors', {
|
|
209
|
+
if (this._options.ignoreHTTPSErrors || this._options.internalIgnoreHTTPSErrors) promises.push(this._browser.session.send('Browser.setIgnoreHTTPSErrors', {
|
|
209
210
|
browserContextId,
|
|
210
211
|
ignoreHTTPSErrors: true
|
|
211
212
|
}));
|
|
@@ -255,10 +256,11 @@ class FFBrowserContext extends _browserContext.BrowserContext {
|
|
|
255
256
|
});
|
|
256
257
|
}));
|
|
257
258
|
}
|
|
258
|
-
|
|
259
|
+
const proxy = this._options.proxyOverride || this._options.proxy;
|
|
260
|
+
if (proxy) {
|
|
259
261
|
promises.push(this._browser.session.send('Browser.setContextProxy', {
|
|
260
262
|
browserContextId: this._browserContextId,
|
|
261
|
-
...toJugglerProxyOptions(
|
|
263
|
+
...toJugglerProxyOptions(proxy)
|
|
262
264
|
}));
|
|
263
265
|
}
|
|
264
266
|
await Promise.all(promises);
|
|
@@ -52,18 +52,6 @@ class FFExecutionContext {
|
|
|
52
52
|
checkException(payload.exceptionDetails);
|
|
53
53
|
return payload.result.objectId;
|
|
54
54
|
}
|
|
55
|
-
rawCallFunctionNoReply(func, ...args) {
|
|
56
|
-
this._session.send('Runtime.callFunction', {
|
|
57
|
-
functionDeclaration: func.toString(),
|
|
58
|
-
args: args.map(a => a instanceof js.JSHandle ? {
|
|
59
|
-
objectId: a._objectId
|
|
60
|
-
} : {
|
|
61
|
-
value: a
|
|
62
|
-
}),
|
|
63
|
-
returnByValue: true,
|
|
64
|
-
executionContextId: this._executionContextId
|
|
65
|
-
}).catch(() => {});
|
|
66
|
-
}
|
|
67
55
|
async evaluateWithArguments(expression, returnByValue, utilityScript, values, objectIds) {
|
|
68
56
|
const payload = await this._session.send('Runtime.callFunction', {
|
|
69
57
|
functionDeclaration: expression,
|
|
@@ -101,9 +89,6 @@ class FFExecutionContext {
|
|
|
101
89
|
objectId
|
|
102
90
|
});
|
|
103
91
|
}
|
|
104
|
-
objectCount(objectId) {
|
|
105
|
-
throw new Error('Method not implemented in Firefox.');
|
|
106
|
-
}
|
|
107
92
|
}
|
|
108
93
|
exports.FFExecutionContext = FFExecutionContext;
|
|
109
94
|
function checkException(exceptionDetails) {
|