@vpalmisano/webrtcperf 4.4.1 → 4.4.3

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.
@@ -99,6 +99,8 @@ class Session extends events_1.default {
99
99
  id;
100
100
  /** The throttle configuration index assigned to the session. */
101
101
  throttleIndex;
102
+ /** If true, the network will be throttled using the browser internal throttling mechanism. */
103
+ useBrowserThrottling;
102
104
  /** The test page url. */
103
105
  url;
104
106
  /** The url query. */
@@ -152,7 +154,7 @@ class Session extends events_1.default {
152
154
  });
153
155
  constructor({ chromiumUrl, chromiumPath, chromiumFieldTrials, windowWidth, windowHeight, deviceScaleFactor, display,
154
156
  /* audioRedForOpus, */
155
- url, urlQuery, customUrlHandler, customUrlHandlerFn, mediaPath, videoWidth, videoHeight, videoFramerate, useFakeMedia, enableGpu, enableBrowserLogging, startTimestamp, sessions, tabsPerSession, spawnPeriod, statsInterval, disabledVideoCodecs, localStorage, sessionStorage, clearCookies, scriptPath, showPageLog, pageLogFilter, pageLogPath, userAgent, id, throttleIndex, evaluateAfter, exposedFunctions, scriptParams, blockedUrls, extraHeaders, responseModifiers, downloadResponses, extraCSS, cookies, overridePermissions, hardwareConcurrency, debuggingPort, debuggingAddress, randomAudioPeriod, maxVideoDecoders, maxVideoDecodersRange, incognito, serverPort, serverSecret, serverUseHttps, emulateCpuThrottling, }) {
157
+ url, urlQuery, customUrlHandler, customUrlHandlerFn, mediaPath, videoWidth, videoHeight, videoFramerate, useFakeMedia, enableGpu, enableBrowserLogging, startTimestamp, sessions, tabsPerSession, spawnPeriod, statsInterval, disabledVideoCodecs, localStorage, sessionStorage, clearCookies, scriptPath, showPageLog, pageLogFilter, pageLogPath, userAgent, id, throttleIndex, useBrowserThrottling, evaluateAfter, exposedFunctions, scriptParams, blockedUrls, extraHeaders, responseModifiers, downloadResponses, extraCSS, cookies, overridePermissions, hardwareConcurrency, debuggingPort, debuggingAddress, randomAudioPeriod, maxVideoDecoders, maxVideoDecodersRange, incognito, serverPort, serverSecret, serverUseHttps, emulateCpuThrottling, }) {
156
158
  super();
157
159
  log.debug('constructor', { id });
158
160
  this.id = id;
@@ -230,6 +232,7 @@ class Session extends events_1.default {
230
232
  this.serverUseHttps = serverUseHttps;
231
233
  this.emulateCpuThrottling = emulateCpuThrottling;
232
234
  this.throttleIndex = throttleIndex;
235
+ this.useBrowserThrottling = useBrowserThrottling;
233
236
  this.evaluateAfter = evaluateAfter || [];
234
237
  this.exposedFunctions = exposedFunctions || {};
235
238
  if (scriptParams) {
@@ -601,6 +604,8 @@ webrtcperf.config.AUDIO_URL = "http${this.serverUseHttps ? 's' : ''}://localhost
601
604
  await this.context.overridePermissions(new URL(url).origin, this.overridePermissions);
602
605
  }
603
606
  const page = await this.getNewPage(tabIndex);
607
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
608
+ const pageCDPSession = page._client();
604
609
  await page.setBypassCSP(true);
605
610
  if (this.userAgent) {
606
611
  await page.setUserAgent(this.userAgent);
@@ -632,8 +637,7 @@ Object.defineProperty(window.screen.orientation, 'type', { value: 'landscape-pri
632
637
  // Clear cookies.
633
638
  if (this.clearCookies) {
634
639
  try {
635
- const client = await page.target().createCDPSession();
636
- await client.send('Network.clearBrowserCookies');
640
+ await pageCDPSession.send('Network.clearBrowserCookies');
637
641
  }
638
642
  catch (err) {
639
643
  log.error(`clearCookies error: ${err.stack}`);
@@ -671,8 +675,6 @@ Object.defineProperty(window.screen.orientation, 'type', { value: 'landscape-pri
671
675
  });
672
676
  // Enable request interception.
673
677
  let setRequestInterceptionState = true;
674
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
675
- const pageCDPSession = page._client();
676
678
  await pageCDPSession.send('Network.setBypassServiceWorker', {
677
679
  bypass: true,
678
680
  });
@@ -857,20 +859,25 @@ Object.defineProperty(window.screen.orientation, 'type', { value: 'landscape-pri
857
859
  await page.emulateCPUThrottling(this.emulateCpuThrottling);
858
860
  }
859
861
  // PeerConnectionExternal
860
- await page.exposeFunction('createPeerConnectionExternal',
861
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
862
- async (options) => {
863
- const pc = new utils_1.PeerConnectionExternal(options);
864
- return { id: pc.id };
865
- });
866
- await page.exposeFunction('callPeerConnectionExternalMethod',
867
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
868
- async (id, name, arg) => {
869
- const pc = utils_1.PeerConnectionExternal.get(id);
862
+ /* await page.exposeFunction(
863
+ 'createPeerConnectionExternal',
864
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
865
+ async (options: any) => {
866
+ const pc = new PeerConnectionExternal(options)
867
+ return { id: pc.id }
868
+ },
869
+ )
870
+
871
+ await page.exposeFunction(
872
+ 'callPeerConnectionExternalMethod',
873
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
874
+ async (id: number, name: PeerConnectionExternalMethod, arg: any) => {
875
+ const pc = PeerConnectionExternal.get(id)
870
876
  if (pc) {
871
- return pc[name](arg);
877
+ return pc[name](arg)
872
878
  }
873
- });
879
+ },
880
+ )*/
874
881
  // Simulate keypress
875
882
  await page.exposeFunction('keypressText', async (selector, text, delay = 20) => {
876
883
  await page.type(selector, text, { delay });
@@ -1010,73 +1017,28 @@ Object.defineProperty(window.screen.orientation, 'type', { value: 'landscape-pri
1010
1017
  await page.evaluate(() => webrtcperf.stopFakeScreenshare());
1011
1018
  }
1012
1019
  });
1013
- // HTTP stats.
1014
- const resourcesStats = {
1015
- sentBytes: 0,
1016
- recvBytes: 0,
1017
- recvLatency: new stats_1.FastStats({ store_data: false }),
1018
- wsSentBytes: 0,
1019
- wsRecvBytes: 0,
1020
- wsRecvLatency: new stats_1.FastStats({ store_data: false }),
1021
- };
1022
- this.httpResourcesStats.set(index, resourcesStats);
1023
- const pendingRequests = new Map();
1024
- pageCDPSession.on('Network.requestWillBeSent', event => {
1025
- if (event.request.url.startsWith('data:'))
1026
- return;
1027
- const { requestId, request, timestamp } = event;
1028
- const sentBytes = request.postDataEntries?.reduce((acc, entry) => acc + (entry.bytes?.length || 0), 0);
1029
- //log.log('Network.requestWillBeSent', event.type, request.url, sentBytes)
1030
- if (sentBytes)
1031
- resourcesStats.sentBytes += sentBytes;
1032
- pendingRequests.set(requestId, { url: request.url, timestamp });
1033
- });
1034
- pageCDPSession.on('Network.responseReceived', event => {
1035
- const request = pendingRequests.get(event.requestId);
1036
- if (!request)
1037
- return;
1038
- const { response } = event;
1039
- if (response.fromDiskCache) {
1040
- pendingRequests.delete(event.requestId);
1041
- return;
1042
- }
1043
- resourcesStats.recvBytes += response.encodedDataLength;
1044
- });
1045
- pageCDPSession.on('Network.dataReceived', event => {
1046
- const request = pendingRequests.get(event.requestId);
1047
- if (!request)
1048
- return;
1049
- resourcesStats.recvBytes += event.encodedDataLength;
1050
- });
1051
- pageCDPSession.on('Network.loadingFinished', event => {
1052
- const request = pendingRequests.get(event.requestId);
1053
- if (!request)
1054
- return;
1055
- pendingRequests.delete(event.requestId);
1056
- const { timestamp } = event;
1057
- resourcesStats.recvLatency.push(timestamp - request.timestamp);
1020
+ await page.exposeFunction('webrtcperf_reload', () => {
1021
+ return page.reload();
1058
1022
  });
1059
- pageCDPSession.on('Network.webSocketCreated', event => {
1060
- pendingRequests.set(event.requestId, { url: event.url, timestamp: Date.now() });
1061
- });
1062
- pageCDPSession.on('Network.webSocketHandshakeResponseReceived', event => {
1063
- const request = pendingRequests.get(event.requestId);
1064
- if (!request)
1065
- return;
1066
- pendingRequests.delete(event.requestId);
1067
- resourcesStats.wsRecvLatency.push((Date.now() - request.timestamp) / 1000);
1068
- });
1069
- pageCDPSession.on('Network.webSocketFrameSent', event => {
1070
- resourcesStats.wsSentBytes += event.response.payloadData.length;
1071
- });
1072
- pageCDPSession.on('Network.webSocketFrameReceived', event => {
1073
- resourcesStats.wsRecvBytes += event.response.payloadData.length;
1074
- });
1075
- // hardware concurrency
1023
+ // HTTP stats.
1024
+ this.setupPageNetworkStats(pageCDPSession, index);
1025
+ // Hardware concurrency.
1076
1026
  if (this.hardwareConcurrency) {
1077
1027
  const plugin = NavigatorHardwareConcurrency({ hardwareConcurrency: this.hardwareConcurrency });
1078
1028
  await plugin.onPageCreated(page);
1079
1029
  }
1030
+ // Network throttling.
1031
+ if (this.throttleIndex > -1 && (process.platform !== 'linux' || this.useBrowserThrottling)) {
1032
+ log.debug(`Using internal network throttling`);
1033
+ await pageCDPSession.send('Network.emulateNetworkConditions', {
1034
+ offline: false,
1035
+ uploadThroughput: 100000000 / 8,
1036
+ downloadThroughput: 100000000 / 8,
1037
+ latency: 0,
1038
+ packetLoss: 0,
1039
+ packetQueueLength: 0,
1040
+ });
1041
+ }
1080
1042
  // Load page script.
1081
1043
  {
1082
1044
  const filePath = (0, utils_1.resolvePackagePath)('node_modules/@vpalmisano/webrtcperf-js/dist/webrtcperf.js');
@@ -1134,6 +1096,12 @@ Object.defineProperty(window.screen.orientation, 'type', { value: 'landscape-pri
1134
1096
  }
1135
1097
  // add to pages map
1136
1098
  this.pages.set(index, page);
1099
+ if (this.throttleIndex > -1 && (process.platform !== 'linux' || this.useBrowserThrottling)) {
1100
+ await this.applyNetworkThrottling(pageCDPSession);
1101
+ throttler_1.throttleNotifier.on('change', async () => {
1102
+ await this.applyNetworkThrottling(pageCDPSession);
1103
+ });
1104
+ }
1137
1105
  log.debug(`Page ${index + 1} "${url}" loaded in ${(Date.now() - pageLoadTime) / 1000}s`);
1138
1106
  for (let i = 0; i < this.evaluateAfter.length; i++) {
1139
1107
  await page.evaluate(
@@ -1141,6 +1109,87 @@ Object.defineProperty(window.screen.orientation, 'type', { value: 'landscape-pri
1141
1109
  this.evaluateAfter[i].pageFunction, ...this.evaluateAfter[i].args);
1142
1110
  }
1143
1111
  }
1112
+ setupPageNetworkStats(pageCDPSession, index) {
1113
+ const resourcesStats = {
1114
+ sentBytes: 0,
1115
+ recvBytes: 0,
1116
+ recvLatency: new stats_1.FastStats({ store_data: false }),
1117
+ wsSentBytes: 0,
1118
+ wsRecvBytes: 0,
1119
+ wsRecvLatency: new stats_1.FastStats({ store_data: false }),
1120
+ };
1121
+ this.httpResourcesStats.set(index, resourcesStats);
1122
+ const pendingRequests = new Map();
1123
+ pageCDPSession.on('Network.requestWillBeSent', event => {
1124
+ if (event.request.url.startsWith('data:'))
1125
+ return;
1126
+ const { requestId, request, timestamp } = event;
1127
+ const sentBytes = request.postDataEntries?.reduce((acc, entry) => acc + (entry.bytes?.length || 0), 0);
1128
+ //log.log('Network.requestWillBeSent', event.type, request.url, sentBytes)
1129
+ if (sentBytes)
1130
+ resourcesStats.sentBytes += sentBytes;
1131
+ pendingRequests.set(requestId, { url: request.url, timestamp });
1132
+ });
1133
+ pageCDPSession.on('Network.responseReceived', event => {
1134
+ const request = pendingRequests.get(event.requestId);
1135
+ if (!request)
1136
+ return;
1137
+ const { response } = event;
1138
+ if (response.fromDiskCache) {
1139
+ pendingRequests.delete(event.requestId);
1140
+ return;
1141
+ }
1142
+ resourcesStats.recvBytes += response.encodedDataLength;
1143
+ });
1144
+ pageCDPSession.on('Network.dataReceived', event => {
1145
+ const request = pendingRequests.get(event.requestId);
1146
+ if (!request)
1147
+ return;
1148
+ resourcesStats.recvBytes += event.encodedDataLength;
1149
+ });
1150
+ pageCDPSession.on('Network.loadingFinished', event => {
1151
+ const request = pendingRequests.get(event.requestId);
1152
+ if (!request)
1153
+ return;
1154
+ pendingRequests.delete(event.requestId);
1155
+ const { timestamp } = event;
1156
+ resourcesStats.recvLatency.push(timestamp - request.timestamp);
1157
+ });
1158
+ pageCDPSession.on('Network.webSocketCreated', event => {
1159
+ pendingRequests.set(event.requestId, { url: event.url, timestamp: Date.now() });
1160
+ });
1161
+ pageCDPSession.on('Network.webSocketHandshakeResponseReceived', event => {
1162
+ const request = pendingRequests.get(event.requestId);
1163
+ if (!request)
1164
+ return;
1165
+ pendingRequests.delete(event.requestId);
1166
+ resourcesStats.wsRecvLatency.push((Date.now() - request.timestamp) / 1000);
1167
+ });
1168
+ pageCDPSession.on('Network.webSocketFrameSent', event => {
1169
+ resourcesStats.wsSentBytes += event.response.payloadData.length;
1170
+ });
1171
+ pageCDPSession.on('Network.webSocketFrameReceived', event => {
1172
+ resourcesStats.wsRecvBytes += event.response.payloadData.length;
1173
+ });
1174
+ }
1175
+ async applyNetworkThrottling(pageCDPSession) {
1176
+ const throttleUpValues = (0, throttler_1.getSessionThrottleValues)(this.throttleIndex, 'up');
1177
+ const throttleDownValues = (0, throttler_1.getSessionThrottleValues)(this.throttleIndex, 'down');
1178
+ const params = {
1179
+ offline: false,
1180
+ uploadThroughput: throttleUpValues.rate || -1,
1181
+ downloadThroughput: throttleDownValues.rate || -1,
1182
+ latency: Math.max(throttleUpValues.delay || 0, throttleDownValues.delay || 0),
1183
+ packetLoss: Math.max(throttleUpValues.loss || 0, throttleDownValues.loss || 0),
1184
+ packetQueueLength: Math.max(throttleUpValues.queue || 0, throttleDownValues.queue || 0),
1185
+ };
1186
+ log.debug(`Apply internal network throttling: ${JSON.stringify(params)}`);
1187
+ await pageCDPSession.send('Network.emulateNetworkConditions', {
1188
+ ...params,
1189
+ uploadThroughput: params.uploadThroughput !== -1 ? params.uploadThroughput / 8 : -1,
1190
+ downloadThroughput: params.downloadThroughput !== -1 ? params.downloadThroughput / 8 : -1,
1191
+ });
1192
+ }
1144
1193
  async getNewPage(tabIndex) {
1145
1194
  log.debug(`getNewPage ${tabIndex}`);
1146
1195
  (0, assert_1.default)(this.context, 'NoBrowserContextCreated');