chrome-devtools-frontend 1.0.1690116 → 1.0.1690531
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/.gitmodules +4 -0
- package/front_end/core/root/Runtime.ts +1 -0
- package/front_end/core/sdk/NetworkRequest.ts +50 -4
- package/front_end/core/sdk/NetworkRequestAccess.ts +172 -0
- package/front_end/core/sdk/SecurityOrigin.ts +25 -0
- package/front_end/core/sdk/sdk.ts +2 -0
- package/front_end/generated/SupportedCSSProperties.ts +1 -1
- package/front_end/models/ai_assistance/AiAgent2.ts +4 -1
- package/front_end/models/ai_assistance/AiConversation.ts +29 -18
- package/front_end/panels/ai_assistance/components/chatMessage.css +3 -1
- package/front_end/panels/application/components/BackForwardCacheView.ts +1 -1
- package/front_end/panels/application/components/EndpointsGrid.ts +2 -1
- package/front_end/panels/application/components/PermissionsPolicySection.ts +1 -1
- package/front_end/panels/application/components/ServiceWorkerRouterView.ts +1 -1
- package/front_end/panels/application/components/TrustTokensView.ts +1 -1
- package/front_end/panels/application/preloading/components/PreloadingDetailsReportView.ts +2 -1
- package/front_end/panels/application/preloading/components/RuleSetDetailsView.ts +2 -1
- package/front_end/panels/application/preloading/components/UsedPreloadingView.ts +1 -1
- package/front_end/panels/common/CPUThrottlingOption.ts +12 -6
- package/front_end/panels/common/DOMLinkifier.ts +1 -1
- package/front_end/panels/common/ExtensionView.ts +2 -1
- package/front_end/panels/console/ConsolePinPane.ts +4 -2
- package/front_end/panels/console/ConsoleSidebar.ts +6 -2
- package/front_end/panels/console/PromptBuilder.ts +1 -1
- package/front_end/panels/coverage/CoverageListView.ts +1 -1
- package/front_end/panels/coverage/CoverageModel.ts +6 -4
- package/front_end/panels/css_overview/CSSOverviewCompletedView.ts +9 -9
- package/front_end/panels/css_overview/CSSOverviewPanel.ts +3 -3
- package/front_end/panels/css_overview/CSSOverviewProcessingView.ts +2 -2
- package/front_end/panels/css_overview/CSSOverviewSidebarPanel.ts +3 -3
- package/front_end/panels/css_overview/CSSOverviewStartView.ts +3 -3
- package/front_end/panels/developer_resources/DeveloperResourcesListView.ts +1 -1
- package/front_end/panels/elements/ComputedStyleWidget.ts +1 -1
- package/front_end/panels/elements/ElementsTreeElement.ts +4 -3
- package/front_end/panels/elements/ElementsTreeOutline.ts +2 -2
- package/front_end/panels/elements/MetricsSidebarPane.ts +1 -1
- package/front_end/panels/elements/PropertyNameCategories.ts +1 -1
- package/front_end/panels/elements/ShortcutTreeElement.ts +2 -1
- package/front_end/panels/elements/StandaloneStylesContainer.ts +1 -1
- package/front_end/panels/elements/StylePropertiesSection.ts +1 -1
- package/front_end/panels/elements/StylesSidebarPane.ts +3 -2
- package/front_end/panels/elements/components/StylePropertyEditor.ts +160 -148
- package/front_end/panels/emulation/MediaQueryInspector.ts +2 -1
- package/front_end/panels/issues/AffectedLazyLoadImagesView.ts +1 -1
- package/front_end/panels/linear_memory_inspector/components/linearMemoryInspector.css +2 -2
- package/front_end/panels/linear_memory_inspector/components/linearMemoryNavigator.css +1 -1
- package/front_end/panels/linear_memory_inspector/components/linearMemoryValueInterpreter.css +5 -5
- package/front_end/panels/linear_memory_inspector/components/linearMemoryViewer.css +6 -6
- package/front_end/panels/linear_memory_inspector/components/valueInterpreterDisplay.css +6 -6
- package/front_end/panels/linear_memory_inspector/components/valueInterpreterSettings.css +2 -2
- package/front_end/panels/network/NetworkDataGridNode.ts +11 -9
- package/front_end/panels/network/NetworkLogView.ts +4 -1
- package/front_end/panels/network/RequestConditionsDrawer.ts +2 -2
- package/front_end/panels/network/RequestHeadersView.ts +1 -1
- package/front_end/panels/network/RequestPayloadView.ts +1 -1
- package/front_end/panels/network/RequestResponseView.ts +1 -1
- package/front_end/panels/network/RequestTimingView.ts +1 -1
- package/front_end/panels/network/ShowMoreDetailsWidget.ts +1 -1
- package/front_end/panels/network/components/ResponseHeaderSection.ts +1 -1
- package/front_end/panels/sources/BreakpointEditDialog.ts +1 -1
- package/front_end/panels/sources/CallStackSidebarPane.ts +1 -1
- package/front_end/panels/sources/DebuggerPausedMessage.ts +8 -6
- package/front_end/panels/sources/ProfilePlugin.ts +2 -1
- package/front_end/panels/sources/ScopeChainSidebarPane.ts +1 -1
- package/front_end/panels/timeline/IsolateSelector.ts +1 -1
- package/front_end/panels/timeline/LayoutShiftsTrackAppender.ts +1 -1
- package/front_end/panels/timeline/NetworkTrackAppender.ts +1 -1
- package/front_end/panels/timeline/TimelineFlameChartDataProvider.ts +1 -1
- package/front_end/panels/timeline/TimelineHistoryManager.ts +1 -1
- package/front_end/panels/timeline/TimelinePaintProfilerView.ts +7 -3
- package/front_end/panels/timeline/TimelinePanel.ts +3 -3
- package/front_end/panels/timeline/TimelineTreeView.ts +1 -1
- package/front_end/panels/timeline/TimelineUIUtils.ts +4 -4
- package/front_end/panels/timeline/components/LayoutShiftDetails.ts +4 -3
- package/front_end/panels/timeline/components/LiveMetricsView.ts +1 -1
- package/front_end/panels/timeline/components/NetworkRequestDetails.ts +25 -24
- package/front_end/panels/timeline/components/RelatedInsightChips.ts +4 -3
- package/front_end/panels/timeline/components/Sidebar.ts +1 -1
- package/front_end/panels/timeline/components/SidebarAnnotationsTab.ts +4 -3
- package/front_end/panels/timeline/utils/Helpers.ts +1 -1
- package/front_end/panels/timeline/utils/ImageCache.ts +5 -3
- package/front_end/panels/web_audio/WebAudioView.ts +3 -3
- package/front_end/panels/webauthn/WebauthnPane.ts +5 -11
- package/front_end/third_party/acorn/acorn.ts +3 -3
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/third_party/chromium/ahem/ahem.d.ts +1 -0
- package/front_end/third_party/csp_evaluator/package/csp.ts +4 -4
- package/front_end/third_party/csp_evaluator/package/parser.ts +3 -1
- package/front_end/third_party/csp_evaluator/package/utils.ts +1 -1
- package/front_end/third_party/diff/diff_match_patch.d.ts +10 -0
- package/front_end/third_party/json5/json5.ts +2 -2
- package/front_end/ui/components/buttons/floatingButton.css +25 -0
- package/front_end/ui/components/srgb_overlay/SrgbOverlay.ts +1 -1
- package/front_end/ui/components/suggestion_input/SuggestionInput.ts +45 -25
- package/front_end/ui/legacy/ContextMenu.ts +2 -2
- package/front_end/ui/legacy/DropTarget.ts +6 -1
- package/front_end/ui/legacy/EmptyWidget.ts +1 -1
- package/front_end/ui/legacy/GlassPane.ts +1 -1
- package/front_end/ui/legacy/ShortcutRegistry.ts +2 -2
- package/front_end/ui/legacy/SplitWidget.ts +2 -1
- package/front_end/ui/legacy/StackedPane.ts +1 -1
- package/front_end/ui/legacy/TargetCrashedScreen.ts +1 -1
- package/front_end/ui/legacy/TextPrompt.ts +2 -1
- package/front_end/ui/legacy/Toolbar.ts +1 -1
- package/front_end/ui/legacy/Treeoutline.ts +13 -37
- package/front_end/ui/legacy/UIUtils.ts +6 -3
- package/front_end/ui/legacy/ViewManager.ts +1 -1
- package/front_end/ui/legacy/Widget.ts +1 -1
- package/front_end/ui/legacy/components/color_picker/Spectrum.ts +7 -1
- package/front_end/ui/legacy/components/data_grid/DataGrid.ts +1 -1
- package/front_end/ui/legacy/components/data_grid/DataGridElement.ts +3 -2
- package/front_end/ui/legacy/components/inline_editor/AnimationTimingModel.ts +1 -1
- package/front_end/ui/legacy/components/inline_editor/BezierEditor.ts +48 -44
- package/front_end/ui/legacy/components/inline_editor/CSSAngleUtils.ts +1 -1
- package/front_end/ui/legacy/components/object_ui/CustomPreviewComponent.ts +141 -106
- package/front_end/ui/legacy/components/object_ui/ObjectPopoverHelper.ts +1 -1
- package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +10 -10
- package/front_end/ui/legacy/components/perf_ui/pieChart.css +7 -5
- package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +8 -5
- package/front_end/ui/legacy/components/utils/JSPresentationUtils.ts +1 -1
- package/front_end/ui/legacy/components/utils/Linkifier.ts +5 -5
- package/front_end/ui/legacy/inspectorCommon.css +11 -0
- package/front_end/ui/visual_logging/Debugging.ts +2 -1
- package/front_end/ui/visual_logging/KnownContextValues.ts +1 -1
- package/front_end/ui/visual_logging/LoggingDriver.ts +3 -3
- package/front_end/ui/visual_logging/LoggingEvents.ts +5 -5
- package/front_end/ui/visual_logging/LoggingState.ts +1 -1
- package/front_end/ui/visual_logging/visual_logging.ts +67 -56
- package/package.json +2 -1
- package/front_end/third_party/acorn/acorn-tsconfig.json +0 -12
- package/front_end/third_party/acorn/estree-tsconfig.json +0 -8
- package/front_end/third_party/chromium/client-variations/client-variations-tsconfig.json +0 -8
- package/front_end/third_party/codemirror/codemirror-legacy-types-tsconfig.json +0 -8
- package/front_end/third_party/codemirror/codemirror-tsconfig.json +0 -15
- package/front_end/third_party/codemirror.next/bundle-tsconfig.json +0 -24
- package/front_end/third_party/intl-messageformat/intl-messageformat-tsconfig.json +0 -16
- package/front_end/third_party/json5/json5-tsconfig.json +0 -8
- package/front_end/third_party/legacy-javascript/legacy-javascript-tsconfig.json +0 -8
- package/front_end/third_party/lighthouse/lighthouse-tsconfig.json +0 -11
- package/front_end/third_party/lighthouse/report/bundle-tsconfig.json +0 -8
- package/front_end/third_party/lit/lit-tsconfig.json +0 -15
- package/front_end/third_party/marked/marked-tsconfig.json +0 -8
- package/front_end/third_party/puppeteer/puppeteer-tsconfig.json +0 -191
- package/front_end/third_party/third-party-web/third-party-web-tsconfig.json +0 -8
- package/front_end/third_party/wasmparser/wasmparser-tsconfig.json +0 -9
- package/front_end/third_party/web-vitals/web-vitals-tsconfig.json +0 -47
package/.gitmodules
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
[submodule "test/ai_evals/eval_data"]
|
|
2
|
+
path = test/ai_evals/eval_data
|
|
3
|
+
url = https://chrome-internal.googlesource.com/devtools/chrome-devtools-evals
|
|
4
|
+
gclient-condition = checkout_ai_evals == True
|
|
1
5
|
[submodule "third_party/clang-format/script"]
|
|
2
6
|
path = third_party/clang-format/script
|
|
3
7
|
url = https://chromium.googlesource.com/external/github.com/llvm/llvm-project/clang/tools/clang-format
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
Events as NetworkManagerEvents,
|
|
17
17
|
NetworkManager,
|
|
18
18
|
} from './NetworkManager.js';
|
|
19
|
+
import {SecurityOrigin} from './SecurityOrigin.js';
|
|
19
20
|
import {ServerSentEvents} from './ServerSentEvents.js';
|
|
20
21
|
import {ServerTiming} from './ServerTiming.js';
|
|
21
22
|
import {Type} from './Target.js';
|
|
@@ -388,6 +389,55 @@ export class NetworkRequest extends Common.ObjectWrapper.ObjectWrapper<EventType
|
|
|
388
389
|
return this.#backendRequestId;
|
|
389
390
|
}
|
|
390
391
|
|
|
392
|
+
/**
|
|
393
|
+
* Returns the security origin of the target resource URL (`request.url()`) for this network request.
|
|
394
|
+
*
|
|
395
|
+
* For example, if an inspected document at `https://example.com/index.html` initiates a fetch
|
|
396
|
+
* to `https://api.github.com/users`, `requestURLSecurityOrigin()` returns the origin for
|
|
397
|
+
* `https://api.github.com`.
|
|
398
|
+
*
|
|
399
|
+
* For imported HAR files, the origin is mapped to an isolated virtual domain
|
|
400
|
+
* (`imported-har://${authority}`) to ensure recorded network traffic never collides with
|
|
401
|
+
* live web origins.
|
|
402
|
+
*
|
|
403
|
+
* @see {@link initiatorSecurityOrigin} to obtain the origin of the document that initiated the request.
|
|
404
|
+
*/
|
|
405
|
+
requestURLSecurityOrigin(): SecurityOrigin {
|
|
406
|
+
return this.#resolveSecurityOrigin(this.#url);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Returns the security origin of the document or context (`request.documentURL`) that initiated
|
|
411
|
+
* this network request.
|
|
412
|
+
*
|
|
413
|
+
* For example, if an inspected document at `https://example.com/index.html` initiates a fetch
|
|
414
|
+
* to `https://api.github.com/users`, `initiatorSecurityOrigin()` returns the origin for
|
|
415
|
+
* `https://example.com`.
|
|
416
|
+
*
|
|
417
|
+
* If `documentURL` is empty, invalid, or an opaque context (such as a `data:` URL or sandboxed
|
|
418
|
+
* iframe), this returns a unique opaque `SecurityOrigin`.
|
|
419
|
+
*
|
|
420
|
+
* For imported HAR files, the origin is mapped to an isolated virtual domain
|
|
421
|
+
* (`imported-har://${authority}`) matching the imported initiating document.
|
|
422
|
+
*
|
|
423
|
+
* @see {@link requestURLSecurityOrigin} to obtain the origin of the target resource URL being requested.
|
|
424
|
+
*/
|
|
425
|
+
initiatorSecurityOrigin(): SecurityOrigin {
|
|
426
|
+
return this.#resolveSecurityOrigin(this.#documentURL);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
#resolveSecurityOrigin(url: Platform.DevToolsPath.UrlString): SecurityOrigin {
|
|
430
|
+
if (this.#isImportedHar) {
|
|
431
|
+
const parsed = Common.ParsedURL.ParsedURL.fromString(url);
|
|
432
|
+
if (!parsed || !parsed.host) {
|
|
433
|
+
return SecurityOrigin.createUniqueOpaque();
|
|
434
|
+
}
|
|
435
|
+
const authority = parsed.host + (parsed.port ? ':' + parsed.port : '');
|
|
436
|
+
return SecurityOrigin.create(`imported-har://${authority}`);
|
|
437
|
+
}
|
|
438
|
+
return SecurityOrigin.create(url);
|
|
439
|
+
}
|
|
440
|
+
|
|
391
441
|
url(): Platform.DevToolsPath.UrlString {
|
|
392
442
|
return this.#url;
|
|
393
443
|
}
|
|
@@ -486,10 +536,6 @@ export class NetworkRequest extends Common.ObjectWrapper.ObjectWrapper<EventType
|
|
|
486
536
|
return this.#securityDetails;
|
|
487
537
|
}
|
|
488
538
|
|
|
489
|
-
securityOrigin(): string {
|
|
490
|
-
return this.#parsedURL.securityOrigin();
|
|
491
|
-
}
|
|
492
|
-
|
|
493
539
|
setSecurityDetails(securityDetails: Protocol.Network.SecurityDetails): void {
|
|
494
540
|
this.#securityDetails = securityDetails;
|
|
495
541
|
}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
// Copyright 2026 The Chromium Authors
|
|
2
|
+
// Use of this source code is governed by a BSD-style license that can be
|
|
3
|
+
// found in the LICENSE file.
|
|
4
|
+
|
|
5
|
+
import type * as NetworkRequest from './NetworkRequest.js';
|
|
6
|
+
import * as SecurityOrigin from './SecurityOrigin.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Specifies how a network request's response data (body and headers) can be accessed
|
|
10
|
+
* relative to the initiating context's security origin.
|
|
11
|
+
*
|
|
12
|
+
* DevTools features that inspect network requests (such as AI Assistance) must respect
|
|
13
|
+
* the browser Same-Origin Policy (SOP) and Cross-Origin Resource Sharing (CORS) rules:
|
|
14
|
+
* - Same-origin responses are fully readable by the initiating document.
|
|
15
|
+
* - Cross-origin responses with valid CORS headers (`Access-Control-Allow-Origin`) are readable.
|
|
16
|
+
* - Opaque cross-origin responses (such as `no-cors` fetches to third-party endpoints) are NOT
|
|
17
|
+
* readable by the page and must never have their response bodies or restricted headers exposed
|
|
18
|
+
* to unauthorized contexts (b/513821237).
|
|
19
|
+
*/
|
|
20
|
+
export const enum ResponseAccessMode {
|
|
21
|
+
/** The request target URL is same-origin with the initiator context. */
|
|
22
|
+
SAME_ORIGIN = 'SAME_ORIGIN',
|
|
23
|
+
/** The request is cross-origin, but explicit CORS response headers permit access by the initiator. */
|
|
24
|
+
CORS_ALLOWED = 'CORS_ALLOWED',
|
|
25
|
+
/** The request is cross-origin without CORS authorization; response body and unexposed headers are restricted. */
|
|
26
|
+
OPAQUE_CROSS_ORIGIN = 'OPAQUE_CROSS_ORIGIN',
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Standard CORS-safelisted response headers that are exposed on cross-origin requests
|
|
31
|
+
* without requiring explicit `Access-Control-Expose-Headers`.
|
|
32
|
+
*
|
|
33
|
+
* @see https://fetch.spec.whatwg.org/#cors-safelisted-response-header-name
|
|
34
|
+
*/
|
|
35
|
+
export const CORS_SAFELISTED_RESPONSE_HEADERS: ReadonlySet<string> = new Set([
|
|
36
|
+
'cache-control',
|
|
37
|
+
'content-language',
|
|
38
|
+
'content-length',
|
|
39
|
+
'content-type',
|
|
40
|
+
'expires',
|
|
41
|
+
'last-modified',
|
|
42
|
+
'pragma',
|
|
43
|
+
]);
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Placeholder text replacing response body content when cross-origin access is forbidden.
|
|
47
|
+
*/
|
|
48
|
+
export const REDACTED_RESPONSE_BODY = '<redacted cross-origin response body>';
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Returns whether a network request used credentials (cookies, authorization headers,
|
|
52
|
+
* or server-indicated credentials mode).
|
|
53
|
+
*
|
|
54
|
+
* @param request The network request to inspect.
|
|
55
|
+
* @returns True if the request included credentials or requires credentialed CORS.
|
|
56
|
+
* @see https://fetch.spec.whatwg.org/#credentials
|
|
57
|
+
*/
|
|
58
|
+
export function isRequestCredentialed(request: NetworkRequest.NetworkRequest): boolean {
|
|
59
|
+
const hasAuthHeaders = Boolean(
|
|
60
|
+
request.requestHeaderValue('authorization') || request.requestHeaderValue('proxy-authorization'),
|
|
61
|
+
);
|
|
62
|
+
const hasCookies = request.includedRequestCookies().length > 0 || request.responseCookies.length > 0 ||
|
|
63
|
+
Boolean(request.requestHeaderValue('cookie')) || Boolean(request.responseHeaderValue('set-cookie'));
|
|
64
|
+
const hasAllowCredentials =
|
|
65
|
+
request.responseHeaderValue('access-control-allow-credentials')?.trim().toLowerCase() === 'true';
|
|
66
|
+
|
|
67
|
+
return hasAuthHeaders || hasCookies || hasAllowCredentials;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Evaluates the response access mode for a network request relative to an initiator origin.
|
|
72
|
+
*
|
|
73
|
+
* Evaluation rules:
|
|
74
|
+
* 1. If `initiatorOrigin` is omitted, the origin is derived from `request.documentURL`. If
|
|
75
|
+
* `documentURL` is invalid or opaque, access mode defaults to `OPAQUE_CROSS_ORIGIN`.
|
|
76
|
+
* 2. If the initiator origin is opaque (e.g. sandboxed iframe or `data:` URL), returns `OPAQUE_CROSS_ORIGIN`.
|
|
77
|
+
* 3. If the initiator origin is same-origin with the request URL, returns `SAME_ORIGIN`.
|
|
78
|
+
* 4. If Chrome's network stack flagged a CORS error (`corsErrorStatus`), returns `OPAQUE_CROSS_ORIGIN`.
|
|
79
|
+
* 5. If the server provided an `Access-Control-Allow-Origin` header:
|
|
80
|
+
* - Wildcard `*` grants `CORS_ALLOWED` only if the request does not include credentials. Under the
|
|
81
|
+
* Fetch specification, wildcard `*` is invalid for credentialed requests.
|
|
82
|
+
* - An explicit match against the initiator origin grants `CORS_ALLOWED`.
|
|
83
|
+
* 6. Otherwise, returns `OPAQUE_CROSS_ORIGIN`.
|
|
84
|
+
*
|
|
85
|
+
* @param request The network request being inspected.
|
|
86
|
+
* @param initiatorOrigin The security origin of the initiating context (e.g. page or conversation origin).
|
|
87
|
+
* @returns The evaluated `ResponseAccessMode`.
|
|
88
|
+
*/
|
|
89
|
+
export function evaluateResponseAccessMode(
|
|
90
|
+
request: NetworkRequest.NetworkRequest,
|
|
91
|
+
initiatorOrigin?: SecurityOrigin.SecurityOrigin,
|
|
92
|
+
): ResponseAccessMode {
|
|
93
|
+
const effectiveInitiatorOrigin = initiatorOrigin ?? SecurityOrigin.SecurityOrigin.create(request.documentURL);
|
|
94
|
+
|
|
95
|
+
// Opaque initiator contexts (e.g. data: URLs, sandboxed iframes) are never permitted
|
|
96
|
+
// to inspect cross-origin response content.
|
|
97
|
+
if (effectiveInitiatorOrigin.isOpaque()) {
|
|
98
|
+
return ResponseAccessMode.OPAQUE_CROSS_ORIGIN;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const resourceOrigin = SecurityOrigin.SecurityOrigin.create(request.url());
|
|
102
|
+
if (effectiveInitiatorOrigin.isSameOriginWith(resourceOrigin)) {
|
|
103
|
+
return ResponseAccessMode.SAME_ORIGIN;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// If the browser blocked the request with a CORS error, treat the response
|
|
107
|
+
// as opaque regardless of any Access-Control-Allow-Origin header value.
|
|
108
|
+
if (request.corsErrorStatus()) {
|
|
109
|
+
return ResponseAccessMode.OPAQUE_CROSS_ORIGIN;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const allowOriginHeader = request.responseHeaderValue('access-control-allow-origin')?.trim();
|
|
113
|
+
if (!allowOriginHeader) {
|
|
114
|
+
return ResponseAccessMode.OPAQUE_CROSS_ORIGIN;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const isCredentialed = isRequestCredentialed(request);
|
|
118
|
+
|
|
119
|
+
// Under the Fetch specification, wildcard '*' is forbidden from exposing responses if credentials are used.
|
|
120
|
+
if (allowOriginHeader === '*' && !isCredentialed) {
|
|
121
|
+
return ResponseAccessMode.CORS_ALLOWED;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (allowOriginHeader.toLowerCase() === effectiveInitiatorOrigin.siteId().toLowerCase()) {
|
|
125
|
+
return ResponseAccessMode.CORS_ALLOWED;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return ResponseAccessMode.OPAQUE_CROSS_ORIGIN;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Filters the response headers of a network request based on its access mode.
|
|
133
|
+
*
|
|
134
|
+
* - `SAME_ORIGIN`: Returns all response headers.
|
|
135
|
+
* - `CORS_ALLOWED`: Returns CORS-safelisted headers plus headers exposed via
|
|
136
|
+
* `Access-Control-Expose-Headers`.
|
|
137
|
+
* - `OPAQUE_CROSS_ORIGIN`: Returns only CORS-safelisted response headers. Under the Fetch
|
|
138
|
+
* specification, opaque responses do not expose headers configured by `Access-Control-Expose-Headers`.
|
|
139
|
+
*
|
|
140
|
+
* @param request The network request whose headers are being filtered.
|
|
141
|
+
* @param accessMode The evaluated response access mode for this request.
|
|
142
|
+
* @returns Array of allowed header name/value pairs.
|
|
143
|
+
*/
|
|
144
|
+
export function getFilterableResponseHeaders(
|
|
145
|
+
request: NetworkRequest.NetworkRequest,
|
|
146
|
+
accessMode: ResponseAccessMode,
|
|
147
|
+
): Array<{name: string, value: string}> {
|
|
148
|
+
if (accessMode === ResponseAccessMode.SAME_ORIGIN) {
|
|
149
|
+
return request.responseHeaders;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (accessMode === ResponseAccessMode.OPAQUE_CROSS_ORIGIN) {
|
|
153
|
+
return request.responseHeaders.filter(header => {
|
|
154
|
+
const lowerName = header.name.toLowerCase().trim();
|
|
155
|
+
return CORS_SAFELISTED_RESPONSE_HEADERS.has(lowerName);
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// For CORS_ALLOWED requests, parse Access-Control-Expose-Headers.
|
|
160
|
+
const exposeHeadersValue = request.responseHeaderValue('access-control-expose-headers')?.trim() || '';
|
|
161
|
+
const exposedSet = new Set(
|
|
162
|
+
exposeHeadersValue.split(',').map(h => h.trim().toLowerCase()).filter(Boolean),
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
const isCredentialed = isRequestCredentialed(request);
|
|
166
|
+
const allowWildcardExposure = !isCredentialed && exposedSet.has('*');
|
|
167
|
+
|
|
168
|
+
return request.responseHeaders.filter(header => {
|
|
169
|
+
const lowerName = header.name.toLowerCase().trim();
|
|
170
|
+
return CORS_SAFELISTED_RESPONSE_HEADERS.has(lowerName) || allowWildcardExposure || exposedSet.has(lowerName);
|
|
171
|
+
});
|
|
172
|
+
}
|
|
@@ -30,6 +30,15 @@ const OPAQUE_PREFIXES = [
|
|
|
30
30
|
'blob:null',
|
|
31
31
|
] as const;
|
|
32
32
|
|
|
33
|
+
/**
|
|
34
|
+
* String prefixes for imported artifact schemes (e.g., HAR recordings, traces).
|
|
35
|
+
* Imported entities operate in an isolated origin domain (`imported-har://${domain}`)
|
|
36
|
+
* that never matches live web origins (`https://${domain}`).
|
|
37
|
+
*/
|
|
38
|
+
export const IMPORTED_ORIGIN_PREFIXES: ReadonlySet<string> = new Set([
|
|
39
|
+
'imported-har:',
|
|
40
|
+
]);
|
|
41
|
+
|
|
33
42
|
function isOpaqueUrlString(url: string): boolean {
|
|
34
43
|
const lower = url.trim().toLowerCase();
|
|
35
44
|
if (OPAQUE_EXACT_MATCHES.has(lower)) {
|
|
@@ -86,6 +95,22 @@ export class SecurityOrigin {
|
|
|
86
95
|
return SecurityOrigin.createUniqueOpaque();
|
|
87
96
|
}
|
|
88
97
|
|
|
98
|
+
// Custom imported schemes (e.g. `imported-har:`) are not supported by standard URL parsers.
|
|
99
|
+
// We extract the host to construct a domain-scoped origin (`imported-har://${host}`).
|
|
100
|
+
// This isolates imported artifacts from live web pages (`imported-har://example.com` != `https://example.com`),
|
|
101
|
+
// while enabling same-origin comparison between requests within the same imported session domain.
|
|
102
|
+
for (const prefix of IMPORTED_ORIGIN_PREFIXES) {
|
|
103
|
+
if (rawUrl.toLowerCase().startsWith(prefix)) {
|
|
104
|
+
const afterScheme = rawUrl.substring(prefix.length).replace(/^\/+/, '');
|
|
105
|
+
const slashIndex = afterScheme.indexOf('/');
|
|
106
|
+
const host = slashIndex === -1 ? afterScheme : afterScheme.substring(0, slashIndex);
|
|
107
|
+
if (!host) {
|
|
108
|
+
return SecurityOrigin.createUniqueOpaque();
|
|
109
|
+
}
|
|
110
|
+
return new SecurityOrigin({type: 'origin', value: `${prefix}//${host.toLowerCase()}`});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
89
114
|
if (rawUrl.toLowerCase().startsWith('file://')) {
|
|
90
115
|
const parsed = Common.ParsedURL.ParsedURL.fromString(rawUrl as Platform.DevToolsPath.UrlString);
|
|
91
116
|
if (!parsed) {
|
|
@@ -58,6 +58,7 @@ import * as LayerTreeBase from './LayerTreeBase.js';
|
|
|
58
58
|
import * as LogModel from './LogModel.js';
|
|
59
59
|
import * as NetworkManager from './NetworkManager.js';
|
|
60
60
|
import * as NetworkRequest from './NetworkRequest.js';
|
|
61
|
+
import * as NetworkRequestAccess from './NetworkRequestAccess.js';
|
|
61
62
|
import * as OverlayColorGenerator from './OverlayColorGenerator.js';
|
|
62
63
|
import * as OverlayModel from './OverlayModel.js';
|
|
63
64
|
import * as OverlayPersistentHighlighter from './OverlayPersistentHighlighter.js';
|
|
@@ -146,6 +147,7 @@ export {
|
|
|
146
147
|
LogModel,
|
|
147
148
|
NetworkManager,
|
|
148
149
|
NetworkRequest,
|
|
150
|
+
NetworkRequestAccess,
|
|
149
151
|
OverlayColorGenerator,
|
|
150
152
|
OverlayModel,
|
|
151
153
|
OverlayPersistentHighlighter,
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// found in the LICENSE file.
|
|
4
4
|
|
|
5
5
|
import * as Host from '../../core/host/host.js';
|
|
6
|
+
import * as Root from '../../core/root/root.js';
|
|
6
7
|
import * as SDK from '../../core/sdk/sdk.js';
|
|
7
8
|
import type * as LHModel from '../lighthouse/lighthouse.js';
|
|
8
9
|
import type * as Trace from '../trace/trace.js';
|
|
@@ -78,7 +79,9 @@ export class AiAgent2 extends AiAgent<unknown> {
|
|
|
78
79
|
// TODO: The static preamble is a placeholder and will eventually live server-side.
|
|
79
80
|
readonly preamble: string = preamble;
|
|
80
81
|
readonly clientFeature: Host.AidaClient.ClientFeature = Host.AidaClient.ClientFeature.CHROME_DEVTOOLS_V2_AGENT;
|
|
81
|
-
|
|
82
|
+
get userTier(): string|undefined {
|
|
83
|
+
return Root.Runtime.hostConfig.devToolsAiV2Architecture?.userTier;
|
|
84
|
+
}
|
|
82
85
|
|
|
83
86
|
#changes: ChangeManager;
|
|
84
87
|
#execJs: typeof executeJsCode;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// Copyright 2024 The Chromium Authors
|
|
2
2
|
// Use of this source code is governed by a BSD-style license that can be
|
|
3
3
|
// found in the LICENSE file.
|
|
4
|
-
import * as Common from '../../core/common/common.js';
|
|
5
4
|
import * as Host from '../../core/host/host.js';
|
|
6
5
|
import * as Platform from '../../core/platform/platform.js';
|
|
7
6
|
import * as Root from '../../core/root/root.js';
|
|
@@ -46,14 +45,13 @@ export const NOT_FOUND_IMAGE_DATA = '';
|
|
|
46
45
|
export const CONTEXT_TITLE = 'Analyzing data';
|
|
47
46
|
const MAX_TITLE_LENGTH = 80;
|
|
48
47
|
/**
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
* - `about
|
|
52
|
-
* - `chrome://terms`:
|
|
53
|
-
* audit.
|
|
48
|
+
* Page URL prefixes permitted during an AI agent run.
|
|
49
|
+
* Agents trigger these navigations internally:
|
|
50
|
+
* - `about:blank`: Used before recording a performance trace to ensure a clean state.
|
|
51
|
+
* - `chrome://terms`: Used by Lighthouse during Back-Forward Cache audits.
|
|
54
52
|
*/
|
|
55
53
|
export const ALLOWED_PAGE_NAVIGATIONS: Platform.DevToolsPath.UrlString[] = [
|
|
56
|
-
Platform.DevToolsPath.urlString`about
|
|
54
|
+
Platform.DevToolsPath.urlString`about:blank`,
|
|
57
55
|
Platform.DevToolsPath.urlString`chrome://terms`,
|
|
58
56
|
];
|
|
59
57
|
|
|
@@ -431,14 +429,17 @@ export class AiConversation {
|
|
|
431
429
|
} = {},
|
|
432
430
|
): AsyncGenerator<ResponseData, void, void> {
|
|
433
431
|
this.#navigationOccurredDuringRun = false;
|
|
434
|
-
const originAtRunStart =
|
|
432
|
+
const originAtRunStart = getPrimaryPageSecurityOrigin(this.#targetManager);
|
|
435
433
|
const listener = (): void => {
|
|
436
|
-
//
|
|
437
|
-
//
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
const
|
|
441
|
-
|
|
434
|
+
// Prevent the agent from executing tools or reading data from an untrusted origin
|
|
435
|
+
// if the page navigates unexpectedly during execution.
|
|
436
|
+
const newInspectedURL = this.#targetManager.primaryPageTarget()?.inspectedURL();
|
|
437
|
+
const newOrigin = newInspectedURL ? SDK.SecurityOrigin.SecurityOrigin.create(newInspectedURL) : undefined;
|
|
438
|
+
const isSameOrigin = Boolean(originAtRunStart && newOrigin && originAtRunStart.isSameOriginWith(newOrigin));
|
|
439
|
+
const isAllowedNavigation =
|
|
440
|
+
Boolean(newInspectedURL && ALLOWED_PAGE_NAVIGATIONS.some(allowed => newInspectedURL.startsWith(allowed)));
|
|
441
|
+
|
|
442
|
+
if (!isSameOrigin && !isAllowedNavigation) {
|
|
442
443
|
this.#navigationOccurredDuringRun = true;
|
|
443
444
|
}
|
|
444
445
|
};
|
|
@@ -551,6 +552,10 @@ export class AiConversation {
|
|
|
551
552
|
return this.#type;
|
|
552
553
|
}
|
|
553
554
|
|
|
555
|
+
/**
|
|
556
|
+
* Returns the permitted origin for agent tool execution, or blocks execution
|
|
557
|
+
* if an unapproved cross-origin navigation occurred during the current run.
|
|
558
|
+
*/
|
|
554
559
|
allowedOrigin = (): AllowedOriginResult => {
|
|
555
560
|
if (this.#navigationOccurredDuringRun) {
|
|
556
561
|
return {blocked: true};
|
|
@@ -558,7 +563,7 @@ export class AiConversation {
|
|
|
558
563
|
if (this.#origin) {
|
|
559
564
|
return {origin: this.origin};
|
|
560
565
|
}
|
|
561
|
-
this.#origin =
|
|
566
|
+
this.#origin = getPrimaryPageSecurityOrigin(this.#targetManager);
|
|
562
567
|
|
|
563
568
|
return {origin: this.origin};
|
|
564
569
|
};
|
|
@@ -574,10 +579,16 @@ function isAiAssistanceServerSideLoggingAllowed(): boolean {
|
|
|
574
579
|
return !Root.Runtime.hostConfig.aidaAvailability?.disallowLogging;
|
|
575
580
|
}
|
|
576
581
|
|
|
577
|
-
|
|
582
|
+
/**
|
|
583
|
+
* Returns the security origin of the primary page target.
|
|
584
|
+
*
|
|
585
|
+
* @param targetManager Target manager used to locate the primary page target.
|
|
586
|
+
* @returns The parsed SecurityOrigin, or undefined if no target or inspected URL exists.
|
|
587
|
+
*/
|
|
588
|
+
function getPrimaryPageSecurityOrigin(
|
|
578
589
|
targetManager: SDK.TargetManager.TargetManager,
|
|
579
|
-
):
|
|
590
|
+
): SDK.SecurityOrigin.SecurityOrigin|undefined {
|
|
580
591
|
const target = targetManager.primaryPageTarget();
|
|
581
592
|
const inspectedURL = target?.inspectedURL();
|
|
582
|
-
return inspectedURL ?
|
|
593
|
+
return inspectedURL ? SDK.SecurityOrigin.SecurityOrigin.create(inspectedURL) : undefined;
|
|
583
594
|
}
|
|
@@ -460,7 +460,7 @@ export class BackForwardCacheView extends UI.Widget.Widget {
|
|
|
460
460
|
#historyIndex = 0;
|
|
461
461
|
#view: View;
|
|
462
462
|
|
|
463
|
-
constructor(view = DEFAULT_VIEW) {
|
|
463
|
+
constructor(view: View = DEFAULT_VIEW) {
|
|
464
464
|
super({useShadowDom: true, delegatesFocus: true});
|
|
465
465
|
this.#view = view;
|
|
466
466
|
}
|
|
@@ -71,7 +71,8 @@ export const DEFAULT_VIEW = (input: ViewInput, output: undefined, target: HTMLEl
|
|
|
71
71
|
type View = typeof DEFAULT_VIEW;
|
|
72
72
|
|
|
73
73
|
export class EndpointsGrid extends UI.Widget.Widget {
|
|
74
|
-
endpoints
|
|
74
|
+
endpoints: Map<string, Protocol.Network.ReportingApiEndpoint[]> =
|
|
75
|
+
new Map<string, Protocol.Network.ReportingApiEndpoint[]>();
|
|
75
76
|
#view: View;
|
|
76
77
|
|
|
77
78
|
constructor(element?: HTMLElement, view: View = DEFAULT_VIEW) {
|
|
@@ -218,7 +218,7 @@ export class PermissionsPolicySection extends UI.Widget.Widget {
|
|
|
218
218
|
#showDetails = false;
|
|
219
219
|
#view: View;
|
|
220
220
|
|
|
221
|
-
constructor(element?: HTMLElement, view = DEFAULT_VIEW) {
|
|
221
|
+
constructor(element?: HTMLElement, view: View = DEFAULT_VIEW) {
|
|
222
222
|
super(element, {useShadowDom: false});
|
|
223
223
|
this.#view = view;
|
|
224
224
|
}
|
|
@@ -45,7 +45,7 @@ export class ServiceWorkerRouterView extends UI.Widget.Widget {
|
|
|
45
45
|
#rules: SDK.ServiceWorkerManager.ServiceWorkerRouterRule[] = [];
|
|
46
46
|
#view: View;
|
|
47
47
|
|
|
48
|
-
constructor(element?: HTMLElement, view = DEFAULT_VIEW) {
|
|
48
|
+
constructor(element?: HTMLElement, view: View = DEFAULT_VIEW) {
|
|
49
49
|
super(element, {useShadowDom: true});
|
|
50
50
|
this.#view = view;
|
|
51
51
|
}
|
|
@@ -141,7 +141,7 @@ export class TrustTokensView extends UI.Widget.VBox {
|
|
|
141
141
|
#tokens: Protocol.Storage.TrustTokens[] = [];
|
|
142
142
|
#view: View;
|
|
143
143
|
|
|
144
|
-
constructor(element?: HTMLElement, view = DEFAULT_VIEW) {
|
|
144
|
+
constructor(element?: HTMLElement, view: View = DEFAULT_VIEW) {
|
|
145
145
|
super(element, {useShadowDom: true});
|
|
146
146
|
this.#view = view;
|
|
147
147
|
}
|
|
@@ -443,7 +443,8 @@ export class PreloadingDetailsReportView extends UI.Widget.VBox {
|
|
|
443
443
|
#data: PreloadingDetailsReportViewData = null;
|
|
444
444
|
#view: typeof DEFAULT_VIEW;
|
|
445
445
|
|
|
446
|
-
constructor(element?: HTMLElement,
|
|
446
|
+
constructor(element?: HTMLElement,
|
|
447
|
+
view: (input: ViewInput, _output: undefined, target: HTMLElement) => void = DEFAULT_VIEW) {
|
|
447
448
|
super(element);
|
|
448
449
|
this.#view = view;
|
|
449
450
|
}
|
|
@@ -79,7 +79,8 @@ export class RuleSetDetailsView extends UI.Widget.VBox {
|
|
|
79
79
|
#ruleSet: RuleSet|null = null;
|
|
80
80
|
#shouldPrettyPrint = true;
|
|
81
81
|
|
|
82
|
-
constructor(element?: HTMLElement,
|
|
82
|
+
constructor(element?: HTMLElement,
|
|
83
|
+
view: (input: ViewInput|null, _output: object, target: HTMLElement) => void = DEFAULT_VIEW) {
|
|
83
84
|
super(element, {useShadowDom: true});
|
|
84
85
|
this.#view = view;
|
|
85
86
|
}
|
|
@@ -425,7 +425,7 @@ const DEFAULT_VIEW: View = (input, _output, target) => {
|
|
|
425
425
|
export class UsedPreloadingView extends UI.Widget.VBox {
|
|
426
426
|
readonly #view: View;
|
|
427
427
|
|
|
428
|
-
constructor(view = DEFAULT_VIEW) {
|
|
428
|
+
constructor(view: View = DEFAULT_VIEW) {
|
|
429
429
|
super({useShadowDom: true});
|
|
430
430
|
this.#view = view;
|
|
431
431
|
}
|
|
@@ -66,10 +66,14 @@ function makeFixedPresetThrottlingOption(rate: CPUThrottlingRates): CPUThrottlin
|
|
|
66
66
|
};
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
export const NoThrottlingOption =
|
|
70
|
-
|
|
71
|
-
export const
|
|
72
|
-
|
|
69
|
+
export const NoThrottlingOption: CPUThrottlingOption =
|
|
70
|
+
makeFixedPresetThrottlingOption(CPUThrottlingRates.NO_THROTTLING);
|
|
71
|
+
export const MidTierThrottlingOption: CPUThrottlingOption =
|
|
72
|
+
makeFixedPresetThrottlingOption(CPUThrottlingRates.MID_TIER_MOBILE);
|
|
73
|
+
export const LowTierThrottlingOption: CPUThrottlingOption =
|
|
74
|
+
makeFixedPresetThrottlingOption(CPUThrottlingRates.LOW_TIER_MOBILE);
|
|
75
|
+
export const ExtraSlowThrottlingOption: CPUThrottlingOption =
|
|
76
|
+
makeFixedPresetThrottlingOption(CPUThrottlingRates.EXTRA_SLOW);
|
|
73
77
|
|
|
74
78
|
function makeCalibratedThrottlingOption(calibratedDeviceType: CalibratedDeviceType): CPUThrottlingOption {
|
|
75
79
|
const getSettingValue = (): number|CalibrationError|null => {
|
|
@@ -109,8 +113,10 @@ function makeCalibratedThrottlingOption(calibratedDeviceType: CalibratedDeviceTy
|
|
|
109
113
|
};
|
|
110
114
|
}
|
|
111
115
|
|
|
112
|
-
export const CalibratedLowTierMobileThrottlingOption =
|
|
113
|
-
|
|
116
|
+
export const CalibratedLowTierMobileThrottlingOption: CPUThrottlingOption =
|
|
117
|
+
makeCalibratedThrottlingOption('low-tier-mobile');
|
|
118
|
+
export const CalibratedMidTierMobileThrottlingOption: CPUThrottlingOption =
|
|
119
|
+
makeCalibratedThrottlingOption('mid-tier-mobile');
|
|
114
120
|
|
|
115
121
|
export function calibrationErrorToString(error: CalibrationError): string {
|
|
116
122
|
if (error === CalibrationError.DEVICE_TOO_WEAK) {
|
|
@@ -91,7 +91,7 @@ export class DOMNodeLink extends UI.Widget.Widget {
|
|
|
91
91
|
#options: Options|undefined = undefined;
|
|
92
92
|
#view: View;
|
|
93
93
|
|
|
94
|
-
constructor(element?: HTMLElement, node?: SDK.DOMModel.DOMNode, options?: Options, view = DEFAULT_VIEW) {
|
|
94
|
+
constructor(element?: HTMLElement, node?: SDK.DOMModel.DOMNode, options?: Options, view: View = DEFAULT_VIEW) {
|
|
95
95
|
super(element, {useShadowDom: true});
|
|
96
96
|
this.element.classList.remove('vbox');
|
|
97
97
|
this.#node = node;
|
|
@@ -41,7 +41,8 @@ export class ExtensionView extends UI.Widget.Widget {
|
|
|
41
41
|
#frameIndex?: number;
|
|
42
42
|
|
|
43
43
|
#view: typeof DEFAULT_VIEW;
|
|
44
|
-
constructor(server: ExtensionServer, id: string, src: string, className: string,
|
|
44
|
+
constructor(server: ExtensionServer, id: string, src: string, className: string,
|
|
45
|
+
view: (input: ViewInput, output: ViewOutput, target: HTMLElement) => void = DEFAULT_VIEW) {
|
|
45
46
|
super();
|
|
46
47
|
this.#view = view;
|
|
47
48
|
this.#server = server;
|
|
@@ -109,7 +109,8 @@ export class ConsolePinPane extends UI.Widget.VBox {
|
|
|
109
109
|
readonly #pinModel: ConsolePinModel;
|
|
110
110
|
readonly #focusOut: () => void;
|
|
111
111
|
|
|
112
|
-
constructor(focusOut: () => void,
|
|
112
|
+
constructor(focusOut: () => void,
|
|
113
|
+
view: (input: PaneViewInput, _output: object, target: HTMLElement) => void = DEFAULT_PANE_VIEW) {
|
|
113
114
|
super({useShadowDom: true});
|
|
114
115
|
this.#focusOut = focusOut;
|
|
115
116
|
this.#view = view;
|
|
@@ -294,7 +295,8 @@ export class ConsolePinPresenter extends UI.Widget.Widget {
|
|
|
294
295
|
#deletePinIcon!: Buttons.Button.Button;
|
|
295
296
|
readonly #selfXssWarningDisabledSetting: Common.Settings.Setting<boolean>;
|
|
296
297
|
|
|
297
|
-
constructor(element?: HTMLElement,
|
|
298
|
+
constructor(element?: HTMLElement,
|
|
299
|
+
view: (input: ViewInput, output: ViewOutput, target: HTMLElement) => void = DEFAULT_VIEW) {
|
|
298
300
|
super(element);
|
|
299
301
|
this.#view = view;
|
|
300
302
|
|
|
@@ -117,7 +117,11 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
|
117
117
|
};
|
|
118
118
|
|
|
119
119
|
export class ConsoleFilterGroup {
|
|
120
|
-
readonly urlGroups
|
|
120
|
+
readonly urlGroups: Map<string|null, {
|
|
121
|
+
filter: ConsoleFilter,
|
|
122
|
+
url: string|null,
|
|
123
|
+
count: number,
|
|
124
|
+
}> = new Map<string|null, {filter: ConsoleFilter, url: string|null, count: number}>();
|
|
121
125
|
messageCount = 0;
|
|
122
126
|
readonly name: GroupName;
|
|
123
127
|
readonly filter: ConsoleFilter;
|
|
@@ -190,7 +194,7 @@ export class ConsoleSidebar extends ConsoleSidebarBase {
|
|
|
190
194
|
Common.Settings.Settings.instance().createSetting<string|null>('console.sidebar-selected-filter', null);
|
|
191
195
|
#selectedFilter = this.#groups.find(group => group.name === this.#selectedFilterSetting.get())?.filter;
|
|
192
196
|
|
|
193
|
-
constructor(element?: HTMLElement, view = DEFAULT_VIEW) {
|
|
197
|
+
constructor(element?: HTMLElement, view: View = DEFAULT_VIEW) {
|
|
194
198
|
super(element, {
|
|
195
199
|
useShadowDom: 'pure',
|
|
196
200
|
});
|
|
@@ -203,7 +203,7 @@ export function lineWhitespace(line: string): string|null {
|
|
|
203
203
|
|
|
204
204
|
export function formatRelatedCode(
|
|
205
205
|
{text, columnNumber, lineNumber}: {text: string, columnNumber: number, lineNumber: number},
|
|
206
|
-
maxCodeSize = MAX_CODE_SIZE): string {
|
|
206
|
+
maxCodeSize: number = MAX_CODE_SIZE): string {
|
|
207
207
|
const lines = text.split('\n');
|
|
208
208
|
if (lines[lineNumber].length >= maxCodeSize / 2) {
|
|
209
209
|
const start = Math.max(columnNumber - maxCodeSize / 2, 0);
|