chrome-devtools-frontend 1.0.1539972 → 1.0.1541552
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/eslint.config.mjs +167 -151
- package/front_end/Tests.js +5 -1
- package/front_end/core/common/Revealer.ts +5 -0
- package/front_end/core/common/Settings.ts +106 -95
- package/front_end/core/host/InspectorFrontendHost.ts +10 -10
- package/front_end/core/sdk/NetworkManager.ts +16 -11
- package/front_end/core/sdk/sdk-meta.ts +0 -35
- package/front_end/entrypoints/main/MainImpl.ts +15 -7
- package/front_end/entrypoints/shell/shell.ts +1 -0
- package/front_end/entrypoints/trace_app/trace_app.ts +1 -0
- package/front_end/foundation/README.md +10 -0
- package/front_end/foundation/Universe.ts +29 -0
- package/front_end/foundation/foundation.ts +7 -0
- package/front_end/generated/InspectorBackendCommands.ts +6 -3
- package/front_end/generated/SupportedCSSProperties.js +13 -0
- package/front_end/generated/protocol.ts +58 -2
- package/front_end/models/ai_assistance/BuiltInAi.ts +2 -1
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +44 -34
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +121 -56
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.ts +104 -62
- package/front_end/models/ai_assistance/performance/AIQueries.ts +56 -2
- package/front_end/{panels/issues → models/issues_manager}/IssueAggregator.ts +83 -65
- package/front_end/models/issues_manager/issues_manager.ts +2 -0
- package/front_end/models/trace/Processor.ts +5 -4
- package/front_end/models/trace/insights/types.ts +1 -1
- package/front_end/models/trace/types/TraceEvents.ts +1 -1
- package/front_end/models/workspace/IgnoreListManager.ts +41 -47
- package/front_end/models/workspace/workspace-meta.ts +40 -0
- package/front_end/panels/ai_assistance/components/MarkdownRendererWithCodeBlock.ts +1 -1
- package/front_end/panels/ai_assistance/components/PerformanceAgentMarkdownRenderer.ts +1 -1
- package/front_end/panels/animation/AnimationTimeline.ts +4 -4
- package/front_end/panels/animation/AnimationUI.ts +28 -34
- package/front_end/panels/elements/ElementsTreeElement.ts +37 -9
- package/front_end/panels/elements/LayoutPane.ts +2 -2
- package/front_end/panels/elements/components/AdornerManager.ts +9 -9
- package/front_end/panels/elements/layoutPane.css +5 -9
- package/front_end/panels/event_listeners/EventListenersView.ts +1 -1
- package/front_end/panels/explain/components/ConsoleInsight.ts +498 -449
- package/front_end/panels/issues/AffectedResourcesView.ts +3 -4
- package/front_end/panels/issues/CorsIssueDetailsView.ts +1 -2
- package/front_end/panels/issues/IssueView.ts +1 -1
- package/front_end/panels/issues/IssuesPane.ts +12 -15
- package/front_end/panels/issues/issues.ts +0 -2
- package/front_end/panels/network/NetworkDataGridNode.ts +2 -1
- package/front_end/panels/network/RequestConditionsDrawer.ts +149 -46
- package/front_end/panels/network/RequestTimingView.ts +13 -8
- package/front_end/panels/network/network-meta.ts +11 -0
- package/front_end/panels/settings/emulation/components/userAgentClientHintsForm.css +1 -1
- package/front_end/panels/sources/DebuggerPlugin.ts +1 -1
- package/front_end/panels/sources/WatchExpressionsSidebarPane.ts +1 -1
- package/front_end/panels/sources/breakpointsView.css +1 -1
- package/front_end/panels/sources/sourcesPanel.css +2 -2
- package/front_end/panels/timeline/TimelineFlameChartView.ts +3 -3
- package/front_end/panels/timeline/TimelinePanel.ts +3 -3
- package/front_end/panels/timeline/components/LayoutShiftDetails.ts +16 -10
- package/front_end/panels/timeline/components/SidebarSingleInsightSet.ts +2 -0
- package/front_end/panels/timeline/overlays/components/EntryLabelOverlay.ts +4 -1
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/third_party/puppeteer/README.chromium +2 -2
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkManager.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkManager.js +3 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkManager.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.d.ts +2 -2
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js +2 -2
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +4 -4
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkManager.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkManager.js +3 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkManager.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.d.ts +2 -2
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js +2 -2
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.js +1 -1
- package/front_end/third_party/puppeteer/package/package.json +1 -1
- package/front_end/third_party/puppeteer/package/src/cdp/NetworkManager.ts +3 -1
- package/front_end/third_party/puppeteer/package/src/revisions.ts +2 -2
- package/front_end/third_party/puppeteer/package/src/util/version.ts +1 -1
- package/front_end/ui/components/markdown_view/MarkdownView.ts +6 -6
- package/front_end/ui/components/snackbars/Snackbars.docs.ts +46 -0
- package/front_end/ui/{components/docs/context_menu/basic.ts → legacy/ContextMenu.docs.ts} +58 -25
- package/front_end/ui/legacy/UIUtils.ts +2 -1
- package/front_end/ui/legacy/components/inline_editor/BezierEditor.ts +1 -1
- package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +148 -125
- package/front_end/ui/legacy/components/perf_ui/TimelineOverviewPane.ts +3 -3
- package/front_end/ui/legacy/components/perf_ui/pieChart.css +1 -1
- package/front_end/ui/legacy/components/utils/Linkifier.ts +1 -1
- package/front_end/ui/legacy/inspectorCommon.css +3 -2
- package/front_end/ui/visual_logging/KnownContextValues.ts +1 -0
- package/mcp/mcp.ts +16 -0
- package/package.json +2 -1
- package/front_end/ui/components/docs/context_menu/basic.html +0 -45
- package/front_end/ui/components/docs/linkifier/simple-url.html +0 -25
- package/front_end/ui/components/docs/linkifier/simple-url.ts +0 -25
- package/front_end/ui/components/docs/panel_feedback/basic.html +0 -25
- package/front_end/ui/components/docs/panel_feedback/basic.ts +0 -21
- package/front_end/ui/components/docs/panel_feedback/button.html +0 -25
- package/front_end/ui/components/docs/panel_feedback/button.ts +0 -19
- package/front_end/ui/components/docs/panel_introduction_steps/basic.html +0 -25
- package/front_end/ui/components/docs/panel_introduction_steps/basic.ts +0 -28
- package/front_end/ui/components/docs/perf_piechart/basic-with-legend.html +0 -20
- package/front_end/ui/components/docs/perf_piechart/basic-with-legend.ts +0 -20
- package/front_end/ui/components/docs/perf_piechart/basic-without-legend.html +0 -20
- package/front_end/ui/components/docs/perf_piechart/basic-without-legend.ts +0 -18
- package/front_end/ui/components/docs/snackbars/basic.html +0 -17
- package/front_end/ui/components/docs/snackbars/basic.ts +0 -50
|
@@ -18,7 +18,6 @@ import * as Components from '../../ui/legacy/components/utils/utils.js';
|
|
|
18
18
|
import * as UI from '../../ui/legacy/legacy.js';
|
|
19
19
|
import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
|
|
20
20
|
|
|
21
|
-
import type {AggregatedIssue} from './IssueAggregator.js';
|
|
22
21
|
import type {IssueView} from './IssueView.js';
|
|
23
22
|
|
|
24
23
|
const UIStrings = {
|
|
@@ -65,7 +64,7 @@ export interface CreateRequestCellOptions {
|
|
|
65
64
|
*/
|
|
66
65
|
export abstract class AffectedResourcesView extends UI.TreeOutline.TreeElement {
|
|
67
66
|
readonly #parentView: IssueView;
|
|
68
|
-
protected issue: AggregatedIssue;
|
|
67
|
+
protected issue: IssuesManager.IssueAggregator.AggregatedIssue;
|
|
69
68
|
protected affectedResourcesCountElement: HTMLElement;
|
|
70
69
|
protected affectedResources: HTMLElement;
|
|
71
70
|
#affectedResourcesCount: number;
|
|
@@ -73,7 +72,7 @@ export abstract class AffectedResourcesView extends UI.TreeOutline.TreeElement {
|
|
|
73
72
|
#unresolvedFrameIds: Set<string>;
|
|
74
73
|
protected requestResolver: Logs.RequestResolver.RequestResolver;
|
|
75
74
|
|
|
76
|
-
constructor(parent: IssueView, issue: AggregatedIssue, jslogContext: string) {
|
|
75
|
+
constructor(parent: IssueView, issue: IssuesManager.IssueAggregator.AggregatedIssue, jslogContext: string) {
|
|
77
76
|
super(/* title */ undefined, /* expandable */ undefined, jslogContext);
|
|
78
77
|
this.#parentView = parent;
|
|
79
78
|
this.issue = issue;
|
|
@@ -91,7 +90,7 @@ export abstract class AffectedResourcesView extends UI.TreeOutline.TreeElement {
|
|
|
91
90
|
* Sets the issue to take the resources from. Does not
|
|
92
91
|
* trigger an update, the caller needs to do that explicitly.
|
|
93
92
|
*/
|
|
94
|
-
setIssue(issue: AggregatedIssue): void {
|
|
93
|
+
setIssue(issue: IssuesManager.IssueAggregator.AggregatedIssue): void {
|
|
95
94
|
this.issue = issue;
|
|
96
95
|
}
|
|
97
96
|
|
|
@@ -11,7 +11,6 @@ import * as IssuesManager from '../../models/issues_manager/issues_manager.js';
|
|
|
11
11
|
import * as NetworkForward from '../../panels/network/forward/forward.js';
|
|
12
12
|
|
|
13
13
|
import {AffectedItem, AffectedResourcesView} from './AffectedResourcesView.js';
|
|
14
|
-
import type {AggregatedIssue} from './IssueAggregator.js';
|
|
15
14
|
import type {IssueView} from './IssueView.js';
|
|
16
15
|
|
|
17
16
|
const UIStrings = {
|
|
@@ -128,7 +127,7 @@ const str_ = i18n.i18n.registerUIStrings('panels/issues/CorsIssueDetailsView.ts'
|
|
|
128
127
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
129
128
|
|
|
130
129
|
export class CorsIssueDetailsView extends AffectedResourcesView {
|
|
131
|
-
constructor(parent: IssueView, issue: AggregatedIssue, jslogContext: string) {
|
|
130
|
+
constructor(parent: IssueView, issue: IssuesManager.IssueAggregator.AggregatedIssue, jslogContext: string) {
|
|
132
131
|
super(parent, issue, jslogContext);
|
|
133
132
|
this.affectedResourcesCountElement.classList.add('cors-issue-affected-resource-label');
|
|
134
133
|
}
|
|
@@ -8,6 +8,7 @@ import * as Host from '../../core/host/host.js';
|
|
|
8
8
|
import * as i18n from '../../core/i18n/i18n.js';
|
|
9
9
|
import type * as Platform from '../../core/platform/platform.js';
|
|
10
10
|
import * as Protocol from '../../generated/protocol.js';
|
|
11
|
+
import type {AggregatedIssue} from '../../models/issues_manager/IssueAggregator.js';
|
|
11
12
|
import * as IssuesManager from '../../models/issues_manager/issues_manager.js';
|
|
12
13
|
import * as NetworkForward from '../../panels/network/forward/forward.js';
|
|
13
14
|
import * as Adorners from '../../ui/components/adorners/adorners.js';
|
|
@@ -36,7 +37,6 @@ import * as Components from './components/components.js';
|
|
|
36
37
|
import type {HiddenIssuesMenuData} from './components/HideIssuesMenu.js';
|
|
37
38
|
import {CorsIssueDetailsView} from './CorsIssueDetailsView.js';
|
|
38
39
|
import {GenericIssueDetailsView} from './GenericIssueDetailsView.js';
|
|
39
|
-
import type {AggregatedIssue} from './IssueAggregator.js';
|
|
40
40
|
|
|
41
41
|
const UIStrings = {
|
|
42
42
|
/**
|
|
@@ -14,12 +14,6 @@ import * as UI from '../../ui/legacy/legacy.js';
|
|
|
14
14
|
import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
|
|
15
15
|
|
|
16
16
|
import {HiddenIssuesRow} from './HiddenIssuesRow.js';
|
|
17
|
-
import {
|
|
18
|
-
type AggregatedIssue,
|
|
19
|
-
type AggregationKey,
|
|
20
|
-
Events as IssueAggregatorEvents,
|
|
21
|
-
IssueAggregator,
|
|
22
|
-
} from './IssueAggregator.js';
|
|
23
17
|
import {getGroupIssuesByKindSetting, IssueKindView, issueKindViewSortPriority} from './IssueKindView.js';
|
|
24
18
|
import issuesPaneStyles from './issuesPane.css.js';
|
|
25
19
|
import issuesTreeStyles from './issuesTree.css.js';
|
|
@@ -181,14 +175,14 @@ export function getGroupIssuesByCategorySetting(): Common.Settings.Setting<boole
|
|
|
181
175
|
|
|
182
176
|
export class IssuesPane extends UI.Widget.VBox {
|
|
183
177
|
#categoryViews: Map<IssuesManager.Issue.IssueCategory, IssueCategoryView>;
|
|
184
|
-
#issueViews: Map<AggregationKey, IssueView>;
|
|
178
|
+
#issueViews: Map<IssuesManager.IssueAggregator.AggregationKey, IssueView>;
|
|
185
179
|
#kindViews: Map<IssuesManager.Issue.IssueKind, IssueKindView>;
|
|
186
180
|
#showThirdPartyCheckbox: UI.Toolbar.ToolbarSettingCheckbox|null;
|
|
187
181
|
#issuesTree: UI.TreeOutline.TreeOutlineInShadow;
|
|
188
182
|
#hiddenIssuesRow: HiddenIssuesRow;
|
|
189
183
|
#noIssuesMessageDiv: UI.EmptyWidget.EmptyWidget;
|
|
190
184
|
#issuesManager: IssuesManager.IssuesManager.IssuesManager;
|
|
191
|
-
#aggregator: IssueAggregator;
|
|
185
|
+
#aggregator: IssuesManager.IssueAggregator.IssueAggregator;
|
|
192
186
|
#issueViewUpdatePromise: Promise<void> = Promise.resolve();
|
|
193
187
|
|
|
194
188
|
constructor() {
|
|
@@ -222,9 +216,11 @@ export class IssuesPane extends UI.Widget.VBox {
|
|
|
222
216
|
this.#noIssuesMessageDiv.show(this.contentElement);
|
|
223
217
|
|
|
224
218
|
this.#issuesManager = IssuesManager.IssuesManager.IssuesManager.instance();
|
|
225
|
-
this.#aggregator = new IssueAggregator(this.#issuesManager);
|
|
226
|
-
this.#aggregator.addEventListener(
|
|
227
|
-
|
|
219
|
+
this.#aggregator = new IssuesManager.IssueAggregator.IssueAggregator(this.#issuesManager);
|
|
220
|
+
this.#aggregator.addEventListener(
|
|
221
|
+
IssuesManager.IssueAggregator.Events.AGGREGATED_ISSUE_UPDATED, this.#issueUpdated, this);
|
|
222
|
+
this.#aggregator.addEventListener(
|
|
223
|
+
IssuesManager.IssueAggregator.Events.FULL_UPDATE_REQUIRED, this.#onFullUpdate, this);
|
|
228
224
|
this.#hiddenIssuesRow.hidden = this.#issuesManager.numberOfHiddenIssues() === 0;
|
|
229
225
|
this.#onFullUpdate();
|
|
230
226
|
this.#issuesManager.addEventListener(
|
|
@@ -292,16 +288,16 @@ export class IssuesPane extends UI.Widget.VBox {
|
|
|
292
288
|
return {toolbarContainer};
|
|
293
289
|
}
|
|
294
290
|
|
|
295
|
-
#issueUpdated(event: Common.EventTarget.EventTargetEvent<AggregatedIssue>): void {
|
|
291
|
+
#issueUpdated(event: Common.EventTarget.EventTargetEvent<IssuesManager.IssueAggregator.AggregatedIssue>): void {
|
|
296
292
|
this.#scheduleIssueViewUpdate(event.data);
|
|
297
293
|
}
|
|
298
294
|
|
|
299
|
-
#scheduleIssueViewUpdate(issue: AggregatedIssue): void {
|
|
295
|
+
#scheduleIssueViewUpdate(issue: IssuesManager.IssueAggregator.AggregatedIssue): void {
|
|
300
296
|
this.#issueViewUpdatePromise = this.#issueViewUpdatePromise.then(() => this.#updateIssueView(issue));
|
|
301
297
|
}
|
|
302
298
|
|
|
303
299
|
/** Don't call directly. Use `scheduleIssueViewUpdate` instead. */
|
|
304
|
-
async #updateIssueView(issue: AggregatedIssue): Promise<void> {
|
|
300
|
+
async #updateIssueView(issue: IssuesManager.IssueAggregator.AggregatedIssue): Promise<void> {
|
|
305
301
|
let issueView = this.#issueViews.get(issue.aggregationKey());
|
|
306
302
|
if (!issueView) {
|
|
307
303
|
const description = issue.getDescription();
|
|
@@ -361,7 +357,8 @@ export class IssuesPane extends UI.Widget.VBox {
|
|
|
361
357
|
}
|
|
362
358
|
}
|
|
363
359
|
|
|
364
|
-
#getIssueViewParent(issue: AggregatedIssue): UI.TreeOutline.TreeOutline
|
|
360
|
+
#getIssueViewParent(issue: IssuesManager.IssueAggregator.AggregatedIssue): UI.TreeOutline.TreeOutline
|
|
361
|
+
|UI.TreeOutline.TreeElement {
|
|
365
362
|
if (issue.isHidden()) {
|
|
366
363
|
return this.#hiddenIssuesRow;
|
|
367
364
|
}
|
|
@@ -2,13 +2,11 @@
|
|
|
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
4
|
|
|
5
|
-
import * as IssueAggregator from './IssueAggregator.js';
|
|
6
5
|
import * as IssueRevealer from './IssueRevealer.js';
|
|
7
6
|
import * as IssuesPane from './IssuesPane.js';
|
|
8
7
|
import * as IssueView from './IssueView.js';
|
|
9
8
|
|
|
10
9
|
export {
|
|
11
|
-
IssueAggregator,
|
|
12
10
|
IssueRevealer,
|
|
13
11
|
IssuesPane,
|
|
14
12
|
IssueView,
|
|
@@ -958,7 +958,7 @@ export class NetworkRequestNode extends NetworkNode {
|
|
|
958
958
|
return this.requestInternal.resourceType() === Common.ResourceType.resourceTypes.Prefetch;
|
|
959
959
|
}
|
|
960
960
|
|
|
961
|
-
throttlingConditions():
|
|
961
|
+
throttlingConditions(): SDK.NetworkManager.AppliedNetworkConditions|undefined {
|
|
962
962
|
return SDK.NetworkManager.MultitargetNetworkManager.instance().appliedRequestConditions(this.requestInternal);
|
|
963
963
|
}
|
|
964
964
|
|
|
@@ -1522,6 +1522,7 @@ export class NetworkRequestNode extends NetworkNode {
|
|
|
1522
1522
|
throttlingConditions.conditions.title();
|
|
1523
1523
|
const icon = IconButton.Icon.create('watch');
|
|
1524
1524
|
icon.title = i18nString(UIStrings.wasThrottled, {PH1: throttlingConditionsTitle});
|
|
1525
|
+
icon.addEventListener('click', () => void Common.Revealer.reveal(throttlingConditions));
|
|
1525
1526
|
cell.append(icon);
|
|
1526
1527
|
}
|
|
1527
1528
|
if (this.requestInternal.duration > 0) {
|
|
@@ -18,10 +18,12 @@ import * as UI from '../../ui/legacy/legacy.js';
|
|
|
18
18
|
import {Directives, html, type LitTemplate, nothing, render} from '../../ui/lit/lit.js';
|
|
19
19
|
import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
|
|
20
20
|
import * as MobileThrottling from '../mobile_throttling/mobile_throttling.js';
|
|
21
|
+
import * as PanelUtils from '../utils/utils.js';
|
|
21
22
|
|
|
22
23
|
import requestConditionsDrawerStyles from './requestConditionsDrawer.css.js';
|
|
23
24
|
|
|
24
25
|
const {ref} = Directives;
|
|
26
|
+
const {widgetConfig} = UI.Widget;
|
|
25
27
|
|
|
26
28
|
const UIStrings = {
|
|
27
29
|
/**
|
|
@@ -107,11 +109,11 @@ const UIStrings = {
|
|
|
107
109
|
/**
|
|
108
110
|
* @description Aria label on a button moving an entry up
|
|
109
111
|
*/
|
|
110
|
-
increasePriority: '
|
|
112
|
+
increasePriority: 'Move up (higher patterns are checked first)',
|
|
111
113
|
/**
|
|
112
114
|
* @description Aria label on a button moving an entry down
|
|
113
115
|
*/
|
|
114
|
-
decreasePriority: '
|
|
116
|
+
decreasePriority: 'Move down (higher patterns are checked first)',
|
|
115
117
|
} as const;
|
|
116
118
|
const str_ = i18n.i18n.registerUIStrings('panels/network/RequestConditionsDrawer.ts', UIStrings);
|
|
117
119
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
@@ -178,6 +180,109 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
|
178
180
|
target);
|
|
179
181
|
};
|
|
180
182
|
|
|
183
|
+
interface AffectedCountViewInput {
|
|
184
|
+
count: number;
|
|
185
|
+
}
|
|
186
|
+
type AffectedCountView = (input: AffectedCountViewInput, output: object, target: HTMLElement) => void;
|
|
187
|
+
export const AFFECTED_COUNT_DEFAULT_VIEW: AffectedCountView = (input, output, target) => {
|
|
188
|
+
if (Root.Runtime.hostConfig.devToolsIndividualRequestThrottling?.enabled) {
|
|
189
|
+
render(html`${i18nString(UIStrings.dAffected, {PH1: input.count})}`, target);
|
|
190
|
+
} else {
|
|
191
|
+
render(html`${i18nString(UIStrings.dBlocked, {PH1: input.count})}`, target);
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
function matchesUrl(conditions: SDK.NetworkManager.RequestCondition, url: string): boolean {
|
|
196
|
+
function matchesPattern(pattern: string, url: string): boolean {
|
|
197
|
+
let pos = 0;
|
|
198
|
+
const parts = pattern.split('*');
|
|
199
|
+
for (let index = 0; index < parts.length; index++) {
|
|
200
|
+
const part = parts[index];
|
|
201
|
+
if (!part.length) {
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
pos = url.indexOf(part, pos);
|
|
205
|
+
if (pos === -1) {
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
pos += part.length;
|
|
209
|
+
}
|
|
210
|
+
return true;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return Boolean(
|
|
214
|
+
Root.Runtime.hostConfig.devToolsIndividualRequestThrottling?.enabled ?
|
|
215
|
+
conditions.originalOrUpgradedURLPattern?.test(url) :
|
|
216
|
+
(conditions.wildcardURL && matchesPattern(conditions.wildcardURL, url)));
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export class AffectedCountWidget extends UI.Widget.Widget {
|
|
220
|
+
readonly #view: AffectedCountView;
|
|
221
|
+
#condition?: SDK.NetworkManager.RequestCondition;
|
|
222
|
+
#drawer?: RequestConditionsDrawer;
|
|
223
|
+
constructor(target?: HTMLElement, view = AFFECTED_COUNT_DEFAULT_VIEW) {
|
|
224
|
+
super(target, {classes: ['blocked-url-count']});
|
|
225
|
+
this.#view = view;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
get condition(): SDK.NetworkManager.RequestCondition|undefined {
|
|
229
|
+
return this.#condition;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
set condition(conditions: SDK.NetworkManager.RequestCondition) {
|
|
233
|
+
this.#condition = conditions;
|
|
234
|
+
this.requestUpdate();
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
get drawer(): RequestConditionsDrawer|undefined {
|
|
238
|
+
return this.#drawer;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
set drawer(drawer: RequestConditionsDrawer) {
|
|
242
|
+
this.#drawer = drawer;
|
|
243
|
+
this.requestUpdate();
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
override performUpdate(): void {
|
|
247
|
+
if (!this.#condition || !this.#drawer) {
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const count = !Root.Runtime.hostConfig.devToolsIndividualRequestThrottling?.enabled || this.#condition.isBlocking ?
|
|
252
|
+
this.#drawer.blockedRequestsCount(this.#condition) :
|
|
253
|
+
this.#drawer.throttledRequestsCount(this.#condition);
|
|
254
|
+
|
|
255
|
+
this.#view({count}, {}, this.element);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
override wasShown(): void {
|
|
259
|
+
SDK.TargetManager.TargetManager.instance().addModelListener(
|
|
260
|
+
SDK.NetworkManager.NetworkManager, SDK.NetworkManager.Events.RequestFinished, this.#onRequestFinished, this,
|
|
261
|
+
{scoped: true});
|
|
262
|
+
Logs.NetworkLog.NetworkLog.instance().addEventListener(Logs.NetworkLog.Events.Reset, this.requestUpdate, this);
|
|
263
|
+
super.wasShown();
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
override willHide(): void {
|
|
267
|
+
super.willHide();
|
|
268
|
+
SDK.TargetManager.TargetManager.instance().removeModelListener(
|
|
269
|
+
SDK.NetworkManager.NetworkManager, SDK.NetworkManager.Events.RequestFinished, this.#onRequestFinished, this);
|
|
270
|
+
Logs.NetworkLog.NetworkLog.instance().removeEventListener(Logs.NetworkLog.Events.Reset, this.requestUpdate, this);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
#onRequestFinished(event: Common.EventTarget.EventTargetEvent<SDK.NetworkRequest.NetworkRequest>): void {
|
|
274
|
+
if (!this.#condition) {
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const request = event.data;
|
|
279
|
+
if ((request.appliedNetworkConditionsId && this.#condition.ruleIds.has(request.appliedNetworkConditionsId)) ||
|
|
280
|
+
(request.wasBlocked() && matchesUrl(this.#condition, request.url()))) {
|
|
281
|
+
this.requestUpdate();
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
181
286
|
function learnMore(): LitTemplate {
|
|
182
287
|
return html`<x-link
|
|
183
288
|
href=${NETWORK_REQUEST_BLOCKING_EXPLANATION_URL}
|
|
@@ -196,6 +301,7 @@ export class RequestConditionsDrawer extends UI.Widget.VBox implements
|
|
|
196
301
|
private blockedCountForUrl: Map<Platform.DevToolsPath.UrlString, number>;
|
|
197
302
|
#throttledCount = new Map<string, number>();
|
|
198
303
|
#view: View;
|
|
304
|
+
#listElements = new WeakMap<SDK.NetworkManager.RequestCondition, HTMLElement>();
|
|
199
305
|
|
|
200
306
|
constructor(target?: HTMLElement, view = DEFAULT_VIEW) {
|
|
201
307
|
super(target, {
|
|
@@ -249,9 +355,8 @@ export class RequestConditionsDrawer extends UI.Widget.VBox implements
|
|
|
249
355
|
}
|
|
250
356
|
|
|
251
357
|
renderItem(condition: SDK.NetworkManager.RequestCondition, editable: boolean, index: number): Element {
|
|
252
|
-
const blockedCount = this.blockedRequestsCount(condition);
|
|
253
|
-
const throttledCount = this.#throttledRequestsCount(condition);
|
|
254
358
|
const element = document.createElement('div');
|
|
359
|
+
this.#listElements.set(condition, element);
|
|
255
360
|
element.classList.add('blocked-url');
|
|
256
361
|
const toggle = (e: Event): void => {
|
|
257
362
|
if (editable) {
|
|
@@ -338,20 +443,18 @@ export class RequestConditionsDrawer extends UI.Widget.VBox implements
|
|
|
338
443
|
aria-details=url-pattern-${index}>
|
|
339
444
|
${constructorStringOrWildcardURL}
|
|
340
445
|
</div>
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
<
|
|
353
|
-
? blockedCount
|
|
354
|
-
: throttledCount})}</div>`,
|
|
446
|
+
<devtools-widget
|
|
447
|
+
class=conditions-selector
|
|
448
|
+
?disabled=${!editable}
|
|
449
|
+
.widgetConfig=${UI.Widget.widgetConfig(
|
|
450
|
+
MobileThrottling.NetworkThrottlingSelector.NetworkThrottlingSelectorWidget, {
|
|
451
|
+
variant:
|
|
452
|
+
MobileThrottling.NetworkThrottlingSelector.NetworkThrottlingSelect.Variant.INDIVIDUAL_REQUEST_CONDITIONS,
|
|
453
|
+
jslogContext: 'request-conditions',
|
|
454
|
+
onConditionsChanged,
|
|
455
|
+
currentConditions: condition.conditions,
|
|
456
|
+
})}></devtools-widget>
|
|
457
|
+
<devtools-widget .widgetConfig=${widgetConfig(AffectedCountWidget, {condition, drawer: this})}></devtools-widget>`,
|
|
355
458
|
// clang-format on
|
|
356
459
|
element);
|
|
357
460
|
} else {
|
|
@@ -365,7 +468,7 @@ export class RequestConditionsDrawer extends UI.Widget.VBox implements
|
|
|
365
468
|
?disabled=${!editable}
|
|
366
469
|
.jslog=${VisualLogging.toggle().track({ change: true })}>
|
|
367
470
|
<div @click=${toggle} class=blocked-url-label>${wildcardURL}</div>
|
|
368
|
-
<
|
|
471
|
+
<devtools-widget .widgetConfig=${widgetConfig(AffectedCountWidget, {condition, drawer: this})}></devtools-widget>`,
|
|
369
472
|
// clang-format on
|
|
370
473
|
element);
|
|
371
474
|
}
|
|
@@ -461,20 +564,17 @@ export class RequestConditionsDrawer extends UI.Widget.VBox implements
|
|
|
461
564
|
this.requestUpdate();
|
|
462
565
|
}
|
|
463
566
|
|
|
464
|
-
|
|
567
|
+
blockedRequestsCount(condition: SDK.NetworkManager.RequestCondition): number {
|
|
465
568
|
let result = 0;
|
|
466
569
|
for (const blockedUrl of this.blockedCountForUrl.keys()) {
|
|
467
|
-
|
|
468
|
-
condition.originalOrUpgradedURLPattern?.test(blockedUrl) :
|
|
469
|
-
(condition.wildcardURL && this.matches(condition.wildcardURL, blockedUrl));
|
|
470
|
-
if (match) {
|
|
570
|
+
if (matchesUrl(condition, blockedUrl)) {
|
|
471
571
|
result += (this.blockedCountForUrl.get(blockedUrl) as number);
|
|
472
572
|
}
|
|
473
573
|
}
|
|
474
574
|
return result;
|
|
475
575
|
}
|
|
476
576
|
|
|
477
|
-
|
|
577
|
+
throttledRequestsCount(condition: SDK.NetworkManager.RequestCondition): number {
|
|
478
578
|
let result = 0;
|
|
479
579
|
for (const ruleId of condition.ruleIds) {
|
|
480
580
|
result += this.#throttledCount.get(ruleId) ?? 0;
|
|
@@ -482,27 +582,9 @@ export class RequestConditionsDrawer extends UI.Widget.VBox implements
|
|
|
482
582
|
return result;
|
|
483
583
|
}
|
|
484
584
|
|
|
485
|
-
private matches(pattern: string, url: string): boolean {
|
|
486
|
-
let pos = 0;
|
|
487
|
-
const parts = pattern.split('*');
|
|
488
|
-
for (let index = 0; index < parts.length; index++) {
|
|
489
|
-
const part = parts[index];
|
|
490
|
-
if (!part.length) {
|
|
491
|
-
continue;
|
|
492
|
-
}
|
|
493
|
-
pos = url.indexOf(part, pos);
|
|
494
|
-
if (pos === -1) {
|
|
495
|
-
return false;
|
|
496
|
-
}
|
|
497
|
-
pos += part.length;
|
|
498
|
-
}
|
|
499
|
-
return true;
|
|
500
|
-
}
|
|
501
|
-
|
|
502
585
|
private onNetworkLogReset(_event: Common.EventTarget.EventTargetEvent<Logs.NetworkLog.ResetEvent>): void {
|
|
503
586
|
this.blockedCountForUrl.clear();
|
|
504
587
|
this.#throttledCount.clear();
|
|
505
|
-
this.update();
|
|
506
588
|
}
|
|
507
589
|
|
|
508
590
|
private onRequestFinished(event: Common.EventTarget.EventTargetEvent<SDK.NetworkRequest.NetworkRequest>): void {
|
|
@@ -515,10 +597,8 @@ export class RequestConditionsDrawer extends UI.Widget.VBox implements
|
|
|
515
597
|
const count = this.blockedCountForUrl.get(request.url()) || 0;
|
|
516
598
|
this.blockedCountForUrl.set(request.url(), count + 1);
|
|
517
599
|
}
|
|
518
|
-
if (request.appliedNetworkConditionsId || request.wasBlocked()) {
|
|
519
|
-
this.update();
|
|
520
|
-
}
|
|
521
600
|
}
|
|
601
|
+
|
|
522
602
|
override wasShown(): void {
|
|
523
603
|
UI.Context.Context.instance().setFlavor(RequestConditionsDrawer, this);
|
|
524
604
|
super.wasShown();
|
|
@@ -528,6 +608,20 @@ export class RequestConditionsDrawer extends UI.Widget.VBox implements
|
|
|
528
608
|
super.willHide();
|
|
529
609
|
UI.Context.Context.instance().setFlavor(RequestConditionsDrawer, null);
|
|
530
610
|
}
|
|
611
|
+
|
|
612
|
+
static async reveal(appliedConditions: SDK.NetworkManager.AppliedNetworkConditions): Promise<void> {
|
|
613
|
+
await UI.ViewManager.ViewManager.instance().showView('network.blocked-urls');
|
|
614
|
+
const drawer = UI.Context.Context.instance().flavor(RequestConditionsDrawer);
|
|
615
|
+
if (!drawer) {
|
|
616
|
+
console.assert(!!drawer, 'Drawer not initialized');
|
|
617
|
+
return;
|
|
618
|
+
}
|
|
619
|
+
const conditions = drawer.manager.requestConditions.conditions.find(
|
|
620
|
+
condition => condition.ruleIds.has(appliedConditions.appliedNetworkConditionsId) &&
|
|
621
|
+
condition.constructorString && condition.constructorString === appliedConditions.urlPattern);
|
|
622
|
+
const element = (conditions && drawer.#listElements.get(conditions));
|
|
623
|
+
element && PanelUtils.PanelUtils.highlightElement(element);
|
|
624
|
+
}
|
|
531
625
|
}
|
|
532
626
|
|
|
533
627
|
export class ActionDelegate implements UI.ActionRegistration.ActionDelegate {
|
|
@@ -550,3 +644,12 @@ export class ActionDelegate implements UI.ActionRegistration.ActionDelegate {
|
|
|
550
644
|
return false;
|
|
551
645
|
}
|
|
552
646
|
}
|
|
647
|
+
|
|
648
|
+
export class AppliedConditionsRevealer implements
|
|
649
|
+
Common.Revealer.Revealer<SDK.NetworkManager.AppliedNetworkConditions> {
|
|
650
|
+
async reveal(request: SDK.NetworkManager.AppliedNetworkConditions): Promise<void> {
|
|
651
|
+
if (request.urlPattern) {
|
|
652
|
+
await RequestConditionsDrawer.reveal(request);
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
}
|
|
@@ -307,11 +307,16 @@ interface ViewInput {
|
|
|
307
307
|
serverTimings: SDK.ServerTiming.ServerTiming[];
|
|
308
308
|
fetchDetails?: UI.TreeOutline.TreeOutlineInShadow;
|
|
309
309
|
routerDetails?: UI.TreeOutline.TreeOutlineInShadow;
|
|
310
|
-
wasThrottled?: SDK.NetworkManager.
|
|
310
|
+
wasThrottled?: SDK.NetworkManager.AppliedNetworkConditions;
|
|
311
311
|
}
|
|
312
312
|
|
|
313
313
|
type View = (input: ViewInput, output: object, target: HTMLElement) => void;
|
|
314
314
|
export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
315
|
+
const revealThrottled = (): void => {
|
|
316
|
+
if (input.wasThrottled) {
|
|
317
|
+
void Common.Revealer.reveal(input.wasThrottled);
|
|
318
|
+
}
|
|
319
|
+
};
|
|
315
320
|
const scale = 100 / (input.endTime - input.startTime);
|
|
316
321
|
const isClickable = (range: NetworkTimeCalculator.RequestTimeRange): boolean =>
|
|
317
322
|
range.name === 'serviceworker-respondwith' || range.name === 'serviceworker-routerevaluation';
|
|
@@ -376,11 +381,11 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
|
376
381
|
}
|
|
377
382
|
};
|
|
378
383
|
|
|
379
|
-
const throttledRequestTitle = input.wasThrottled ?
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
+
const throttledRequestTitle = input.wasThrottled ? i18nString(UIStrings.wasThrottled, {
|
|
385
|
+
PH1: typeof input.wasThrottled.conditions.title === 'string' ? input.wasThrottled.conditions.title :
|
|
386
|
+
input.wasThrottled.conditions.title()
|
|
387
|
+
}) :
|
|
388
|
+
undefined;
|
|
384
389
|
|
|
385
390
|
const classes = classMap({
|
|
386
391
|
['network-timing-table']: true,
|
|
@@ -503,7 +508,7 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
|
503
508
|
</x-link>
|
|
504
509
|
<td></td>
|
|
505
510
|
<td class=${input.wasThrottled ? 'throttled' : ''} title=${ifDefined(throttledRequestTitle)}>
|
|
506
|
-
${input.wasThrottled ? html` <devtools-icon name=watch ></devtools-icon>` : nothing}
|
|
511
|
+
${input.wasThrottled ? html` <devtools-icon name=watch @click=${revealThrottled}></devtools-icon>` : nothing}
|
|
507
512
|
${i18n.TimeUtilities.secondsToString(input.totalDuration, true)}
|
|
508
513
|
</td>
|
|
509
514
|
</tr>
|
|
@@ -578,7 +583,7 @@ export class RequestTimingView extends UI.Widget.VBox {
|
|
|
578
583
|
requestUnfinished: false,
|
|
579
584
|
fetchDetails: this.#fetchDetailsTree(),
|
|
580
585
|
routerDetails: this.#routerDetailsTree(),
|
|
581
|
-
wasThrottled: conditions?.urlPattern ? conditions
|
|
586
|
+
wasThrottled: conditions?.urlPattern ? conditions : undefined,
|
|
582
587
|
timeRanges,
|
|
583
588
|
};
|
|
584
589
|
this.#view(input, {}, this.contentElement);
|
|
@@ -521,3 +521,14 @@ Common.Revealer.registerRevealer({
|
|
|
521
521
|
return new Network.NetworkPanel.NetworkLogWithFilterRevealer();
|
|
522
522
|
},
|
|
523
523
|
});
|
|
524
|
+
|
|
525
|
+
Common.Revealer.registerRevealer({
|
|
526
|
+
contextTypes() {
|
|
527
|
+
return [SDK.NetworkManager.AppliedNetworkConditions];
|
|
528
|
+
},
|
|
529
|
+
destination: Common.Revealer.RevealerDestination.NETWORK_PANEL,
|
|
530
|
+
async loadRevealer() {
|
|
531
|
+
const Network = await loadNetworkModule();
|
|
532
|
+
return new Network.RequestConditionsDrawer.AppliedConditionsRevealer();
|
|
533
|
+
},
|
|
534
|
+
});
|
|
@@ -2008,7 +2008,7 @@ class ValueDecoration extends CodeMirror.WidgetType {
|
|
|
2008
2008
|
} else {
|
|
2009
2009
|
const propertyValue = ObjectUI.ObjectPropertiesSection.ObjectPropertiesSection.createPropertyValue(
|
|
2010
2010
|
value, /* wasThrown */ false, /* showPreview */ false);
|
|
2011
|
-
nameValuePair.appendChild(propertyValue
|
|
2011
|
+
nameValuePair.appendChild(propertyValue);
|
|
2012
2012
|
}
|
|
2013
2013
|
}
|
|
2014
2014
|
return widget;
|
|
@@ -498,7 +498,7 @@ export class WatchExpression extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
|
498
498
|
const propertyValue =
|
|
499
499
|
ObjectUI.ObjectPropertiesSection.ObjectPropertiesSection.createPropertyValueWithCustomSupport(
|
|
500
500
|
expressionValue, Boolean(exceptionDetails), false /* showPreview */, this.linkifier);
|
|
501
|
-
this.valueElement = propertyValue
|
|
501
|
+
this.valueElement = propertyValue;
|
|
502
502
|
}
|
|
503
503
|
const separatorElement = document.createElement('span');
|
|
504
504
|
separatorElement.classList.add('watch-expressions-separator');
|
|
@@ -622,10 +622,10 @@ export class TimelineFlameChartView extends Common.ObjectWrapper.eventMixin<Even
|
|
|
622
622
|
}
|
|
623
623
|
|
|
624
624
|
const fieldMetricResultsByNavigationId = new Map<string, Trace.Insights.Common.CrUXFieldMetricResults|null>();
|
|
625
|
-
for (const
|
|
626
|
-
if (insightSet.navigation) {
|
|
625
|
+
for (const insightSet of insights.values()) {
|
|
626
|
+
if (insightSet.navigation?.args.data?.navigationId) {
|
|
627
627
|
fieldMetricResultsByNavigationId.set(
|
|
628
|
-
|
|
628
|
+
insightSet.navigation.args.data.navigationId,
|
|
629
629
|
Trace.Insights.Common.getFieldMetricsForInsightSet(
|
|
630
630
|
insightSet, metadata, CrUXManager.CrUXManager.instance().getSelectedScope()));
|
|
631
631
|
}
|
|
@@ -3094,15 +3094,15 @@ export class TimelinePanel extends Common.ObjectWrapper.eventMixin<EventTypes, t
|
|
|
3094
3094
|
};
|
|
3095
3095
|
}
|
|
3096
3096
|
|
|
3097
|
-
const
|
|
3098
|
-
if (!
|
|
3097
|
+
const insightSetId = Array.from(parsedTrace.insights.keys()).find(k => k !== 'NO_NAVIGATION');
|
|
3098
|
+
if (!insightSetId) {
|
|
3099
3099
|
return {
|
|
3100
3100
|
type: AiAssistanceModel.AiAgent.ExternalRequestResponseType.ERROR,
|
|
3101
3101
|
message: 'The trace was loaded successfully but no navigation was detected.',
|
|
3102
3102
|
};
|
|
3103
3103
|
}
|
|
3104
3104
|
|
|
3105
|
-
const insightsForNav = parsedTrace.insights.get(
|
|
3105
|
+
const insightsForNav = parsedTrace.insights.get(insightSetId);
|
|
3106
3106
|
if (!insightsForNav) {
|
|
3107
3107
|
return {
|
|
3108
3108
|
type: AiAssistanceModel.AiAgent.ExternalRequestResponseType.ERROR,
|