@checkly/playwright-core 1.42.18 → 1.47.20-alpha
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/ThirdPartyNotices.txt +144 -109
- package/browsers.json +15 -25
- package/lib/androidServerImpl.js +1 -1
- package/lib/browserServerImpl.js +1 -1
- package/lib/cli/driver.js +1 -3
- package/lib/cli/program.js +5 -10
- package/lib/client/android.js +1 -1
- package/lib/client/api.js +7 -0
- package/lib/client/browserContext.js +37 -5
- package/lib/client/browserType.js +19 -11
- package/lib/client/channelOwner.js +19 -16
- package/lib/client/clientInstrumentation.js +17 -7
- package/lib/client/clock.js +68 -0
- package/lib/client/connection.js +9 -6
- package/lib/client/electron.js +7 -5
- package/lib/client/elementHandle.js +44 -14
- package/lib/client/eventEmitter.js +314 -0
- package/lib/client/fetch.js +81 -28
- package/lib/client/frame.js +2 -4
- package/lib/client/jsHandle.js +7 -1
- package/lib/client/locator.js +9 -0
- package/lib/client/network.js +12 -9
- package/lib/client/page.js +45 -23
- package/lib/client/playwright.js +3 -0
- package/lib/client/tracing.js +7 -4
- package/lib/common/socksProxy.js +2 -2
- package/lib/generated/clockSource.js +7 -0
- package/lib/generated/injectedScriptSource.js +1 -1
- package/lib/generated/recorderSource.js +1 -1
- package/lib/generated/utilityScriptSource.js +1 -1
- package/lib/protocol/serializers.js +12 -11
- package/lib/protocol/validator.js +137 -55
- package/lib/server/bidi/bidiBrowser.js +296 -0
- package/lib/server/bidi/bidiConnection.js +206 -0
- package/lib/server/bidi/bidiExecutionContext.js +162 -0
- package/lib/server/bidi/bidiFirefox.js +110 -0
- package/lib/server/bidi/bidiInput.js +174 -0
- package/lib/server/bidi/bidiNetworkManager.js +304 -0
- package/lib/server/bidi/bidiPage.js +456 -0
- package/lib/server/bidi/third_party/bidiDeserializer.js +93 -0
- package/lib/server/bidi/third_party/bidiKeyboard.js +238 -0
- package/lib/server/bidi/third_party/bidiProtocol.js +139 -0
- package/lib/server/bidi/third_party/bidiSerializer.js +144 -0
- package/lib/server/browser.js +9 -1
- package/lib/server/browserContext.js +97 -22
- package/lib/server/browserType.js +27 -20
- package/lib/server/chromium/chromium.js +30 -15
- package/lib/server/chromium/chromiumSwitches.js +6 -3
- package/lib/server/chromium/crBrowser.js +11 -17
- package/lib/server/chromium/crConnection.js +2 -2
- package/lib/server/chromium/crDragDrop.js +28 -29
- package/lib/server/chromium/crNetworkManager.js +130 -84
- package/lib/server/chromium/crPage.js +34 -79
- package/lib/server/chromium/crProtocolHelper.js +3 -1
- package/lib/server/chromium/crServiceWorker.js +20 -23
- package/lib/server/chromium/videoRecorder.js +1 -1
- package/lib/server/clock.js +125 -0
- package/lib/server/codegen/csharp.js +299 -0
- package/lib/server/codegen/java.js +235 -0
- package/lib/server/codegen/javascript.js +223 -0
- package/lib/server/codegen/jsonl.js +47 -0
- package/lib/server/codegen/language.js +76 -0
- package/lib/server/codegen/languages.js +30 -0
- package/lib/server/codegen/python.js +265 -0
- package/lib/server/codegen/types.js +5 -0
- package/lib/server/debugController.js +3 -5
- package/lib/server/deviceDescriptors.js +9 -4
- package/lib/server/deviceDescriptorsSource.json +239 -119
- package/lib/server/dispatchers/androidDispatcher.js +1 -1
- package/lib/server/dispatchers/browserContextDispatcher.js +51 -7
- package/lib/server/dispatchers/dispatcher.js +36 -40
- package/lib/server/dispatchers/frameDispatcher.js +1 -2
- package/lib/server/dispatchers/jsHandleDispatcher.js +1 -1
- package/lib/server/dispatchers/jsonPipeDispatcher.js +4 -6
- package/lib/server/dispatchers/localUtilsDispatcher.js +19 -5
- package/lib/server/dispatchers/networkDispatchers.js +2 -2
- package/lib/server/dispatchers/pageDispatcher.js +5 -2
- package/lib/server/dispatchers/playwrightDispatcher.js +1 -0
- package/lib/server/dispatchers/writableStreamDispatcher.js +8 -5
- package/lib/server/dom.js +90 -53
- package/lib/server/electron/electron.js +21 -4
- package/lib/server/fetch.js +74 -25
- package/lib/server/fileUploadUtils.js +7 -3
- package/lib/server/firefox/ffBrowser.js +36 -25
- package/lib/server/firefox/ffConnection.js +2 -2
- package/lib/server/firefox/ffNetworkManager.js +6 -4
- package/lib/server/firefox/ffPage.js +22 -24
- package/lib/server/firefox/firefox.js +25 -6
- package/lib/server/frameSelectors.js +2 -2
- package/lib/server/frames.js +205 -159
- package/lib/server/har/harTracer.js +4 -12
- package/lib/server/helper.js +3 -3
- package/lib/server/index.js +18 -0
- package/lib/server/input.js +18 -8
- package/lib/server/instrumentation.js +0 -4
- package/lib/server/isomorphic/utilityScriptSerializers.js +19 -5
- package/lib/server/javascript.js +3 -2
- package/lib/server/launchApp.js +3 -2
- package/lib/server/network.js +14 -4
- package/lib/server/page.js +75 -46
- package/lib/server/playwright.js +5 -2
- package/lib/server/recorder/codeGenerator.js +2 -1
- package/lib/server/recorder/contextRecorder.js +316 -0
- package/lib/server/recorder/csharp.js +2 -1
- package/lib/server/recorder/java.js +2 -1
- package/lib/server/recorder/javascript.js +2 -1
- package/lib/server/recorder/jsonl.js +2 -1
- package/lib/server/recorder/language.js +2 -1
- package/lib/server/recorder/python.js +2 -1
- package/lib/server/recorder/recorderApp.js +14 -5
- package/lib/server/recorder/recorderCollection.js +127 -0
- package/lib/server/recorder/recorderRunner.js +177 -0
- package/lib/server/recorder/recorderUtils.js +23 -0
- package/lib/server/recorder/throttledFile.js +46 -0
- package/lib/server/recorder/utils.js +2 -1
- package/lib/server/recorder.js +42 -418
- package/lib/server/registry/index.js +99 -100
- package/lib/server/registry/nativeDeps.js +107 -0
- package/lib/server/screenshotter.js +6 -12
- package/lib/server/socksClientCertificatesInterceptor.js +328 -0
- package/lib/server/trace/recorder/snapshotter.js +4 -1
- package/lib/server/trace/recorder/tracing.js +27 -96
- package/lib/server/trace/viewer/traceViewer.js +54 -67
- package/lib/server/transport.js +1 -1
- package/lib/server/webkit/webkit.js +5 -5
- package/lib/server/webkit/wkBrowser.js +14 -14
- package/lib/server/webkit/wkConnection.js +3 -3
- package/lib/server/webkit/wkInterceptableRequest.js +8 -4
- package/lib/server/webkit/wkPage.js +52 -34
- package/lib/server/webkit/wkProvisionalPage.js +36 -1
- package/lib/utils/crypto.js +141 -0
- package/lib/utils/debugLogger.js +2 -0
- package/lib/utils/env.js +4 -2
- package/lib/utils/expectUtils.js +33 -0
- package/lib/utils/fileUtils.js +140 -1
- package/lib/utils/glob.js +2 -1
- package/lib/utils/happy-eyeballs.js +29 -2
- package/lib/utils/hostPlatform.js +13 -4
- package/lib/utils/httpServer.js +54 -13
- package/lib/utils/index.js +53 -31
- package/lib/utils/isomorphic/cssTokenizer.js +1 -1
- package/lib/utils/isomorphic/locatorParser.js +1 -1
- package/lib/utils/isomorphic/mimeType.js +29 -0
- package/lib/utils/isomorphic/stringUtils.js +28 -1
- package/lib/utils/isomorphic/urlMatch.js +120 -0
- package/lib/utils/mimeType.js +2 -1
- package/lib/utils/network.js +7 -35
- package/lib/utils/stackTrace.js +2 -4
- package/lib/utils/timeoutRunner.js +11 -76
- package/lib/utils/zones.js +23 -60
- package/lib/utilsBundle.js +2 -1
- package/lib/utilsBundleImpl/index.js +33 -31
- package/lib/vite/htmlReport/index.html +12 -12
- package/lib/vite/recorder/assets/codeMirrorModule-C-fQ5QZD.js +24 -0
- package/lib/vite/recorder/assets/{codicon-zGuYmc9o.ttf → codicon-DCmgc-ay.ttf} +0 -0
- package/lib/vite/recorder/assets/index-B-MT5gKo.css +1 -0
- package/lib/vite/recorder/assets/index-D-5S5PPN.js +47 -0
- package/lib/vite/recorder/index.html +2 -2
- package/lib/vite/traceViewer/assets/codeMirrorModule-5yiV-3wl.js +16831 -0
- package/lib/vite/traceViewer/assets/codeMirrorModule-B7Z3vq11.js +24 -0
- package/lib/vite/traceViewer/assets/codeMirrorModule-C6p3E9Zg.js +24 -0
- package/lib/vite/traceViewer/assets/codeMirrorModule-CqYUz5ms.js +24 -0
- package/lib/vite/traceViewer/assets/codeMirrorModule-Dx6AXgMV.js +16838 -0
- package/lib/vite/traceViewer/assets/codeMirrorModule-T_sdMrbM.js +24 -0
- package/lib/vite/traceViewer/assets/codeMirrorModule-V7N6ppkd.js +15585 -0
- package/lib/vite/traceViewer/assets/testServerConnection-D-tXL3sj.js +224 -0
- package/lib/vite/traceViewer/assets/testServerConnection-DeE2kSzz.js +1 -0
- package/lib/vite/traceViewer/assets/workbench-Bjkiwcr1.js +19119 -0
- package/lib/vite/traceViewer/assets/workbench-C43LWZEX.js +72 -0
- package/lib/vite/traceViewer/assets/workbench-C5OQh9VX.js +19119 -0
- package/lib/vite/traceViewer/assets/workbench-DrQjKdyE.js +72 -0
- package/lib/vite/traceViewer/assets/workbench-caTaZnzx.js +72 -0
- package/lib/vite/traceViewer/assets/workbench-u2lRPMOT.js +72 -0
- package/lib/vite/traceViewer/assets/wsPort-EUvw-dwH.js +18540 -0
- package/lib/vite/traceViewer/assets/xtermModule-CZ7sDYXB.js +6529 -0
- package/lib/vite/traceViewer/assets/xtermModule-_6TC5FYT.js +6529 -0
- package/lib/vite/traceViewer/codeMirrorModule.Cy8X9Wtw.css +344 -0
- package/lib/vite/traceViewer/codeMirrorModule.svF_VrcJ.css +344 -0
- package/lib/vite/traceViewer/codicon.DCmgc-ay.ttf +0 -0
- package/lib/vite/traceViewer/embedded.BQq6Psnz.js +104 -0
- package/lib/vite/traceViewer/embedded.BVDVQOzc.js +2 -0
- package/lib/vite/traceViewer/embedded.Bn8Ptzv6.js +2 -0
- package/lib/vite/traceViewer/embedded.CvhnUgIi.js +2 -0
- package/lib/vite/traceViewer/embedded.D27cnKiB.js +104 -0
- package/lib/vite/traceViewer/embedded.DPqrDeET.js +2 -0
- package/lib/vite/traceViewer/embedded.DjZq4InJ.css +68 -0
- package/lib/vite/traceViewer/embedded.html +16 -0
- package/lib/vite/traceViewer/embedded.w7WN2u1R.css +1 -0
- package/lib/vite/traceViewer/index.5mge2rY_.css +124 -0
- package/lib/vite/traceViewer/index.6KJ-JQ0L.js +180 -0
- package/lib/vite/traceViewer/index.B8dgQwuN.js +2 -0
- package/lib/vite/traceViewer/index.BGj8jY3H.js +2 -0
- package/lib/vite/traceViewer/index.C0EgJ4oW.js +195 -0
- package/lib/vite/traceViewer/index.CUpI-BFe.js +195 -0
- package/lib/vite/traceViewer/{index.-g_5lMbJ.css → index.CrbWWHbf.css} +1 -1
- package/lib/vite/traceViewer/index.QanXxRUb.css +131 -0
- package/lib/vite/traceViewer/index._cX8k4co.js +2 -0
- package/lib/vite/traceViewer/index.html +5 -4
- package/lib/vite/traceViewer/index.pMAN88y-.js +2 -0
- package/lib/vite/traceViewer/snapshot.html +1 -1
- package/lib/vite/traceViewer/sw.bundle.js +3 -4
- package/lib/vite/traceViewer/uiMode.D-tg1Oci.js +1730 -0
- package/lib/vite/traceViewer/uiMode.D3cNFP6u.css +1 -0
- package/lib/vite/traceViewer/uiMode.DKjMBMlc.js +1730 -0
- package/lib/vite/traceViewer/uiMode.DVWUEIHq.css +1424 -0
- package/lib/vite/traceViewer/uiMode.DVrL7a1K.js +10 -0
- package/lib/vite/traceViewer/uiMode.Dg9oJCQU.js +10 -0
- package/lib/vite/traceViewer/uiMode.DwZAzstF.js +10 -0
- package/lib/vite/traceViewer/uiMode.html +5 -4
- package/lib/vite/traceViewer/uiMode.iq7CyYy7.js +1490 -0
- package/lib/vite/traceViewer/uiMode.jY2s-9ps.js +10 -0
- package/lib/vite/traceViewer/uiMode.xvJHbkzl.css +1324 -0
- package/lib/vite/traceViewer/workbench.B3X2QtYa.css +3702 -0
- package/lib/vite/traceViewer/workbench.DyTpxWVb.css +1 -0
- package/lib/vite/traceViewer/wsPort.p5jUwABW.css +3450 -0
- package/lib/vite/traceViewer/xtermModule.4oRVGWQ-.css +209 -0
- package/lib/vite/traceViewer/xtermModule.OKEVRlkP.css +209 -0
- package/package.json +2 -2
- package/types/protocol.d.ts +960 -78
- package/types/structs.d.ts +1 -1
- package/types/types.d.ts +3083 -2448
- package/lib/vite/recorder/assets/codeMirrorModule-W69B4LBB.js +0 -24
- package/lib/vite/recorder/assets/index-Ly3PcVUb.js +0 -47
- package/lib/vite/recorder/assets/index-ljsTwXtJ.css +0 -1
- package/lib/vite/traceViewer/assets/codeMirrorModule-0bpaqixv.js +0 -24
- package/lib/vite/traceViewer/assets/codeMirrorModule-wLpsbIhd.js +0 -24
- package/lib/vite/traceViewer/assets/wsPort-_JBDEilC.js +0 -69
- package/lib/vite/traceViewer/assets/wsPort-f2dAQL4I.js +0 -69
- package/lib/vite/traceViewer/index.-_8-eHEE.js +0 -2
- package/lib/vite/traceViewer/index.u51inEcm.js +0 -2
- package/lib/vite/traceViewer/uiMode.9CwNsWc6.js +0 -10
- package/lib/vite/traceViewer/uiMode.Fb0bNA4H.js +0 -10
- package/lib/vite/traceViewer/uiMode.pWy0Re7G.css +0 -1
- package/lib/vite/traceViewer/wsPort.zR1WIy9-.css +0 -1
- /package/lib/vite/recorder/assets/{codeMirrorModule-Hs9-1ZG4.css → codeMirrorModule-ez37Vkbh.css} +0 -0
- /package/lib/vite/traceViewer/assets/{xtermModule-Yt6xwiJ_.js → xtermModule-BeNbaIVa.js} +0 -0
- /package/lib/vite/traceViewer/{codeMirrorModule.Hs9-1ZG4.css → codeMirrorModule.ez37Vkbh.css} +0 -0
- /package/lib/vite/traceViewer/{xtermModule.0lwXJFHT.css → xtermModule.DSXBckUd.css} +0 -0
|
@@ -5,10 +5,11 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.BrowserContext = void 0;
|
|
7
7
|
exports.assertBrowserContextIsNotOwned = assertBrowserContextIsNotOwned;
|
|
8
|
+
exports.createClientCertificatesProxyIfNeeded = createClientCertificatesProxyIfNeeded;
|
|
8
9
|
exports.normalizeProxySettings = normalizeProxySettings;
|
|
9
10
|
exports.validateBrowserContextOptions = validateBrowserContextOptions;
|
|
11
|
+
exports.verifyClientCertificates = verifyClientCertificates;
|
|
10
12
|
exports.verifyGeolocation = verifyGeolocation;
|
|
11
|
-
var os = _interopRequireWildcard(require("os"));
|
|
12
13
|
var _timeoutSettings = require("../common/timeoutSettings");
|
|
13
14
|
var _utils = require("../utils");
|
|
14
15
|
var _fileUtils = require("../utils/fileUtils");
|
|
@@ -24,6 +25,9 @@ var _harRecorder = require("./har/harRecorder");
|
|
|
24
25
|
var _recorder = require("./recorder");
|
|
25
26
|
var consoleApiSource = _interopRequireWildcard(require("../generated/consoleApiSource"));
|
|
26
27
|
var _fetch = require("./fetch");
|
|
28
|
+
var _clock = require("./clock");
|
|
29
|
+
var _socksClientCertificatesInterceptor = require("./socksClientCertificatesInterceptor");
|
|
30
|
+
var _recorderApp = require("./recorder/recorderApp");
|
|
27
31
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
28
32
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
29
33
|
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
@@ -72,6 +76,8 @@ class BrowserContext extends _instrumentation.SdkObject {
|
|
|
72
76
|
this._routesInFlight = new Set();
|
|
73
77
|
this._debugger = void 0;
|
|
74
78
|
this._closeReason = void 0;
|
|
79
|
+
this.clock = void 0;
|
|
80
|
+
this._clientCertificatesProxy = void 0;
|
|
75
81
|
this.attribution.context = this;
|
|
76
82
|
this._browser = browser;
|
|
77
83
|
this._options = options;
|
|
@@ -81,6 +87,7 @@ class BrowserContext extends _instrumentation.SdkObject {
|
|
|
81
87
|
this.fetchRequest = new _fetch.BrowserContextAPIRequestContext(this);
|
|
82
88
|
if (this._options.recordHar) this._harRecorders.set('', new _harRecorder.HarRecorder(this, null, this._options.recordHar));
|
|
83
89
|
this.tracing = new _tracing.Tracing(this, browser.options.tracesDir);
|
|
90
|
+
this.clock = new _clock.Clock(this);
|
|
84
91
|
}
|
|
85
92
|
isPersistentContext() {
|
|
86
93
|
return this._isPersistentContext;
|
|
@@ -97,17 +104,17 @@ class BrowserContext extends _instrumentation.SdkObject {
|
|
|
97
104
|
this._debugger = new _debugger.Debugger(this);
|
|
98
105
|
|
|
99
106
|
// When PWDEBUG=1, show inspector for each context.
|
|
100
|
-
if ((0, _utils.debugMode)() === 'inspector') await _recorder.Recorder.show(this, {
|
|
107
|
+
if ((0, _utils.debugMode)() === 'inspector') await _recorder.Recorder.show(this, _recorderApp.RecorderApp.factory(this), {
|
|
101
108
|
pauseOnNextStatement: true
|
|
102
109
|
});
|
|
103
110
|
|
|
104
111
|
// When paused, show inspector.
|
|
105
|
-
if (this._debugger.isPaused()) _recorder.Recorder.showInspector(this);
|
|
112
|
+
if (this._debugger.isPaused()) _recorder.Recorder.showInspector(this, _recorderApp.RecorderApp.factory(this));
|
|
106
113
|
this._debugger.on(_debugger.Debugger.Events.PausedStateChanged, () => {
|
|
107
|
-
_recorder.Recorder.showInspector(this);
|
|
114
|
+
if (this._debugger.isPaused()) _recorder.Recorder.showInspector(this, _recorderApp.RecorderApp.factory(this));
|
|
108
115
|
});
|
|
109
116
|
if ((0, _utils.debugMode)() === 'console') await this.extendInjectedScript(consoleApiSource.source);
|
|
110
|
-
if (this._options.serviceWorkers === 'block') await this.addInitScript(`\
|
|
117
|
+
if (this._options.serviceWorkers === 'block') await this.addInitScript(`\nif (navigator.serviceWorker) navigator.serviceWorker.register = async () => { console.warn('Service Worker registration blocked by Playwright'); };\n`);
|
|
111
118
|
if (this._options.permissions) await this.grantPermissions(this._options.permissions);
|
|
112
119
|
}
|
|
113
120
|
debugger() {
|
|
@@ -168,6 +175,7 @@ class BrowserContext extends _instrumentation.SdkObject {
|
|
|
168
175
|
await this._resetStorage();
|
|
169
176
|
await this._removeExposedBindings();
|
|
170
177
|
await this._removeInitScripts();
|
|
178
|
+
this.clock.markAsUninstalled();
|
|
171
179
|
// TODO: following can be optimized to not perform noops.
|
|
172
180
|
if (this._options.permissions) await this.grantPermissions(this._options.permissions);else await this.clearPermissions();
|
|
173
181
|
await this.setExtraHTTPHeaders(this._options.extraHTTPHeaders || []);
|
|
@@ -183,11 +191,13 @@ class BrowserContext extends _instrumentation.SdkObject {
|
|
|
183
191
|
this._didCloseInternal();
|
|
184
192
|
}
|
|
185
193
|
_didCloseInternal() {
|
|
194
|
+
var _this$_clientCertific;
|
|
186
195
|
if (this._closedStatus === 'closed') {
|
|
187
196
|
// We can come here twice if we close browser context and browser
|
|
188
197
|
// at the same time.
|
|
189
198
|
return;
|
|
190
199
|
}
|
|
200
|
+
(_this$_clientCertific = this._clientCertificatesProxy) === null || _this$_clientCertific === void 0 || _this$_clientCertific.close().catch(() => {});
|
|
191
201
|
this.tracing.abort();
|
|
192
202
|
if (this._isPersistentContext) this.onClosePersistent();
|
|
193
203
|
this._closePromiseFulfill(new Error('Context closed'));
|
|
@@ -200,6 +210,22 @@ class BrowserContext extends _instrumentation.SdkObject {
|
|
|
200
210
|
if (urls && !Array.isArray(urls)) urls = [urls];
|
|
201
211
|
return await this.doGetCookies(urls);
|
|
202
212
|
}
|
|
213
|
+
async clearCookies(options) {
|
|
214
|
+
const currentCookies = await this.cookies();
|
|
215
|
+
await this.doClearCookies();
|
|
216
|
+
const matches = (cookie, prop, value) => {
|
|
217
|
+
if (!value) return true;
|
|
218
|
+
if (value instanceof RegExp) {
|
|
219
|
+
value.lastIndex = 0;
|
|
220
|
+
return value.test(cookie[prop]);
|
|
221
|
+
}
|
|
222
|
+
return cookie[prop] === value;
|
|
223
|
+
};
|
|
224
|
+
const cookiesToReadd = currentCookies.filter(cookie => {
|
|
225
|
+
return !matches(cookie, 'name', options.name) || !matches(cookie, 'domain', options.domain) || !matches(cookie, 'path', options.path);
|
|
226
|
+
});
|
|
227
|
+
await this.addCookies(cookiesToReadd);
|
|
228
|
+
}
|
|
203
229
|
setHTTPCredentials(httpCredentials) {
|
|
204
230
|
return this.doSetHTTPCredentials(httpCredentials);
|
|
205
231
|
}
|
|
@@ -210,13 +236,14 @@ class BrowserContext extends _instrumentation.SdkObject {
|
|
|
210
236
|
}
|
|
211
237
|
const binding = new _page6.PageBinding(name, playwrightBinding, needsHandle);
|
|
212
238
|
this._pageBindings.set(name, binding);
|
|
213
|
-
await this.
|
|
239
|
+
await this.doAddInitScript(binding.initScript);
|
|
240
|
+
const frames = this.pages().map(page => page.frames()).flat();
|
|
241
|
+
await Promise.all(frames.map(frame => frame.evaluateExpression(binding.initScript.source).catch(e => {})));
|
|
214
242
|
}
|
|
215
243
|
async _removeExposedBindings() {
|
|
216
|
-
for (const key of this._pageBindings
|
|
217
|
-
if (!
|
|
244
|
+
for (const [key, binding] of this._pageBindings) {
|
|
245
|
+
if (!binding.internal) this._pageBindings.delete(key);
|
|
218
246
|
}
|
|
219
|
-
await this.doRemoveExposedBindings();
|
|
220
247
|
}
|
|
221
248
|
async grantPermissions(permissions, origin) {
|
|
222
249
|
let resolvedOrigin = '*';
|
|
@@ -294,13 +321,14 @@ class BrowserContext extends _instrumentation.SdkObject {
|
|
|
294
321
|
password: password || ''
|
|
295
322
|
};
|
|
296
323
|
}
|
|
297
|
-
async addInitScript(
|
|
298
|
-
|
|
299
|
-
|
|
324
|
+
async addInitScript(source) {
|
|
325
|
+
const initScript = new _page6.InitScript(source);
|
|
326
|
+
this.initScripts.push(initScript);
|
|
327
|
+
await this.doAddInitScript(initScript);
|
|
300
328
|
}
|
|
301
329
|
async _removeInitScripts() {
|
|
302
|
-
this.initScripts
|
|
303
|
-
await this.
|
|
330
|
+
this.initScripts = this.initScripts.filter(script => script.internal);
|
|
331
|
+
await this.doRemoveNonInternalInitScripts();
|
|
304
332
|
}
|
|
305
333
|
async setRequestInterceptor(handler) {
|
|
306
334
|
this._requestInterceptor = handler;
|
|
@@ -371,7 +399,28 @@ class BrowserContext extends _instrumentation.SdkObject {
|
|
|
371
399
|
cookies: await this.cookies(),
|
|
372
400
|
origins: []
|
|
373
401
|
};
|
|
374
|
-
|
|
402
|
+
const originsToSave = new Set(this._origins);
|
|
403
|
+
|
|
404
|
+
// First try collecting storage stage from existing pages.
|
|
405
|
+
for (const page of this.pages()) {
|
|
406
|
+
const origin = page.mainFrame().origin();
|
|
407
|
+
if (!origin || !originsToSave.has(origin)) continue;
|
|
408
|
+
try {
|
|
409
|
+
const storage = await page.mainFrame().nonStallingEvaluateInExistingContext(`({
|
|
410
|
+
localStorage: Object.keys(localStorage).map(name => ({ name, value: localStorage.getItem(name) })),
|
|
411
|
+
})`, 'utility');
|
|
412
|
+
if (storage.localStorage.length) result.origins.push({
|
|
413
|
+
origin,
|
|
414
|
+
localStorage: storage.localStorage
|
|
415
|
+
});
|
|
416
|
+
originsToSave.delete(origin);
|
|
417
|
+
} catch {
|
|
418
|
+
// When failed on the live page, we'll retry on the blank page below.
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// If there are still origins to save, create a blank page to iterate over origins.
|
|
423
|
+
if (originsToSave.size) {
|
|
375
424
|
const internalMetadata = (0, _instrumentation.serverSideCallMetadata)();
|
|
376
425
|
const page = await this.newPage(internalMetadata);
|
|
377
426
|
await page._setServerRequestInterceptor(handler => {
|
|
@@ -381,7 +430,7 @@ class BrowserContext extends _instrumentation.SdkObject {
|
|
|
381
430
|
}).catch(() => {});
|
|
382
431
|
return true;
|
|
383
432
|
});
|
|
384
|
-
for (const origin of
|
|
433
|
+
for (const origin of originsToSave) {
|
|
385
434
|
const originStorage = {
|
|
386
435
|
origin,
|
|
387
436
|
localStorage: []
|
|
@@ -431,7 +480,7 @@ class BrowserContext extends _instrumentation.SdkObject {
|
|
|
431
480
|
}
|
|
432
481
|
async _resetCookies() {
|
|
433
482
|
var _this$_options$storag2, _this$_options$storag3;
|
|
434
|
-
await this.
|
|
483
|
+
await this.doClearCookies();
|
|
435
484
|
if ((_this$_options$storag2 = this._options.storageState) !== null && _this$_options$storag2 !== void 0 && _this$_options$storag2.cookies) await this.addCookies((_this$_options$storag3 = this._options.storageState) === null || _this$_options$storag3 === void 0 ? void 0 : _this$_options$storag3.cookies);
|
|
436
485
|
}
|
|
437
486
|
isSettingStorageState() {
|
|
@@ -478,6 +527,9 @@ class BrowserContext extends _instrumentation.SdkObject {
|
|
|
478
527
|
this.on(BrowserContext.Events.Page, installInPage);
|
|
479
528
|
return Promise.all(this.pages().map(installInPage));
|
|
480
529
|
}
|
|
530
|
+
async safeNonStallingEvaluateInAllFrames(expression, world, options = {}) {
|
|
531
|
+
await Promise.all(this.pages().map(page => page.safeNonStallingEvaluateInAllFrames(expression, world, options)));
|
|
532
|
+
}
|
|
481
533
|
async _harStart(page, options) {
|
|
482
534
|
const harId = (0, _utils.createGuid)();
|
|
483
535
|
this._harRecorders.set(harId, new _harRecorder.HarRecorder(this, page, options));
|
|
@@ -522,10 +574,26 @@ function assertBrowserContextIsNotOwned(context) {
|
|
|
522
574
|
if (page._ownedContext) throw new Error('Please use browser.newContext() for multi-page scripts that share the context.');
|
|
523
575
|
}
|
|
524
576
|
}
|
|
577
|
+
async function createClientCertificatesProxyIfNeeded(options, browserOptions) {
|
|
578
|
+
var _options$clientCertif, _options$proxy, _options$proxy2, _browserOptions$proxy, _browserOptions$proxy2;
|
|
579
|
+
if (!((_options$clientCertif = options.clientCertificates) !== null && _options$clientCertif !== void 0 && _options$clientCertif.length)) return;
|
|
580
|
+
if ((_options$proxy = options.proxy) !== null && _options$proxy !== void 0 && _options$proxy.server && ((_options$proxy2 = options.proxy) === null || _options$proxy2 === void 0 ? void 0 : _options$proxy2.server) !== 'per-context' || browserOptions !== null && browserOptions !== void 0 && (_browserOptions$proxy = browserOptions.proxy) !== null && _browserOptions$proxy !== void 0 && _browserOptions$proxy.server && (browserOptions === null || browserOptions === void 0 || (_browserOptions$proxy2 = browserOptions.proxy) === null || _browserOptions$proxy2 === void 0 ? void 0 : _browserOptions$proxy2.server) !== 'http://per-context') throw new Error('Cannot specify both proxy and clientCertificates');
|
|
581
|
+
verifyClientCertificates(options.clientCertificates);
|
|
582
|
+
const clientCertificatesProxy = new _socksClientCertificatesInterceptor.ClientCertificatesProxy(options);
|
|
583
|
+
options.proxy = {
|
|
584
|
+
server: await clientCertificatesProxy.listen()
|
|
585
|
+
};
|
|
586
|
+
options.ignoreHTTPSErrors = true;
|
|
587
|
+
return clientCertificatesProxy;
|
|
588
|
+
}
|
|
525
589
|
function validateBrowserContextOptions(options, browserOptions) {
|
|
526
590
|
if (options.noDefaultViewport && options.deviceScaleFactor !== undefined) throw new Error(`"deviceScaleFactor" option is not supported with null "viewport"`);
|
|
527
591
|
if (options.noDefaultViewport && !!options.isMobile) throw new Error(`"isMobile" option is not supported with null "viewport"`);
|
|
528
|
-
if (options.acceptDownloads === undefined) options.acceptDownloads = 'accept';
|
|
592
|
+
if (options.acceptDownloads === undefined && browserOptions.name !== 'electron') options.acceptDownloads = 'accept';
|
|
593
|
+
// Electron requires explicit acceptDownloads: true since we wait for
|
|
594
|
+
// https://github.com/electron/electron/pull/41718 to be widely shipped.
|
|
595
|
+
// In 6-12 months, we can remove this check.
|
|
596
|
+
else if (options.acceptDownloads === undefined && browserOptions.name === 'electron') options.acceptDownloads = 'internal-browser-default';
|
|
529
597
|
if (!options.viewport && !options.noDefaultViewport) options.viewport = {
|
|
530
598
|
width: 1280,
|
|
531
599
|
height: 720
|
|
@@ -550,10 +618,7 @@ function validateBrowserContextOptions(options, browserOptions) {
|
|
|
550
618
|
options.recordVideo.size.width &= ~1;
|
|
551
619
|
options.recordVideo.size.height &= ~1;
|
|
552
620
|
}
|
|
553
|
-
if (options.proxy)
|
|
554
|
-
if (!browserOptions.proxy && browserOptions.isChromium && os.platform() === 'win32') throw new Error(`Browser needs to be launched with the global proxy. If all contexts override the proxy, global proxy will be never used and can be any string, for example "launch({ proxy: { server: 'http://per-context' } })"`);
|
|
555
|
-
options.proxy = normalizeProxySettings(options.proxy);
|
|
556
|
-
}
|
|
621
|
+
if (options.proxy) options.proxy = normalizeProxySettings(options.proxy);
|
|
557
622
|
verifyGeolocation(options.geolocation);
|
|
558
623
|
}
|
|
559
624
|
function verifyGeolocation(geolocation) {
|
|
@@ -568,6 +633,16 @@ function verifyGeolocation(geolocation) {
|
|
|
568
633
|
if (latitude < -90 || latitude > 90) throw new Error(`geolocation.latitude: precondition -90 <= LATITUDE <= 90 failed.`);
|
|
569
634
|
if (accuracy < 0) throw new Error(`geolocation.accuracy: precondition 0 <= ACCURACY failed.`);
|
|
570
635
|
}
|
|
636
|
+
function verifyClientCertificates(clientCertificates) {
|
|
637
|
+
if (!clientCertificates) return;
|
|
638
|
+
for (const cert of clientCertificates) {
|
|
639
|
+
if (!cert.origin) throw new Error(`clientCertificates.origin is required`);
|
|
640
|
+
if (!cert.cert && !cert.key && !cert.passphrase && !cert.pfx) throw new Error('None of cert, key, passphrase or pfx is specified');
|
|
641
|
+
if (cert.cert && !cert.key) throw new Error('cert is specified without key');
|
|
642
|
+
if (!cert.cert && cert.key) throw new Error('key is specified without cert');
|
|
643
|
+
if (cert.pfx && (cert.cert || cert.key)) throw new Error('pfx is specified together with cert, key or passphrase');
|
|
644
|
+
}
|
|
645
|
+
}
|
|
571
646
|
function normalizeProxySettings(proxy) {
|
|
572
647
|
let {
|
|
573
648
|
server,
|
|
@@ -19,7 +19,6 @@ var _fileUtils = require("../utils/fileUtils");
|
|
|
19
19
|
var _helper = require("./helper");
|
|
20
20
|
var _debugLogger = require("../utils/debugLogger");
|
|
21
21
|
var _instrumentation = require("./instrumentation");
|
|
22
|
-
var _manualPromise = require("../utils/manualPromise");
|
|
23
22
|
var _protocolError = require("./protocolError");
|
|
24
23
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
25
24
|
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
@@ -45,6 +44,7 @@ class BrowserType extends _instrumentation.SdkObject {
|
|
|
45
44
|
constructor(parent, browserName) {
|
|
46
45
|
super(parent, 'browser-type');
|
|
47
46
|
this._name = void 0;
|
|
47
|
+
this._useBidi = false;
|
|
48
48
|
this.attribution.browserType = this;
|
|
49
49
|
this._name = browserName;
|
|
50
50
|
}
|
|
@@ -56,6 +56,7 @@ class BrowserType extends _instrumentation.SdkObject {
|
|
|
56
56
|
}
|
|
57
57
|
async launch(metadata, options, protocolLogger) {
|
|
58
58
|
options = this._validateLaunchOptions(options);
|
|
59
|
+
if (this._useBidi) options.useWebSocket = true;
|
|
59
60
|
const controller = new _progress.ProgressController(metadata, this);
|
|
60
61
|
controller.setLogName('browser');
|
|
61
62
|
const browser = await controller.run(progress => {
|
|
@@ -69,13 +70,22 @@ class BrowserType extends _instrumentation.SdkObject {
|
|
|
69
70
|
}
|
|
70
71
|
async launchPersistentContext(metadata, userDataDir, options) {
|
|
71
72
|
options = this._validateLaunchOptions(options);
|
|
73
|
+
if (this._useBidi) options.useWebSocket = true;
|
|
72
74
|
const controller = new _progress.ProgressController(metadata, this);
|
|
73
|
-
const persistent =
|
|
75
|
+
const persistent = {
|
|
76
|
+
...options
|
|
77
|
+
};
|
|
74
78
|
controller.setLogName('browser');
|
|
75
|
-
const browser = await controller.run(progress => {
|
|
76
|
-
|
|
79
|
+
const browser = await controller.run(async progress => {
|
|
80
|
+
// Note: Any initial TLS requests will fail since we rely on the Page/Frames initialize which sets ignoreHTTPSErrors.
|
|
81
|
+
const clientCertificatesProxy = await (0, _browserContext.createClientCertificatesProxyIfNeeded)(persistent);
|
|
82
|
+
if (clientCertificatesProxy) options.proxy = persistent.proxy;
|
|
83
|
+
progress.cleanupWhenAborted(() => clientCertificatesProxy === null || clientCertificatesProxy === void 0 ? void 0 : clientCertificatesProxy.close());
|
|
84
|
+
const browser = await this._innerLaunchWithRetries(progress, options, persistent, _helper.helper.debugProtocolLogger(), userDataDir).catch(e => {
|
|
77
85
|
throw this._rewriteStartupLog(e);
|
|
78
86
|
});
|
|
87
|
+
browser._defaultContext._clientCertificatesProxy = clientCertificatesProxy;
|
|
88
|
+
return browser;
|
|
79
89
|
}, _timeoutSettings.TimeoutSettings.launchTimeout(options));
|
|
80
90
|
return browser._defaultContext;
|
|
81
91
|
}
|
|
@@ -122,14 +132,14 @@ class BrowserType extends _instrumentation.SdkObject {
|
|
|
122
132
|
};
|
|
123
133
|
if (persistent) (0, _browserContext.validateBrowserContextOptions)(persistent, browserOptions);
|
|
124
134
|
copyTestHooks(options, browserOptions);
|
|
125
|
-
const browser = await this.
|
|
135
|
+
const browser = await this.connectToTransport(transport, browserOptions);
|
|
126
136
|
browser._userDataDirForTest = userDataDir;
|
|
127
137
|
// We assume no control when using custom arguments, and do not prepare the default context in that case.
|
|
128
138
|
if (persistent && !options.ignoreAllDefaultArgs) await browser._defaultContext._loadDefaultContext(progress);
|
|
129
139
|
return browser;
|
|
130
140
|
}
|
|
131
141
|
async _launchProcess(progress, options, isPersistent, browserLogsCollector, userDataDir) {
|
|
132
|
-
var
|
|
142
|
+
var _await$readyState$wai;
|
|
133
143
|
const {
|
|
134
144
|
ignoreDefaultArgs,
|
|
135
145
|
ignoreAllDefaultArgs,
|
|
@@ -155,7 +165,7 @@ class BrowserType extends _instrumentation.SdkObject {
|
|
|
155
165
|
tempDirectories.push(userDataDir);
|
|
156
166
|
}
|
|
157
167
|
const browserArguments = [];
|
|
158
|
-
if (ignoreAllDefaultArgs) browserArguments.push(...args);else if (ignoreDefaultArgs) browserArguments.push(...this.
|
|
168
|
+
if (ignoreAllDefaultArgs) browserArguments.push(...args);else if (ignoreDefaultArgs) browserArguments.push(...this.defaultArgs(options, isPersistent, userDataDir).filter(arg => ignoreDefaultArgs.indexOf(arg) === -1));else browserArguments.push(...this.defaultArgs(options, isPersistent, userDataDir));
|
|
159
169
|
let executable;
|
|
160
170
|
if (executablePath) {
|
|
161
171
|
if (!(await (0, _fileUtils.existsAsync)(executablePath))) throw new Error(`Failed to launch ${this._name} because executable doesn't exist at ${executablePath}`);
|
|
@@ -166,8 +176,7 @@ class BrowserType extends _instrumentation.SdkObject {
|
|
|
166
176
|
executable = registryExecutable.executablePathOrDie(this.attribution.playwright.options.sdkLanguage);
|
|
167
177
|
await _registry.registry.validateHostRequirementsForExecutablesIfNeeded([registryExecutable], this.attribution.playwright.options.sdkLanguage);
|
|
168
178
|
}
|
|
169
|
-
const
|
|
170
|
-
const waitForJuggler = this._name === 'firefox' ? new _manualPromise.ManualPromise() : undefined;
|
|
179
|
+
const readyState = this.readyState(options);
|
|
171
180
|
// Note: it is important to define these variables before launchProcess, so that we don't get
|
|
172
181
|
// "Cannot access 'browserServer' before initialization" if something went wrong.
|
|
173
182
|
let transport = undefined;
|
|
@@ -179,16 +188,12 @@ class BrowserType extends _instrumentation.SdkObject {
|
|
|
179
188
|
} = await (0, _processLauncher.launchProcess)({
|
|
180
189
|
command: executable,
|
|
181
190
|
args: browserArguments,
|
|
182
|
-
env: this.
|
|
191
|
+
env: this.amendEnvironment(env, userDataDir, executable, browserArguments),
|
|
183
192
|
handleSIGINT,
|
|
184
193
|
handleSIGTERM,
|
|
185
194
|
handleSIGHUP,
|
|
186
195
|
log: message => {
|
|
187
|
-
|
|
188
|
-
const match = message.match(/DevTools listening on (.*)/);
|
|
189
|
-
if (match) waitForWSEndpoint.resolve(match[1]);
|
|
190
|
-
}
|
|
191
|
-
if (waitForJuggler && message.includes('Juggler listening to the pipe')) waitForJuggler.resolve();
|
|
196
|
+
readyState === null || readyState === void 0 || readyState.onBrowserOutput(message);
|
|
192
197
|
progress.log(message);
|
|
193
198
|
browserLogsCollector.log(message);
|
|
194
199
|
},
|
|
@@ -199,11 +204,11 @@ class BrowserType extends _instrumentation.SdkObject {
|
|
|
199
204
|
// We try to gracefully close to prevent crash reporting and core dumps.
|
|
200
205
|
// Note that it's fine to reuse the pipe transport, since
|
|
201
206
|
// our connection ignores kBrowserCloseMessageId.
|
|
202
|
-
this.
|
|
207
|
+
this.attemptToGracefullyCloseBrowser(transport);
|
|
203
208
|
},
|
|
204
209
|
onExit: (exitCode, signal) => {
|
|
205
210
|
// Unblock launch when browser prematurely exits.
|
|
206
|
-
|
|
211
|
+
readyState === null || readyState === void 0 || readyState.onBrowserExit();
|
|
207
212
|
if (browserProcess && browserProcess.onclose) browserProcess.onclose(exitCode, signal);
|
|
208
213
|
}
|
|
209
214
|
});
|
|
@@ -224,8 +229,7 @@ class BrowserType extends _instrumentation.SdkObject {
|
|
|
224
229
|
kill
|
|
225
230
|
};
|
|
226
231
|
progress.cleanupWhenAborted(() => closeOrKill(progress.timeUntilDeadline()));
|
|
227
|
-
const wsEndpoint = await
|
|
228
|
-
await waitForJuggler;
|
|
232
|
+
const wsEndpoint = (_await$readyState$wai = await (readyState === null || readyState === void 0 ? void 0 : readyState.waitUntilReady())) === null || _await$readyState$wai === void 0 ? void 0 : _await$readyState$wai.wsEndpoint;
|
|
229
233
|
if (options.useWebSocket) {
|
|
230
234
|
transport = await _transport.WebSocketTransport.connect(progress, wsEndpoint);
|
|
231
235
|
} else {
|
|
@@ -289,7 +293,10 @@ class BrowserType extends _instrumentation.SdkObject {
|
|
|
289
293
|
}
|
|
290
294
|
_rewriteStartupLog(error) {
|
|
291
295
|
if (!(0, _protocolError.isProtocolError)(error)) return error;
|
|
292
|
-
return this.
|
|
296
|
+
return this.doRewriteStartupLog(error);
|
|
297
|
+
}
|
|
298
|
+
readyState(options) {
|
|
299
|
+
return undefined;
|
|
293
300
|
}
|
|
294
301
|
}
|
|
295
302
|
exports.BrowserType = BrowserType;
|
|
@@ -99,14 +99,6 @@ class Chromium extends _browserType.BrowserType {
|
|
|
99
99
|
artifactsDir,
|
|
100
100
|
downloadsPath: options.downloadsPath || artifactsDir,
|
|
101
101
|
tracesDir: options.tracesDir || artifactsDir,
|
|
102
|
-
// On Windows context level proxies only work, if there isn't a global proxy
|
|
103
|
-
// set. This is currently a bug in the CR/Windows networking stack. By
|
|
104
|
-
// passing an arbitrary value we disable the check in PW land which warns
|
|
105
|
-
// users in normal (launch/launchServer) mode since otherwise connectOverCDP
|
|
106
|
-
// does not work at all with proxies on Windows.
|
|
107
|
-
proxy: {
|
|
108
|
-
server: 'per-context'
|
|
109
|
-
},
|
|
110
102
|
originalLaunchOptions: {}
|
|
111
103
|
};
|
|
112
104
|
(0, _browserContext.validateBrowserContextOptions)(persistent, browserOptions);
|
|
@@ -121,7 +113,7 @@ class Chromium extends _browserType.BrowserType {
|
|
|
121
113
|
const directory = _registry.registry.findExecutable('chromium').directory;
|
|
122
114
|
return directory ? new _crDevTools.CRDevTools(_path.default.join(directory, 'devtools-preferences.json')) : undefined;
|
|
123
115
|
}
|
|
124
|
-
async
|
|
116
|
+
async connectToTransport(transport, options) {
|
|
125
117
|
let devtools = this._devtools;
|
|
126
118
|
if (options.__testHookForDevTools) {
|
|
127
119
|
devtools = this._createDevTools();
|
|
@@ -129,19 +121,19 @@ class Chromium extends _browserType.BrowserType {
|
|
|
129
121
|
}
|
|
130
122
|
return _crBrowser.CRBrowser.connect(this.attribution.playwright, transport, options, devtools);
|
|
131
123
|
}
|
|
132
|
-
|
|
124
|
+
doRewriteStartupLog(error) {
|
|
133
125
|
if (!error.logs) return error;
|
|
134
126
|
if (error.logs.includes('Missing X server')) error.logs = '\n' + (0, _ascii.wrapInASCIIBox)(_browserType.kNoXServerRunningError, 1);
|
|
135
127
|
// These error messages are taken from Chromium source code as of July, 2020:
|
|
136
128
|
// https://github.com/chromium/chromium/blob/70565f67e79f79e17663ad1337dc6e63ee207ce9/content/browser/zygote_host/zygote_host_impl_linux.cc
|
|
137
129
|
if (!error.logs.includes('crbug.com/357670') && !error.logs.includes('No usable sandbox!') && !error.logs.includes('crbug.com/638180')) return error;
|
|
138
|
-
error.logs = [`Chromium sandboxing failed!`, `================================`, `To
|
|
130
|
+
error.logs = [`Chromium sandboxing failed!`, `================================`, `To avoid the sandboxing issue, do either of the following:`, ` - (preferred): Configure your environment to support sandboxing`, ` - (alternative): Launch Chromium without sandbox using 'chromiumSandbox: false' option`, `================================`, ``].join('\n');
|
|
139
131
|
return error;
|
|
140
132
|
}
|
|
141
|
-
|
|
133
|
+
amendEnvironment(env, userDataDir, executable, browserArguments) {
|
|
142
134
|
return env;
|
|
143
135
|
}
|
|
144
|
-
|
|
136
|
+
attemptToGracefullyCloseBrowser(transport) {
|
|
145
137
|
const message = {
|
|
146
138
|
method: 'Browser.close',
|
|
147
139
|
id: _crConnection.kBrowserCloseMessageId,
|
|
@@ -255,7 +247,7 @@ class Chromium extends _browserType.BrowserType {
|
|
|
255
247
|
throw e;
|
|
256
248
|
}
|
|
257
249
|
}
|
|
258
|
-
|
|
250
|
+
defaultArgs(options, isPersistent, userDataDir) {
|
|
259
251
|
const chromeArguments = this._innerDefaultArgs(options);
|
|
260
252
|
chromeArguments.push(`--user-data-dir=${userDataDir}`);
|
|
261
253
|
if (options.useWebSocket) chromeArguments.push('--remote-debugging-port=0');else chromeArguments.push('--remote-debugging-pipe');
|
|
@@ -280,7 +272,7 @@ class Chromium extends _browserType.BrowserType {
|
|
|
280
272
|
}
|
|
281
273
|
if (options.devtools) chromeArguments.push('--auto-open-devtools-for-tabs');
|
|
282
274
|
if (options.headless) {
|
|
283
|
-
if (process.env.PLAYWRIGHT_CHROMIUM_USE_HEADLESS_NEW) chromeArguments.push('--headless=new');else chromeArguments.push('--headless');
|
|
275
|
+
if (process.env.PLAYWRIGHT_CHROMIUM_USE_HEADLESS_NEW) chromeArguments.push('--headless=new');else chromeArguments.push('--headless=old');
|
|
284
276
|
chromeArguments.push('--hide-scrollbars', '--mute-audio', '--blink-settings=primaryHoverType=2,availableHoverTypes=2,primaryPointerType=4,availablePointerTypes=4');
|
|
285
277
|
}
|
|
286
278
|
if (options.chromiumSandbox !== true) chromeArguments.push('--no-sandbox');
|
|
@@ -303,8 +295,31 @@ class Chromium extends _browserType.BrowserType {
|
|
|
303
295
|
chromeArguments.push(...args);
|
|
304
296
|
return chromeArguments;
|
|
305
297
|
}
|
|
298
|
+
readyState(options) {
|
|
299
|
+
var _options$args;
|
|
300
|
+
if (options.useWebSocket || (_options$args = options.args) !== null && _options$args !== void 0 && _options$args.some(a => a.startsWith('--remote-debugging-port'))) return new ChromiumReadyState();
|
|
301
|
+
return undefined;
|
|
302
|
+
}
|
|
306
303
|
}
|
|
307
304
|
exports.Chromium = Chromium;
|
|
305
|
+
class ChromiumReadyState {
|
|
306
|
+
constructor() {
|
|
307
|
+
this._wsEndpoint = new _manualPromise.ManualPromise();
|
|
308
|
+
}
|
|
309
|
+
onBrowserOutput(message) {
|
|
310
|
+
const match = message.match(/DevTools listening on (.*)/);
|
|
311
|
+
if (match) this._wsEndpoint.resolve(match[1]);
|
|
312
|
+
}
|
|
313
|
+
onBrowserExit() {
|
|
314
|
+
this._wsEndpoint.resolve(undefined);
|
|
315
|
+
}
|
|
316
|
+
async waitUntilReady() {
|
|
317
|
+
const wsEndpoint = await this._wsEndpoint;
|
|
318
|
+
return {
|
|
319
|
+
wsEndpoint
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
}
|
|
308
323
|
async function urlToWSEndpoint(progress, endpointURL, headers) {
|
|
309
324
|
if (endpointURL.startsWith('ws')) return endpointURL;
|
|
310
325
|
progress.log(`<ws preparing> retrieving websocket url from ${endpointURL}`);
|
|
@@ -25,7 +25,7 @@ exports.chromiumSwitches = void 0;
|
|
|
25
25
|
|
|
26
26
|
const chromiumSwitches = exports.chromiumSwitches = ['--disable-field-trial-config',
|
|
27
27
|
// https://source.chromium.org/chromium/chromium/src/+/main:testing/variations/README.md
|
|
28
|
-
'--disable-background-networking', '--
|
|
28
|
+
'--disable-background-networking', '--disable-background-timer-throttling', '--disable-backgrounding-occluded-windows', '--disable-back-forward-cache',
|
|
29
29
|
// Avoids surprises like main request not being intercepted during page.goBack().
|
|
30
30
|
'--disable-breakpad', '--disable-client-side-phishing-detection', '--disable-component-extensions-with-background-pages', '--disable-component-update',
|
|
31
31
|
// Avoids unneeded network activity after startup.
|
|
@@ -34,8 +34,11 @@ const chromiumSwitches = exports.chromiumSwitches = ['--disable-field-trial-conf
|
|
|
34
34
|
// Translate - https://github.com/microsoft/playwright/issues/16126
|
|
35
35
|
// HttpsUpgrades - https://github.com/microsoft/playwright/pull/27605
|
|
36
36
|
// PaintHolding - https://github.com/microsoft/playwright/issues/28023
|
|
37
|
-
|
|
37
|
+
// PlzDedicatedWorker - https://github.com/microsoft/playwright/issues/31747
|
|
38
|
+
'--disable-features=ImprovedCookieControls,LazyFrameLoading,GlobalMediaControls,DestroyProfileOnBrowserClose,MediaRouter,DialMediaRouteProvider,AcceptCHFrame,AutoExpandDetailsElement,CertificateTransparencyComponentUpdater,AvoidUnnecessaryBeforeUnloadCheckSync,Translate,HttpsUpgrades,PaintHolding,PlzDedicatedWorker', '--allow-pre-commit-input', '--disable-hang-monitor', '--disable-ipc-flooding-protection', '--disable-popup-blocking', '--disable-prompt-on-repost', '--disable-renderer-backgrounding', '--force-color-profile=srgb', '--metrics-recording-only', '--no-first-run', '--enable-automation', '--password-store=basic', '--use-mock-keychain',
|
|
38
39
|
// See https://chromium-review.googlesource.com/c/chromium/src/+/2436773
|
|
39
40
|
'--no-service-autorun', '--export-tagged-pdf',
|
|
40
41
|
// https://chromium-review.googlesource.com/c/chromium/src/+/4853540
|
|
41
|
-
'--disable-search-engine-choice-screen'
|
|
42
|
+
'--disable-search-engine-choice-screen',
|
|
43
|
+
// https://issues.chromium.org/41491762
|
|
44
|
+
'--unsafely-disable-devtools-self-xss-warnings'];
|
|
@@ -298,7 +298,7 @@ class CRBrowserContext extends _browserContext.BrowserContext {
|
|
|
298
298
|
async _initialize() {
|
|
299
299
|
(0, _utils.assert)(!Array.from(this._browser._crPages.values()).some(page => page._browserContext === this));
|
|
300
300
|
const promises = [super._initialize()];
|
|
301
|
-
if (this._browser.options.name !== '
|
|
301
|
+
if (this._browser.options.name !== 'clank' && this._options.acceptDownloads !== 'internal-browser-default') {
|
|
302
302
|
promises.push(this._browser._session.send('Browser.setDownloadBehavior', {
|
|
303
303
|
behavior: this._options.acceptDownloads === 'accept' ? 'allowAndName' : 'deny',
|
|
304
304
|
browserContextId: this._browserContextId,
|
|
@@ -365,7 +365,7 @@ class CRBrowserContext extends _browserContext.BrowserContext {
|
|
|
365
365
|
browserContextId: this._browserContextId
|
|
366
366
|
});
|
|
367
367
|
}
|
|
368
|
-
async
|
|
368
|
+
async doClearCookies() {
|
|
369
369
|
await this._browser._session.send('Storage.clearCookies', {
|
|
370
370
|
browserContextId: this._browserContextId
|
|
371
371
|
});
|
|
@@ -373,7 +373,7 @@ class CRBrowserContext extends _browserContext.BrowserContext {
|
|
|
373
373
|
async doGrantPermissions(origin, permissions) {
|
|
374
374
|
const webPermissionToProtocol = new Map([['geolocation', 'geolocation'], ['midi', 'midi'], ['notifications', 'notifications'], ['camera', 'videoCapture'], ['microphone', 'audioCapture'], ['background-sync', 'backgroundSync'], ['ambient-light-sensor', 'sensors'], ['accelerometer', 'sensors'], ['gyroscope', 'sensors'], ['magnetometer', 'sensors'], ['accessibility-events', 'accessibilityEvents'], ['clipboard-read', 'clipboardReadWrite'], ['clipboard-write', 'clipboardSanitizedWrite'], ['payment-handler', 'paymentHandler'],
|
|
375
375
|
// chrome-specific permissions we have.
|
|
376
|
-
['midi-sysex', 'midiSysex']]);
|
|
376
|
+
['midi-sysex', 'midiSysex'], ['storage-access', 'storageAccess']]);
|
|
377
377
|
const filtered = permissions.map(permission => {
|
|
378
378
|
const protocolPermission = webPermissionToProtocol.get(permission);
|
|
379
379
|
if (!protocolPermission) throw new Error('Unknown permission: ' + permission);
|
|
@@ -398,7 +398,7 @@ class CRBrowserContext extends _browserContext.BrowserContext {
|
|
|
398
398
|
async setExtraHTTPHeaders(headers) {
|
|
399
399
|
this._options.extraHTTPHeaders = headers;
|
|
400
400
|
for (const page of this.pages()) await page._delegate.updateExtraHTTPHeaders();
|
|
401
|
-
for (const sw of this.serviceWorkers()) await sw.updateExtraHTTPHeaders(
|
|
401
|
+
for (const sw of this.serviceWorkers()) await sw.updateExtraHTTPHeaders();
|
|
402
402
|
}
|
|
403
403
|
async setUserAgent(userAgent) {
|
|
404
404
|
this._options.userAgent = userAgent;
|
|
@@ -408,24 +408,18 @@ class CRBrowserContext extends _browserContext.BrowserContext {
|
|
|
408
408
|
async setOffline(offline) {
|
|
409
409
|
this._options.offline = offline;
|
|
410
410
|
for (const page of this.pages()) await page._delegate.updateOffline();
|
|
411
|
-
for (const sw of this.serviceWorkers()) await sw.updateOffline(
|
|
411
|
+
for (const sw of this.serviceWorkers()) await sw.updateOffline();
|
|
412
412
|
}
|
|
413
413
|
async doSetHTTPCredentials(httpCredentials) {
|
|
414
414
|
this._options.httpCredentials = httpCredentials;
|
|
415
415
|
for (const page of this.pages()) await page._delegate.updateHttpCredentials();
|
|
416
|
-
for (const sw of this.serviceWorkers()) await sw.updateHttpCredentials(
|
|
416
|
+
for (const sw of this.serviceWorkers()) await sw.updateHttpCredentials();
|
|
417
417
|
}
|
|
418
|
-
async doAddInitScript(
|
|
419
|
-
for (const page of this.pages()) await page._delegate.addInitScript(
|
|
418
|
+
async doAddInitScript(initScript) {
|
|
419
|
+
for (const page of this.pages()) await page._delegate.addInitScript(initScript);
|
|
420
420
|
}
|
|
421
|
-
async
|
|
422
|
-
for (const page of this.pages()) await page._delegate.
|
|
423
|
-
}
|
|
424
|
-
async doExposeBinding(binding) {
|
|
425
|
-
for (const page of this.pages()) await page._delegate.exposeBinding(binding);
|
|
426
|
-
}
|
|
427
|
-
async doRemoveExposedBindings() {
|
|
428
|
-
for (const page of this.pages()) await page._delegate.removeExposedBindings();
|
|
421
|
+
async doRemoveNonInternalInitScripts() {
|
|
422
|
+
for (const page of this.pages()) await page._delegate.removeNonInternalInitScripts();
|
|
429
423
|
}
|
|
430
424
|
async doUpdateRequestInterception() {
|
|
431
425
|
for (const page of this.pages()) await page._delegate.updateRequestInterception();
|
|
@@ -478,7 +472,7 @@ class CRBrowserContext extends _browserContext.BrowserContext {
|
|
|
478
472
|
}
|
|
479
473
|
}
|
|
480
474
|
async clearCache() {
|
|
481
|
-
for (const page of this._crPages()) await page.
|
|
475
|
+
for (const page of this._crPages()) await page._networkManager.clearCache();
|
|
482
476
|
}
|
|
483
477
|
async cancelDownload(guid) {
|
|
484
478
|
// The upstream CDP method is implemented in a way that no explicit error would be given
|
|
@@ -72,11 +72,11 @@ class CRConnection extends _events.EventEmitter {
|
|
|
72
72
|
const session = this._sessions.get(message.sessionId || '');
|
|
73
73
|
if (session) session._onMessage(message);
|
|
74
74
|
}
|
|
75
|
-
_onClose() {
|
|
75
|
+
_onClose(reason) {
|
|
76
76
|
this._closed = true;
|
|
77
77
|
this._transport.onmessage = undefined;
|
|
78
78
|
this._transport.onclose = undefined;
|
|
79
|
-
this._browserDisconnectedLogs = _helper.helper.formatBrowserLogs(this._browserLogsCollector.recentLogs());
|
|
79
|
+
this._browserDisconnectedLogs = _helper.helper.formatBrowserLogs(this._browserLogsCollector.recentLogs(), reason);
|
|
80
80
|
this.rootSession.dispose();
|
|
81
81
|
Promise.resolve().then(() => this.emit(ConnectionEvents.Disconnected));
|
|
82
82
|
}
|