patchright-core 1.57.0 → 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 (148) hide show
  1. package/ThirdPartyNotices.txt +3223 -308
  2. package/browsers.json +21 -22
  3. package/lib/cli/program.js +4 -5
  4. package/lib/client/api.js +3 -0
  5. package/lib/client/browser.js +3 -5
  6. package/lib/client/browserContext.js +40 -4
  7. package/lib/client/browserType.js +4 -3
  8. package/lib/client/connection.js +4 -0
  9. package/lib/client/elementHandle.js +3 -0
  10. package/lib/client/events.js +3 -0
  11. package/lib/client/fetch.js +3 -4
  12. package/lib/client/frame.js +10 -1
  13. package/lib/client/locator.js +8 -0
  14. package/lib/client/network.js +5 -1
  15. package/lib/client/page.js +29 -1
  16. package/lib/client/pageAgent.js +64 -0
  17. package/lib/client/platform.js +3 -0
  18. package/lib/client/tracing.js +1 -1
  19. package/lib/generated/injectedScriptSource.js +1 -1
  20. package/lib/generated/pollingRecorderSource.js +1 -1
  21. package/lib/mcpBundle.js +84 -0
  22. package/lib/mcpBundleImpl/index.js +147 -0
  23. package/lib/protocol/serializers.js +5 -0
  24. package/lib/protocol/validator.js +88 -4
  25. package/lib/remote/playwrightServer.js +1 -2
  26. package/lib/server/agent/actionRunner.js +335 -0
  27. package/lib/server/agent/actions.js +128 -0
  28. package/lib/server/agent/codegen.js +111 -0
  29. package/lib/server/agent/context.js +150 -0
  30. package/lib/server/agent/expectTools.js +156 -0
  31. package/lib/server/agent/pageAgent.js +204 -0
  32. package/lib/server/agent/performTools.js +262 -0
  33. package/lib/server/agent/tool.js +109 -0
  34. package/lib/server/artifact.js +1 -1
  35. package/lib/server/bidi/bidiBrowser.js +56 -12
  36. package/lib/server/bidi/bidiChromium.js +8 -12
  37. package/lib/server/bidi/bidiConnection.js +1 -0
  38. package/lib/server/bidi/bidiDeserializer.js +116 -0
  39. package/lib/server/bidi/bidiExecutionContext.js +75 -29
  40. package/lib/server/bidi/bidiFirefox.js +6 -8
  41. package/lib/server/bidi/bidiNetworkManager.js +1 -1
  42. package/lib/server/bidi/bidiPage.js +39 -28
  43. package/lib/server/bidi/third_party/bidiProtocolCore.js +1 -0
  44. package/lib/server/browserContext.js +34 -26
  45. package/lib/server/browserType.js +12 -4
  46. package/lib/server/chromium/chromium.js +14 -20
  47. package/lib/server/chromium/chromiumSwitches.js +2 -2
  48. package/lib/server/chromium/crBrowser.js +22 -12
  49. package/lib/server/chromium/crConnection.js +0 -5
  50. package/lib/server/chromium/crCoverage.js +13 -1
  51. package/lib/server/chromium/crDevTools.js +0 -2
  52. package/lib/server/chromium/crNetworkManager.js +92 -12
  53. package/lib/server/chromium/crPage.js +62 -116
  54. package/lib/server/codegen/javascript.js +6 -29
  55. package/lib/server/deviceDescriptorsSource.json +56 -56
  56. package/lib/server/dispatchers/browserContextDispatcher.js +3 -2
  57. package/lib/server/dispatchers/dispatcher.js +6 -13
  58. package/lib/server/dispatchers/frameDispatcher.js +1 -1
  59. package/lib/server/dispatchers/jsHandleDispatcher.js +2 -2
  60. package/lib/server/dispatchers/pageAgentDispatcher.js +96 -0
  61. package/lib/server/dispatchers/pageDispatcher.js +4 -0
  62. package/lib/server/dom.js +12 -3
  63. package/lib/server/electron/electron.js +5 -2
  64. package/lib/server/firefox/ffBrowser.js +10 -20
  65. package/lib/server/firefox/ffConnection.js +0 -5
  66. package/lib/server/firefox/ffNetworkManager.js +2 -2
  67. package/lib/server/firefox/ffPage.js +15 -18
  68. package/lib/server/firefox/firefox.js +6 -8
  69. package/lib/server/frameSelectors.js +16 -4
  70. package/lib/server/frames.js +251 -86
  71. package/lib/server/instrumentation.js +3 -0
  72. package/lib/server/javascript.js +8 -4
  73. package/lib/server/launchApp.js +2 -1
  74. package/lib/server/network.js +50 -12
  75. package/lib/server/page.js +61 -91
  76. package/lib/server/progress.js +26 -6
  77. package/lib/server/recorder/recorderApp.js +79 -100
  78. package/lib/server/registry/browserFetcher.js +6 -4
  79. package/lib/server/registry/index.js +172 -149
  80. package/lib/server/registry/oopDownloadBrowserMain.js +3 -0
  81. package/lib/server/screencast.js +190 -0
  82. package/lib/server/screenshotter.js +6 -0
  83. package/lib/server/trace/recorder/snapshotter.js +17 -8
  84. package/lib/server/trace/recorder/snapshotterInjected.js +30 -72
  85. package/lib/server/trace/recorder/tracing.js +29 -21
  86. package/lib/server/trace/viewer/traceParser.js +72 -0
  87. package/lib/server/trace/viewer/traceViewer.js +21 -17
  88. package/lib/server/utils/expectUtils.js +87 -2
  89. package/lib/server/utils/hostPlatform.js +15 -0
  90. package/lib/server/utils/httpServer.js +5 -20
  91. package/lib/server/utils/network.js +37 -28
  92. package/lib/server/utils/nodePlatform.js +6 -0
  93. package/lib/server/{chromium/videoRecorder.js → videoRecorder.js} +22 -13
  94. package/lib/server/webkit/webkit.js +4 -6
  95. package/lib/server/webkit/wkBrowser.js +2 -6
  96. package/lib/server/webkit/wkConnection.js +1 -6
  97. package/lib/server/webkit/wkInterceptableRequest.js +29 -1
  98. package/lib/server/webkit/wkPage.js +75 -46
  99. package/lib/utils/isomorphic/ariaSnapshot.js +60 -2
  100. package/lib/utils/isomorphic/lruCache.js +51 -0
  101. package/lib/utils/isomorphic/protocolMetainfo.js +9 -1
  102. package/lib/utils/isomorphic/stringUtils.js +49 -0
  103. package/lib/utils/isomorphic/trace/entries.js +16 -0
  104. package/lib/utils/isomorphic/trace/snapshotRenderer.js +499 -0
  105. package/lib/utils/isomorphic/trace/snapshotServer.js +120 -0
  106. package/lib/utils/isomorphic/trace/snapshotStorage.js +89 -0
  107. package/lib/utils/isomorphic/trace/traceLoader.js +131 -0
  108. package/lib/utils/isomorphic/trace/traceModel.js +365 -0
  109. package/lib/utils/isomorphic/trace/traceModernizer.js +400 -0
  110. package/lib/utils/isomorphic/trace/versions/traceV3.js +16 -0
  111. package/lib/utils/isomorphic/trace/versions/traceV4.js +16 -0
  112. package/lib/utils/isomorphic/trace/versions/traceV5.js +16 -0
  113. package/lib/utils/isomorphic/trace/versions/traceV6.js +16 -0
  114. package/lib/utils/isomorphic/trace/versions/traceV7.js +16 -0
  115. package/lib/utils/isomorphic/trace/versions/traceV8.js +16 -0
  116. package/lib/utils/isomorphic/yaml.js +84 -0
  117. package/lib/utils.js +2 -0
  118. package/lib/utilsBundle.js +2 -5
  119. package/lib/utilsBundleImpl/index.js +165 -165
  120. package/lib/vite/htmlReport/index.html +21 -21
  121. package/lib/vite/recorder/assets/codeMirrorModule-CFUTFUO7.js +32 -0
  122. package/lib/vite/{traceViewer/codeMirrorModule.C3UTv-Ge.css → recorder/assets/codeMirrorModule-DYBRYzYX.css} +1 -1
  123. package/lib/vite/recorder/assets/{index-Ri0uHF7I.css → index-BSjZa4pk.css} +1 -1
  124. package/lib/vite/recorder/assets/index-CVkBxsGf.js +193 -0
  125. package/lib/vite/recorder/index.html +2 -2
  126. package/lib/vite/traceViewer/assets/codeMirrorModule-BVA4h_ZY.js +32 -0
  127. package/lib/vite/traceViewer/assets/defaultSettingsView-CjfmcdOz.js +266 -0
  128. package/lib/vite/{recorder/assets/codeMirrorModule-C3UTv-Ge.css → traceViewer/codeMirrorModule.DYBRYzYX.css} +1 -1
  129. package/lib/vite/traceViewer/defaultSettingsView.7ch9cixO.css +1 -0
  130. package/lib/vite/traceViewer/index.BVu7tZDe.css +1 -0
  131. package/lib/vite/traceViewer/index.BtyWtaE-.js +2 -0
  132. package/lib/vite/traceViewer/index.html +4 -4
  133. package/lib/vite/traceViewer/sw.bundle.js +5 -3
  134. package/lib/vite/traceViewer/uiMode.fyrXARf2.js +5 -0
  135. package/lib/vite/traceViewer/uiMode.html +3 -3
  136. package/package.json +2 -1
  137. package/types/protocol.d.ts +738 -159
  138. package/types/types.d.ts +25 -38
  139. package/lib/server/bidi/third_party/bidiDeserializer.js +0 -98
  140. package/lib/server/trace/test/inMemorySnapshotter.js +0 -87
  141. package/lib/vite/recorder/assets/codeMirrorModule-CBbSe-ZI.js +0 -25
  142. package/lib/vite/recorder/assets/index-CpZVd2nA.js +0 -193
  143. package/lib/vite/traceViewer/assets/codeMirrorModule-DHz0wP2C.js +0 -25
  144. package/lib/vite/traceViewer/assets/defaultSettingsView-WsZP88O6.js +0 -266
  145. package/lib/vite/traceViewer/defaultSettingsView.ConWv5KN.css +0 -1
  146. package/lib/vite/traceViewer/index.C4Y3Aw8n.css +0 -1
  147. package/lib/vite/traceViewer/index.C8xAeo93.js +0 -2
  148. package/lib/vite/traceViewer/uiMode.BltraIJB.js +0 -5
@@ -55,6 +55,24 @@ var import_recorderApp = require("./recorder/recorderApp");
55
55
  var import_selectors = require("./selectors");
56
56
  var import_tracing = require("./trace/recorder/tracing");
57
57
  var rawStorageSource = __toESM(require("../generated/storageScriptSource"));
58
+ const BrowserContextEvent = {
59
+ Console: "console",
60
+ Close: "close",
61
+ Page: "page",
62
+ // Can't use just 'error' due to node.js special treatment of error events.
63
+ // @see https://nodejs.org/api/events.html#events_error_events
64
+ PageError: "pageerror",
65
+ Request: "request",
66
+ Response: "response",
67
+ RequestFailed: "requestfailed",
68
+ RequestFinished: "requestfinished",
69
+ RequestAborted: "requestaborted",
70
+ RequestFulfilled: "requestfulfilled",
71
+ RequestContinued: "requestcontinued",
72
+ BeforeClose: "beforeclose",
73
+ VideoStarted: "videostarted",
74
+ RecorderEvent: "recorderevent"
75
+ };
58
76
  class BrowserContext extends import_instrumentation.SdkObject {
59
77
  constructor(browser, options, browserContextId) {
60
78
  super(browser, "browser-context");
@@ -69,6 +87,7 @@ class BrowserContext extends import_instrumentation.SdkObject {
69
87
  this._creatingStorageStatePage = false;
70
88
  this.initScripts = [];
71
89
  this._routesInFlight = /* @__PURE__ */ new Set();
90
+ this._consoleApiExposed = false;
72
91
  this.attribution.context = this;
73
92
  this._browser = browser;
74
93
  this._options = options;
@@ -82,24 +101,7 @@ class BrowserContext extends import_instrumentation.SdkObject {
82
101
  this.dialogManager = new import_dialog.DialogManager(this.instrumentation);
83
102
  }
84
103
  static {
85
- this.Events = {
86
- Console: "console",
87
- Close: "close",
88
- Page: "page",
89
- // Can't use just 'error' due to node.js special treatment of error events.
90
- // @see https://nodejs.org/api/events.html#events_error_events
91
- PageError: "pageerror",
92
- Request: "request",
93
- Response: "response",
94
- RequestFailed: "requestfailed",
95
- RequestFinished: "requestfinished",
96
- RequestAborted: "requestaborted",
97
- RequestFulfilled: "requestfulfilled",
98
- RequestContinued: "requestcontinued",
99
- BeforeClose: "beforeclose",
100
- VideoStarted: "videostarted",
101
- RecorderEvent: "recorderevent"
102
- };
104
+ this.Events = BrowserContextEvent;
103
105
  }
104
106
  isPersistentContext() {
105
107
  return this._isPersistentContext;
@@ -119,12 +121,8 @@ class BrowserContext extends import_instrumentation.SdkObject {
119
121
  if (this._debugger.isPaused())
120
122
  import_recorderApp.RecorderApp.showInspectorNoReply(this);
121
123
  });
122
- if ((0, import_debug.debugMode)() === "console") {
123
- await this.extendInjectedScript(`
124
- function installConsoleApi(injectedScript) { injectedScript.consoleApi.install(); }
125
- module.exports = { default: () => installConsoleApi };
126
- `);
127
- }
124
+ if ((0, import_debug.debugMode)() === "console")
125
+ await this.exposeConsoleApi();
128
126
  if (this._options.serviceWorkers === "block")
129
127
  await this.addInitScript(void 0, `navigator.serviceWorker.register = async () => { };`);
130
128
  if (this._options.permissions)
@@ -133,6 +131,15 @@ class BrowserContext extends import_instrumentation.SdkObject {
133
131
  debugger() {
134
132
  return this._debugger;
135
133
  }
134
+ async exposeConsoleApi() {
135
+ if (this._consoleApiExposed)
136
+ return;
137
+ this._consoleApiExposed = true;
138
+ await this.extendInjectedScript(`
139
+ function installConsoleApi(injectedScript) { injectedScript.consoleApi.install(); }
140
+ module.exports = { default: () => installConsoleApi };
141
+ `);
142
+ }
136
143
  async _ensureVideosPath() {
137
144
  if (this._options.recordVideo)
138
145
  await (0, import_fileUtils.mkdirIfNeeded)(import_path.default.join(this._options.recordVideo.dir, "dummy"));
@@ -309,7 +316,7 @@ class BrowserContext extends import_instrumentation.SdkObject {
309
316
  const pageOrError = await progress.race(page.waitForInitializedOrError());
310
317
  if (pageOrError instanceof Error)
311
318
  throw pageOrError;
312
- await page.mainFrame()._waitForLoadState(progress, "load");
319
+ await page.mainFrame().waitForLoadState(progress, "load");
313
320
  return page;
314
321
  }
315
322
  async _loadDefaultContext(progress) {
@@ -669,7 +676,8 @@ const defaultNewContextParamValues = {
669
676
  acceptDownloads: "accept",
670
677
  strictSelectors: false,
671
678
  serviceWorkers: "allow",
672
- locale: "en-US"
679
+ locale: "en-US",
680
+ focusControl: false
673
681
  };
674
682
  // Annotate the CommonJS export names for ESM import in node:
675
683
  0 && (module.exports = {
@@ -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 {};
@@ -114,7 +114,8 @@ class Chromium extends import_browserType.BrowserType {
114
114
  };
115
115
  (0, import_browserContext.validateBrowserContextOptions)(persistent, browserOptions);
116
116
  const browser = await progress.race(import_crBrowser.CRBrowser.connect(this.attribution.playwright, chromeTransport, browserOptions));
117
- browser._isCollocatedWithServer = false;
117
+ if (!options.isLocal)
118
+ browser._isCollocatedWithServer = false;
118
119
  browser.on(import_browser.Browser.Events.Disconnected, doCleanup);
119
120
  return browser;
120
121
  } catch (error) {
@@ -128,13 +129,8 @@ class Chromium extends import_browserType.BrowserType {
128
129
  return directory ? new import_crDevTools.CRDevTools(import_path.default.join(directory, "devtools-preferences.json")) : void 0;
129
130
  }
130
131
  async connectToTransport(transport, options, browserLogsCollector) {
131
- let devtools = this._devtools;
132
- if (options.__testHookForDevTools) {
133
- devtools = this._createDevTools();
134
- await options.__testHookForDevTools(devtools);
135
- }
136
132
  try {
137
- 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);
138
134
  } catch (e) {
139
135
  if (browserLogsCollector.recentLogs().some((log) => log.includes("Failed to create a ProcessSingleton for your profile directory."))) {
140
136
  throw new Error(
@@ -144,14 +140,12 @@ class Chromium extends import_browserType.BrowserType {
144
140
  throw e;
145
141
  }
146
142
  }
147
- doRewriteStartupLog(error) {
148
- if (!error.logs)
149
- return error;
150
- if (error.logs.includes("Missing X server"))
151
- error.logs = "\n" + (0, import_ascii.wrapInASCIIBox)(import_browserType.kNoXServerRunningError, 1);
152
- if (!error.logs.includes("crbug.com/357670") && !error.logs.includes("No usable sandbox!") && !error.logs.includes("crbug.com/638180"))
153
- return error;
154
- 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 [
155
149
  `Chromium sandboxing failed!`,
156
150
  `================================`,
157
151
  `To avoid the sandboxing issue, do either of the following:`,
@@ -160,7 +154,6 @@ class Chromium extends import_browserType.BrowserType {
160
154
  `================================`,
161
155
  ``
162
156
  ].join("\n");
163
- return error;
164
157
  }
165
158
  amendEnvironment(env) {
166
159
  return env;
@@ -284,11 +277,8 @@ class Chromium extends import_browserType.BrowserType {
284
277
  if (args.find((arg) => !arg.startsWith("-")))
285
278
  throw new Error("Arguments can not specify page to be opened");
286
279
  const chromeArguments = [...(0, import_chromiumSwitches.chromiumSwitches)(options.assistantMode, options.channel)];
287
- if (import_os.default.platform() === "darwin") {
288
- chromeArguments.push("--enable-unsafe-swiftshader");
280
+ if (import_os.default.platform() !== "darwin" || !(0, import_utils.hasGpuMac)()) {
289
281
  }
290
- if (options.devtools)
291
- chromeArguments.push("--auto-open-devtools-for-tabs");
292
282
  if (options.headless) {
293
283
  chromeArguments.push("--headless");
294
284
  chromeArguments.push(
@@ -324,6 +314,10 @@ class Chromium extends import_browserType.BrowserType {
324
314
  return waitForReadyState(options, browserLogsCollector);
325
315
  }
326
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";
327
321
  if (options.channel)
328
322
  return options.channel;
329
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",
@@ -284,11 +284,12 @@ class CRBrowser extends import_browser.Browser {
284
284
  return this._clientRootSessionPromise;
285
285
  }
286
286
  }
287
+ const CREvents = {
288
+ ServiceWorker: "serviceworker"
289
+ };
287
290
  class CRBrowserContext extends import_browserContext.BrowserContext {
288
291
  static {
289
- this.CREvents = {
290
- ServiceWorker: "serviceworker"
291
- };
292
+ this.CREvents = CREvents;
292
293
  }
293
294
  constructor(browser, browserContextId, options) {
294
295
  super(browser, options, browserContextId);
@@ -388,15 +389,24 @@ class CRBrowserContext extends import_browserContext.BrowserContext {
388
389
  ["midi-sysex", "midiSysex"],
389
390
  ["storage-access", "storageAccess"],
390
391
  ["local-fonts", "localFonts"],
391
- ["local-network-access", "localNetworkAccess"]
392
+ ["local-network-access", ["localNetworkAccess", "localNetwork", "loopbackNetwork"]]
392
393
  ]);
393
- const filtered = permissions.map((permission) => {
394
- const protocolPermission = webPermissionToProtocol.get(permission);
395
- if (!protocolPermission)
396
- throw new Error("Unknown permission: " + permission);
397
- return protocolPermission;
398
- });
399
- 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
+ }
400
410
  }
401
411
  async doClearPermissions() {
402
412
  await this._browser._session.send("Browser.resetPermissions", { browserContextId: this._browserContextId });
@@ -469,7 +479,7 @@ class CRBrowserContext extends import_browserContext.BrowserContext {
469
479
  }
470
480
  }
471
481
  async stopVideoRecording() {
472
- await Promise.all(this._crPages().map((crPage) => crPage._mainFrameSession._stopVideoRecording()));
482
+ await Promise.all(this._crPages().map((crPage) => crPage._page.screencast.stopVideoRecording()));
473
483
  }
474
484
  onClosePersistent() {
475
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);
@@ -731,6 +763,12 @@ class RouteImpl {
731
763
  }
732
764
  if (this._networkId != event.networkId || !this._sessionManager._alreadyTrackedNetworkIds.has(event.networkId)) return;
733
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
+ }
734
772
  if (event.responseStatusCode >= 301 && event.responseStatusCode <= 308 || event.redirectedRequestId && !event.responseStatusCode) {
735
773
  await this._session.send("Fetch.continueRequest", { requestId: event.requestId, interceptResponse: true });
736
774
  } else {
@@ -745,7 +783,11 @@ class RouteImpl {
745
783
  });
746
784
  }
747
785
  } catch (error) {
748
- 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
+ }
749
791
  }
750
792
  }
751
793
  }
@@ -876,6 +918,44 @@ class ResponseExtraInfoTracker {
876
918
  this._requests.delete(requestId);
877
919
  }
878
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
+ }
879
959
  // Annotate the CommonJS export names for ESM import in node:
880
960
  0 && (module.exports = {
881
961
  CRNetworkManager