chrome-devtools-frontend 1.0.1724140 → 1.0.1726686
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/.agents/skills/review-ui-widgets/SKILL.md +7 -7
- package/.agents/skills/ui-eng-vision-local-lit-renderer/SKILL.md +12 -0
- package/.agents/skills/ui-eng-vision-widget-promoter/SKILL.md +3 -3
- package/.agents/skills/ui-widgets/SKILL.md +2 -1
- package/docs/cookbook/dependencies.md +6 -4
- package/front_end/core/i18n/i18nImpl.ts +1 -1
- package/front_end/core/root/Runtime.ts +1 -1
- package/front_end/core/sdk/ResourceTreeModel.ts +16 -0
- package/front_end/entrypoints/js_app/js_app.ts +2 -5
- package/front_end/entrypoints/node_app/node_app.ts +2 -3
- package/front_end/generated/InspectorBackendCommands.ts +1 -1
- package/front_end/generated/protocol.ts +1 -0
- package/front_end/models/ai_assistance/skills/lighthouse.md +2 -1
- package/front_end/models/ai_assistance/skills/network.md +1 -0
- package/front_end/models/ai_assistance/tools/ExecuteJavaScript.ts +26 -2
- package/front_end/models/ai_assistance/tools/GetLighthouseAudits.ts +1 -1
- package/front_end/models/ai_assistance/tools/ListNetworkRequests.ts +2 -7
- package/front_end/models/ai_assistance/tools/RunLighthouse.ts +2 -2
- package/front_end/models/comment_manager/CommentManager.ts +0 -6
- package/front_end/models/comment_manager/CommentThread.ts +23 -19
- package/front_end/models/elements/StyleChanges.ts +66 -0
- package/front_end/models/trace/EventsSerializer.ts +2 -7
- package/front_end/models/trace/ModelImpl.ts +0 -2
- package/front_end/models/trace/handlers/FlowsHandler.ts +37 -29
- package/front_end/models/trace/helpers/SyntheticEvents.ts +10 -37
- package/front_end/models/trace/insights/RenderBlocking.ts +3 -1
- package/front_end/models/trace/lantern/simulation/Simulator.ts +4 -0
- package/front_end/models/trace/lantern/types/Lantern.ts +1 -0
- package/front_end/panels/accessibility/SourceOrderView.ts +1 -1
- package/front_end/panels/application/ApplicationPanelSidebar.ts +90 -0
- package/front_end/panels/application/StorageView.ts +196 -174
- package/front_end/panels/application/SubAppsView.ts +2 -2
- package/front_end/panels/application/preloading/PreloadingView.ts +360 -336
- package/front_end/panels/application/preloading/components/PreloadingDisabledInfobar.ts +2 -2
- package/front_end/panels/application/preloading/components/PreloadingGrid.ts +6 -3
- package/front_end/panels/application/preloading/components/RuleSetGrid.ts +17 -17
- package/front_end/panels/application/preloading/components/UsedPreloadingView.ts +2 -2
- package/front_end/panels/application/preloading/preloadingView.css +12 -4
- package/front_end/panels/application/preloading/preloadingViewDropDown.css +1 -1
- package/front_end/panels/application/storageView.css +16 -21
- package/front_end/panels/browser_debugger/CategorizedBreakpointsSidebarPane.ts +2 -2
- package/front_end/panels/browser_debugger/browser_debugger-meta.ts +6 -8
- package/front_end/panels/comments/CommentsPane.ts +26 -9
- package/front_end/panels/comments/commentsPane.css +25 -6
- package/front_end/panels/common/CommentThreadWidget.ts +2 -2
- package/front_end/panels/common/CommentsOverlayWidget.ts +94 -35
- package/front_end/panels/common/commentThreadWidget.css +17 -0
- package/front_end/panels/common/commentsOverlay.css +5 -10
- package/front_end/panels/common/common-meta.ts +11 -1
- package/front_end/panels/elements/ClassesPaneWidget.ts +130 -88
- package/front_end/panels/elements/ColorSwatchPopoverIcon.ts +7 -33
- package/front_end/panels/elements/DOMTreeWidget.ts +7 -3
- package/front_end/panels/elements/ElementStatePaneWidget.ts +11 -1
- package/front_end/panels/elements/PropertyRenderer.ts +3 -2
- package/front_end/panels/elements/StyleEditorWidget.ts +60 -41
- package/front_end/panels/elements/StylePropertiesSection.ts +32 -5
- package/front_end/panels/elements/StylePropertyTreeElement.ts +227 -162
- package/front_end/panels/event_listeners/EventListenersView.ts +11 -8
- package/front_end/panels/linear_memory_inspector/components/ValueInterpreterSettings.ts +1 -1
- package/front_end/panels/network/NetworkDataGridNode.ts +3 -1
- package/front_end/panels/network/RequestConditionsDrawer.ts +1 -1
- package/front_end/panels/network/RequestPayloadView.ts +12 -5
- package/front_end/panels/profiler/HeapProfileView.ts +28 -6
- package/front_end/panels/profiler/HeapSnapshotDataGrids.ts +7 -3
- package/front_end/panels/protocol_monitor/JSONEditor.ts +0 -1
- package/front_end/panels/recorder/RecorderPanel.ts +2 -2
- package/front_end/panels/settings/SettingsScreen.ts +1 -1
- package/front_end/panels/sources/NavigatorView.ts +105 -45
- package/front_end/panels/sources/ScopeChainSidebarPane.ts +8 -5
- package/front_end/panels/sources/SourcesNavigator.ts +421 -213
- package/front_end/panels/sources/SourcesPanel.ts +6 -4
- package/front_end/panels/sources/WatchExpressionsSidebarPane.ts +10 -5
- package/front_end/panels/sources/sources-meta.ts +4 -15
- package/front_end/panels/sources/sourcesNavigator.css +5 -0
- package/front_end/panels/timeline/ModificationsManager.ts +0 -2
- package/front_end/panels/timeline/README.md +2 -0
- package/front_end/panels/timeline/TimelineCommentController.ts +132 -30
- package/front_end/panels/timeline/TimelinePanel.ts +4 -0
- package/front_end/panels/timeline/components/IgnoreListSetting.ts +1 -1
- package/front_end/panels/timeline/utils/Treemap.ts +8 -0
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/ui/comments/CommentAnchorResolver.ts +3 -0
- package/front_end/ui/comments/CommentOverlayManager.ts +2 -4
- package/front_end/ui/components/lists/List.ts +14 -1
- package/front_end/ui/components/panel_feedback/PreviewToggle.ts +1 -1
- package/front_end/ui/components/text_editor/AiCodeCompletionProvider.ts +23 -14
- package/front_end/ui/components/text_editor/AiCodeGenerationProvider.ts +3 -0
- package/front_end/ui/legacy/Toolbar.ts +0 -1
- package/front_end/ui/legacy/Treeoutline.ts +7 -2
- package/front_end/ui/legacy/UIUtils.ts +4 -1
- package/front_end/ui/legacy/components/inline_editor/Swatches.ts +19 -6
- package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +20 -11
- package/front_end/ui/legacy/components/source_frame/XMLView.ts +27 -7
- package/front_end/ui/visual_logging/KnownContextValues.ts +1 -0
- package/package.json +1 -1
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
// Copyright 2022 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
|
-
/* eslint-disable @devtools/no-imperative-dom-api */
|
|
5
|
-
/* eslint-disable @devtools/no-lit-render-outside-of-view */
|
|
6
4
|
|
|
7
5
|
import '../../../ui/kit/kit.js';
|
|
8
6
|
import '../../../ui/legacy/legacy.js';
|
|
@@ -26,8 +24,8 @@ import * as PreloadingHelper from './helper/helper.js';
|
|
|
26
24
|
import preloadingViewStyles from './preloadingView.css.js';
|
|
27
25
|
import preloadingViewDropDownStyles from './preloadingViewDropDown.css.js';
|
|
28
26
|
|
|
29
|
-
const {
|
|
30
|
-
const {widget} = UI.Widget;
|
|
27
|
+
const {live} = Directives;
|
|
28
|
+
const {widget, widgetRef} = UI.Widget;
|
|
31
29
|
|
|
32
30
|
const UIStrings = {
|
|
33
31
|
/**
|
|
@@ -102,6 +100,10 @@ const UIStrings = {
|
|
|
102
100
|
* @description Link text to learn more about speculation rules.
|
|
103
101
|
*/
|
|
104
102
|
learnMore: 'Learn more',
|
|
103
|
+
/**
|
|
104
|
+
* @description Tooltip text for the button to clear speculative loads.
|
|
105
|
+
*/
|
|
106
|
+
clearSpeculativeLoads: 'Clear speculative loads',
|
|
105
107
|
} as const;
|
|
106
108
|
const str_ = i18n.i18n.registerUIStrings('panels/application/preloading/PreloadingView.ts', UIStrings);
|
|
107
109
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
@@ -189,69 +191,29 @@ class PreloadingUIUtils {
|
|
|
189
191
|
}
|
|
190
192
|
|
|
191
193
|
function pageURL(): Platform.DevToolsPath.UrlString {
|
|
192
|
-
return SDK.TargetManager.TargetManager.instance().scopeTarget()?.inspectedURL()
|
|
193
|
-
|
|
194
|
+
return SDK.TargetManager.TargetManager.instance().scopeTarget()?.inspectedURL() ??
|
|
195
|
+
Platform.DevToolsPath.EmptyUrlString;
|
|
194
196
|
}
|
|
195
197
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
private readonly ruleSetDetailsRef:
|
|
206
|
-
Directives.Ref<UI.Widget.WidgetElement<PreloadingComponents.RuleSetDetailsView.RuleSetDetailsView>>;
|
|
207
|
-
|
|
208
|
-
private shouldPrettyPrint = Common.Settings.Settings.instance()
|
|
209
|
-
.resolve(SettingsUI.SourcesSettings.autoPrettyPrintMinifiedSettingDescriptor)
|
|
210
|
-
.get();
|
|
211
|
-
|
|
212
|
-
constructor(model: SDK.PreloadingModel.PreloadingModel) {
|
|
213
|
-
super({useShadowDom: true});
|
|
214
|
-
this.registerRequiredCSS(emptyWidgetStyles, preloadingViewStyles);
|
|
198
|
+
interface RuleSetViewInput {
|
|
199
|
+
warnings?: Protocol.Preload.PreloadEnabledStateUpdatedEvent;
|
|
200
|
+
rows: PreloadingComponents.RuleSetGrid.RuleSetGridRow[];
|
|
201
|
+
pageURL: Platform.DevToolsPath.UrlString;
|
|
202
|
+
ruleSet: Protocol.Preload.RuleSet|null;
|
|
203
|
+
shouldPrettyPrint: boolean;
|
|
204
|
+
onRuleSetSelected: (id: Protocol.Preload.RuleSetId) => void;
|
|
205
|
+
onPrettyPrintToggle: () => void;
|
|
206
|
+
}
|
|
215
207
|
|
|
216
|
-
|
|
217
|
-
SDK.TargetManager.TargetManager.instance().addScopeChangeListener(this.onScopeChange.bind(this));
|
|
218
|
-
SDK.TargetManager.TargetManager.instance().addModelListener(
|
|
219
|
-
SDK.PreloadingModel.PreloadingModel, SDK.PreloadingModel.Events.MODEL_UPDATED, this.render, this,
|
|
220
|
-
{scoped: true});
|
|
221
|
-
SDK.TargetManager.TargetManager.instance().addModelListener(
|
|
222
|
-
SDK.PreloadingModel.PreloadingModel, SDK.PreloadingModel.Events.WARNINGS_UPDATED, e => {
|
|
223
|
-
Object.assign(this.warningsView, e.data);
|
|
224
|
-
}, this, {scoped: true});
|
|
225
|
-
|
|
226
|
-
// this (VBox)
|
|
227
|
-
// +- warningsContainer
|
|
228
|
-
// +- PreloadingWarningsView
|
|
229
|
-
// +- hsplit
|
|
230
|
-
// +- leftContainer
|
|
231
|
-
// +- RuleSetGrid
|
|
232
|
-
// +- rightContainer
|
|
233
|
-
// +- RuleSetDetailsView
|
|
234
|
-
//
|
|
235
|
-
// - If an row of RuleSetGrid selected, RuleSetDetailsView shows details of it.
|
|
236
|
-
// - If not, RuleSetDetailsView hides.
|
|
237
|
-
|
|
238
|
-
this.warningsContainer = document.createElement('div');
|
|
239
|
-
this.warningsContainer.classList.add('flex-none');
|
|
240
|
-
this.contentElement.insertBefore(this.warningsContainer, this.contentElement.firstChild);
|
|
241
|
-
this.warningsView.show(this.warningsContainer);
|
|
242
|
-
|
|
243
|
-
this.ruleSetGrid.addEventListener(
|
|
244
|
-
PreloadingComponents.RuleSetGrid.Events.SELECT, this.onRuleSetsGridCellFocused, this);
|
|
245
|
-
this.ruleSetDetailsRef =
|
|
246
|
-
createRef<UI.Widget.WidgetElement<PreloadingComponents.RuleSetDetailsView.RuleSetDetailsView>>();
|
|
247
|
-
const onPrettyPrintToggle = (): void => {
|
|
248
|
-
this.shouldPrettyPrint = !this.shouldPrettyPrint;
|
|
249
|
-
this.updateRuleSetDetails();
|
|
250
|
-
};
|
|
208
|
+
type RuleSetView = (input: RuleSetViewInput, output: undefined, target: HTMLElement) => void;
|
|
251
209
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
210
|
+
const RULE_SET_DEFAULT_VIEW: RuleSetView = (input, _output, target) => {
|
|
211
|
+
// clang-format off
|
|
212
|
+
render(
|
|
213
|
+
html`
|
|
214
|
+
<style>${emptyWidgetStyles}</style>
|
|
215
|
+
<style>${preloadingViewStyles}</style>
|
|
216
|
+
${widget(PreloadingComponents.PreloadingDisabledInfobar.PreloadingDisabledInfobar, input.warnings)}
|
|
255
217
|
<div class="empty-state">
|
|
256
218
|
<span class="empty-state-header">${i18nString(UIStrings.noRulesDetected)}</span>
|
|
257
219
|
<div class="empty-state-description">
|
|
@@ -263,66 +225,89 @@ export class PreloadingRuleSetView extends UI.Widget.VBox {
|
|
|
263
225
|
>${i18nString(UIStrings.learnMore)}</devtools-link>
|
|
264
226
|
</div>
|
|
265
227
|
</div>
|
|
266
|
-
<devtools-split-view sidebar-position="second">
|
|
267
|
-
<div slot="main"
|
|
228
|
+
<devtools-split-view sidebar-position="second" show=${input.ruleSet === null ? 'main' : 'both'}>
|
|
229
|
+
<div slot="main">
|
|
230
|
+
${widget(PreloadingComponents.RuleSetGrid.RuleSetGrid, {
|
|
231
|
+
data: {rows: input.rows, pageURL: input.pageURL},
|
|
232
|
+
onSelect: input.onRuleSetSelected,
|
|
233
|
+
})}
|
|
268
234
|
</div>
|
|
269
235
|
<div slot="sidebar" jslog=${VisualLogging.section('rule-set-details')}>
|
|
270
|
-
|
|
271
|
-
ruleSet:
|
|
272
|
-
shouldPrettyPrint:
|
|
273
|
-
})}
|
|
236
|
+
${widget(PreloadingComponents.RuleSetDetailsView.RuleSetDetailsView, {
|
|
237
|
+
ruleSet: input.ruleSet,
|
|
238
|
+
shouldPrettyPrint: input.shouldPrettyPrint,
|
|
239
|
+
})}
|
|
274
240
|
</div>
|
|
275
241
|
</devtools-split-view>
|
|
276
|
-
<div class="pretty-print-button"
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
242
|
+
<div class="pretty-print-button">
|
|
243
|
+
<devtools-button
|
|
244
|
+
.iconName=${'brackets'}
|
|
245
|
+
.toggledIconName=${'brackets'}
|
|
246
|
+
.toggled=${input.shouldPrettyPrint}
|
|
247
|
+
.toggleType=${Buttons.Button.ToggleType.PRIMARY}
|
|
248
|
+
.title=${i18nString(UIStrings.prettyPrint)}
|
|
249
|
+
.variant=${Buttons.Button.Variant.ICON_TOGGLE}
|
|
250
|
+
.size=${Buttons.Button.Size.REGULAR}
|
|
251
|
+
.jslogContext=${'preloading-status-panel-pretty-print'}
|
|
252
|
+
@click=${input.onPrettyPrintToggle}>
|
|
253
|
+
</devtools-button>
|
|
254
|
+
</div>
|
|
255
|
+
`,
|
|
256
|
+
target, {container: {classes: input.rows.length === 0 ? ['empty'] : []}});
|
|
257
|
+
// clang-format on
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
export class PreloadingRuleSetView extends UI.Widget.VBox {
|
|
261
|
+
private model: SDK.PreloadingModel.PreloadingModel;
|
|
262
|
+
private focusedRuleSetId: Protocol.Preload.RuleSetId|null = null;
|
|
263
|
+
readonly #view: RuleSetView;
|
|
264
|
+
#warnings?: Protocol.Preload.PreloadEnabledStateUpdatedEvent;
|
|
265
|
+
|
|
266
|
+
private shouldPrettyPrint = Common.Settings.Settings.instance()
|
|
267
|
+
.resolve(SettingsUI.SourcesSettings.autoPrettyPrintMinifiedSettingDescriptor)
|
|
268
|
+
.get();
|
|
269
|
+
|
|
270
|
+
readonly #onRuleSetSelected = (id: Protocol.Preload.RuleSetId): void => {
|
|
271
|
+
this.focusedRuleSetId = id;
|
|
272
|
+
this.requestUpdate();
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
readonly #onPrettyPrintToggle = (): void => {
|
|
276
|
+
this.shouldPrettyPrint = !this.shouldPrettyPrint;
|
|
277
|
+
this.requestUpdate();
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
constructor(model: SDK.PreloadingModel.PreloadingModel, view: RuleSetView = RULE_SET_DEFAULT_VIEW) {
|
|
281
|
+
super({useShadowDom: true});
|
|
282
|
+
this.#view = view;
|
|
283
|
+
|
|
284
|
+
this.model = model;
|
|
285
|
+
SDK.TargetManager.TargetManager.instance().addScopeChangeListener(this.onScopeChange.bind(this));
|
|
286
|
+
SDK.TargetManager.TargetManager.instance().addModelListener(SDK.PreloadingModel.PreloadingModel,
|
|
287
|
+
SDK.PreloadingModel.Events.MODEL_UPDATED,
|
|
288
|
+
this.requestUpdate, this, {scoped: true});
|
|
289
|
+
SDK.TargetManager.TargetManager.instance().addModelListener(SDK.PreloadingModel.PreloadingModel,
|
|
290
|
+
SDK.PreloadingModel.Events.WARNINGS_UPDATED, e => {
|
|
291
|
+
this.#warnings = e.data;
|
|
292
|
+
this.requestUpdate();
|
|
293
|
+
}, this, {scoped: true});
|
|
291
294
|
}
|
|
292
295
|
|
|
293
296
|
override wasShown(): void {
|
|
294
297
|
super.wasShown();
|
|
295
|
-
|
|
296
|
-
this.warningsView.wasShown();
|
|
297
|
-
|
|
298
|
-
this.render();
|
|
298
|
+
this.requestUpdate();
|
|
299
299
|
}
|
|
300
300
|
|
|
301
301
|
onScopeChange(): void {
|
|
302
302
|
const model = SDK.TargetManager.TargetManager.instance().scopeTarget()?.model(SDK.PreloadingModel.PreloadingModel);
|
|
303
303
|
assertNotNullOrUndefined(model);
|
|
304
304
|
this.model = model;
|
|
305
|
-
this.
|
|
305
|
+
this.requestUpdate();
|
|
306
306
|
}
|
|
307
307
|
|
|
308
308
|
revealRuleSet(revealInfo: PreloadingHelper.PreloadingForward.RuleSetView): void {
|
|
309
309
|
this.focusedRuleSetId = revealInfo.ruleSetId;
|
|
310
|
-
this.
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
private updateRuleSetDetails(): void {
|
|
314
|
-
const ruleSet = this.getRuleSet();
|
|
315
|
-
const widget = this.ruleSetDetailsRef.value?.getWidget();
|
|
316
|
-
if (widget) {
|
|
317
|
-
widget.shouldPrettyPrint = this.shouldPrettyPrint;
|
|
318
|
-
widget.ruleSet = ruleSet;
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
if (ruleSet === null) {
|
|
322
|
-
this.hsplit.setAttribute('show', 'main');
|
|
323
|
-
} else {
|
|
324
|
-
this.hsplit.setAttribute('show', 'both');
|
|
325
|
-
}
|
|
310
|
+
this.requestUpdate();
|
|
326
311
|
}
|
|
327
312
|
|
|
328
313
|
private getRuleSet(): Protocol.Preload.RuleSet|null {
|
|
@@ -330,37 +315,25 @@ export class PreloadingRuleSetView extends UI.Widget.VBox {
|
|
|
330
315
|
return id === null ? null : this.model.getRuleSetById(id);
|
|
331
316
|
}
|
|
332
317
|
|
|
333
|
-
|
|
334
|
-
// Update rule sets grid
|
|
318
|
+
override performUpdate(): void {
|
|
335
319
|
const countsByRuleSetId = this.model.getPreloadCountsByRuleSetId();
|
|
336
|
-
const
|
|
320
|
+
const rows = this.model.getAllRuleSets().map(({id, value}) => {
|
|
337
321
|
const countsByStatus = countsByRuleSetId.get(id) || new Map<SDK.PreloadingModel.PreloadingStatus, number>();
|
|
338
322
|
return {
|
|
339
323
|
ruleSet: value,
|
|
340
324
|
preloadsStatusSummary: PreloadingUIUtils.preloadsStatusSummary(countsByStatus),
|
|
341
325
|
};
|
|
342
326
|
});
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
this
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
private onRuleSetsGridCellFocused(event: Common.EventTarget.EventTargetEvent<Protocol.Preload.RuleSetId>): void {
|
|
354
|
-
this.focusedRuleSetId = event.data;
|
|
355
|
-
this.render();
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
getInfobarContainerForTest(): HTMLElement {
|
|
359
|
-
return this.warningsView.contentElement;
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
getRuleSetGridForTest(): PreloadingComponents.RuleSetGrid.RuleSetGrid {
|
|
363
|
-
return this.ruleSetGrid;
|
|
327
|
+
const input: RuleSetViewInput = {
|
|
328
|
+
warnings: this.#warnings,
|
|
329
|
+
rows,
|
|
330
|
+
pageURL: pageURL(),
|
|
331
|
+
ruleSet: this.getRuleSet(),
|
|
332
|
+
shouldPrettyPrint: this.shouldPrettyPrint,
|
|
333
|
+
onRuleSetSelected: this.#onRuleSetSelected,
|
|
334
|
+
onPrettyPrintToggle: this.#onPrettyPrintToggle,
|
|
335
|
+
};
|
|
336
|
+
this.#view(input, /* output= */ undefined, this.contentElement);
|
|
364
337
|
}
|
|
365
338
|
}
|
|
366
339
|
|
|
@@ -440,118 +413,175 @@ export function applyFilterText(filterText: string, rows: PreloadingComponents.P
|
|
|
440
413
|
});
|
|
441
414
|
}
|
|
442
415
|
|
|
416
|
+
interface PreloadingWarnings {
|
|
417
|
+
disabledByPreference: boolean;
|
|
418
|
+
disabledByDataSaver: boolean;
|
|
419
|
+
disabledByBatterySaver: boolean;
|
|
420
|
+
disabledByHoldbackPrefetchSpeculationRules: boolean;
|
|
421
|
+
disabledByHoldbackPrerenderSpeculationRules: boolean;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
interface AttemptViewInput {
|
|
425
|
+
warnings?: PreloadingWarnings;
|
|
426
|
+
rows: PreloadingComponents.PreloadingGrid.PreloadingGridRow[];
|
|
427
|
+
isEmpty: boolean;
|
|
428
|
+
pageURL: Platform.DevToolsPath.UrlString;
|
|
429
|
+
details: PreloadingComponents.PreloadingDetailsReportView.PreloadingDetailsReportViewData;
|
|
430
|
+
ruleSetSelectorToolbarItem: UI.Toolbar.ToolbarItem;
|
|
431
|
+
filterText: string;
|
|
432
|
+
onFilterChanged: (filterText: string) => void;
|
|
433
|
+
onClear: () => void;
|
|
434
|
+
onAttemptSelected: ({rowId}: {rowId: string}) => void;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
interface AttemptViewOutput {
|
|
438
|
+
doSplitWidgetLayout?: () => void;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
type AttemptView = (input: AttemptViewInput, output: AttemptViewOutput, target: HTMLElement) => void;
|
|
442
|
+
|
|
443
|
+
const ATTEMPT_DEFAULT_VIEW: AttemptView = (input, output, target) => {
|
|
444
|
+
// clang-format off
|
|
445
|
+
render(
|
|
446
|
+
html`
|
|
447
|
+
<style>${emptyWidgetStyles}</style>
|
|
448
|
+
<style>${preloadingViewStyles}</style>
|
|
449
|
+
${widget(PreloadingComponents.PreloadingDisabledInfobar.PreloadingDisabledInfobar, input.warnings)}
|
|
450
|
+
<devtools-toolbar class="preloading-toolbar" jslog=${VisualLogging.toolbar()}>
|
|
451
|
+
${input.ruleSetSelectorToolbarItem.element}
|
|
452
|
+
<devtools-toolbar-input
|
|
453
|
+
type="filter"
|
|
454
|
+
.value=${live(input.filterText)}
|
|
455
|
+
@change=${(e: CustomEvent<string>) => input.onFilterChanged(e.detail)}>
|
|
456
|
+
</devtools-toolbar-input>
|
|
457
|
+
<div class="toolbar-divider"></div>
|
|
458
|
+
<devtools-button
|
|
459
|
+
title=${i18nString(UIStrings.clearSpeculativeLoads)}
|
|
460
|
+
aria-label=${i18nString(UIStrings.clearSpeculativeLoads)}
|
|
461
|
+
.iconName=${'clear'}
|
|
462
|
+
.variant=${Buttons.Button.Variant.TOOLBAR}
|
|
463
|
+
.jslogContext=${'clear-speculative-loads'}
|
|
464
|
+
@click=${input.onClear}>
|
|
465
|
+
</devtools-button>
|
|
466
|
+
</devtools-toolbar>
|
|
467
|
+
<div class="empty-state">
|
|
468
|
+
<span class="empty-state-header">${i18nString(UIStrings.noPrefetchAttempts)}</span>
|
|
469
|
+
<div class="empty-state-description">
|
|
470
|
+
<span>${i18nString(UIStrings.prefetchDescription)}</span>
|
|
471
|
+
<devtools-link
|
|
472
|
+
class="devtools-link"
|
|
473
|
+
href=${SPECULATION_EXPLANATION_URL}
|
|
474
|
+
jslogcontext="learn-more"
|
|
475
|
+
>${i18nString(UIStrings.learnMore)}</devtools-link>
|
|
476
|
+
</div>
|
|
477
|
+
</div>
|
|
478
|
+
<devtools-split-view sidebar-position="second" ${
|
|
479
|
+
widgetRef(
|
|
480
|
+
UI.SplitWidget.SplitWidget,
|
|
481
|
+
w => {
|
|
482
|
+
output.doSplitWidgetLayout = () => w.doLayout();
|
|
483
|
+
})}>
|
|
484
|
+
<div slot="main" class="overflow-auto">
|
|
485
|
+
${widget(PreloadingComponents.PreloadingGrid.PreloadingGrid, {
|
|
486
|
+
rows: input.rows,
|
|
487
|
+
pageURL: input.pageURL,
|
|
488
|
+
onSelect: input.onAttemptSelected,
|
|
489
|
+
})}
|
|
490
|
+
</div>
|
|
491
|
+
<div slot="sidebar" class="overflow-auto">
|
|
492
|
+
${widget(PreloadingComponents.PreloadingDetailsReportView.PreloadingDetailsReportView, {
|
|
493
|
+
data: input.details,
|
|
494
|
+
})}
|
|
495
|
+
</div>
|
|
496
|
+
</devtools-split-view>
|
|
497
|
+
`,
|
|
498
|
+
target, {container: {classes: input.isEmpty ? ['empty'] : []}});
|
|
499
|
+
// clang-format on
|
|
500
|
+
};
|
|
501
|
+
|
|
443
502
|
export class PreloadingAttemptView extends UI.Widget.VBox {
|
|
444
503
|
private model: SDK.PreloadingModel.PreloadingModel;
|
|
445
504
|
// Note that we use id of (representative) preloading attempt while we show pipelines in grid.
|
|
446
505
|
// This is because `NOT_TRIGGERED` preloading attempts don't have pipeline id and we can use it.
|
|
447
506
|
private focusedPreloadingAttemptId: SDK.PreloadingModel.PreloadingAttemptId|null = null;
|
|
507
|
+
readonly #view: AttemptView;
|
|
508
|
+
readonly #viewOutput: AttemptViewOutput = {};
|
|
509
|
+
readonly #ruleSetSelector: PreloadingRuleSetSelector;
|
|
510
|
+
#warnings?: PreloadingWarnings;
|
|
511
|
+
#filterText = '';
|
|
512
|
+
|
|
513
|
+
readonly #onFilterChanged = (filterText: string): void => {
|
|
514
|
+
this.#filterText = filterText;
|
|
515
|
+
this.requestUpdate();
|
|
516
|
+
};
|
|
517
|
+
|
|
518
|
+
readonly #onClear = (): void => {
|
|
519
|
+
const model = SDK.TargetManager.TargetManager.instance().scopeTarget()?.model(SDK.PreloadingModel.PreloadingModel);
|
|
520
|
+
if (!model) {
|
|
521
|
+
return;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
model.reset();
|
|
525
|
+
this.#filterText = '';
|
|
526
|
+
this.#ruleSetSelector.select(null);
|
|
527
|
+
this.requestUpdate();
|
|
528
|
+
};
|
|
529
|
+
|
|
530
|
+
readonly #onAttemptSelected = ({rowId}: {rowId: string}): void => {
|
|
531
|
+
this.focusedPreloadingAttemptId = rowId;
|
|
532
|
+
this.requestUpdate();
|
|
533
|
+
};
|
|
534
|
+
|
|
535
|
+
readonly #onWarningsUpdated =
|
|
536
|
+
(event: Common.EventTarget.EventTargetEvent<Protocol.Preload.PreloadEnabledStateUpdatedEvent>): void => {
|
|
537
|
+
this.#warnings = {
|
|
538
|
+
disabledByPreference: event.data.disabledByPreference,
|
|
539
|
+
disabledByDataSaver: event.data.disabledByDataSaver,
|
|
540
|
+
disabledByBatterySaver: event.data.disabledByBatterySaver,
|
|
541
|
+
disabledByHoldbackPrefetchSpeculationRules: event.data.disabledByHoldbackPrefetchSpeculationRules,
|
|
542
|
+
disabledByHoldbackPrerenderSpeculationRules: event.data.disabledByHoldbackPrerenderSpeculationRules,
|
|
543
|
+
};
|
|
544
|
+
this.requestUpdate();
|
|
545
|
+
};
|
|
448
546
|
|
|
449
|
-
|
|
450
|
-
private readonly warningsView = new PreloadingComponents.PreloadingDisabledInfobar.PreloadingDisabledInfobar();
|
|
451
|
-
private readonly preloadingGrid = new PreloadingComponents.PreloadingGrid.PreloadingGrid();
|
|
452
|
-
private readonly preloadingGridContainer: HTMLDivElement;
|
|
453
|
-
private readonly renderContainer: HTMLElement;
|
|
454
|
-
private readonly ruleSetSelector: PreloadingRuleSetSelector;
|
|
455
|
-
private readonly textFilterUI: UI.Toolbar.ToolbarFilter;
|
|
456
|
-
private hsplit?: UI.SplitWidget.SplitWidget;
|
|
457
|
-
private clearButton: UI.Toolbar.ToolbarButton;
|
|
458
|
-
|
|
459
|
-
constructor(model: SDK.PreloadingModel.PreloadingModel) {
|
|
547
|
+
constructor(model: SDK.PreloadingModel.PreloadingModel, view: AttemptView = ATTEMPT_DEFAULT_VIEW) {
|
|
460
548
|
super({
|
|
461
549
|
jslog: `${VisualLogging.pane('preloading-speculations')}`,
|
|
462
550
|
useShadowDom: true,
|
|
463
551
|
});
|
|
464
|
-
this
|
|
552
|
+
this.#view = view;
|
|
465
553
|
|
|
466
554
|
this.model = model;
|
|
467
555
|
SDK.TargetManager.TargetManager.instance().addScopeChangeListener(this.onScopeChange.bind(this));
|
|
468
|
-
SDK.TargetManager.TargetManager.instance().addModelListener(
|
|
469
|
-
SDK.PreloadingModel.PreloadingModel, SDK.PreloadingModel.Events.MODEL_UPDATED, this.render, this,
|
|
470
|
-
{scoped: true});
|
|
471
|
-
SDK.TargetManager.TargetManager.instance().addModelListener(
|
|
472
|
-
SDK.PreloadingModel.PreloadingModel, SDK.PreloadingModel.Events.WARNINGS_UPDATED, e => {
|
|
473
|
-
Object.assign(this.warningsView, e.data);
|
|
474
|
-
}, this, {scoped: true});
|
|
475
|
-
|
|
476
|
-
// this (VBox)
|
|
477
|
-
// +- warningsContainer
|
|
478
|
-
// +- PreloadingWarningsView
|
|
479
|
-
// +- VBox
|
|
480
|
-
// +- toolbar (filtering)
|
|
481
|
-
// +- hsplit
|
|
482
|
-
// +- leftContainer
|
|
483
|
-
// +- PreloadingGrid
|
|
484
|
-
// +- rightContainer
|
|
485
|
-
// +- PreloadingDetailsReportView
|
|
486
|
-
//
|
|
487
|
-
// - If an row of PreloadingGrid selected, PreloadingDetailsReportView shows details of it.
|
|
488
|
-
// - If not, PreloadingDetailsReportView shows some messages.
|
|
489
|
-
|
|
490
|
-
this.warningsContainer = document.createElement('div');
|
|
491
|
-
this.warningsContainer.classList.add('flex-none');
|
|
492
|
-
this.contentElement.insertBefore(this.warningsContainer, this.contentElement.firstChild);
|
|
493
|
-
this.warningsView.show(this.warningsContainer);
|
|
494
|
-
|
|
495
|
-
const vbox = new UI.Widget.VBox();
|
|
496
|
-
|
|
497
|
-
const toolbar = vbox.contentElement.createChild('devtools-toolbar', 'preloading-toolbar');
|
|
498
|
-
toolbar.setAttribute('jslog', `${VisualLogging.toolbar()}`);
|
|
499
|
-
|
|
500
|
-
// Rule set dropdown first
|
|
501
|
-
this.ruleSetSelector = new PreloadingRuleSetSelector(() => this.render());
|
|
502
|
-
toolbar.appendToolbarItem(this.ruleSetSelector.item());
|
|
503
|
-
|
|
504
|
-
// Text filter second
|
|
505
|
-
this.textFilterUI = new UI.Toolbar.ToolbarFilter(undefined, 1, 1);
|
|
506
|
-
this.textFilterUI.addEventListener(UI.Toolbar.ToolbarInput.Event.TEXT_CHANGED, this.onTextFilterChanged, this);
|
|
507
|
-
toolbar.appendToolbarItem(this.textFilterUI);
|
|
508
|
-
|
|
509
|
-
// Separator between text filter and clear button
|
|
510
|
-
toolbar.appendToolbarItem(new UI.Toolbar.ToolbarSeparator());
|
|
511
|
-
|
|
512
|
-
// Clear button last (rightmost)
|
|
513
|
-
this.clearButton =
|
|
514
|
-
new UI.Toolbar.ToolbarButton('Clear speculative loads', 'clear', undefined, 'clear-speculative-loads');
|
|
515
|
-
this.clearButton.addEventListener(UI.Toolbar.ToolbarButton.Events.CLICK, () => {
|
|
516
|
-
const model =
|
|
517
|
-
SDK.TargetManager.TargetManager.instance().scopeTarget()?.model(SDK.PreloadingModel.PreloadingModel);
|
|
518
|
-
if (!model) {
|
|
519
|
-
return;
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
model.reset();
|
|
523
|
-
// Reset UI state
|
|
524
|
-
this.textFilterUI.setValue('');
|
|
525
|
-
this.ruleSetSelector.select(null);
|
|
526
|
-
this.render();
|
|
527
|
-
});
|
|
528
|
-
toolbar.appendToolbarItem(this.clearButton);
|
|
529
|
-
|
|
530
|
-
this.preloadingGrid.onSelect = this.onPreloadingGridCellFocused.bind(this);
|
|
531
556
|
|
|
532
|
-
this
|
|
533
|
-
this.preloadingGridContainer.className = 'preloading-grid-widget-container';
|
|
534
|
-
this.preloadingGridContainer.style.height = '100%';
|
|
535
|
-
this.preloadingGrid.show(this.preloadingGridContainer, null, true);
|
|
536
|
-
|
|
537
|
-
this.renderContainer = vbox.contentElement;
|
|
538
|
-
|
|
539
|
-
vbox.show(this.contentElement);
|
|
557
|
+
this.#ruleSetSelector = new PreloadingRuleSetSelector(() => this.requestUpdate());
|
|
540
558
|
}
|
|
541
559
|
|
|
542
560
|
override wasShown(): void {
|
|
543
561
|
super.wasShown();
|
|
562
|
+
SDK.TargetManager.TargetManager.instance().addModelListener(SDK.PreloadingModel.PreloadingModel,
|
|
563
|
+
SDK.PreloadingModel.Events.MODEL_UPDATED,
|
|
564
|
+
this.requestUpdate, this, {scoped: true});
|
|
565
|
+
SDK.TargetManager.TargetManager.instance().addModelListener(SDK.PreloadingModel.PreloadingModel,
|
|
566
|
+
SDK.PreloadingModel.Events.WARNINGS_UPDATED,
|
|
567
|
+
this.#onWarningsUpdated, this, {scoped: true});
|
|
568
|
+
this.requestUpdate();
|
|
569
|
+
}
|
|
544
570
|
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
571
|
+
override willHide(): void {
|
|
572
|
+
super.willHide();
|
|
573
|
+
SDK.TargetManager.TargetManager.instance().removeModelListener(
|
|
574
|
+
SDK.PreloadingModel.PreloadingModel, SDK.PreloadingModel.Events.MODEL_UPDATED, this.requestUpdate, this);
|
|
575
|
+
SDK.TargetManager.TargetManager.instance().removeModelListener(SDK.PreloadingModel.PreloadingModel,
|
|
576
|
+
SDK.PreloadingModel.Events.WARNINGS_UPDATED,
|
|
577
|
+
this.#onWarningsUpdated, this);
|
|
548
578
|
}
|
|
549
579
|
|
|
550
580
|
onScopeChange(): void {
|
|
551
581
|
const model = SDK.TargetManager.TargetManager.instance().scopeTarget()?.model(SDK.PreloadingModel.PreloadingModel);
|
|
552
582
|
assertNotNullOrUndefined(model);
|
|
553
583
|
this.model = model;
|
|
554
|
-
this.
|
|
584
|
+
this.requestUpdate();
|
|
555
585
|
}
|
|
556
586
|
|
|
557
587
|
setFilter(filter: PreloadingHelper.PreloadingForward.AttemptViewWithFilter): void {
|
|
@@ -560,15 +590,11 @@ export class PreloadingAttemptView extends UI.Widget.VBox {
|
|
|
560
590
|
id = null;
|
|
561
591
|
}
|
|
562
592
|
|
|
563
|
-
this
|
|
593
|
+
this.#ruleSetSelector.select(id);
|
|
564
594
|
|
|
565
595
|
// Reset text filter when navigating from Rules view to clear any existing filter
|
|
566
|
-
this
|
|
567
|
-
this.
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
private onTextFilterChanged(): void {
|
|
571
|
-
this.render();
|
|
596
|
+
this.#filterText = '';
|
|
597
|
+
this.requestUpdate();
|
|
572
598
|
}
|
|
573
599
|
|
|
574
600
|
private getPreloadingDetailsData(): PreloadingComponents.PreloadingDetailsReportView.PreloadingDetailsReportViewData {
|
|
@@ -587,9 +613,9 @@ export class PreloadingAttemptView extends UI.Widget.VBox {
|
|
|
587
613
|
};
|
|
588
614
|
}
|
|
589
615
|
|
|
590
|
-
|
|
616
|
+
override performUpdate(): void {
|
|
591
617
|
// Update preloading grid
|
|
592
|
-
const filteringRuleSetId = this
|
|
618
|
+
const filteringRuleSetId = this.#ruleSetSelector.getSelected();
|
|
593
619
|
const rows = this.model.getRepresentativePreloadingAttempts(filteringRuleSetId).map(({id, value}) => {
|
|
594
620
|
const attempt = value;
|
|
595
621
|
const pipeline = this.model.getPipeline(attempt);
|
|
@@ -609,139 +635,103 @@ export class PreloadingAttemptView extends UI.Widget.VBox {
|
|
|
609
635
|
};
|
|
610
636
|
});
|
|
611
637
|
|
|
612
|
-
// Apply text filter
|
|
613
|
-
const filteredRows = applyFilterText(this.textFilterUI.valueWithoutSuggestion(), rows);
|
|
614
|
-
|
|
615
|
-
this.preloadingGrid.rows = filteredRows;
|
|
616
|
-
this.preloadingGrid.pageURL = pageURL();
|
|
617
638
|
// Only show empty state when there are truly no speculations (not when filter has no matches)
|
|
618
|
-
const wasEmpty = this.contentElement.classList.contains('empty');
|
|
619
639
|
const isEmpty = rows.length === 0;
|
|
620
|
-
|
|
640
|
+
|
|
641
|
+
const input: AttemptViewInput = {
|
|
642
|
+
warnings: this.#warnings,
|
|
643
|
+
rows: applyFilterText(this.#filterText, rows),
|
|
644
|
+
isEmpty,
|
|
645
|
+
pageURL: pageURL(),
|
|
646
|
+
details: this.getPreloadingDetailsData(),
|
|
647
|
+
ruleSetSelectorToolbarItem: this.#ruleSetSelector.item(),
|
|
648
|
+
filterText: this.#filterText,
|
|
649
|
+
onFilterChanged: this.#onFilterChanged,
|
|
650
|
+
onClear: this.#onClear,
|
|
651
|
+
onAttemptSelected: this.#onAttemptSelected,
|
|
652
|
+
};
|
|
653
|
+
this.#view(input, this.#viewOutput, this.contentElement);
|
|
621
654
|
|
|
622
655
|
// When this view starts empty, the split view gets laid out while hidden and collapses
|
|
623
656
|
// its sidebar to 0. Re-layout once it becomes visible.
|
|
624
|
-
if (
|
|
625
|
-
this.
|
|
657
|
+
if (!isEmpty) {
|
|
658
|
+
this.#viewOutput.doSplitWidgetLayout?.();
|
|
626
659
|
}
|
|
627
|
-
|
|
628
|
-
// clang-format off
|
|
629
|
-
render(html`
|
|
630
|
-
<div class="empty-state">
|
|
631
|
-
<span class="empty-state-header">${i18nString(UIStrings.noPrefetchAttempts)}</span>
|
|
632
|
-
<div class="empty-state-description">
|
|
633
|
-
<span>${i18nString(UIStrings.prefetchDescription)}</span>
|
|
634
|
-
<devtools-link
|
|
635
|
-
class="devtools-link"
|
|
636
|
-
href=${SPECULATION_EXPLANATION_URL}
|
|
637
|
-
jslogcontext="learn-more"
|
|
638
|
-
>${i18nString(UIStrings.learnMore)}</devtools-link>
|
|
639
|
-
</div>
|
|
640
|
-
</div>
|
|
641
|
-
<devtools-split-view sidebar-position="second" ${
|
|
642
|
-
UI.Widget.widgetRef(
|
|
643
|
-
UI.SplitWidget.SplitWidget,
|
|
644
|
-
w => {
|
|
645
|
-
this.hsplit = w;
|
|
646
|
-
})}>
|
|
647
|
-
<div slot="main" class="overflow-auto" style="height: 100%">
|
|
648
|
-
${this.preloadingGridContainer}
|
|
649
|
-
</div>
|
|
650
|
-
<div slot="sidebar" class="overflow-auto" style="height: 100%">
|
|
651
|
-
${widget(PreloadingComponents.PreloadingDetailsReportView.PreloadingDetailsReportView, {
|
|
652
|
-
data: this.getPreloadingDetailsData(),
|
|
653
|
-
})}
|
|
654
|
-
</div>
|
|
655
|
-
</devtools-split-view>
|
|
656
|
-
`, this.renderContainer, {host: this});
|
|
657
|
-
// clang-format on
|
|
658
|
-
}
|
|
659
|
-
|
|
660
|
-
private onPreloadingGridCellFocused({rowId}: {rowId: string}): void {
|
|
661
|
-
this.focusedPreloadingAttemptId = rowId;
|
|
662
|
-
this.render();
|
|
663
660
|
}
|
|
664
661
|
|
|
665
662
|
getRuleSetSelectorToolbarItemForTest(): UI.Toolbar.ToolbarItem {
|
|
666
|
-
return this
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
getPreloadingGridForTest(): PreloadingComponents.PreloadingGrid.PreloadingGrid {
|
|
670
|
-
return this.preloadingGrid;
|
|
671
|
-
}
|
|
672
|
-
|
|
673
|
-
getPreloadingDetailsForTest(): PreloadingComponents.PreloadingDetailsReportView.PreloadingDetailsReportView {
|
|
674
|
-
const widgetElement = this.renderContainer.querySelector('div[slot="sidebar"] devtools-widget') as
|
|
675
|
-
UI.Widget.WidgetElement<PreloadingComponents.PreloadingDetailsReportView.PreloadingDetailsReportView>|
|
|
676
|
-
null;
|
|
677
|
-
const widget = widgetElement?.getWidget();
|
|
678
|
-
assertNotNullOrUndefined(widget);
|
|
679
|
-
return widget;
|
|
663
|
+
return this.#ruleSetSelector.item();
|
|
680
664
|
}
|
|
681
665
|
|
|
682
666
|
selectRuleSetOnFilterForTest(id: Protocol.Preload.RuleSetId|null): void {
|
|
683
|
-
this
|
|
667
|
+
this.#ruleSetSelector.select(id);
|
|
684
668
|
}
|
|
685
669
|
}
|
|
686
670
|
|
|
671
|
+
interface SummaryViewInput {
|
|
672
|
+
warnings?: Protocol.Preload.PreloadEnabledStateUpdatedEvent;
|
|
673
|
+
usedPreloading: PreloadingComponents.UsedPreloadingView.UsedPreloadingViewData;
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
type SummaryView = (input: SummaryViewInput, output: undefined, target: HTMLElement) => void;
|
|
677
|
+
|
|
678
|
+
const SUMMARY_DEFAULT_VIEW: SummaryView = (input, _output, target) => {
|
|
679
|
+
// clang-format off
|
|
680
|
+
render(
|
|
681
|
+
html`
|
|
682
|
+
${widget(PreloadingComponents.PreloadingDisabledInfobar.PreloadingDisabledInfobar, input.warnings)}
|
|
683
|
+
${widget(PreloadingComponents.UsedPreloadingView.UsedPreloadingView, {data: input.usedPreloading})}
|
|
684
|
+
`,
|
|
685
|
+
target);
|
|
686
|
+
// clang-format on
|
|
687
|
+
};
|
|
688
|
+
|
|
687
689
|
export class PreloadingSummaryView extends UI.Widget.VBox {
|
|
688
690
|
private model: SDK.PreloadingModel.PreloadingModel;
|
|
691
|
+
readonly #view: SummaryView;
|
|
692
|
+
#warnings?: Protocol.Preload.PreloadEnabledStateUpdatedEvent;
|
|
689
693
|
|
|
690
|
-
|
|
691
|
-
private readonly warningsView = new PreloadingComponents.PreloadingDisabledInfobar.PreloadingDisabledInfobar();
|
|
692
|
-
private readonly usedPreloading = new PreloadingComponents.UsedPreloadingView.UsedPreloadingView();
|
|
693
|
-
|
|
694
|
-
constructor(model: SDK.PreloadingModel.PreloadingModel) {
|
|
694
|
+
constructor(model: SDK.PreloadingModel.PreloadingModel, view: SummaryView = SUMMARY_DEFAULT_VIEW) {
|
|
695
695
|
super({
|
|
696
696
|
jslog: `${VisualLogging.pane('speculative-loads')}`,
|
|
697
697
|
useShadowDom: true,
|
|
698
698
|
});
|
|
699
|
-
this
|
|
699
|
+
this.#view = view;
|
|
700
700
|
|
|
701
701
|
this.model = model;
|
|
702
702
|
SDK.TargetManager.TargetManager.instance().addScopeChangeListener(this.onScopeChange.bind(this));
|
|
703
|
-
SDK.TargetManager.TargetManager.instance().addModelListener(
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
SDK.TargetManager.TargetManager.instance().addModelListener(
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
this.warningsContainer = document.createElement('div');
|
|
712
|
-
this.warningsContainer.classList.add('flex-none');
|
|
713
|
-
this.contentElement.insertBefore(this.warningsContainer, this.contentElement.firstChild);
|
|
714
|
-
this.warningsView.show(this.warningsContainer);
|
|
715
|
-
|
|
716
|
-
this.usedPreloading.show(this.contentElement);
|
|
703
|
+
SDK.TargetManager.TargetManager.instance().addModelListener(SDK.PreloadingModel.PreloadingModel,
|
|
704
|
+
SDK.PreloadingModel.Events.MODEL_UPDATED,
|
|
705
|
+
this.requestUpdate, this, {scoped: true});
|
|
706
|
+
SDK.TargetManager.TargetManager.instance().addModelListener(SDK.PreloadingModel.PreloadingModel,
|
|
707
|
+
SDK.PreloadingModel.Events.WARNINGS_UPDATED, e => {
|
|
708
|
+
this.#warnings = e.data;
|
|
709
|
+
this.requestUpdate();
|
|
710
|
+
}, this, {scoped: true});
|
|
717
711
|
}
|
|
718
712
|
|
|
719
713
|
override wasShown(): void {
|
|
720
714
|
super.wasShown();
|
|
721
|
-
|
|
722
|
-
this.warningsView.wasShown();
|
|
723
|
-
|
|
724
|
-
this.render();
|
|
715
|
+
this.requestUpdate();
|
|
725
716
|
}
|
|
726
717
|
|
|
727
718
|
onScopeChange(): void {
|
|
728
719
|
const model = SDK.TargetManager.TargetManager.instance().scopeTarget()?.model(SDK.PreloadingModel.PreloadingModel);
|
|
729
720
|
assertNotNullOrUndefined(model);
|
|
730
721
|
this.model = model;
|
|
731
|
-
this.
|
|
722
|
+
this.requestUpdate();
|
|
732
723
|
}
|
|
733
724
|
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
725
|
+
override performUpdate(): void {
|
|
726
|
+
const input: SummaryViewInput = {
|
|
727
|
+
warnings: this.#warnings,
|
|
728
|
+
usedPreloading: {
|
|
729
|
+
pageURL: pageURL(),
|
|
730
|
+
previousAttempts: this.model.getRepresentativePreloadingAttemptsOfPreviousPage().map(({value}) => value),
|
|
731
|
+
currentAttempts: this.model.getRepresentativePreloadingAttempts(null).map(({value}) => value),
|
|
732
|
+
},
|
|
740
733
|
};
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
getUsedPreloadingForTest(): PreloadingComponents.UsedPreloadingView.UsedPreloadingView {
|
|
744
|
-
return this.usedPreloading;
|
|
734
|
+
this.#view(input, /* output= */ undefined, this.contentElement);
|
|
745
735
|
}
|
|
746
736
|
}
|
|
747
737
|
|
|
@@ -760,9 +750,9 @@ class PreloadingRuleSetSelector implements
|
|
|
760
750
|
assertNotNullOrUndefined(model);
|
|
761
751
|
this.model = model;
|
|
762
752
|
SDK.TargetManager.TargetManager.instance().addScopeChangeListener(this.onScopeChange.bind(this));
|
|
763
|
-
SDK.TargetManager.TargetManager.instance().addModelListener(
|
|
764
|
-
|
|
765
|
-
|
|
753
|
+
SDK.TargetManager.TargetManager.instance().addModelListener(SDK.PreloadingModel.PreloadingModel,
|
|
754
|
+
SDK.PreloadingModel.Events.MODEL_UPDATED,
|
|
755
|
+
this.onModelUpdated, this, {scoped: true});
|
|
766
756
|
|
|
767
757
|
this.listModel = new UI.ListModel.ListModel();
|
|
768
758
|
|
|
@@ -773,8 +763,8 @@ class PreloadingRuleSetSelector implements
|
|
|
773
763
|
this.toolbarItem = new UI.Toolbar.ToolbarItem(this.dropDown.element);
|
|
774
764
|
this.toolbarItem.setTitle(i18nString(UIStrings.filterFilterByRuleSet));
|
|
775
765
|
this.toolbarItem.element.classList.add('toolbar-has-dropdown');
|
|
776
|
-
this.toolbarItem.element.setAttribute(
|
|
777
|
-
|
|
766
|
+
this.toolbarItem.element.setAttribute('jslog',
|
|
767
|
+
`${VisualLogging.action('filter-by-rule-set').track({click: true})}`);
|
|
778
768
|
|
|
779
769
|
// Initializes `listModel` and `dropDown` using data of the model.
|
|
780
770
|
this.onModelUpdated();
|
|
@@ -864,13 +854,8 @@ class PreloadingRuleSetSelector implements
|
|
|
864
854
|
|
|
865
855
|
// Method for UI.SoftDropDown.Delegate<Protocol.Preload.RuleSetId|typeof AllRuleSetRootId>
|
|
866
856
|
createElementForItem(id: Protocol.Preload.RuleSetId|typeof AllRuleSetRootId): Element {
|
|
867
|
-
const
|
|
868
|
-
|
|
869
|
-
const title = shadowRoot.createChild('div', 'title');
|
|
870
|
-
UI.UIUtils.createTextChild(title, Platform.StringUtilities.trimEndWithMaxLength(this.titleFor(id), 100));
|
|
871
|
-
const subTitle = shadowRoot.createChild('div', 'subtitle');
|
|
872
|
-
UI.UIUtils.createTextChild(subTitle, this.subtitleFor(id));
|
|
873
|
-
return element;
|
|
857
|
+
const selectorElement = new PreloadingRuleSetSelectorElement(this.titleFor(id), this.subtitleFor(id));
|
|
858
|
+
return selectorElement.contentElement;
|
|
874
859
|
}
|
|
875
860
|
|
|
876
861
|
// Method for UI.SoftDropDown.Delegate<Protocol.Preload.RuleSetId|typeof AllRuleSetRootId>
|
|
@@ -884,9 +869,48 @@ class PreloadingRuleSetSelector implements
|
|
|
884
869
|
}
|
|
885
870
|
|
|
886
871
|
// Method for UI.SoftDropDown.Delegate<Protocol.Preload.RuleSetId|typeof AllRuleSetRootId>
|
|
887
|
-
highlightedItemChanged(
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
872
|
+
highlightedItemChanged(_from: Protocol.Preload.RuleSetId|typeof AllRuleSetRootId,
|
|
873
|
+
_to: Protocol.Preload.RuleSetId|typeof AllRuleSetRootId, _fromElement: Element|null,
|
|
874
|
+
_toElement: Element|null): void {
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
interface RuleSetSelectorElementViewInput {
|
|
879
|
+
title: string;
|
|
880
|
+
subtitle: string;
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
type RuleSetSelectorElementView = (input: RuleSetSelectorElementViewInput, output: undefined, target: HTMLElement) =>
|
|
884
|
+
void;
|
|
885
|
+
|
|
886
|
+
const RULE_SET_SELECTOR_ELEMENT_DEFAULT_VIEW: RuleSetSelectorElementView = (input, _output, target) => {
|
|
887
|
+
// clang-format off
|
|
888
|
+
render(
|
|
889
|
+
html`
|
|
890
|
+
<style>${preloadingViewDropDownStyles}</style>
|
|
891
|
+
<div class="title">${Platform.StringUtilities.trimEndWithMaxLength(input.title, 100)}</div>
|
|
892
|
+
<div class="subtitle">${input.subtitle}</div>
|
|
893
|
+
`,
|
|
894
|
+
target);
|
|
895
|
+
// clang-format on
|
|
896
|
+
};
|
|
897
|
+
|
|
898
|
+
class PreloadingRuleSetSelectorElement extends UI.Widget.Widget {
|
|
899
|
+
readonly #title: string;
|
|
900
|
+
readonly #subtitle: string;
|
|
901
|
+
readonly #view: RuleSetSelectorElementView;
|
|
902
|
+
|
|
903
|
+
constructor(title: string, subtitle: string,
|
|
904
|
+
view: RuleSetSelectorElementView = RULE_SET_SELECTOR_ELEMENT_DEFAULT_VIEW) {
|
|
905
|
+
super({useShadowDom: true});
|
|
906
|
+
this.markAsExternallyManaged();
|
|
907
|
+
this.#title = title;
|
|
908
|
+
this.#subtitle = subtitle;
|
|
909
|
+
this.#view = view;
|
|
910
|
+
this.requestUpdate();
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
override performUpdate(): void {
|
|
914
|
+
this.#view({title: this.#title, subtitle: this.#subtitle}, /* output= */ undefined, this.contentElement);
|
|
891
915
|
}
|
|
892
916
|
}
|