chrome-devtools-mcp 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -9
- package/build/node_modules/chrome-devtools-frontend/front_end/core/common/Console.js +1 -8
- package/build/node_modules/chrome-devtools-frontend/front_end/core/common/ParsedURL.js +10 -20
- package/build/node_modules/chrome-devtools-frontend/front_end/core/common/SegmentedRange.js +1 -2
- package/build/node_modules/chrome-devtools-frontend/front_end/core/common/Settings.js +3 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/core/common/StringOutputStream.js +1 -4
- package/build/node_modules/chrome-devtools-frontend/front_end/core/host/AidaClient.js +19 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/core/host/DispatchHttpRequestClient.js +54 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/core/host/GdpClient.js +6 -51
- package/build/node_modules/chrome-devtools-frontend/front_end/core/host/InspectorFrontendHost.js +2 -2
- package/build/node_modules/chrome-devtools-frontend/front_end/core/host/InspectorFrontendHostAPI.js +32 -29
- package/build/node_modules/chrome-devtools-frontend/front_end/core/host/UserMetrics.js +14 -6
- package/build/node_modules/chrome-devtools-frontend/front_end/core/host/host.js +2 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/core/protocol_client/CDPConnection.js +17 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/core/protocol_client/InspectorBackend.js +68 -188
- package/build/node_modules/chrome-devtools-frontend/front_end/core/protocol_client/protocol_client.js +2 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/AnimationModel.js +1 -2
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSMatchedStyles.js +3 -3
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSModel.js +1 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSProperty.js +3 -6
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSPropertyParserMatchers.js +14 -10
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSStyleDeclaration.js +4 -4
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/ChildTargetManager.js +5 -33
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/Connections.js +9 -46
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/DOMModel.js +1 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/DebuggerModel.js +1 -2
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/EnhancedTracesParser.js +17 -3
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/NetworkManager.js +59 -37
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/NetworkRequest.js +5 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/RehydratingConnection.js +102 -4
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/SourceMap.js +2 -3
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/sdk-meta.js +8 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/generated/InspectorBackendCommands.js +1 -39
- package/build/node_modules/chrome-devtools-frontend/front_end/generated/SupportedCSSProperties.js +58 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.js +46 -45
- package/build/node_modules/chrome-devtools-frontend/front_end/models/ai_assistance/performance/AIContext.js +10 -25
- package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/CompilerScriptMapping.js +1 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/DebuggerWorkspaceBinding.js +1 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/models/cpu_profile/ProfileTreeModel.js +6 -7
- package/build/node_modules/chrome-devtools-frontend/front_end/models/stack_trace/StackTraceModel.js +1 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/handlers/NetworkRequestsHandler.js +12 -3
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/types/TraceEvents.js +3 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace_source_maps_resolver/SourceMapsResolver.js +1 -1
- package/build/node_modules/chrome-devtools-frontend/mcp/mcp.js +14 -0
- package/build/src/DevToolsConnectionAdapter.js +1 -0
- package/build/src/DevtoolsUtils.js +44 -0
- package/build/src/McpContext.js +117 -7
- package/build/src/McpResponse.js +32 -21
- package/build/src/PageCollector.js +21 -9
- package/build/src/browser.js +8 -8
- package/build/src/cli.js +8 -3
- package/build/src/formatters/networkFormatter.js +2 -2
- package/build/src/formatters/snapshotFormatter.js +18 -6
- package/build/src/main.js +7 -2
- package/build/src/third_party/THIRD_PARTY_NOTICES +72 -52
- package/build/src/third_party/index.js +12684 -6052
- package/build/src/tools/emulation.js +37 -44
- package/build/src/tools/input.js +36 -6
- package/build/src/tools/network.js +27 -5
- package/build/src/tools/pages.js +59 -33
- package/build/src/tools/performance.js +5 -2
- package/build/src/tools/screenshot.js +2 -1
- package/build/src/tools/snapshot.js +13 -4
- package/build/src/trace-processing/parse.js +6 -16
- package/build/src/utils/keyboard.js +291 -0
- package/package.json +7 -6
|
@@ -6,7 +6,7 @@ import * as Common from '../common/common.js';
|
|
|
6
6
|
import * as Host from '../host/host.js';
|
|
7
7
|
import * as ProtocolClient from '../protocol_client/protocol_client.js';
|
|
8
8
|
import * as Root from '../root/root.js';
|
|
9
|
-
import {
|
|
9
|
+
import { RehydratingConnectionTransport } from './RehydratingConnection.js';
|
|
10
10
|
const UIStrings = {
|
|
11
11
|
/**
|
|
12
12
|
* @description Text on the remote debugging window to indicate the connection is lost
|
|
@@ -66,7 +66,7 @@ export class MainConnection {
|
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
|
-
export class
|
|
69
|
+
export class WebSocketTransport {
|
|
70
70
|
#socket;
|
|
71
71
|
onMessage = null;
|
|
72
72
|
#onDisconnect = null;
|
|
@@ -150,7 +150,7 @@ export class WebSocketConnection {
|
|
|
150
150
|
});
|
|
151
151
|
}
|
|
152
152
|
}
|
|
153
|
-
export class
|
|
153
|
+
export class StubTransport {
|
|
154
154
|
onMessage = null;
|
|
155
155
|
#onDisconnect = null;
|
|
156
156
|
setOnMessage(onMessage) {
|
|
@@ -166,7 +166,7 @@ export class StubConnection {
|
|
|
166
166
|
const messageObject = JSON.parse(message);
|
|
167
167
|
const error = {
|
|
168
168
|
message: 'This is a stub connection, can\'t dispatch message.',
|
|
169
|
-
code: ProtocolClient.
|
|
169
|
+
code: ProtocolClient.CDPConnection.CDPErrorStatus.DEVTOOLS_STUB_ERROR,
|
|
170
170
|
data: messageObject,
|
|
171
171
|
};
|
|
172
172
|
if (this.onMessage) {
|
|
@@ -181,62 +181,25 @@ export class StubConnection {
|
|
|
181
181
|
this.onMessage = null;
|
|
182
182
|
}
|
|
183
183
|
}
|
|
184
|
-
export class ParallelConnection {
|
|
185
|
-
#connection;
|
|
186
|
-
#sessionId;
|
|
187
|
-
onMessage = null;
|
|
188
|
-
#onDisconnect = null;
|
|
189
|
-
constructor(connection, sessionId) {
|
|
190
|
-
this.#connection = connection;
|
|
191
|
-
this.#sessionId = sessionId;
|
|
192
|
-
}
|
|
193
|
-
setOnMessage(onMessage) {
|
|
194
|
-
this.onMessage = onMessage;
|
|
195
|
-
}
|
|
196
|
-
setOnDisconnect(onDisconnect) {
|
|
197
|
-
this.#onDisconnect = onDisconnect;
|
|
198
|
-
}
|
|
199
|
-
getOnDisconnect() {
|
|
200
|
-
return this.#onDisconnect;
|
|
201
|
-
}
|
|
202
|
-
sendRawMessage(message) {
|
|
203
|
-
const messageObject = JSON.parse(message);
|
|
204
|
-
// If the message isn't for a specific session, it must be for the root session.
|
|
205
|
-
if (!messageObject.sessionId) {
|
|
206
|
-
messageObject.sessionId = this.#sessionId;
|
|
207
|
-
}
|
|
208
|
-
this.#connection.sendRawMessage(JSON.stringify(messageObject));
|
|
209
|
-
}
|
|
210
|
-
getSessionId() {
|
|
211
|
-
return this.#sessionId;
|
|
212
|
-
}
|
|
213
|
-
async disconnect() {
|
|
214
|
-
if (this.#onDisconnect) {
|
|
215
|
-
this.#onDisconnect.call(null, 'force disconnect');
|
|
216
|
-
}
|
|
217
|
-
this.#onDisconnect = null;
|
|
218
|
-
this.onMessage = null;
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
184
|
export async function initMainConnection(createRootTarget, onConnectionLost) {
|
|
222
|
-
ProtocolClient.ConnectionTransport.ConnectionTransport.setFactory(
|
|
185
|
+
ProtocolClient.ConnectionTransport.ConnectionTransport.setFactory(createMainTransport.bind(null, onConnectionLost));
|
|
223
186
|
await createRootTarget();
|
|
224
187
|
Host.InspectorFrontendHost.InspectorFrontendHostInstance.connectionReady();
|
|
225
188
|
}
|
|
226
|
-
function
|
|
189
|
+
function createMainTransport(onConnectionLost) {
|
|
227
190
|
if (Root.Runtime.Runtime.isTraceApp()) {
|
|
228
|
-
return new
|
|
191
|
+
return new RehydratingConnectionTransport(onConnectionLost);
|
|
229
192
|
}
|
|
230
193
|
const wsParam = Root.Runtime.Runtime.queryParam('ws');
|
|
231
194
|
const wssParam = Root.Runtime.Runtime.queryParam('wss');
|
|
232
195
|
if (wsParam || wssParam) {
|
|
233
196
|
const ws = (wsParam ? `ws://${wsParam}` : `wss://${wssParam}`);
|
|
234
|
-
return new
|
|
197
|
+
return new WebSocketTransport(ws, onConnectionLost);
|
|
235
198
|
}
|
|
236
199
|
const notEmbeddedOrWs = Host.InspectorFrontendHost.InspectorFrontendHostInstance.isHostedMode();
|
|
237
200
|
if (notEmbeddedOrWs) {
|
|
238
201
|
// eg., hosted mode (e.g. `http://localhost:9222/devtools/inspector.html`) without a WebSocket URL,
|
|
239
|
-
return new
|
|
202
|
+
return new StubTransport();
|
|
240
203
|
}
|
|
241
204
|
return new MainConnection();
|
|
242
205
|
}
|
|
@@ -509,6 +509,7 @@ export class DOMNode {
|
|
|
509
509
|
});
|
|
510
510
|
}
|
|
511
511
|
async getSubtree(depth, pierce) {
|
|
512
|
+
console.assert(depth > 0, 'Do not fetch an infinite subtree to avoid crashing the renderer for large documents');
|
|
512
513
|
const response = await this.#agent.invoke_requestChildNodes({ nodeId: this.id, depth, pierce });
|
|
513
514
|
return response.getError() ? null : this.childrenInternal;
|
|
514
515
|
}
|
|
@@ -1089,14 +1089,13 @@ export class Scope {
|
|
|
1089
1089
|
#name;
|
|
1090
1090
|
#ordinal;
|
|
1091
1091
|
#locationRange;
|
|
1092
|
-
#object;
|
|
1092
|
+
#object = null;
|
|
1093
1093
|
constructor(callFrame, ordinal) {
|
|
1094
1094
|
this.#callFrame = callFrame;
|
|
1095
1095
|
this.#payload = callFrame.getPayload().scopeChain[ordinal];
|
|
1096
1096
|
this.#type = this.#payload.type;
|
|
1097
1097
|
this.#name = this.#payload.name;
|
|
1098
1098
|
this.#ordinal = ordinal;
|
|
1099
|
-
this.#object = null;
|
|
1100
1099
|
const start = this.#payload.startLocation ? Location.fromPayload(callFrame.debuggerModel, this.#payload.startLocation) : null;
|
|
1101
1100
|
const end = this.#payload.endLocation ? Location.fromPayload(callFrame.debuggerModel, this.#payload.endLocation) : null;
|
|
1102
1101
|
if (start && end && start.scriptId === end.scriptId) {
|
package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/EnhancedTracesParser.js
CHANGED
|
@@ -14,6 +14,7 @@ export class EnhancedTracesParser {
|
|
|
14
14
|
#targets = [];
|
|
15
15
|
#executionContexts = [];
|
|
16
16
|
#scripts = [];
|
|
17
|
+
#resources = [];
|
|
17
18
|
static enhancedTraceVersion = 1;
|
|
18
19
|
constructor(trace) {
|
|
19
20
|
this.#trace = trace;
|
|
@@ -34,6 +35,9 @@ export class EnhancedTracesParser {
|
|
|
34
35
|
if (frame.url === 'about:blank') {
|
|
35
36
|
continue;
|
|
36
37
|
}
|
|
38
|
+
if (!frame.isInPrimaryMainFrame) {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
37
41
|
const frameId = frame.frame;
|
|
38
42
|
if (!this.#targets.find(target => target.targetId === frameId)) {
|
|
39
43
|
const frameType = frame.isOutermostMainFrame ? 'page' : 'iframe';
|
|
@@ -184,7 +188,8 @@ export class EnhancedTracesParser {
|
|
|
184
188
|
// this fake event. Would avoid a lot of wasteful (de)serialization. Maybe add SDK.Script.hydratedSourceMap.
|
|
185
189
|
this.resolveSourceMap(script);
|
|
186
190
|
}
|
|
187
|
-
|
|
191
|
+
this.#resources = this.#trace.metadata.resources ?? [];
|
|
192
|
+
return this.groupContextsAndScriptsUnderTarget(this.#targets, this.#executionContexts, this.#scripts, this.#resources);
|
|
188
193
|
}
|
|
189
194
|
resolveSourceMap(script) {
|
|
190
195
|
if (script.sourceMapURL?.startsWith('data:')) {
|
|
@@ -253,7 +258,7 @@ export class EnhancedTracesParser {
|
|
|
253
258
|
isFunctionCallEvent(event) {
|
|
254
259
|
return this.isTraceEvent(event) && event.cat === 'devtools.timeline' && event.name === 'FunctionCall';
|
|
255
260
|
}
|
|
256
|
-
groupContextsAndScriptsUnderTarget(targets, executionContexts, scripts) {
|
|
261
|
+
groupContextsAndScriptsUnderTarget(targets, executionContexts, scripts, resources) {
|
|
257
262
|
const data = [];
|
|
258
263
|
const targetIds = new Set();
|
|
259
264
|
const targetToExecutionContexts = new Map();
|
|
@@ -262,11 +267,13 @@ export class EnhancedTracesParser {
|
|
|
262
267
|
const executionContextIsolateToTarget = new Map();
|
|
263
268
|
const targetToScripts = new Map();
|
|
264
269
|
const orphanScripts = [];
|
|
270
|
+
const targetToResources = new Map();
|
|
265
271
|
// Initialize all the mapping needed
|
|
266
272
|
for (const target of targets) {
|
|
267
273
|
targetIds.add(target.targetId);
|
|
268
274
|
targetToExecutionContexts.set(target.targetId, []);
|
|
269
275
|
targetToScripts.set(target.targetId, []);
|
|
276
|
+
targetToResources.set(target.targetId, []);
|
|
270
277
|
}
|
|
271
278
|
// Put all of the known execution contexts under respective targets
|
|
272
279
|
for (const executionContext of executionContexts) {
|
|
@@ -318,12 +325,19 @@ export class EnhancedTracesParser {
|
|
|
318
325
|
console.error('Script can\'t be linked to any target', orphanScript);
|
|
319
326
|
}
|
|
320
327
|
}
|
|
328
|
+
for (const resource of resources) {
|
|
329
|
+
const frameId = resource.frame;
|
|
330
|
+
if (targetIds.has(frameId)) {
|
|
331
|
+
targetToResources.get(frameId)?.push(resource);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
321
334
|
// Now all the scripts are linked to a target, we want to make sure all the scripts are pointing to a valid
|
|
322
335
|
// execution context. If not, we will create an artificial execution context for the script
|
|
323
336
|
for (const target of targets) {
|
|
324
337
|
const targetId = target.targetId;
|
|
325
338
|
const executionContexts = targetToExecutionContexts.get(targetId) || [];
|
|
326
339
|
const scripts = targetToScripts.get(targetId) || [];
|
|
340
|
+
const resources = targetToResources.get(targetId) || [];
|
|
327
341
|
for (const script of scripts) {
|
|
328
342
|
if (!executionContexts.find(context => context.id === script.executionContextId)) {
|
|
329
343
|
const artificialContext = {
|
|
@@ -343,7 +357,7 @@ export class EnhancedTracesParser {
|
|
|
343
357
|
}
|
|
344
358
|
}
|
|
345
359
|
// Finally, we put all the information into the data structure we want to return as.
|
|
346
|
-
data.push({ target, executionContexts, scripts });
|
|
360
|
+
data.push({ target, executionContexts, scripts, resources });
|
|
347
361
|
}
|
|
348
362
|
return data;
|
|
349
363
|
}
|
|
@@ -824,7 +824,7 @@ export class NetworkDispatcher {
|
|
|
824
824
|
}
|
|
825
825
|
requestIntercepted({}) {
|
|
826
826
|
}
|
|
827
|
-
requestWillBeSentExtraInfo({ requestId, associatedCookies, headers, clientSecurityState, connectTiming, siteHasCookieInOtherPartition }) {
|
|
827
|
+
requestWillBeSentExtraInfo({ requestId, associatedCookies, headers, clientSecurityState, connectTiming, siteHasCookieInOtherPartition, appliedNetworkConditionsId }) {
|
|
828
828
|
const blockedRequestCookies = [];
|
|
829
829
|
const includedRequestCookies = [];
|
|
830
830
|
for (const { blockedReasons, exemptionReason, cookie } of associatedCookies) {
|
|
@@ -842,6 +842,7 @@ export class NetworkDispatcher {
|
|
|
842
842
|
clientSecurityState,
|
|
843
843
|
connectTiming,
|
|
844
844
|
siteHasCookieInOtherPartition,
|
|
845
|
+
appliedNetworkConditionsId,
|
|
845
846
|
};
|
|
846
847
|
this.getExtraInfoBuilder(requestId).addRequestExtraInfo(extraRequestInfo);
|
|
847
848
|
}
|
|
@@ -1241,18 +1242,6 @@ export class NetworkDispatcher {
|
|
|
1241
1242
|
}
|
|
1242
1243
|
request.setTrustTokenOperationDoneEvent(event);
|
|
1243
1244
|
}
|
|
1244
|
-
subresourceWebBundleMetadataReceived() {
|
|
1245
|
-
// TODO: remove implementation after deleting this methods from definition in Network.pdl
|
|
1246
|
-
}
|
|
1247
|
-
subresourceWebBundleMetadataError() {
|
|
1248
|
-
// TODO: remove implementation after deleting this methods from definition in Network.pdl
|
|
1249
|
-
}
|
|
1250
|
-
subresourceWebBundleInnerResponseParsed() {
|
|
1251
|
-
// TODO: remove implementation after deleting this methods from definition in Network.pdl
|
|
1252
|
-
}
|
|
1253
|
-
subresourceWebBundleInnerResponseError() {
|
|
1254
|
-
// TODO: remove implementation after deleting this methods from definition in Network.pdl
|
|
1255
|
-
}
|
|
1256
1245
|
reportingApiReportAdded(data) {
|
|
1257
1246
|
this.#manager.dispatchEventToListeners(Events.ReportingApiReportAdded, data.report);
|
|
1258
1247
|
}
|
|
@@ -1330,6 +1319,7 @@ export class RequestCondition extends Common.ObjectWrapper.ObjectWrapper {
|
|
|
1330
1319
|
#pattern;
|
|
1331
1320
|
#enabled;
|
|
1332
1321
|
#conditions;
|
|
1322
|
+
#ruleIds = new Set();
|
|
1333
1323
|
static createFromSetting(setting) {
|
|
1334
1324
|
if ('urlPattern' in setting) {
|
|
1335
1325
|
const pattern = RequestURLPattern.create(setting.urlPattern) ?? {
|
|
@@ -1356,6 +1346,12 @@ export class RequestCondition extends Common.ObjectWrapper.ObjectWrapper {
|
|
|
1356
1346
|
this.#enabled = enabled;
|
|
1357
1347
|
this.#conditions = conditions;
|
|
1358
1348
|
}
|
|
1349
|
+
get isBlocking() {
|
|
1350
|
+
return this.conditions === BlockingConditions;
|
|
1351
|
+
}
|
|
1352
|
+
get ruleIds() {
|
|
1353
|
+
return this.#ruleIds;
|
|
1354
|
+
}
|
|
1359
1355
|
get constructorString() {
|
|
1360
1356
|
return this.#pattern instanceof RequestURLPattern ? this.#pattern.constructorString :
|
|
1361
1357
|
this.#pattern.upgradedPattern?.constructorString;
|
|
@@ -1396,6 +1392,7 @@ export class RequestCondition extends Common.ObjectWrapper.ObjectWrapper {
|
|
|
1396
1392
|
}
|
|
1397
1393
|
set conditions(conditions) {
|
|
1398
1394
|
this.#conditions = conditions;
|
|
1395
|
+
this.#ruleIds = new Set();
|
|
1399
1396
|
this.dispatchEventToListeners("request-condition-changed" /* RequestCondition.Events.REQUEST_CONDITION_CHANGED */);
|
|
1400
1397
|
}
|
|
1401
1398
|
toSetting() {
|
|
@@ -1416,6 +1413,8 @@ export class RequestConditions extends Common.ObjectWrapper.ObjectWrapper {
|
|
|
1416
1413
|
#setting = Common.Settings.Settings.instance().createSetting('network-blocked-patterns', []);
|
|
1417
1414
|
#conditionsEnabledSetting = Common.Settings.Settings.instance().moduleSetting('request-blocking-enabled');
|
|
1418
1415
|
#conditions = [];
|
|
1416
|
+
#requestConditionsById = new Map();
|
|
1417
|
+
#conditionsAppliedForTestPromise = Promise.resolve();
|
|
1419
1418
|
constructor() {
|
|
1420
1419
|
super();
|
|
1421
1420
|
for (const condition of this.#setting.get()) {
|
|
@@ -1504,6 +1503,7 @@ export class RequestConditions extends Common.ObjectWrapper.ObjectWrapper {
|
|
|
1504
1503
|
}
|
|
1505
1504
|
if (Root.Runtime.hostConfig.devToolsIndividualRequestThrottling?.enabled) {
|
|
1506
1505
|
const urlPatterns = [];
|
|
1506
|
+
// We store all this info out-of-band to prevent races with changing conditions while the promise is still pending
|
|
1507
1507
|
const matchedNetworkConditions = [];
|
|
1508
1508
|
if (this.conditionsEnabled) {
|
|
1509
1509
|
for (const condition of this.#conditions) {
|
|
@@ -1515,41 +1515,51 @@ export class RequestConditions extends Common.ObjectWrapper.ObjectWrapper {
|
|
|
1515
1515
|
const block = !isNonBlockingCondition(conditions);
|
|
1516
1516
|
urlPatterns.push({ urlPattern, block });
|
|
1517
1517
|
if (!block) {
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
latency: conditions.latency,
|
|
1521
|
-
downloadThroughput: conditions.download < 0 ? 0 : conditions.download,
|
|
1522
|
-
uploadThroughput: conditions.upload < 0 ? 0 : conditions.upload,
|
|
1523
|
-
packetLoss: (conditions.packetLoss ?? 0) < 0 ? 0 : conditions.packetLoss,
|
|
1524
|
-
packetQueueLength: conditions.packetQueueLength,
|
|
1525
|
-
packetReordering: conditions.packetReordering,
|
|
1526
|
-
connectionType: NetworkManager.connectionType(conditions),
|
|
1527
|
-
});
|
|
1518
|
+
const { ruleIds } = condition;
|
|
1519
|
+
matchedNetworkConditions.push({ ruleIds, urlPattern, conditions });
|
|
1528
1520
|
}
|
|
1529
1521
|
}
|
|
1530
1522
|
if (globalConditions) {
|
|
1531
|
-
matchedNetworkConditions.push({
|
|
1532
|
-
urlPattern: '',
|
|
1533
|
-
latency: globalConditions.latency,
|
|
1534
|
-
downloadThroughput: globalConditions.download < 0 ? 0 : globalConditions.download,
|
|
1535
|
-
uploadThroughput: globalConditions.upload < 0 ? 0 : globalConditions.upload,
|
|
1536
|
-
packetLoss: (globalConditions.packetLoss ?? 0) < 0 ? 0 : globalConditions.packetLoss,
|
|
1537
|
-
packetQueueLength: globalConditions.packetQueueLength,
|
|
1538
|
-
packetReordering: globalConditions.packetReordering,
|
|
1539
|
-
connectionType: NetworkManager.connectionType(globalConditions),
|
|
1540
|
-
});
|
|
1523
|
+
matchedNetworkConditions.push({ conditions: globalConditions });
|
|
1541
1524
|
}
|
|
1542
1525
|
}
|
|
1526
|
+
const promises = [];
|
|
1543
1527
|
for (const agent of agents) {
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1528
|
+
promises.push(agent.invoke_setBlockedURLs({ urlPatterns }));
|
|
1529
|
+
promises.push(agent
|
|
1530
|
+
.invoke_emulateNetworkConditionsByRule({
|
|
1531
|
+
offline,
|
|
1532
|
+
matchedNetworkConditions: matchedNetworkConditions.map(({ urlPattern, conditions }) => ({
|
|
1533
|
+
urlPattern: urlPattern ?? '',
|
|
1534
|
+
latency: conditions.latency,
|
|
1535
|
+
downloadThroughput: conditions.download < 0 ? 0 : conditions.download,
|
|
1536
|
+
uploadThroughput: conditions.upload < 0 ? 0 : conditions.upload,
|
|
1537
|
+
packetLoss: (conditions.packetLoss ?? 0) < 0 ? 0 : conditions.packetLoss,
|
|
1538
|
+
packetQueueLength: conditions.packetQueueLength,
|
|
1539
|
+
packetReordering: conditions.packetReordering,
|
|
1540
|
+
connectionType: NetworkManager.connectionType(conditions),
|
|
1541
|
+
}))
|
|
1542
|
+
})
|
|
1543
|
+
.then(response => {
|
|
1544
|
+
if (!response.getError()) {
|
|
1545
|
+
for (let i = 0; i < response.ruleIds.length; ++i) {
|
|
1546
|
+
const ruleId = response.ruleIds[i];
|
|
1547
|
+
const { ruleIds, conditions, urlPattern } = matchedNetworkConditions[i];
|
|
1548
|
+
if (ruleIds) {
|
|
1549
|
+
this.#requestConditionsById.set(ruleId, { urlPattern, conditions });
|
|
1550
|
+
matchedNetworkConditions[i].ruleIds?.add(ruleId);
|
|
1551
|
+
}
|
|
1552
|
+
}
|
|
1553
|
+
}
|
|
1554
|
+
}));
|
|
1555
|
+
promises.push(agent.invoke_overrideNetworkState({
|
|
1547
1556
|
offline,
|
|
1548
1557
|
latency: globalConditions?.latency ?? 0,
|
|
1549
1558
|
downloadThroughput: !globalConditions || globalConditions.download < 0 ? 0 : globalConditions.download,
|
|
1550
1559
|
uploadThroughput: !globalConditions || globalConditions.upload < 0 ? 0 : globalConditions.upload,
|
|
1551
|
-
});
|
|
1560
|
+
}));
|
|
1552
1561
|
}
|
|
1562
|
+
this.#conditionsAppliedForTestPromise = this.#conditionsAppliedForTestPromise.then(() => Promise.all(promises));
|
|
1553
1563
|
return urlPatterns.length > 0;
|
|
1554
1564
|
}
|
|
1555
1565
|
const urls = this.conditionsEnabled ?
|
|
@@ -1561,6 +1571,12 @@ export class RequestConditions extends Common.ObjectWrapper.ObjectWrapper {
|
|
|
1561
1571
|
}
|
|
1562
1572
|
return urls.length > 0;
|
|
1563
1573
|
}
|
|
1574
|
+
conditionsAppliedForTest() {
|
|
1575
|
+
return this.#conditionsAppliedForTestPromise;
|
|
1576
|
+
}
|
|
1577
|
+
conditionsForId(appliedNetworkConditionsId) {
|
|
1578
|
+
return this.#requestConditionsById.get(appliedNetworkConditionsId);
|
|
1579
|
+
}
|
|
1564
1580
|
}
|
|
1565
1581
|
_a = RequestConditions;
|
|
1566
1582
|
let multiTargetNetworkManagerInstance;
|
|
@@ -1872,6 +1888,12 @@ export class MultitargetNetworkManager extends Common.ObjectWrapper.ObjectWrappe
|
|
|
1872
1888
|
resolve({ success, content, errorDescription });
|
|
1873
1889
|
}, allowRemoteFilePaths));
|
|
1874
1890
|
}
|
|
1891
|
+
appliedRequestConditions(requestInternal) {
|
|
1892
|
+
if (!requestInternal.appliedNetworkConditionsId) {
|
|
1893
|
+
return undefined;
|
|
1894
|
+
}
|
|
1895
|
+
return this.requestConditions.conditionsForId(requestInternal.appliedNetworkConditionsId);
|
|
1896
|
+
}
|
|
1875
1897
|
}
|
|
1876
1898
|
export class InterceptedRequest {
|
|
1877
1899
|
#fetchAgent;
|
|
@@ -306,6 +306,7 @@ export class NetworkRequest extends Common.ObjectWrapper.ObjectWrapper {
|
|
|
306
306
|
#directSocketChunks = [];
|
|
307
307
|
#isIpProtectionUsed;
|
|
308
308
|
#isAdRelated;
|
|
309
|
+
#appliedNetworkConditionsId;
|
|
309
310
|
constructor(requestId, backendRequestId, url, documentURL, frameId, loaderId, initiator, hasUserGesture) {
|
|
310
311
|
super();
|
|
311
312
|
this.#requestId = requestId;
|
|
@@ -374,6 +375,9 @@ export class NetworkRequest extends Common.ObjectWrapper.ObjectWrapper {
|
|
|
374
375
|
get loaderId() {
|
|
375
376
|
return this.#loaderId;
|
|
376
377
|
}
|
|
378
|
+
get appliedNetworkConditionsId() {
|
|
379
|
+
return this.#appliedNetworkConditionsId;
|
|
380
|
+
}
|
|
377
381
|
setRemoteAddress(ip, port) {
|
|
378
382
|
this.#remoteAddress = ip + ':' + port;
|
|
379
383
|
this.dispatchEventToListeners(Events.REMOTE_ADDRESS_CHANGED, this);
|
|
@@ -1251,6 +1255,7 @@ export class NetworkRequest extends Common.ObjectWrapper.ObjectWrapper {
|
|
|
1251
1255
|
this.#hasExtraRequestInfo = true;
|
|
1252
1256
|
this.setRequestHeadersText(''); // Mark request headers as non-provisional
|
|
1253
1257
|
this.#clientSecurityState = extraRequestInfo.clientSecurityState;
|
|
1258
|
+
this.#appliedNetworkConditionsId = extraRequestInfo.appliedNetworkConditionsId;
|
|
1254
1259
|
if (extraRequestInfo.connectTiming) {
|
|
1255
1260
|
this.setConnectTimingFromExtraInfo(extraRequestInfo.connectTiming);
|
|
1256
1261
|
}
|
package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/RehydratingConnection.js
CHANGED
|
@@ -22,7 +22,7 @@ const UIStrings = {
|
|
|
22
22
|
};
|
|
23
23
|
const str_ = i18n.i18n.registerUIStrings('core/sdk/RehydratingConnection.ts', UIStrings);
|
|
24
24
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
25
|
-
export class
|
|
25
|
+
export class RehydratingConnectionTransport {
|
|
26
26
|
rehydratingConnectionState = 1 /* RehydratingConnectionState.UNINITIALIZED */;
|
|
27
27
|
onDisconnect = null;
|
|
28
28
|
onMessage = null;
|
|
@@ -63,7 +63,7 @@ export class RehydratingConnection {
|
|
|
63
63
|
this.#rehydratingWindow.opener.postMessage({ type: 'REHYDRATING_WINDOW_READY' });
|
|
64
64
|
}
|
|
65
65
|
else if (this.#rehydratingWindow !== window.top) {
|
|
66
|
-
this.#rehydratingWindow.parent.postMessage({ type: 'REHYDRATING_IFRAME_READY' });
|
|
66
|
+
this.#rehydratingWindow.parent.postMessage({ type: 'REHYDRATING_IFRAME_READY' }, '*');
|
|
67
67
|
}
|
|
68
68
|
else {
|
|
69
69
|
this.#onConnectionLost(i18nString(UIStrings.noHostWindow));
|
|
@@ -108,6 +108,7 @@ export class RehydratingConnection {
|
|
|
108
108
|
const target = hydratingDataPerTarget.target;
|
|
109
109
|
const executionContexts = hydratingDataPerTarget.executionContexts;
|
|
110
110
|
const scripts = hydratingDataPerTarget.scripts;
|
|
111
|
+
const resources = hydratingDataPerTarget.resources;
|
|
111
112
|
this.postToFrontend({
|
|
112
113
|
method: 'Target.targetCreated',
|
|
113
114
|
params: {
|
|
@@ -122,7 +123,7 @@ export class RehydratingConnection {
|
|
|
122
123
|
},
|
|
123
124
|
});
|
|
124
125
|
sessionId += 1;
|
|
125
|
-
const session = new RehydratingSession(sessionId, target, executionContexts, scripts, this);
|
|
126
|
+
const session = new RehydratingSession(sessionId, target, executionContexts, scripts, resources, this);
|
|
126
127
|
this.sessions.set(sessionId, session);
|
|
127
128
|
session.declareSessionAttachedToTarget();
|
|
128
129
|
}
|
|
@@ -208,12 +209,14 @@ export class RehydratingSession extends RehydratingSessionBase {
|
|
|
208
209
|
target;
|
|
209
210
|
executionContexts = [];
|
|
210
211
|
scripts = [];
|
|
211
|
-
|
|
212
|
+
resources = [];
|
|
213
|
+
constructor(sessionId, target, executionContexts, scripts, resources, connection) {
|
|
212
214
|
super(connection);
|
|
213
215
|
this.sessionId = sessionId;
|
|
214
216
|
this.target = target;
|
|
215
217
|
this.executionContexts = executionContexts;
|
|
216
218
|
this.scripts = scripts;
|
|
219
|
+
this.resources = resources;
|
|
217
220
|
}
|
|
218
221
|
sendMessageToFrontend(payload, attachSessionId = true) {
|
|
219
222
|
// Attach the session's Id to the message.
|
|
@@ -230,12 +233,31 @@ export class RehydratingSession extends RehydratingSessionBase {
|
|
|
230
233
|
case 'Debugger.enable':
|
|
231
234
|
this.handleDebuggerEnable(data.id);
|
|
232
235
|
break;
|
|
236
|
+
case 'CSS.enable':
|
|
237
|
+
this.sendMessageToFrontend({
|
|
238
|
+
id: data.id,
|
|
239
|
+
result: {},
|
|
240
|
+
});
|
|
241
|
+
break;
|
|
233
242
|
case 'Debugger.getScriptSource':
|
|
234
243
|
if (data.params) {
|
|
235
244
|
const params = data.params;
|
|
236
245
|
this.handleDebuggerGetScriptSource(data.id, params.scriptId);
|
|
237
246
|
}
|
|
238
247
|
break;
|
|
248
|
+
case 'Page.getResourceTree':
|
|
249
|
+
this.handleGetResourceTree(data.id);
|
|
250
|
+
break;
|
|
251
|
+
case 'Page.getResourceContent': {
|
|
252
|
+
const request = data.params;
|
|
253
|
+
this.handleGetResourceContent(request.frameId, request.url, data.id);
|
|
254
|
+
break;
|
|
255
|
+
}
|
|
256
|
+
case 'CSS.getStyleSheetText': {
|
|
257
|
+
const request = data.params;
|
|
258
|
+
this.handleGetStyleSheetText(request.styleSheetId, data.id);
|
|
259
|
+
break;
|
|
260
|
+
}
|
|
239
261
|
default:
|
|
240
262
|
this.sendMessageToFrontend({
|
|
241
263
|
id: data.id,
|
|
@@ -298,7 +320,20 @@ export class RehydratingSession extends RehydratingSessionBase {
|
|
|
298
320
|
// script parsed event to communicate the current script state and respond with a mock
|
|
299
321
|
// debugger id.
|
|
300
322
|
handleDebuggerEnable(id) {
|
|
323
|
+
const htmlResourceUrls = new Set(this.resources.filter(r => r.mimeType === 'text/html').map(r => r.url));
|
|
301
324
|
for (const script of this.scripts) {
|
|
325
|
+
// Handle inline scripts.
|
|
326
|
+
if (htmlResourceUrls.has(script.url)) {
|
|
327
|
+
script.embedderName = script.url;
|
|
328
|
+
// We don't have the actual embedded offset from this trace event. Non-zero
|
|
329
|
+
// values are important though: that is what `Script.isInlineScript()`
|
|
330
|
+
// checks. Otherwise these scripts would try to show individually within the
|
|
331
|
+
// Sources panel.
|
|
332
|
+
script.startColumn = 1;
|
|
333
|
+
script.startLine = 1;
|
|
334
|
+
script.endColumn = 1;
|
|
335
|
+
script.endLine = 1;
|
|
336
|
+
}
|
|
302
337
|
this.sendMessageToFrontend({
|
|
303
338
|
method: 'Debugger.scriptParsed',
|
|
304
339
|
params: script,
|
|
@@ -312,4 +347,67 @@ export class RehydratingSession extends RehydratingSessionBase {
|
|
|
312
347
|
},
|
|
313
348
|
});
|
|
314
349
|
}
|
|
350
|
+
handleGetResourceTree(id) {
|
|
351
|
+
const resources = this.resources.filter(r => r.mimeType === 'text/html' || r.mimeType === 'text/css');
|
|
352
|
+
if (!resources.length) {
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
const frameTree = {
|
|
356
|
+
frame: {
|
|
357
|
+
id: this.target.targetId,
|
|
358
|
+
url: this.target.url,
|
|
359
|
+
},
|
|
360
|
+
childFrames: [],
|
|
361
|
+
resources: resources.map(r => ({
|
|
362
|
+
url: r.url,
|
|
363
|
+
type: r.mimeType === 'text/html' ? 'Document' : 'Stylesheet',
|
|
364
|
+
mimeType: r.mimeType,
|
|
365
|
+
contentSize: r.content.length,
|
|
366
|
+
})),
|
|
367
|
+
};
|
|
368
|
+
this.sendMessageToFrontend({
|
|
369
|
+
id,
|
|
370
|
+
result: {
|
|
371
|
+
frameTree,
|
|
372
|
+
},
|
|
373
|
+
});
|
|
374
|
+
const stylesheets = this.resources.filter(r => r.mimeType === 'text/css');
|
|
375
|
+
for (const stylesheet of stylesheets) {
|
|
376
|
+
this.sendMessageToFrontend({
|
|
377
|
+
method: 'CSS.styleSheetAdded',
|
|
378
|
+
params: {
|
|
379
|
+
header: {
|
|
380
|
+
styleSheetId: `sheet.${stylesheet.frame}.${stylesheet.url}`,
|
|
381
|
+
frameId: stylesheet.frame,
|
|
382
|
+
sourceURL: stylesheet.url,
|
|
383
|
+
},
|
|
384
|
+
},
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
handleGetResourceContent(frame, url, id) {
|
|
389
|
+
const resource = this.resources.find(r => r.frame === frame && r.url === url);
|
|
390
|
+
if (!resource) {
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
this.sendMessageToFrontend({
|
|
394
|
+
id,
|
|
395
|
+
result: {
|
|
396
|
+
content: resource.content,
|
|
397
|
+
base64Encoded: false,
|
|
398
|
+
},
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
handleGetStyleSheetText(stylesheetId, id) {
|
|
402
|
+
const resource = this.resources.find(r => `sheet.${r.frame}.${r.url}` === stylesheetId);
|
|
403
|
+
if (!resource) {
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
this.sendMessageToFrontend({
|
|
407
|
+
id,
|
|
408
|
+
result: {
|
|
409
|
+
text: resource.content,
|
|
410
|
+
},
|
|
411
|
+
});
|
|
412
|
+
}
|
|
315
413
|
}
|
|
@@ -57,7 +57,7 @@ export class SourceMap {
|
|
|
57
57
|
#compiledURL;
|
|
58
58
|
#sourceMappingURL;
|
|
59
59
|
#baseURL;
|
|
60
|
-
#mappings;
|
|
60
|
+
#mappings = null;
|
|
61
61
|
#sourceInfos = [];
|
|
62
62
|
#sourceInfoByURL = new Map();
|
|
63
63
|
#script;
|
|
@@ -75,7 +75,6 @@ export class SourceMap {
|
|
|
75
75
|
this.#sourceMappingURL = sourceMappingURL;
|
|
76
76
|
this.#baseURL = (Common.ParsedURL.schemeIs(sourceMappingURL, 'data:')) ? compiledURL : sourceMappingURL;
|
|
77
77
|
this.#debugId = 'debugId' in payload ? payload.debugId : undefined;
|
|
78
|
-
this.#mappings = null;
|
|
79
78
|
if ('sections' in this.#json) {
|
|
80
79
|
if (this.#json.sections.find(section => 'url' in section)) {
|
|
81
80
|
Common.Console.Console.instance().warn(`SourceMap "${sourceMappingURL}" contains unsupported "URL" field in one of its sections.`);
|
|
@@ -306,7 +305,7 @@ export class SourceMap {
|
|
|
306
305
|
#computeReverseMappings(mappings) {
|
|
307
306
|
const reverseMappingsPerUrl = new Map();
|
|
308
307
|
for (let i = 0; i < mappings.length; i++) {
|
|
309
|
-
const entryUrl = mappings[i]
|
|
308
|
+
const entryUrl = mappings[i]?.sourceURL;
|
|
310
309
|
if (!entryUrl) {
|
|
311
310
|
continue;
|
|
312
311
|
}
|
|
@@ -351,7 +351,11 @@ const UIStrings = {
|
|
|
351
351
|
/**
|
|
352
352
|
* @description Label of a checkbox in the DevTools settings UI.
|
|
353
353
|
*/
|
|
354
|
-
enableRemoteFileLoading: 'Allow
|
|
354
|
+
enableRemoteFileLoading: 'Allow loading remote file path resources in DevTools',
|
|
355
|
+
/**
|
|
356
|
+
* @description Tooltip text for a setting that controls whether external resource can be loaded in DevTools.
|
|
357
|
+
*/
|
|
358
|
+
remoteFileLoadingInfo: 'Example resource are source maps. Disabled by default for security reasons.',
|
|
355
359
|
/**
|
|
356
360
|
* @description Tooltip text for a setting that controls the network cache. Disabling the network cache can simulate the network connections of users that are visiting a page for the first time.
|
|
357
361
|
*/
|
|
@@ -1114,4 +1118,7 @@ Common.Settings.registerSettingExtension({
|
|
|
1114
1118
|
settingName: 'network.enable-remote-file-loading',
|
|
1115
1119
|
settingType: "boolean" /* Common.Settings.SettingType.BOOLEAN */,
|
|
1116
1120
|
defaultValue: false,
|
|
1121
|
+
learnMore: {
|
|
1122
|
+
tooltip: i18nLazyString(UIStrings.remoteFileLoadingInfo),
|
|
1123
|
+
}
|
|
1117
1124
|
});
|