@checkly/playwright-core 1.42.17 → 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.
Files changed (234) hide show
  1. package/ThirdPartyNotices.txt +144 -109
  2. package/browsers.json +15 -25
  3. package/lib/androidServerImpl.js +1 -1
  4. package/lib/browserServerImpl.js +1 -1
  5. package/lib/cli/driver.js +1 -3
  6. package/lib/cli/program.js +5 -10
  7. package/lib/client/android.js +1 -1
  8. package/lib/client/api.js +7 -0
  9. package/lib/client/browserContext.js +37 -5
  10. package/lib/client/browserType.js +19 -11
  11. package/lib/client/channelOwner.js +19 -16
  12. package/lib/client/clientInstrumentation.js +17 -7
  13. package/lib/client/clock.js +68 -0
  14. package/lib/client/connection.js +9 -6
  15. package/lib/client/electron.js +7 -5
  16. package/lib/client/elementHandle.js +44 -14
  17. package/lib/client/eventEmitter.js +314 -0
  18. package/lib/client/fetch.js +81 -28
  19. package/lib/client/frame.js +2 -4
  20. package/lib/client/jsHandle.js +7 -1
  21. package/lib/client/locator.js +9 -0
  22. package/lib/client/network.js +12 -9
  23. package/lib/client/page.js +45 -23
  24. package/lib/client/playwright.js +3 -0
  25. package/lib/client/tracing.js +7 -4
  26. package/lib/common/socksProxy.js +2 -2
  27. package/lib/generated/clockSource.js +7 -0
  28. package/lib/generated/injectedScriptSource.js +1 -1
  29. package/lib/generated/recorderSource.js +1 -1
  30. package/lib/generated/utilityScriptSource.js +1 -1
  31. package/lib/protocol/serializers.js +12 -11
  32. package/lib/protocol/validator.js +137 -55
  33. package/lib/server/bidi/bidiBrowser.js +296 -0
  34. package/lib/server/bidi/bidiConnection.js +206 -0
  35. package/lib/server/bidi/bidiExecutionContext.js +162 -0
  36. package/lib/server/bidi/bidiFirefox.js +110 -0
  37. package/lib/server/bidi/bidiInput.js +174 -0
  38. package/lib/server/bidi/bidiNetworkManager.js +304 -0
  39. package/lib/server/bidi/bidiPage.js +456 -0
  40. package/lib/server/bidi/third_party/bidiDeserializer.js +93 -0
  41. package/lib/server/bidi/third_party/bidiKeyboard.js +238 -0
  42. package/lib/server/bidi/third_party/bidiProtocol.js +139 -0
  43. package/lib/server/bidi/third_party/bidiSerializer.js +144 -0
  44. package/lib/server/browser.js +9 -1
  45. package/lib/server/browserContext.js +97 -22
  46. package/lib/server/browserType.js +27 -20
  47. package/lib/server/chromium/chromium.js +30 -15
  48. package/lib/server/chromium/chromiumSwitches.js +6 -3
  49. package/lib/server/chromium/crBrowser.js +11 -17
  50. package/lib/server/chromium/crConnection.js +2 -2
  51. package/lib/server/chromium/crDragDrop.js +28 -29
  52. package/lib/server/chromium/crNetworkManager.js +130 -84
  53. package/lib/server/chromium/crPage.js +34 -79
  54. package/lib/server/chromium/crProtocolHelper.js +3 -1
  55. package/lib/server/chromium/crServiceWorker.js +20 -23
  56. package/lib/server/chromium/videoRecorder.js +1 -1
  57. package/lib/server/clock.js +125 -0
  58. package/lib/server/codegen/csharp.js +299 -0
  59. package/lib/server/codegen/java.js +235 -0
  60. package/lib/server/codegen/javascript.js +223 -0
  61. package/lib/server/codegen/jsonl.js +47 -0
  62. package/lib/server/codegen/language.js +76 -0
  63. package/lib/server/codegen/languages.js +30 -0
  64. package/lib/server/codegen/python.js +265 -0
  65. package/lib/server/codegen/types.js +5 -0
  66. package/lib/server/debugController.js +3 -5
  67. package/lib/server/deviceDescriptors.js +9 -4
  68. package/lib/server/deviceDescriptorsSource.json +239 -119
  69. package/lib/server/dispatchers/androidDispatcher.js +1 -1
  70. package/lib/server/dispatchers/browserContextDispatcher.js +51 -7
  71. package/lib/server/dispatchers/dispatcher.js +36 -40
  72. package/lib/server/dispatchers/frameDispatcher.js +1 -2
  73. package/lib/server/dispatchers/jsHandleDispatcher.js +1 -1
  74. package/lib/server/dispatchers/jsonPipeDispatcher.js +4 -6
  75. package/lib/server/dispatchers/localUtilsDispatcher.js +19 -5
  76. package/lib/server/dispatchers/networkDispatchers.js +2 -2
  77. package/lib/server/dispatchers/pageDispatcher.js +5 -2
  78. package/lib/server/dispatchers/playwrightDispatcher.js +1 -0
  79. package/lib/server/dispatchers/writableStreamDispatcher.js +8 -5
  80. package/lib/server/dom.js +90 -53
  81. package/lib/server/electron/electron.js +21 -4
  82. package/lib/server/fetch.js +74 -25
  83. package/lib/server/fileUploadUtils.js +7 -3
  84. package/lib/server/firefox/ffBrowser.js +36 -25
  85. package/lib/server/firefox/ffConnection.js +2 -2
  86. package/lib/server/firefox/ffNetworkManager.js +6 -4
  87. package/lib/server/firefox/ffPage.js +22 -24
  88. package/lib/server/firefox/firefox.js +25 -6
  89. package/lib/server/frameSelectors.js +2 -2
  90. package/lib/server/frames.js +205 -159
  91. package/lib/server/har/harTracer.js +4 -12
  92. package/lib/server/helper.js +3 -3
  93. package/lib/server/index.js +18 -0
  94. package/lib/server/input.js +18 -8
  95. package/lib/server/instrumentation.js +0 -4
  96. package/lib/server/isomorphic/utilityScriptSerializers.js +19 -5
  97. package/lib/server/javascript.js +3 -2
  98. package/lib/server/launchApp.js +3 -2
  99. package/lib/server/network.js +14 -4
  100. package/lib/server/page.js +75 -46
  101. package/lib/server/playwright.js +5 -2
  102. package/lib/server/recorder/codeGenerator.js +2 -1
  103. package/lib/server/recorder/contextRecorder.js +316 -0
  104. package/lib/server/recorder/csharp.js +2 -1
  105. package/lib/server/recorder/java.js +2 -1
  106. package/lib/server/recorder/javascript.js +2 -1
  107. package/lib/server/recorder/jsonl.js +2 -1
  108. package/lib/server/recorder/language.js +2 -1
  109. package/lib/server/recorder/python.js +2 -1
  110. package/lib/server/recorder/recorderApp.js +14 -5
  111. package/lib/server/recorder/recorderCollection.js +127 -0
  112. package/lib/server/recorder/recorderRunner.js +177 -0
  113. package/lib/server/recorder/recorderUtils.js +23 -0
  114. package/lib/server/recorder/throttledFile.js +46 -0
  115. package/lib/server/recorder/utils.js +2 -1
  116. package/lib/server/recorder.js +42 -418
  117. package/lib/server/registry/index.js +99 -100
  118. package/lib/server/registry/nativeDeps.js +107 -0
  119. package/lib/server/screenshotter.js +6 -12
  120. package/lib/server/socksClientCertificatesInterceptor.js +328 -0
  121. package/lib/server/trace/recorder/snapshotter.js +4 -1
  122. package/lib/server/trace/recorder/tracing.js +27 -96
  123. package/lib/server/trace/viewer/traceViewer.js +54 -67
  124. package/lib/server/transport.js +1 -1
  125. package/lib/server/webkit/webkit.js +5 -5
  126. package/lib/server/webkit/wkBrowser.js +14 -14
  127. package/lib/server/webkit/wkConnection.js +3 -3
  128. package/lib/server/webkit/wkInterceptableRequest.js +8 -4
  129. package/lib/server/webkit/wkPage.js +52 -34
  130. package/lib/server/webkit/wkProvisionalPage.js +36 -1
  131. package/lib/utils/crypto.js +141 -0
  132. package/lib/utils/debugLogger.js +2 -0
  133. package/lib/utils/env.js +4 -2
  134. package/lib/utils/expectUtils.js +33 -0
  135. package/lib/utils/fileUtils.js +140 -1
  136. package/lib/utils/glob.js +2 -1
  137. package/lib/utils/happy-eyeballs.js +29 -2
  138. package/lib/utils/hostPlatform.js +13 -4
  139. package/lib/utils/httpServer.js +54 -13
  140. package/lib/utils/index.js +53 -31
  141. package/lib/utils/isomorphic/cssTokenizer.js +1 -1
  142. package/lib/utils/isomorphic/locatorParser.js +1 -1
  143. package/lib/utils/isomorphic/mimeType.js +29 -0
  144. package/lib/utils/isomorphic/stringUtils.js +28 -1
  145. package/lib/utils/isomorphic/urlMatch.js +120 -0
  146. package/lib/utils/mimeType.js +2 -1
  147. package/lib/utils/network.js +7 -35
  148. package/lib/utils/stackTrace.js +2 -4
  149. package/lib/utils/timeoutRunner.js +11 -76
  150. package/lib/utils/zones.js +23 -60
  151. package/lib/utilsBundle.js +2 -1
  152. package/lib/utilsBundleImpl/index.js +33 -31
  153. package/lib/vite/htmlReport/index.html +12 -12
  154. package/lib/vite/recorder/assets/codeMirrorModule-C-fQ5QZD.js +24 -0
  155. package/lib/vite/recorder/assets/{codicon-zGuYmc9o.ttf → codicon-DCmgc-ay.ttf} +0 -0
  156. package/lib/vite/recorder/assets/index-B-MT5gKo.css +1 -0
  157. package/lib/vite/recorder/assets/index-D-5S5PPN.js +47 -0
  158. package/lib/vite/recorder/index.html +2 -2
  159. package/lib/vite/traceViewer/assets/codeMirrorModule-5yiV-3wl.js +16831 -0
  160. package/lib/vite/traceViewer/assets/codeMirrorModule-B7Z3vq11.js +24 -0
  161. package/lib/vite/traceViewer/assets/codeMirrorModule-C6p3E9Zg.js +24 -0
  162. package/lib/vite/traceViewer/assets/codeMirrorModule-CqYUz5ms.js +24 -0
  163. package/lib/vite/traceViewer/assets/codeMirrorModule-Dx6AXgMV.js +16838 -0
  164. package/lib/vite/traceViewer/assets/codeMirrorModule-T_sdMrbM.js +24 -0
  165. package/lib/vite/traceViewer/assets/codeMirrorModule-V7N6ppkd.js +15585 -0
  166. package/lib/vite/traceViewer/assets/testServerConnection-D-tXL3sj.js +224 -0
  167. package/lib/vite/traceViewer/assets/testServerConnection-DeE2kSzz.js +1 -0
  168. package/lib/vite/traceViewer/assets/workbench-Bjkiwcr1.js +19119 -0
  169. package/lib/vite/traceViewer/assets/workbench-C43LWZEX.js +72 -0
  170. package/lib/vite/traceViewer/assets/workbench-C5OQh9VX.js +19119 -0
  171. package/lib/vite/traceViewer/assets/workbench-DrQjKdyE.js +72 -0
  172. package/lib/vite/traceViewer/assets/workbench-caTaZnzx.js +72 -0
  173. package/lib/vite/traceViewer/assets/workbench-u2lRPMOT.js +72 -0
  174. package/lib/vite/traceViewer/assets/wsPort-EUvw-dwH.js +18540 -0
  175. package/lib/vite/traceViewer/assets/xtermModule-CZ7sDYXB.js +6529 -0
  176. package/lib/vite/traceViewer/assets/xtermModule-_6TC5FYT.js +6529 -0
  177. package/lib/vite/traceViewer/codeMirrorModule.Cy8X9Wtw.css +344 -0
  178. package/lib/vite/traceViewer/codeMirrorModule.svF_VrcJ.css +344 -0
  179. package/lib/vite/traceViewer/codicon.DCmgc-ay.ttf +0 -0
  180. package/lib/vite/traceViewer/embedded.BQq6Psnz.js +104 -0
  181. package/lib/vite/traceViewer/embedded.BVDVQOzc.js +2 -0
  182. package/lib/vite/traceViewer/embedded.Bn8Ptzv6.js +2 -0
  183. package/lib/vite/traceViewer/embedded.CvhnUgIi.js +2 -0
  184. package/lib/vite/traceViewer/embedded.D27cnKiB.js +104 -0
  185. package/lib/vite/traceViewer/embedded.DPqrDeET.js +2 -0
  186. package/lib/vite/traceViewer/embedded.DjZq4InJ.css +68 -0
  187. package/lib/vite/traceViewer/embedded.html +16 -0
  188. package/lib/vite/traceViewer/embedded.w7WN2u1R.css +1 -0
  189. package/lib/vite/traceViewer/index.5mge2rY_.css +124 -0
  190. package/lib/vite/traceViewer/index.6KJ-JQ0L.js +180 -0
  191. package/lib/vite/traceViewer/index.B8dgQwuN.js +2 -0
  192. package/lib/vite/traceViewer/index.BGj8jY3H.js +2 -0
  193. package/lib/vite/traceViewer/index.C0EgJ4oW.js +195 -0
  194. package/lib/vite/traceViewer/index.CUpI-BFe.js +195 -0
  195. package/lib/vite/traceViewer/{index.-g_5lMbJ.css → index.CrbWWHbf.css} +1 -1
  196. package/lib/vite/traceViewer/index.QanXxRUb.css +131 -0
  197. package/lib/vite/traceViewer/index._cX8k4co.js +2 -0
  198. package/lib/vite/traceViewer/index.html +5 -4
  199. package/lib/vite/traceViewer/index.pMAN88y-.js +2 -0
  200. package/lib/vite/traceViewer/snapshot.html +1 -1
  201. package/lib/vite/traceViewer/sw.bundle.js +3 -4
  202. package/lib/vite/traceViewer/uiMode.D-tg1Oci.js +1730 -0
  203. package/lib/vite/traceViewer/uiMode.D3cNFP6u.css +1 -0
  204. package/lib/vite/traceViewer/uiMode.DKjMBMlc.js +1730 -0
  205. package/lib/vite/traceViewer/uiMode.DVWUEIHq.css +1424 -0
  206. package/lib/vite/traceViewer/uiMode.DVrL7a1K.js +10 -0
  207. package/lib/vite/traceViewer/uiMode.Dg9oJCQU.js +10 -0
  208. package/lib/vite/traceViewer/uiMode.DwZAzstF.js +10 -0
  209. package/lib/vite/traceViewer/uiMode.html +5 -4
  210. package/lib/vite/traceViewer/uiMode.iq7CyYy7.js +1490 -0
  211. package/lib/vite/traceViewer/uiMode.jY2s-9ps.js +10 -0
  212. package/lib/vite/traceViewer/uiMode.xvJHbkzl.css +1324 -0
  213. package/lib/vite/traceViewer/workbench.B3X2QtYa.css +3702 -0
  214. package/lib/vite/traceViewer/workbench.DyTpxWVb.css +1 -0
  215. package/lib/vite/traceViewer/wsPort.p5jUwABW.css +3450 -0
  216. package/lib/vite/traceViewer/xtermModule.4oRVGWQ-.css +209 -0
  217. package/lib/vite/traceViewer/xtermModule.OKEVRlkP.css +209 -0
  218. package/package.json +2 -2
  219. package/types/protocol.d.ts +960 -78
  220. package/types/structs.d.ts +1 -1
  221. package/types/types.d.ts +3083 -2448
  222. package/lib/vite/recorder/assets/codeMirrorModule-I9ks4y7D.js +0 -24
  223. package/lib/vite/recorder/assets/index-ljsTwXtJ.css +0 -1
  224. package/lib/vite/recorder/assets/index-yg8ypzl6.js +0 -47
  225. package/lib/vite/traceViewer/assets/codeMirrorModule-0bpaqixv.js +0 -24
  226. package/lib/vite/traceViewer/assets/wsPort-_JBDEilC.js +0 -69
  227. package/lib/vite/traceViewer/index.u51inEcm.js +0 -2
  228. package/lib/vite/traceViewer/uiMode.Fb0bNA4H.js +0 -10
  229. package/lib/vite/traceViewer/uiMode.pWy0Re7G.css +0 -1
  230. package/lib/vite/traceViewer/wsPort.zR1WIy9-.css +0 -1
  231. /package/lib/vite/recorder/assets/{codeMirrorModule-Hs9-1ZG4.css → codeMirrorModule-ez37Vkbh.css} +0 -0
  232. /package/lib/vite/traceViewer/assets/{xtermModule-Yt6xwiJ_.js → xtermModule-BeNbaIVa.js} +0 -0
  233. /package/lib/vite/traceViewer/{codeMirrorModule.Hs9-1ZG4.css → codeMirrorModule.ez37Vkbh.css} +0 -0
  234. /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(`\nnavigator.serviceWorker.register = async () => { console.warn('Service Worker registration blocked by Playwright'); };\n`);
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.doExposeBinding(binding);
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.keys()) {
217
- if (!key.startsWith('__pw')) this._pageBindings.delete(key);
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(script) {
298
- this.initScripts.push(script);
299
- await this.doAddInitScript(script);
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.splice(0, this.initScripts.length);
303
- await this.doRemoveInitScripts();
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
- if (this._origins.size) {
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 this._origins) {
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.clearCookies();
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 = options;
75
+ const persistent = {
76
+ ...options
77
+ };
74
78
  controller.setLogName('browser');
75
- const browser = await controller.run(progress => {
76
- return this._innerLaunchWithRetries(progress, options, persistent, _helper.helper.debugProtocolLogger(), userDataDir).catch(e => {
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._connectToTransport(transport, browserOptions);
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 _options$args;
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._defaultArgs(options, isPersistent, userDataDir).filter(arg => ignoreDefaultArgs.indexOf(arg) === -1));else browserArguments.push(...this._defaultArgs(options, isPersistent, userDataDir));
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 waitForWSEndpoint = options.useWebSocket || (_options$args = options.args) !== null && _options$args !== void 0 && _options$args.some(a => a.startsWith('--remote-debugging-port')) ? new _manualPromise.ManualPromise() : undefined;
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._amendEnvironment(env, userDataDir, executable, browserArguments),
191
+ env: this.amendEnvironment(env, userDataDir, executable, browserArguments),
183
192
  handleSIGINT,
184
193
  handleSIGTERM,
185
194
  handleSIGHUP,
186
195
  log: message => {
187
- if (waitForWSEndpoint) {
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._attemptToGracefullyCloseBrowser(transport);
207
+ this.attemptToGracefullyCloseBrowser(transport);
203
208
  },
204
209
  onExit: (exitCode, signal) => {
205
210
  // Unblock launch when browser prematurely exits.
206
- waitForJuggler === null || waitForJuggler === void 0 || waitForJuggler.resolve();
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 waitForWSEndpoint;
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._doRewriteStartupLog(error);
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 _connectToTransport(transport, options) {
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
- _doRewriteStartupLog(error) {
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 workaround sandboxing issues, do either of the following:`, ` - (preferred): Configure environment to support sandboxing: https://playwright.dev/docs/troubleshooting`, ` - (alternative): Launch Chromium without sandbox using 'chromiumSandbox: false' option`, `================================`, ``].join('\n');
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
- _amendEnvironment(env, userDataDir, executable, browserArguments) {
133
+ amendEnvironment(env, userDataDir, executable, browserArguments) {
142
134
  return env;
143
135
  }
144
- _attemptToGracefullyCloseBrowser(transport) {
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
- _defaultArgs(options, isPersistent, userDataDir) {
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', '--enable-features=NetworkService,NetworkServiceInProcess', '--disable-background-timer-throttling', '--disable-backgrounding-occluded-windows', '--disable-back-forward-cache',
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
- '--disable-features=ImprovedCookieControls,LazyFrameLoading,GlobalMediaControls,DestroyProfileOnBrowserClose,MediaRouter,DialMediaRouteProvider,AcceptCHFrame,AutoExpandDetailsElement,CertificateTransparencyComponentUpdater,AvoidUnnecessaryBeforeUnloadCheckSync,Translate,HttpsUpgrades,PaintHolding', '--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',
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 !== 'electron' && this._browser.options.name !== 'clank' && this._options.acceptDownloads !== 'internal-browser-default') {
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 clearCookies() {
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(false);
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(false);
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(false);
416
+ for (const sw of this.serviceWorkers()) await sw.updateHttpCredentials();
417
417
  }
418
- async doAddInitScript(source) {
419
- for (const page of this.pages()) await page._delegate.addInitScript(source);
418
+ async doAddInitScript(initScript) {
419
+ for (const page of this.pages()) await page._delegate.addInitScript(initScript);
420
420
  }
421
- async doRemoveInitScripts() {
422
- for (const page of this.pages()) await page._delegate.removeInitScripts();
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._mainFrameSession._networkManager.clearCache();
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
  }