patchright-core 1.56.1 → 1.58.2

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 (180) hide show
  1. package/ThirdPartyNotices.txt +3134 -560
  2. package/bin/install_webkit_wsl.ps1 +1 -3
  3. package/browsers.json +21 -22
  4. package/lib/cli/program.js +16 -60
  5. package/lib/client/api.js +3 -3
  6. package/lib/client/browser.js +3 -5
  7. package/lib/client/browserContext.js +62 -8
  8. package/lib/client/browserType.js +4 -3
  9. package/lib/client/connection.js +4 -0
  10. package/lib/client/consoleMessage.js +5 -1
  11. package/lib/client/electron.js +1 -1
  12. package/lib/client/elementHandle.js +3 -0
  13. package/lib/client/events.js +5 -1
  14. package/lib/client/fetch.js +3 -4
  15. package/lib/client/frame.js +10 -1
  16. package/lib/client/locator.js +12 -1
  17. package/lib/client/network.js +5 -1
  18. package/lib/client/page.js +31 -6
  19. package/lib/client/pageAgent.js +64 -0
  20. package/lib/client/platform.js +3 -0
  21. package/lib/client/playwright.js +1 -5
  22. package/lib/client/tracing.js +7 -5
  23. package/lib/client/worker.js +22 -0
  24. package/lib/generated/clockSource.js +1 -1
  25. package/lib/generated/injectedScriptSource.js +1 -1
  26. package/lib/generated/pollingRecorderSource.js +1 -1
  27. package/lib/inProcessFactory.js +0 -2
  28. package/lib/mcpBundle.js +84 -0
  29. package/lib/mcpBundleImpl/index.js +147 -0
  30. package/lib/protocol/serializers.js +5 -0
  31. package/lib/protocol/validator.js +112 -50
  32. package/lib/remote/playwrightServer.js +1 -2
  33. package/lib/server/agent/actionRunner.js +335 -0
  34. package/lib/server/agent/actions.js +128 -0
  35. package/lib/server/agent/codegen.js +111 -0
  36. package/lib/server/agent/context.js +150 -0
  37. package/lib/server/agent/expectTools.js +156 -0
  38. package/lib/server/agent/pageAgent.js +204 -0
  39. package/lib/server/agent/performTools.js +262 -0
  40. package/lib/server/agent/tool.js +109 -0
  41. package/lib/server/android/android.js +1 -1
  42. package/lib/server/artifact.js +1 -1
  43. package/lib/server/bidi/bidiBrowser.js +81 -22
  44. package/lib/server/bidi/bidiChromium.js +9 -13
  45. package/lib/server/bidi/bidiConnection.js +1 -0
  46. package/lib/server/bidi/bidiDeserializer.js +116 -0
  47. package/lib/server/bidi/bidiExecutionContext.js +75 -29
  48. package/lib/server/bidi/bidiFirefox.js +7 -9
  49. package/lib/server/bidi/bidiNetworkManager.js +1 -1
  50. package/lib/server/bidi/bidiPage.js +61 -30
  51. package/lib/server/bidi/third_party/bidiProtocolCore.js +1 -0
  52. package/lib/server/browserContext.js +43 -36
  53. package/lib/server/browserType.js +12 -4
  54. package/lib/server/chromium/chromium.js +26 -21
  55. package/lib/server/chromium/chromiumSwitches.js +12 -3
  56. package/lib/server/chromium/crBrowser.js +30 -12
  57. package/lib/server/chromium/crConnection.js +0 -5
  58. package/lib/server/chromium/crCoverage.js +13 -1
  59. package/lib/server/chromium/crDevTools.js +0 -2
  60. package/lib/server/chromium/crNetworkManager.js +107 -18
  61. package/lib/server/chromium/crPage.js +68 -124
  62. package/lib/server/chromium/crServiceWorker.js +14 -1
  63. package/lib/server/codegen/javascript.js +6 -29
  64. package/lib/server/console.js +5 -1
  65. package/lib/server/deviceDescriptorsSource.json +56 -56
  66. package/lib/server/dispatchers/browserContextDispatcher.js +26 -8
  67. package/lib/server/dispatchers/dispatcher.js +6 -13
  68. package/lib/server/dispatchers/frameDispatcher.js +1 -1
  69. package/lib/server/dispatchers/jsHandleDispatcher.js +2 -2
  70. package/lib/server/dispatchers/pageAgentDispatcher.js +96 -0
  71. package/lib/server/dispatchers/pageDispatcher.js +14 -22
  72. package/lib/server/dispatchers/playwrightDispatcher.js +0 -4
  73. package/lib/server/dom.js +12 -3
  74. package/lib/server/electron/electron.js +6 -3
  75. package/lib/server/firefox/ffBrowser.js +10 -20
  76. package/lib/server/firefox/ffConnection.js +0 -5
  77. package/lib/server/firefox/ffNetworkManager.js +2 -2
  78. package/lib/server/firefox/ffPage.js +18 -24
  79. package/lib/server/firefox/firefox.js +18 -9
  80. package/lib/server/frameSelectors.js +18 -8
  81. package/lib/server/frames.js +257 -87
  82. package/lib/server/input.js +7 -3
  83. package/lib/server/instrumentation.js +3 -0
  84. package/lib/server/javascript.js +8 -4
  85. package/lib/server/launchApp.js +2 -1
  86. package/lib/server/localUtils.js +4 -8
  87. package/lib/server/network.js +50 -12
  88. package/lib/server/page.js +112 -126
  89. package/lib/server/playwright.js +2 -4
  90. package/lib/server/progress.js +26 -6
  91. package/lib/server/recorder/recorderApp.js +80 -101
  92. package/lib/server/recorder.js +3 -2
  93. package/lib/server/registry/browserFetcher.js +6 -4
  94. package/lib/server/registry/index.js +278 -189
  95. package/lib/server/registry/oopDownloadBrowserMain.js +9 -2
  96. package/lib/server/screencast.js +190 -0
  97. package/lib/server/screenshotter.js +6 -0
  98. package/lib/server/socksClientCertificatesInterceptor.js +1 -1
  99. package/lib/server/trace/recorder/snapshotter.js +17 -8
  100. package/lib/server/trace/recorder/snapshotterInjected.js +30 -72
  101. package/lib/server/trace/recorder/tracing.js +31 -21
  102. package/lib/server/trace/viewer/traceParser.js +72 -0
  103. package/lib/server/trace/viewer/traceViewer.js +45 -40
  104. package/lib/server/utils/comparators.js +3 -25
  105. package/lib/server/utils/expectUtils.js +87 -2
  106. package/lib/server/utils/hostPlatform.js +30 -3
  107. package/lib/server/utils/httpServer.js +5 -20
  108. package/lib/server/utils/imageUtils.js +141 -0
  109. package/lib/server/utils/network.js +55 -40
  110. package/lib/server/utils/nodePlatform.js +6 -0
  111. package/lib/server/{chromium/videoRecorder.js → videoRecorder.js} +35 -24
  112. package/lib/server/webkit/webkit.js +5 -16
  113. package/lib/server/webkit/wkBrowser.js +2 -6
  114. package/lib/server/webkit/wkConnection.js +1 -6
  115. package/lib/server/webkit/wkInterceptableRequest.js +29 -1
  116. package/lib/server/webkit/wkPage.js +76 -51
  117. package/lib/server/webkit/wkWorkers.js +2 -1
  118. package/lib/utils/isomorphic/ariaSnapshot.js +63 -0
  119. package/lib/utils/isomorphic/locatorGenerators.js +24 -8
  120. package/lib/utils/isomorphic/lruCache.js +51 -0
  121. package/lib/utils/isomorphic/mimeType.js +1 -1
  122. package/lib/utils/isomorphic/protocolFormatter.js +3 -0
  123. package/lib/utils/isomorphic/protocolMetainfo.js +11 -2
  124. package/lib/utils/isomorphic/stringUtils.js +49 -0
  125. package/lib/utils/isomorphic/trace/entries.js +16 -0
  126. package/lib/utils/isomorphic/trace/snapshotRenderer.js +499 -0
  127. package/lib/utils/isomorphic/trace/snapshotServer.js +120 -0
  128. package/lib/utils/isomorphic/trace/snapshotStorage.js +89 -0
  129. package/lib/utils/isomorphic/trace/traceLoader.js +131 -0
  130. package/lib/utils/isomorphic/trace/traceModel.js +365 -0
  131. package/lib/utils/isomorphic/trace/traceModernizer.js +400 -0
  132. package/lib/utils/isomorphic/trace/versions/traceV3.js +16 -0
  133. package/lib/utils/isomorphic/trace/versions/traceV4.js +16 -0
  134. package/lib/utils/isomorphic/trace/versions/traceV5.js +16 -0
  135. package/lib/utils/isomorphic/trace/versions/traceV6.js +16 -0
  136. package/lib/utils/isomorphic/trace/versions/traceV7.js +16 -0
  137. package/lib/utils/isomorphic/trace/versions/traceV8.js +16 -0
  138. package/lib/utils/isomorphic/urlMatch.js +19 -5
  139. package/lib/utils/isomorphic/yaml.js +84 -0
  140. package/lib/utils.js +4 -0
  141. package/lib/utilsBundle.js +1 -1
  142. package/lib/utilsBundleImpl/index.js +124 -124
  143. package/lib/vite/htmlReport/index.html +21 -21
  144. package/lib/vite/recorder/assets/codeMirrorModule-CFUTFUO7.js +32 -0
  145. package/lib/vite/recorder/assets/{codeMirrorModule-C3UTv-Ge.css → codeMirrorModule-DYBRYzYX.css} +1 -1
  146. package/lib/vite/recorder/assets/{index-Ri0uHF7I.css → index-BSjZa4pk.css} +1 -1
  147. package/lib/vite/recorder/assets/index-CVkBxsGf.js +193 -0
  148. package/lib/vite/recorder/index.html +2 -2
  149. package/lib/vite/traceViewer/assets/codeMirrorModule-BVA4h_ZY.js +32 -0
  150. package/lib/vite/traceViewer/assets/defaultSettingsView-CjfmcdOz.js +266 -0
  151. package/lib/vite/traceViewer/{codeMirrorModule.C3UTv-Ge.css → codeMirrorModule.DYBRYzYX.css} +1 -1
  152. package/lib/vite/traceViewer/defaultSettingsView.7ch9cixO.css +1 -0
  153. package/lib/vite/traceViewer/index.BVu7tZDe.css +1 -0
  154. package/lib/vite/traceViewer/index.BtyWtaE-.js +2 -0
  155. package/lib/vite/traceViewer/index.html +6 -6
  156. package/lib/vite/traceViewer/manifest.webmanifest +16 -0
  157. package/lib/vite/traceViewer/snapshot.html +3 -3
  158. package/lib/vite/traceViewer/sw.bundle.js +5 -3
  159. package/lib/vite/traceViewer/uiMode.fyrXARf2.js +5 -0
  160. package/lib/vite/traceViewer/uiMode.html +3 -3
  161. package/package.json +2 -1
  162. package/types/protocol.d.ts +939 -245
  163. package/types/types.d.ts +143 -153
  164. package/lib/client/accessibility.js +0 -49
  165. package/lib/server/accessibility.js +0 -69
  166. package/lib/server/bidi/third_party/bidiDeserializer.js +0 -98
  167. package/lib/server/chromium/crAccessibility.js +0 -263
  168. package/lib/server/firefox/ffAccessibility.js +0 -238
  169. package/lib/server/trace/test/inMemorySnapshotter.js +0 -87
  170. package/lib/server/webkit/wkAccessibility.js +0 -237
  171. package/lib/server/webkit/wsl/webkit-wsl-transport-client.js +0 -74
  172. package/lib/server/webkit/wsl/webkit-wsl-transport-server.js +0 -113
  173. package/lib/vite/recorder/assets/codeMirrorModule-RJCXzfmE.js +0 -24
  174. package/lib/vite/recorder/assets/index-Y-X2TGJv.js +0 -193
  175. package/lib/vite/traceViewer/assets/codeMirrorModule-rbQPefq7.js +0 -24
  176. package/lib/vite/traceViewer/assets/defaultSettingsView-CLbol9XR.js +0 -265
  177. package/lib/vite/traceViewer/defaultSettingsView.TQ8_7ybu.css +0 -1
  178. package/lib/vite/traceViewer/index.I8N9v4jT.css +0 -1
  179. package/lib/vite/traceViewer/index.zIVi6mN9.js +0 -2
  180. package/lib/vite/traceViewer/uiMode.B_CpmIpF.js +0 -5
@@ -250,6 +250,13 @@ class BrowserType extends import_instrumentation.SdkObject {
250
250
  this.waitForReadyState(options, browserLogsCollector),
251
251
  exitPromise.then(() => ({ wsEndpoint: void 0 }))
252
252
  ]);
253
+ if (exitPromise.isDone()) {
254
+ const log = import_helper.helper.formatBrowserLogs(browserLogsCollector.recentLogs());
255
+ const updatedLog = this.doRewriteStartupLog(log);
256
+ throw new Error(`Failed to launch the browser process.
257
+ Browser logs:
258
+ ${updatedLog}`);
259
+ }
253
260
  if (options.cdpPort !== void 0 || !this.supportsPipeTransport()) {
254
261
  transport = await import_transport.WebSocketTransport.connect(progress, wsEndpoint);
255
262
  } else {
@@ -276,15 +283,14 @@ class BrowserType extends import_instrumentation.SdkObject {
276
283
  throw new Error("Connecting to SELENIUM_REMOTE_URL is only supported by Chromium");
277
284
  }
278
285
  _validateLaunchOptions(options) {
279
- const { devtools = false } = options;
280
- let { headless = !devtools, downloadsPath, proxy } = options;
286
+ let { headless = true, downloadsPath, proxy } = options;
281
287
  if ((0, import_debug.debugMode)() === "inspector")
282
288
  headless = false;
283
289
  if (downloadsPath && !import_path.default.isAbsolute(downloadsPath))
284
290
  downloadsPath = import_path.default.join(process.cwd(), downloadsPath);
285
291
  if (options.socksProxyPort)
286
292
  proxy = { server: `socks5://127.0.0.1:${options.socksProxyPort}` };
287
- return { ...options, devtools, headless, downloadsPath, proxy };
293
+ return { ...options, headless, downloadsPath, proxy };
288
294
  }
289
295
  _createUserDataDirArgMisuseError(userDataDirArg) {
290
296
  switch (this.attribution.playwright.options.sdkLanguage) {
@@ -301,7 +307,9 @@ class BrowserType extends import_instrumentation.SdkObject {
301
307
  _rewriteStartupLog(error) {
302
308
  if (!(0, import_protocolError.isProtocolError)(error))
303
309
  return error;
304
- return this.doRewriteStartupLog(error);
310
+ if (error.logs)
311
+ error.logs = this.doRewriteStartupLog(error.logs);
312
+ return error;
305
313
  }
306
314
  async waitForReadyState(options, browserLogsCollector) {
307
315
  return {};
@@ -55,11 +55,22 @@ var import_fileUtils = require("../utils/fileUtils");
55
55
  var import_processLauncher = require("../utils/processLauncher");
56
56
  const ARTIFACTS_FOLDER = import_path.default.join(import_os.default.tmpdir(), "playwright-artifacts-");
57
57
  class Chromium extends import_browserType.BrowserType {
58
- constructor(parent) {
58
+ constructor(parent, bidiChromium) {
59
59
  super(parent, "chromium");
60
+ this._bidiChromium = bidiChromium;
60
61
  if ((0, import_utils.debugMode)() === "inspector")
61
62
  this._devtools = this._createDevTools();
62
63
  }
64
+ launch(progress, options, protocolLogger) {
65
+ if (options.channel?.startsWith("bidi-"))
66
+ return this._bidiChromium.launch(progress, options, protocolLogger);
67
+ return super.launch(progress, options, protocolLogger);
68
+ }
69
+ async launchPersistentContext(progress, userDataDir, options) {
70
+ if (options.channel?.startsWith("bidi-"))
71
+ return this._bidiChromium.launchPersistentContext(progress, userDataDir, options);
72
+ return super.launchPersistentContext(progress, userDataDir, options);
73
+ }
63
74
  async connectOverCDP(progress, endpointURL, options) {
64
75
  return await this._connectOverCDPInternal(progress, endpointURL, options);
65
76
  }
@@ -103,7 +114,8 @@ class Chromium extends import_browserType.BrowserType {
103
114
  };
104
115
  (0, import_browserContext.validateBrowserContextOptions)(persistent, browserOptions);
105
116
  const browser = await progress.race(import_crBrowser.CRBrowser.connect(this.attribution.playwright, chromeTransport, browserOptions));
106
- browser._isCollocatedWithServer = false;
117
+ if (!options.isLocal)
118
+ browser._isCollocatedWithServer = false;
107
119
  browser.on(import_browser.Browser.Events.Disconnected, doCleanup);
108
120
  return browser;
109
121
  } catch (error) {
@@ -117,13 +129,8 @@ class Chromium extends import_browserType.BrowserType {
117
129
  return directory ? new import_crDevTools.CRDevTools(import_path.default.join(directory, "devtools-preferences.json")) : void 0;
118
130
  }
119
131
  async connectToTransport(transport, options, browserLogsCollector) {
120
- let devtools = this._devtools;
121
- if (options.__testHookForDevTools) {
122
- devtools = this._createDevTools();
123
- await options.__testHookForDevTools(devtools);
124
- }
125
132
  try {
126
- return await import_crBrowser.CRBrowser.connect(this.attribution.playwright, transport, options, devtools);
133
+ return await import_crBrowser.CRBrowser.connect(this.attribution.playwright, transport, options, this._devtools);
127
134
  } catch (e) {
128
135
  if (browserLogsCollector.recentLogs().some((log) => log.includes("Failed to create a ProcessSingleton for your profile directory."))) {
129
136
  throw new Error(
@@ -133,14 +140,12 @@ class Chromium extends import_browserType.BrowserType {
133
140
  throw e;
134
141
  }
135
142
  }
136
- doRewriteStartupLog(error) {
137
- if (!error.logs)
138
- return error;
139
- if (error.logs.includes("Missing X server"))
140
- error.logs = "\n" + (0, import_ascii.wrapInASCIIBox)(import_browserType.kNoXServerRunningError, 1);
141
- if (!error.logs.includes("crbug.com/357670") && !error.logs.includes("No usable sandbox!") && !error.logs.includes("crbug.com/638180"))
142
- return error;
143
- error.logs = [
143
+ doRewriteStartupLog(logs) {
144
+ if (logs.includes("Missing X server"))
145
+ logs = "\n" + (0, import_ascii.wrapInASCIIBox)(import_browserType.kNoXServerRunningError, 1);
146
+ if (!logs.includes("crbug.com/357670") && !logs.includes("No usable sandbox!") && !logs.includes("crbug.com/638180"))
147
+ return logs;
148
+ return [
144
149
  `Chromium sandboxing failed!`,
145
150
  `================================`,
146
151
  `To avoid the sandboxing issue, do either of the following:`,
@@ -149,7 +154,6 @@ class Chromium extends import_browserType.BrowserType {
149
154
  `================================`,
150
155
  ``
151
156
  ].join("\n");
152
- return error;
153
157
  }
154
158
  amendEnvironment(env) {
155
159
  return env;
@@ -273,11 +277,8 @@ class Chromium extends import_browserType.BrowserType {
273
277
  if (args.find((arg) => !arg.startsWith("-")))
274
278
  throw new Error("Arguments can not specify page to be opened");
275
279
  const chromeArguments = [...(0, import_chromiumSwitches.chromiumSwitches)(options.assistantMode, options.channel)];
276
- if (import_os.default.platform() === "darwin") {
277
- chromeArguments.push("--enable-unsafe-swiftshader");
280
+ if (import_os.default.platform() !== "darwin" || !(0, import_utils.hasGpuMac)()) {
278
281
  }
279
- if (options.devtools)
280
- chromeArguments.push("--auto-open-devtools-for-tabs");
281
282
  if (options.headless) {
282
283
  chromeArguments.push("--headless");
283
284
  chromeArguments.push(
@@ -313,6 +314,10 @@ class Chromium extends import_browserType.BrowserType {
313
314
  return waitForReadyState(options, browserLogsCollector);
314
315
  }
315
316
  getExecutableName(options) {
317
+ if (options.channel && import_registry.registry.isChromiumAlias(options.channel))
318
+ return "chromium";
319
+ if (options.channel === "chromium-tip-of-tree")
320
+ return options.headless ? "chromium-tip-of-tree-headless-shell" : "chromium-tip-of-tree";
316
321
  if (options.channel)
317
322
  return options.channel;
318
323
  return options.headless ? "chromium-headless-shell" : "chromium";
@@ -22,10 +22,10 @@ __export(chromiumSwitches_exports, {
22
22
  });
23
23
  module.exports = __toCommonJS(chromiumSwitches_exports);
24
24
  const disabledFeatures = (assistantMode) => [
25
- // See https://github.com/microsoft/playwright/pull/10380
26
- "AcceptCHFrame",
27
25
  // See https://github.com/microsoft/playwright/issues/14047
28
26
  "AvoidUnnecessaryBeforeUnloadCheckSync",
27
+ // See https://github.com/microsoft/playwright/issues/38568
28
+ "BoundaryEventDispatchTracksNodeRemoval",
29
29
  "DestroyProfileOnBrowserClose",
30
30
  // See https://github.com/microsoft/playwright/pull/13854
31
31
  "DialMediaRouteProvider",
@@ -46,9 +46,11 @@ const disabledFeatures = (assistantMode) => [
46
46
  "AutoDeElevate",
47
47
  // See https://github.com/microsoft/playwright/issues/37714
48
48
  "RenderDocument",
49
+ // Prevents downloading optimization hints on startup.
50
+ "OptimizationHints",
49
51
  assistantMode ? "AutomationControlled" : ""
50
52
  ].filter(Boolean);
51
- const chromiumSwitches = (assistantMode, channel) => [
53
+ const chromiumSwitches = (assistantMode, channel, android) => [
52
54
  "--disable-field-trial-config",
53
55
  // https://source.chromium.org/chromium/chromium/src/+/main:testing/variations/README.md
54
56
  "--disable-background-networking",
@@ -75,6 +77,13 @@ const chromiumSwitches = (assistantMode, channel) => [
75
77
  "--disable-search-engine-choice-screen",
76
78
  // Edge can potentially restart on Windows (msRelaunchNoCompatLayer) which looses its file descriptors (stdout/stderr) and CDP (3/4). Disable until fixed upstream.
77
79
  "--edge-skip-compat-layer-relaunch",
80
+ // This disables Chrome for Testing infobar that is visible in the persistent context.
81
+ // The switch is ignored everywhere else, including Chromium/Chrome/Edge.
82
+ "--disable-infobars",
83
+ // Less annoying popups.
84
+ "--disable-search-engine-choice-screen",
85
+ // Prevents the "three dots" menu crash in IdentityManager::HasPrimaryAccount for ephemeral contexts.
86
+ android ? "" : "--disable-sync",
78
87
  "--disable-blink-features=AutomationControlled"
79
88
  ].filter(Boolean);
80
89
  // Annotate the CommonJS export names for ESM import in node:
@@ -53,6 +53,7 @@ class CRBrowser extends import_browser.Browser {
53
53
  this._crPages = /* @__PURE__ */ new Map();
54
54
  this._serviceWorkers = /* @__PURE__ */ new Map();
55
55
  this._version = "";
56
+ this._majorVersion = 0;
56
57
  this._tracingRecording = false;
57
58
  this._userAgent = "";
58
59
  this._connection = connection;
@@ -75,6 +76,10 @@ class CRBrowser extends import_browser.Browser {
75
76
  await options.__testHookOnConnectToBrowser();
76
77
  const version = await session.send("Browser.getVersion");
77
78
  browser._version = version.product.substring(version.product.indexOf("/") + 1);
79
+ try {
80
+ browser._majorVersion = +browser._version.split(".")[0];
81
+ } catch {
82
+ }
78
83
  browser._userAgent = version.userAgent;
79
84
  browser.options.headful = !version.userAgent.includes("Headless");
80
85
  if (!options.persistent) {
@@ -116,6 +121,9 @@ class CRBrowser extends import_browser.Browser {
116
121
  version() {
117
122
  return this._version;
118
123
  }
124
+ majorVersion() {
125
+ return this._majorVersion;
126
+ }
119
127
  userAgent() {
120
128
  return this._userAgent;
121
129
  }
@@ -276,11 +284,12 @@ class CRBrowser extends import_browser.Browser {
276
284
  return this._clientRootSessionPromise;
277
285
  }
278
286
  }
287
+ const CREvents = {
288
+ ServiceWorker: "serviceworker"
289
+ };
279
290
  class CRBrowserContext extends import_browserContext.BrowserContext {
280
291
  static {
281
- this.CREvents = {
282
- ServiceWorker: "serviceworker"
283
- };
292
+ this.CREvents = CREvents;
284
293
  }
285
294
  constructor(browser, browserContextId, options) {
286
295
  super(browser, options, browserContextId);
@@ -380,15 +389,24 @@ class CRBrowserContext extends import_browserContext.BrowserContext {
380
389
  ["midi-sysex", "midiSysex"],
381
390
  ["storage-access", "storageAccess"],
382
391
  ["local-fonts", "localFonts"],
383
- ["local-network-access", "localNetworkAccess"]
392
+ ["local-network-access", ["localNetworkAccess", "localNetwork", "loopbackNetwork"]]
384
393
  ]);
385
- const filtered = permissions.map((permission) => {
386
- const protocolPermission = webPermissionToProtocol.get(permission);
387
- if (!protocolPermission)
388
- throw new Error("Unknown permission: " + permission);
389
- return protocolPermission;
390
- });
391
- await this._browser._session.send("Browser.grantPermissions", { origin: origin === "*" ? void 0 : origin, browserContextId: this._browserContextId, permissions: filtered });
394
+ const grantPermissions = async (mapping) => {
395
+ const filtered = permissions.flatMap((permission) => {
396
+ const protocolPermission = mapping.get(permission);
397
+ if (!protocolPermission)
398
+ throw new Error("Unknown permission: " + permission);
399
+ return typeof protocolPermission === "string" ? [protocolPermission] : protocolPermission;
400
+ });
401
+ await this._browser._session.send("Browser.grantPermissions", { origin: origin === "*" ? void 0 : origin, browserContextId: this._browserContextId, permissions: filtered });
402
+ };
403
+ try {
404
+ await grantPermissions(webPermissionToProtocol);
405
+ } catch (e) {
406
+ const fallbackMapping = new Map(webPermissionToProtocol);
407
+ fallbackMapping.set("local-network-access", ["localNetworkAccess"]);
408
+ await grantPermissions(fallbackMapping);
409
+ }
392
410
  }
393
411
  async doClearPermissions() {
394
412
  await this._browser._session.send("Browser.resetPermissions", { browserContextId: this._browserContextId });
@@ -461,7 +479,7 @@ class CRBrowserContext extends import_browserContext.BrowserContext {
461
479
  }
462
480
  }
463
481
  async stopVideoRecording() {
464
- await Promise.all(this._crPages().map((crPage) => crPage._mainFrameSession._stopVideoRecording()));
482
+ await Promise.all(this._crPages().map((crPage) => crPage._page.screencast.stopVideoRecording()));
465
483
  }
466
484
  onClosePersistent() {
467
485
  }
@@ -94,11 +94,6 @@ class CRSession extends import_instrumentation.SdkObject {
94
94
  this._parentSession = parentSession;
95
95
  this._sessionId = sessionId;
96
96
  this._eventListener = eventListener;
97
- this.on = super.on;
98
- this.addListener = super.addListener;
99
- this.off = super.removeListener;
100
- this.removeListener = super.removeListener;
101
- this.once = super.once;
102
97
  }
103
98
  _markAsCrashed() {
104
99
  this._crashed = true;
@@ -66,6 +66,7 @@ class JSCoverage {
66
66
  this._eventListeners = [
67
67
  import_eventsHelper.eventsHelper.addEventListener(this._client, "Debugger.scriptParsed", this._onScriptParsed.bind(this)),
68
68
  import_eventsHelper.eventsHelper.addEventListener(this._client, "Runtime.executionContextsCleared", this._onExecutionContextsCleared.bind(this)),
69
+ import_eventsHelper.eventsHelper.addEventListener(this._client, "Page.frameNavigated", this._onFrameNavigated.bind(this)),
69
70
  import_eventsHelper.eventsHelper.addEventListener(this._client, "Debugger.paused", this._onDebuggerPaused.bind(this))
70
71
  ];
71
72
  await Promise.all([
@@ -117,6 +118,11 @@ class JSCoverage {
117
118
  }
118
119
  return coverage;
119
120
  }
121
+ _onFrameNavigated(event) {
122
+ if (event.frame.parentId)
123
+ return;
124
+ this._onExecutionContextsCleared();
125
+ }
120
126
  }
121
127
  class CSSCoverage {
122
128
  constructor(client) {
@@ -136,7 +142,8 @@ class CSSCoverage {
136
142
  this._stylesheetSources.clear();
137
143
  this._eventListeners = [
138
144
  import_eventsHelper.eventsHelper.addEventListener(this._client, "CSS.styleSheetAdded", this._onStyleSheet.bind(this)),
139
- import_eventsHelper.eventsHelper.addEventListener(this._client, "Runtime.executionContextsCleared", this._onExecutionContextsCleared.bind(this))
145
+ import_eventsHelper.eventsHelper.addEventListener(this._client, "Runtime.executionContextsCleared", this._onExecutionContextsCleared.bind(this)),
146
+ import_eventsHelper.eventsHelper.addEventListener(this._client, "Page.frameNavigated", this._onFrameNavigated.bind(this))
140
147
  ];
141
148
  await Promise.all([
142
149
  this._client.send("DOM.enable"),
@@ -192,6 +199,11 @@ class CSSCoverage {
192
199
  }
193
200
  return coverage;
194
201
  }
202
+ _onFrameNavigated(event) {
203
+ if (event.frame.parentId)
204
+ return;
205
+ this._onExecutionContextsCleared();
206
+ }
195
207
  }
196
208
  function convertToDisjointRanges(nestedRanges) {
197
209
  const points = [];
@@ -44,8 +44,6 @@ class CRDevTools {
44
44
  return;
45
45
  const parsed = JSON.parse(event.payload);
46
46
  let result = void 0;
47
- if (this.__testHookOnBinding)
48
- this.__testHookOnBinding(parsed);
49
47
  if (parsed.method === "getPreferences") {
50
48
  if (this._prefs === void 0) {
51
49
  try {
@@ -141,6 +141,8 @@ class CRNetworkManager {
141
141
  async setRequestInterception(value) {
142
142
  this._userRequestInterceptionEnabled = value;
143
143
  await this._updateProtocolRequestInterception();
144
+ if (this._page)
145
+ await this._forEachSession((info) => info.session.send("Network.setCacheDisabled", { cacheDisabled: this._page.needsRequestInterception() }));
144
146
  }
145
147
  async _updateProtocolRequestInterception() {
146
148
  const enabled = this._userRequestInterceptionEnabled || !!this._credentials;
@@ -153,7 +155,9 @@ class CRNetworkManager {
153
155
  const enabled = this._protocolRequestInterceptionEnabled;
154
156
  if (initial && !enabled)
155
157
  return;
156
- const cachePromise = info.session.send("Network.setCacheDisabled", { cacheDisabled: false });
158
+ const hasHarRecorders = !!this._page?.browserContext?._harRecorders?.size;
159
+ const userInterception = this._page ? this._page.needsRequestInterception() : false;
160
+ const cachePromise = info.session.send("Network.setCacheDisabled", { cacheDisabled: userInterception || hasHarRecorders });
157
161
  let fetchPromise = Promise.resolve(void 0);
158
162
  if (!info.workerFrame) {
159
163
  if (enabled)
@@ -265,13 +269,17 @@ class CRNetworkManager {
265
269
  redirectedFrom = request2;
266
270
  }
267
271
  }
272
+ const isInterceptedOptionsPreflight = !!requestPausedEvent && requestPausedEvent.request.method === "OPTIONS" && requestWillBeSentEvent.initiator.type === "preflight";
273
+ if (isInterceptedOptionsPreflight && !(this._page || this._serviceWorker).needsRequestInterception()) {
274
+ requestPausedSessionInfo.session._sendMayFail("Fetch.continueRequest", { requestId: requestPausedEvent.requestId });
275
+ return;
276
+ }
268
277
  let frame = requestWillBeSentEvent.frameId ? this._page?.frameManager.frame(requestWillBeSentEvent.frameId) : requestWillBeSentSessionInfo.workerFrame;
269
278
  if (!frame && this._page && requestPausedEvent && requestPausedEvent.frameId)
270
279
  frame = this._page.frameManager.frame(requestPausedEvent.frameId);
271
280
  if (!frame && this._page && requestWillBeSentEvent.frameId === (this._page?.delegate)._targetId) {
272
281
  frame = this._page.frameManager.frameAttached(requestWillBeSentEvent.frameId, null);
273
282
  }
274
- const isInterceptedOptionsPreflight = !!requestPausedEvent && requestPausedEvent.request.method === "OPTIONS" && requestWillBeSentEvent.initiator.type === "preflight";
275
283
  if (isInterceptedOptionsPreflight && (this._page || this._serviceWorker).needsRequestInterception()) {
276
284
  const requestHeaders = requestPausedEvent.request.headers;
277
285
  const responseHeaders = [
@@ -300,6 +308,10 @@ class CRNetworkManager {
300
308
  if (requestPausedEvent) {
301
309
  if (redirectedFrom || !this._userRequestInterceptionEnabled && this._protocolRequestInterceptionEnabled) {
302
310
  headersOverride = redirectedFrom?._originalRequestRoute?._alreadyContinuedParams?.headers;
311
+ if (headersOverride) {
312
+ const originalHeaders = Object.entries(requestPausedEvent.request.headers).map(([name, value]) => ({ name, value }));
313
+ headersOverride = network.applyHeadersOverrides(originalHeaders, headersOverride);
314
+ }
303
315
  requestPausedSessionInfo.session._sendMayFail("Fetch.continueRequest", { requestId: requestPausedEvent.requestId, headers: headersOverride });
304
316
  } else {
305
317
  route = new RouteImpl(requestPausedSessionInfo.session, requestPausedEvent.requestId, this._page, requestPausedEvent.networkId, this);
@@ -486,12 +498,11 @@ class InterceptableRequest {
486
498
  url,
487
499
  postDataEntries = null
488
500
  } = requestPausedEvent ? requestPausedEvent.request : requestWillBeSentEvent.request;
489
- const type = (requestWillBeSentEvent.type || "").toLowerCase();
490
501
  let postDataBuffer = null;
491
502
  const entries = postDataEntries?.filter((entry) => entry.bytes);
492
503
  if (entries && entries.length)
493
504
  postDataBuffer = Buffer.concat(entries.map((entry) => Buffer.from(entry.bytes, "base64")));
494
- this.request = new network.Request(context, frame, serviceWorker, redirectedFrom?.request || null, documentId, url, type, method, postDataBuffer, headersOverride || (0, import_utils.headersObjectToArray)(headers));
505
+ this.request = new network.Request(context, frame, serviceWorker, redirectedFrom?.request || null, documentId, url, toResourceType(requestWillBeSentEvent.type || "Other"), method, postDataBuffer, headersOverride || (0, import_utils.headersObjectToArray)(headers));
495
506
  }
496
507
  }
497
508
  class RouteImpl {
@@ -528,11 +539,12 @@ class RouteImpl {
528
539
  }
529
540
  async fulfill(response) {
530
541
  const isTextHtml = response.headers.some((header) => header.name.toLowerCase() === "content-type" && header.value.includes("text/html"));
531
- var allInjections = [...this._page.delegate._mainFrameSession._evaluateOnNewDocumentScripts];
532
- for (const binding of this._page.delegate._browserContext._pageBindings.values()) {
533
- if (!allInjections.includes(binding)) allInjections.push(binding);
534
- }
535
- if (isTextHtml && allInjections.length) {
542
+ const pageDelegate = this._page?.delegate || null;
543
+ const initScriptTag = pageDelegate?.initScriptTag || "";
544
+ let allInjections = [];
545
+ if (pageDelegate)
546
+ allInjections = [...pageDelegate._mainFrameSession._evaluateOnNewDocumentScripts];
547
+ if (isTextHtml && allInjections.length && initScriptTag) {
536
548
  let useNonce = false;
537
549
  let scriptNonce = null;
538
550
  if (response.isBase64) {
@@ -583,7 +595,7 @@ class RouteImpl {
583
595
  let scriptId = import_crypto.default.randomBytes(22).toString("hex");
584
596
  let scriptSource = script.source || script;
585
597
  const nonceAttr = useNonce ? `nonce="${scriptNonce}"` : "";
586
- injectionHTML += `<script class="${this._page.delegate.initScriptTag}" ${nonceAttr} id="${scriptId}" type="text/javascript">document.getElementById("${scriptId}")?.remove();${scriptSource}</script>`;
598
+ injectionHTML += `<script class="${initScriptTag}" ${nonceAttr} id="${scriptId}" type="text/javascript">document.getElementById("${scriptId}")?.remove();${scriptSource}</script>`;
587
599
  });
588
600
  const lower = response.body.toLowerCase();
589
601
  const headStartIndex = lower.indexOf("<head");
@@ -593,7 +605,27 @@ class RouteImpl {
593
605
  const headOpenEnd = response.body.indexOf(">", headStartIndex) + 1;
594
606
  const headContent = response.body.slice(headOpenEnd, headEndTagIndex);
595
607
  const headContentLower = headContent.toLowerCase();
596
- const firstScriptIndex = headContentLower.indexOf("<script");
608
+ let firstScriptIndex = -1;
609
+ let searchPos = 0;
610
+ const endSearchPos = headContentLower.length;
611
+ while (searchPos < endSearchPos) {
612
+ const commentStart = headContentLower.indexOf("<!--", searchPos);
613
+ const scriptStart = headContentLower.indexOf("<script", searchPos);
614
+ if (scriptStart === -1 || scriptStart >= endSearchPos) {
615
+ break;
616
+ }
617
+ if (commentStart !== -1 && commentStart < scriptStart) {
618
+ const commentEnd = headContentLower.indexOf("-->", commentStart);
619
+ if (commentEnd !== -1) {
620
+ searchPos = commentEnd + 3;
621
+ continue;
622
+ } else {
623
+ break;
624
+ }
625
+ }
626
+ firstScriptIndex = scriptStart;
627
+ break;
628
+ }
597
629
  if (firstScriptIndex !== -1) {
598
630
  const insertPosition = headOpenEnd + firstScriptIndex;
599
631
  response.body = response.body.slice(0, insertPosition) + injectionHTML + response.body.slice(insertPosition);
@@ -650,10 +682,13 @@ class RouteImpl {
650
682
  let hasScriptSrc = false;
651
683
  for (let directive of directives) {
652
684
  if (!directive.trim()) continue;
653
- const parts = directive.trim().split(/s+/);
654
- if (parts.length === 0) continue;
655
- const directiveName = parts[0].toLowerCase();
656
- const directiveValues = parts.slice(1);
685
+ const directiveMatch = directive.match(/^([a-zA-Z-]+)\s+(.*)$/);
686
+ if (!directiveMatch) {
687
+ fixedDirectives.push(directive);
688
+ continue;
689
+ }
690
+ const directiveName = directiveMatch[1].toLowerCase();
691
+ const directiveValues = directiveMatch[2].split(/\s+/).filter((v) => v.length > 0);
657
692
  switch (directiveName) {
658
693
  case "script-src":
659
694
  hasScriptSrc = true;
@@ -664,6 +699,12 @@ class RouteImpl {
664
699
  if (!values.includes("'unsafe-eval'")) {
665
700
  values.push("'unsafe-eval'");
666
701
  }
702
+ if (!values.includes("'unsafe-inline'") && !scriptNonce) {
703
+ values.push("'unsafe-inline'");
704
+ }
705
+ if (!values.includes("*") && !values.includes("'self'") && !values.some((v) => v.includes("https:"))) {
706
+ values.push("*");
707
+ }
667
708
  fixedDirectives.push(`script-src ${values.join(" ")}`);
668
709
  break;
669
710
  case "style-src":
@@ -709,9 +750,9 @@ class RouteImpl {
709
750
  }
710
751
  if (!hasScriptSrc) {
711
752
  if (scriptNonce) {
712
- fixedDirectives.push(`script-src 'self' 'unsafe-eval' 'nonce-${scriptNonce}'`);
753
+ fixedDirectives.push(`script-src 'self' 'unsafe-eval' 'nonce-${scriptNonce}' *`);
713
754
  } else {
714
- fixedDirectives.push(`script-src 'self' 'unsafe-eval'`);
755
+ fixedDirectives.push(`script-src 'self' 'unsafe-eval' 'unsafe-inline' *`);
715
756
  }
716
757
  }
717
758
  return fixedDirectives.join("; ");
@@ -722,6 +763,12 @@ class RouteImpl {
722
763
  }
723
764
  if (this._networkId != event.networkId || !this._sessionManager._alreadyTrackedNetworkIds.has(event.networkId)) return;
724
765
  try {
766
+ const url = event.request?.url || "";
767
+ const isPrivilegePage = url.startsWith("https://ntp.msn");
768
+ if (isPrivilegePage) {
769
+ await this._session._sendMayFail("Fetch.continueRequest", { requestId: event.requestId });
770
+ return;
771
+ }
725
772
  if (event.responseStatusCode >= 301 && event.responseStatusCode <= 308 || event.redirectedRequestId && !event.responseStatusCode) {
726
773
  await this._session.send("Fetch.continueRequest", { requestId: event.requestId, interceptResponse: true });
727
774
  } else {
@@ -736,7 +783,11 @@ class RouteImpl {
736
783
  });
737
784
  }
738
785
  } catch (error) {
739
- await this._session._sendMayFail("Fetch.continueRequest", { requestId: event.requestId });
786
+ if (error.message.includes("Can only get response body on HeadersReceived pattern matched requests.")) {
787
+ await this._session.send("Fetch.continueRequest", { requestId: event.requestId, interceptResponse: true });
788
+ } else {
789
+ await this._session._sendMayFail("Fetch.continueRequest", { requestId: event.requestId });
790
+ }
740
791
  }
741
792
  }
742
793
  }
@@ -867,6 +918,44 @@ class ResponseExtraInfoTracker {
867
918
  this._requests.delete(requestId);
868
919
  }
869
920
  }
921
+ function toResourceType(type) {
922
+ switch (type) {
923
+ case "Document":
924
+ return "document";
925
+ case "Stylesheet":
926
+ return "stylesheet";
927
+ case "Image":
928
+ return "image";
929
+ case "Media":
930
+ return "media";
931
+ case "Font":
932
+ return "font";
933
+ case "Script":
934
+ return "script";
935
+ case "TextTrack":
936
+ return "texttrack";
937
+ case "XHR":
938
+ return "xhr";
939
+ case "Fetch":
940
+ return "fetch";
941
+ case "EventSource":
942
+ return "eventsource";
943
+ case "WebSocket":
944
+ return "websocket";
945
+ case "Manifest":
946
+ return "manifest";
947
+ case "Ping":
948
+ return "ping";
949
+ case "CSPViolationReport":
950
+ return "cspreport";
951
+ case "Prefetch":
952
+ case "SignedExchange":
953
+ case "Preflight":
954
+ case "FedCM":
955
+ default:
956
+ return "other";
957
+ }
958
+ }
870
959
  // Annotate the CommonJS export names for ESM import in node:
871
960
  0 && (module.exports = {
872
961
  CRNetworkManager