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.
Files changed (95) hide show
  1. package/.agents/skills/review-ui-widgets/SKILL.md +7 -7
  2. package/.agents/skills/ui-eng-vision-local-lit-renderer/SKILL.md +12 -0
  3. package/.agents/skills/ui-eng-vision-widget-promoter/SKILL.md +3 -3
  4. package/.agents/skills/ui-widgets/SKILL.md +2 -1
  5. package/docs/cookbook/dependencies.md +6 -4
  6. package/front_end/core/i18n/i18nImpl.ts +1 -1
  7. package/front_end/core/root/Runtime.ts +1 -1
  8. package/front_end/core/sdk/ResourceTreeModel.ts +16 -0
  9. package/front_end/entrypoints/js_app/js_app.ts +2 -5
  10. package/front_end/entrypoints/node_app/node_app.ts +2 -3
  11. package/front_end/generated/InspectorBackendCommands.ts +1 -1
  12. package/front_end/generated/protocol.ts +1 -0
  13. package/front_end/models/ai_assistance/skills/lighthouse.md +2 -1
  14. package/front_end/models/ai_assistance/skills/network.md +1 -0
  15. package/front_end/models/ai_assistance/tools/ExecuteJavaScript.ts +26 -2
  16. package/front_end/models/ai_assistance/tools/GetLighthouseAudits.ts +1 -1
  17. package/front_end/models/ai_assistance/tools/ListNetworkRequests.ts +2 -7
  18. package/front_end/models/ai_assistance/tools/RunLighthouse.ts +2 -2
  19. package/front_end/models/comment_manager/CommentManager.ts +0 -6
  20. package/front_end/models/comment_manager/CommentThread.ts +23 -19
  21. package/front_end/models/elements/StyleChanges.ts +66 -0
  22. package/front_end/models/trace/EventsSerializer.ts +2 -7
  23. package/front_end/models/trace/ModelImpl.ts +0 -2
  24. package/front_end/models/trace/handlers/FlowsHandler.ts +37 -29
  25. package/front_end/models/trace/helpers/SyntheticEvents.ts +10 -37
  26. package/front_end/models/trace/insights/RenderBlocking.ts +3 -1
  27. package/front_end/models/trace/lantern/simulation/Simulator.ts +4 -0
  28. package/front_end/models/trace/lantern/types/Lantern.ts +1 -0
  29. package/front_end/panels/accessibility/SourceOrderView.ts +1 -1
  30. package/front_end/panels/application/ApplicationPanelSidebar.ts +90 -0
  31. package/front_end/panels/application/StorageView.ts +196 -174
  32. package/front_end/panels/application/SubAppsView.ts +2 -2
  33. package/front_end/panels/application/preloading/PreloadingView.ts +360 -336
  34. package/front_end/panels/application/preloading/components/PreloadingDisabledInfobar.ts +2 -2
  35. package/front_end/panels/application/preloading/components/PreloadingGrid.ts +6 -3
  36. package/front_end/panels/application/preloading/components/RuleSetGrid.ts +17 -17
  37. package/front_end/panels/application/preloading/components/UsedPreloadingView.ts +2 -2
  38. package/front_end/panels/application/preloading/preloadingView.css +12 -4
  39. package/front_end/panels/application/preloading/preloadingViewDropDown.css +1 -1
  40. package/front_end/panels/application/storageView.css +16 -21
  41. package/front_end/panels/browser_debugger/CategorizedBreakpointsSidebarPane.ts +2 -2
  42. package/front_end/panels/browser_debugger/browser_debugger-meta.ts +6 -8
  43. package/front_end/panels/comments/CommentsPane.ts +26 -9
  44. package/front_end/panels/comments/commentsPane.css +25 -6
  45. package/front_end/panels/common/CommentThreadWidget.ts +2 -2
  46. package/front_end/panels/common/CommentsOverlayWidget.ts +94 -35
  47. package/front_end/panels/common/commentThreadWidget.css +17 -0
  48. package/front_end/panels/common/commentsOverlay.css +5 -10
  49. package/front_end/panels/common/common-meta.ts +11 -1
  50. package/front_end/panels/elements/ClassesPaneWidget.ts +130 -88
  51. package/front_end/panels/elements/ColorSwatchPopoverIcon.ts +7 -33
  52. package/front_end/panels/elements/DOMTreeWidget.ts +7 -3
  53. package/front_end/panels/elements/ElementStatePaneWidget.ts +11 -1
  54. package/front_end/panels/elements/PropertyRenderer.ts +3 -2
  55. package/front_end/panels/elements/StyleEditorWidget.ts +60 -41
  56. package/front_end/panels/elements/StylePropertiesSection.ts +32 -5
  57. package/front_end/panels/elements/StylePropertyTreeElement.ts +227 -162
  58. package/front_end/panels/event_listeners/EventListenersView.ts +11 -8
  59. package/front_end/panels/linear_memory_inspector/components/ValueInterpreterSettings.ts +1 -1
  60. package/front_end/panels/network/NetworkDataGridNode.ts +3 -1
  61. package/front_end/panels/network/RequestConditionsDrawer.ts +1 -1
  62. package/front_end/panels/network/RequestPayloadView.ts +12 -5
  63. package/front_end/panels/profiler/HeapProfileView.ts +28 -6
  64. package/front_end/panels/profiler/HeapSnapshotDataGrids.ts +7 -3
  65. package/front_end/panels/protocol_monitor/JSONEditor.ts +0 -1
  66. package/front_end/panels/recorder/RecorderPanel.ts +2 -2
  67. package/front_end/panels/settings/SettingsScreen.ts +1 -1
  68. package/front_end/panels/sources/NavigatorView.ts +105 -45
  69. package/front_end/panels/sources/ScopeChainSidebarPane.ts +8 -5
  70. package/front_end/panels/sources/SourcesNavigator.ts +421 -213
  71. package/front_end/panels/sources/SourcesPanel.ts +6 -4
  72. package/front_end/panels/sources/WatchExpressionsSidebarPane.ts +10 -5
  73. package/front_end/panels/sources/sources-meta.ts +4 -15
  74. package/front_end/panels/sources/sourcesNavigator.css +5 -0
  75. package/front_end/panels/timeline/ModificationsManager.ts +0 -2
  76. package/front_end/panels/timeline/README.md +2 -0
  77. package/front_end/panels/timeline/TimelineCommentController.ts +132 -30
  78. package/front_end/panels/timeline/TimelinePanel.ts +4 -0
  79. package/front_end/panels/timeline/components/IgnoreListSetting.ts +1 -1
  80. package/front_end/panels/timeline/utils/Treemap.ts +8 -0
  81. package/front_end/third_party/chromium/README.chromium +1 -1
  82. package/front_end/ui/comments/CommentAnchorResolver.ts +3 -0
  83. package/front_end/ui/comments/CommentOverlayManager.ts +2 -4
  84. package/front_end/ui/components/lists/List.ts +14 -1
  85. package/front_end/ui/components/panel_feedback/PreviewToggle.ts +1 -1
  86. package/front_end/ui/components/text_editor/AiCodeCompletionProvider.ts +23 -14
  87. package/front_end/ui/components/text_editor/AiCodeGenerationProvider.ts +3 -0
  88. package/front_end/ui/legacy/Toolbar.ts +0 -1
  89. package/front_end/ui/legacy/Treeoutline.ts +7 -2
  90. package/front_end/ui/legacy/UIUtils.ts +4 -1
  91. package/front_end/ui/legacy/components/inline_editor/Swatches.ts +19 -6
  92. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +20 -11
  93. package/front_end/ui/legacy/components/source_frame/XMLView.ts +27 -7
  94. package/front_end/ui/visual_logging/KnownContextValues.ts +1 -0
  95. package/package.json +1 -1
@@ -1,7 +1,10 @@
1
1
  // Copyright 2016 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 */
4
+
5
+ import '../../ui/components/report_view/report_view.js';
6
+ import '../../ui/kit/kit.js';
7
+ import '../../ui/legacy/components/perf_ui/perf_ui.js';
5
8
 
6
9
  import * as Common from '../../core/common/common.js';
7
10
  import * as i18n from '../../core/i18n/i18n.js';
@@ -10,17 +13,16 @@ import * as SDK from '../../core/sdk/sdk.js';
10
13
  import * as Protocol from '../../generated/protocol.js';
11
14
  import * as Buttons from '../../ui/components/buttons/buttons.js';
12
15
  import * as uiI18n from '../../ui/i18n/i18n.js';
13
- import {Icon, Link} from '../../ui/kit/kit.js';
14
- import * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';
16
+ import type * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';
15
17
  import * as UI from '../../ui/legacy/legacy.js';
16
- import {Directives, html, type LitTemplate, render} from '../../ui/lit/lit.js';
18
+ import {Directives, html, type LitTemplate, nothing, render} from '../../ui/lit/lit.js';
17
19
  import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
18
20
 
19
21
  import {IndexedDBModel} from './IndexedDBModel.js';
20
22
  import {ResourcesPanel} from './ResourcesPanel.js';
21
23
  import storageViewStyles from './storageView.css.js';
22
24
 
23
- const {ref} = Directives;
25
+ const {classMap, ifDefined, live, ref} = Directives;
24
26
  const {bindToSetting} = UI.UIUtils;
25
27
 
26
28
  const UIStrings = {
@@ -165,22 +167,33 @@ export const storagePieColors: Map<Protocol.Storage.StorageType, string> =
165
167
  const str_ = i18n.i18n.registerUIStrings('panels/application/StorageView.ts', UIStrings);
166
168
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
167
169
 
168
- export interface ClearSiteDataViewInput {
170
+ export interface ViewInput {
171
+ subtitle: string;
169
172
  settings: Map<Protocol.Storage.StorageType, Common.Settings.Setting<boolean>>;
170
173
  includeThirdPartyCookiesSetting: Common.Settings.Setting<boolean>;
171
174
  includeThirdPartyCookiesDisabled: boolean;
172
175
  clearing: boolean;
176
+ quotaUsage: number|null;
177
+ quotaQuota: number|null;
178
+ quotaOverrideActive: boolean|null;
179
+ pieChartSlices: PerfUI.PieChart.Slice[];
180
+ quotaOverrideEnabled: boolean;
181
+ quotaOverrideValue: string;
182
+ quotaOverrideError: string;
173
183
  onClear: () => void;
184
+ onToggleQuotaOverride: () => void;
185
+ onQuotaOverrideInput: (value: string) => void;
186
+ onApplyQuotaOverride: (value: string) => void;
174
187
  }
175
188
 
176
- export interface ClearSiteDataViewOutput {
189
+ export interface ViewOutput {
177
190
  focusClearButton?: () => void;
191
+ focusQuotaOverrideEditor?: () => void;
178
192
  }
179
193
 
180
- export type ClearSiteDataView = (input: ClearSiteDataViewInput, output: ClearSiteDataViewOutput, target: HTMLElement) =>
181
- void;
194
+ export type View = (input: ViewInput, output: ViewOutput, target: HTMLElement) => void;
182
195
 
183
- export const CLEAR_SITE_DATA_DEFAULT_VIEW: ClearSiteDataView = (input, output, target) => {
196
+ export const DEFAULT_VIEW: View = (input, output, target) => {
184
197
  function renderSettingCheckbox(title: Platform.UIString.LocalizedString, settingName: Protocol.Storage.StorageType,
185
198
  className: string): LitTemplate {
186
199
  const setting = input.settings.get(settingName);
@@ -191,39 +204,147 @@ export const CLEAR_SITE_DATA_DEFAULT_VIEW: ClearSiteDataView = (input, output, t
191
204
  title}</devtools-checkbox>`;
192
205
  }
193
206
 
207
+ function renderClearSiteData(): LitTemplate {
208
+ // clang-format off
209
+ return html`
210
+ <div class="report-section" jslog=${VisualLogging.section('clear-storage')}>
211
+ <devtools-report-section-header role="heading" aria-level="2">
212
+ ${i18nString(UIStrings.clearSiteData)}
213
+ </devtools-report-section-header>
214
+ <devtools-report-section>
215
+ <div class="clear-site-data-checkboxes-row" role="group" aria-label=${i18nString(UIStrings.clearSiteData)}>
216
+ <div class="clear-site-data-checkbox-column">
217
+ ${renderSettingCheckbox(i18nString(UIStrings.cacheStorage), Protocol.Storage.StorageType.Cache_storage, 'cache-storage-checkbox')}
218
+ ${renderSettingCheckbox(i18nString(UIStrings.fileSystem), Protocol.Storage.StorageType.File_systems, 'file-systems-checkbox')}
219
+ ${renderSettingCheckbox(i18nString(UIStrings.indexDB), Protocol.Storage.StorageType.Indexeddb, 'indexeddb-checkbox')}
220
+ ${renderSettingCheckbox(i18nString(UIStrings.localAndSessionStorage), Protocol.Storage.StorageType.Local_storage, 'local-and-session-storage-checkbox')}
221
+ </div>
222
+ <div class="clear-site-data-checkbox-column">
223
+ ${renderSettingCheckbox(i18nString(UIStrings.unregisterServiceWorker), Protocol.Storage.StorageType.Service_workers, 'unregister-service-worker-checkbox')}
224
+ ${renderSettingCheckbox(i18nString(UIStrings.cookies), Protocol.Storage.StorageType.Cookies, 'cookies-checkbox cookies-row')}
225
+ <div class="include-third-party-cookies-row">
226
+ <devtools-checkbox class="third-party-cookies-checkbox"
227
+ title=${i18nString(UIStrings.thirdPartyCookies)}
228
+ ?disabled=${input.includeThirdPartyCookiesDisabled}
229
+ ${bindToSetting(input.includeThirdPartyCookiesSetting)}>
230
+ ${i18nString(UIStrings.thirdPartyCookies)}
231
+ </devtools-checkbox>
232
+ </div>
233
+ </div>
234
+ </div>
235
+ </devtools-report-section>
236
+ <devtools-report-section class="clear-selected-button-row">
237
+ <devtools-button id="storage-view-clear-button"
238
+ .variant=${Buttons.Button.Variant.OUTLINED}
239
+ .disabled=${input.clearing}
240
+ .jslogContext=${'storage.clear-site-data'}
241
+ @click=${input.onClear}
242
+ ${ref(e => {
243
+ output.focusClearButton = e instanceof HTMLElement ? () => e.focus() : undefined;
244
+ })}
245
+ >${input.clearing ? i18nString(UIStrings.clearing) : i18nString(UIStrings.clearSelected)}</devtools-button>
246
+ </devtools-report-section>
247
+ </div>`;
248
+ // clang-format on
249
+ }
250
+
251
+ function quotaTooltip(): string|undefined {
252
+ if (input.quotaUsage === null || input.quotaQuota === null) {
253
+ return undefined;
254
+ }
255
+ return i18nString(UIStrings.storageQuotaUsedWithBytes,
256
+ {PH1: input.quotaUsage.toLocaleString(), PH2: input.quotaQuota.toLocaleString()});
257
+ }
258
+
259
+ function renderQuotaRow(): LitTemplate {
260
+ if (input.quotaUsage === null || input.quotaQuota === null) {
261
+ return nothing;
262
+ }
263
+ const quotaAsString = i18n.ByteUtilities.bytesToString(input.quotaQuota);
264
+ const usageAsString = i18n.ByteUtilities.bytesToString(input.quotaUsage);
265
+ const formattedQuotaAsString = i18nString(UIStrings.storageWithCustomMarker, {PH1: quotaAsString});
266
+ const quota = input.quotaOverrideActive ? html`<b>${formattedQuotaAsString}</b>` : quotaAsString;
267
+ // clang-format off
268
+ return html`
269
+ ${uiI18n.getFormatLocalizedStringTemplate(str_, UIStrings.storageQuotaUsed, {PH1: usageAsString, PH2: quota})}
270
+ ${!input.quotaOverrideActive && input.quotaQuota < 125829120 /* 120 MiB */ ? html`
271
+ <devtools-icon name="info" class="small" style="color: var(--icon-info)"
272
+ title=${i18nString(UIStrings.storageQuotaIsLimitedIn)}></devtools-icon>` : nothing}`;
273
+ // clang-format on
274
+ }
275
+
276
+ function renderUsage(): LitTemplate {
277
+ const pieChartData: PerfUI.PieChart.PieChartData = {
278
+ chartName: i18nString(UIStrings.storageUsage),
279
+ size: 110,
280
+ formatter: i18n.ByteUtilities.bytesToString,
281
+ showLegend: true,
282
+ total: input.quotaUsage ?? 0,
283
+ slices: input.pieChartSlices,
284
+ };
285
+ const onEditorInput = (event: Event): void => {
286
+ input.onQuotaOverrideInput((event.target as HTMLInputElement).value);
287
+ };
288
+ const onEditorKeyUp = (event: KeyboardEvent): void => {
289
+ if (event.key === 'Enter' && !event.isComposing) {
290
+ input.onApplyQuotaOverride((event.target as HTMLInputElement).value);
291
+ event.consume(true);
292
+ }
293
+ };
294
+ const onEditorFocusOut = (event: FocusEvent): void => {
295
+ input.onApplyQuotaOverride((event.target as HTMLInputElement).value);
296
+ event.consume(true);
297
+ };
298
+ // clang-format off
299
+ return html`
300
+ <div class="report-section" jslog=${VisualLogging.section('usage')}>
301
+ <devtools-report-section-header role="heading" aria-level="2">
302
+ ${i18nString(UIStrings.usage)}
303
+ </devtools-report-section-header>
304
+ <devtools-report-section class="quota-usage-row" jslog=${VisualLogging.item('storage-usage')}
305
+ title=${ifDefined(quotaTooltip())}>${renderQuotaRow()}</devtools-report-section>
306
+ <devtools-report-section>
307
+ <devtools-link href="https://developer.chrome.com/docs/devtools/progressive-web-apps#opaque-responses"
308
+ jslogcontext="learn-more">${i18nString(UIStrings.learnMore)}</devtools-link>
309
+ </devtools-report-section>
310
+ <devtools-report-section class="usage-breakdown-row" jslog=${VisualLogging.item('usage-breakdown')}>
311
+ <devtools-perf-piechart .data=${pieChartData}></devtools-perf-piechart>
312
+ </devtools-report-section>
313
+ <devtools-report-section class="quota-override-row">
314
+ <devtools-checkbox .checked=${live(input.quotaOverrideEnabled)}
315
+ title=${i18nString(UIStrings.simulateCustomStorage)}
316
+ @change=${input.onToggleQuotaOverride}
317
+ jslog=${VisualLogging.toggle('simulate-custom-quota').track({change: true})}>
318
+ ${i18nString(UIStrings.simulateCustomStorage)}
319
+ </devtools-checkbox>
320
+ </devtools-report-section>
321
+ <devtools-report-section class=${classMap({hidden: !input.quotaOverrideEnabled})}>
322
+ <input class="quota-override-notification-editor"
323
+ aria-label=${i18nString(UIStrings.simulateCustomStorage)}
324
+ placeholder=${i18nString(UIStrings.pleaseEnterANumber)}
325
+ .value=${live(input.quotaOverrideValue)}
326
+ @input=${onEditorInput}
327
+ @keyup=${onEditorKeyUp}
328
+ @focusout=${onEditorFocusOut}
329
+ ${ref(e => {
330
+ output.focusQuotaOverrideEditor = e instanceof HTMLElement ? () => e.focus() : undefined;
331
+ })}
332
+ jslog=${VisualLogging.textField('quota-override').track({change: true})}>
333
+ <label>${i18nString(UIStrings.mb)}</label>
334
+ </devtools-report-section>
335
+ <devtools-report-section><div class="quota-override-error">${input.quotaOverrideError}</div></devtools-report-section>
336
+ </div>`;
337
+ // clang-format on
338
+ }
339
+
194
340
  // clang-format off
195
341
  render(html`
196
- <div class="report-row clear-site-data-checkboxes-row">
197
- <div class="clear-site-data-checkbox-column">
198
- ${renderSettingCheckbox(i18nString(UIStrings.cacheStorage), Protocol.Storage.StorageType.Cache_storage, 'cache-storage-checkbox')}
199
- ${renderSettingCheckbox(i18nString(UIStrings.fileSystem), Protocol.Storage.StorageType.File_systems, 'file-systems-checkbox')}
200
- ${renderSettingCheckbox(i18nString(UIStrings.indexDB), Protocol.Storage.StorageType.Indexeddb, 'indexeddb-checkbox')}
201
- ${renderSettingCheckbox(i18nString(UIStrings.localAndSessionStorage), Protocol.Storage.StorageType.Local_storage, 'local-and-session-storage-checkbox')}
202
- </div>
203
- <div class="clear-site-data-checkbox-column">
204
- ${renderSettingCheckbox(i18nString(UIStrings.unregisterServiceWorker), Protocol.Storage.StorageType.Service_workers, 'unregister-service-worker-checkbox')}
205
- ${renderSettingCheckbox(i18nString(UIStrings.cookies), Protocol.Storage.StorageType.Cookies, 'cookies-checkbox cookies-row')}
206
- <div class="include-third-party-cookies-row">
207
- <devtools-checkbox class="third-party-cookies-checkbox"
208
- title=${i18nString(UIStrings.thirdPartyCookies)}
209
- ?disabled=${input.includeThirdPartyCookiesDisabled}
210
- ${bindToSetting(input.includeThirdPartyCookiesSetting)}>
211
- ${i18nString(UIStrings.thirdPartyCookies)}
212
- </devtools-checkbox>
213
- </div>
214
- </div>
215
- </div>
216
- <div class="report-row clear-selected-button-row">
217
- <devtools-button id="storage-view-clear-button"
218
- .variant=${Buttons.Button.Variant.OUTLINED}
219
- .disabled=${input.clearing}
220
- .jslogContext=${'storage.clear-site-data'}
221
- @click=${input.onClear}
222
- ${ref(e => {
223
- output.focusClearButton = e instanceof HTMLElement ? () => e.focus() : undefined;
224
- })}
225
- >${input.clearing ? i18nString(UIStrings.clearing) : i18nString(UIStrings.clearSelected)}</devtools-button>
226
- </div>`, target);
342
+ <devtools-report class="clear-storage-header" .data=${{reportTitle: i18nString(UIStrings.storageTitle)}}>
343
+ ${input.subtitle ? html`<div class="report-subtitle" slot="toolbar">${input.subtitle}</div>` : nothing}
344
+ ${renderClearSiteData()}
345
+ <devtools-report-divider></devtools-report-divider>
346
+ ${renderUsage()}
347
+ </devtools-report>`, target);
227
348
  // clang-format on
228
349
  };
229
350
 
@@ -231,30 +352,23 @@ export const CLEAR_SITE_DATA_DEFAULT_VIEW: ClearSiteDataView = (input, output, t
231
352
  * @implements {SDK.TargetManager.Observer}
232
353
  */
233
354
  export class StorageView extends UI.Widget.VBox {
355
+ readonly #view: View;
356
+ readonly #viewOutput: ViewOutput = {};
234
357
  private pieColors: Map<Protocol.Storage.StorageType, string>;
235
- private reportView: UI.ReportView.ReportView;
236
358
  private target: SDK.Target.Target|null = null;
237
359
  private securityOrigin: string|null = null;
238
360
  private storageKey: string|null = null;
239
- private subtitle: string|null = null;
361
+ private subtitle = '';
240
362
  private settings: Map<Protocol.Storage.StorageType, Common.Settings.Setting<boolean>>;
241
363
  private includeThirdPartyCookiesSetting: Common.Settings.Setting<boolean>;
242
- private readonly clearSiteDataView: ClearSiteDataView;
243
- private readonly clearSiteDataViewOutput: ClearSiteDataViewOutput = {};
244
- private readonly clearSiteDataFieldList: HTMLElement;
245
- private quotaRow: HTMLElement;
246
364
  private quotaUsage: number|null = null;
247
365
  private quotaQuota: number|null = null;
248
366
  private quotaOverrideActive: boolean|null = null;
249
367
  private pieChartSlices: PerfUI.PieChart.Slice[] = [];
250
- private pieChart: PerfUI.PieChart.PieChart;
251
368
  private previousOverrideFieldValue = '';
369
+ private quotaOverrideFieldValue = '';
252
370
  private quotaOverrideEnabled = false;
253
371
  private quotaOverrideError = '';
254
- private quotaOverrideCheckbox: UI.UIUtils.CheckboxLabel;
255
- private quotaOverrideControlRow: HTMLElement;
256
- private quotaOverrideEditor: HTMLInputElement;
257
- private quotaOverrideErrorMessage: HTMLElement;
258
372
  private clearing = false;
259
373
  private clearTimerId?: number;
260
374
  private readonly throttler = new Common.Throttler.Throttler(1000);
@@ -266,22 +380,12 @@ export class StorageView extends UI.Widget.VBox {
266
380
  this.onIncludeThirdPartyCookiesSettingChanged(event.data);
267
381
  };
268
382
 
269
- constructor(clearSiteDataView: ClearSiteDataView = CLEAR_SITE_DATA_DEFAULT_VIEW) {
270
- super({useShadowDom: true});
383
+ constructor(element?: HTMLElement, view: View = DEFAULT_VIEW) {
384
+ super(element, {useShadowDom: true, jslog: `${VisualLogging.pane('clear-storage')}`});
385
+ this.#view = view;
271
386
  this.registerRequiredCSS(storageViewStyles);
272
- this.clearSiteDataView = clearSiteDataView;
273
-
274
- this.contentElement.classList.add('clear-storage-container');
275
- this.contentElement.setAttribute('jslog', `${VisualLogging.pane('clear-storage')}`);
276
387
  this.pieColors = storagePieColors;
277
388
 
278
- // TODO(crbug.com/1156978): Replace UI.ReportView.ReportView with ReportView.ts web component.
279
- this.reportView = new UI.ReportView.ReportView(i18nString(UIStrings.storageTitle));
280
- this.reportView.registerRequiredCSS(storageViewStyles);
281
-
282
- this.reportView.element.classList.add('clear-storage-header');
283
- this.reportView.show(this.contentElement);
284
-
285
389
  this.settings = new Map();
286
390
  for (const type of AllStorageTypes) {
287
391
  this.settings.set(
@@ -293,54 +397,6 @@ export class StorageView extends UI.Widget.VBox {
293
397
  this.includeThirdPartyCookiesSetting =
294
398
  Common.Settings.Settings.instance().createSetting('clear-storage-include-third-party-cookies', false);
295
399
 
296
- const clearSiteData = this.reportView.appendSection(i18nString(UIStrings.clearSiteData));
297
- clearSiteData.element.setAttribute('jslog', `${VisualLogging.section('clear-storage')}`);
298
- this.clearSiteDataFieldList = clearSiteData.getFieldElement();
299
- clearSiteData.markFieldListAsGroup();
300
-
301
- const quota = this.reportView.appendSection(i18nString(UIStrings.usage));
302
- quota.element.setAttribute('jslog', `${VisualLogging.section('usage')}`);
303
- this.quotaRow = quota.appendSelectableRow();
304
- this.quotaRow.classList.add('quota-usage-row');
305
- this.quotaRow.setAttribute('jslog', `${VisualLogging.item('storage-usage')}`);
306
- const learnMoreRow = quota.appendRow();
307
- const learnMore = Link.create(
308
- 'https://developer.chrome.com/docs/devtools/progressive-web-apps#opaque-responses',
309
- i18nString(UIStrings.learnMore), undefined, 'learn-more');
310
- learnMoreRow.appendChild(learnMore);
311
- this.pieChart = new PerfUI.PieChart.PieChart();
312
- const usageBreakdownRow = quota.appendRow();
313
- usageBreakdownRow.classList.add('usage-breakdown-row');
314
- usageBreakdownRow.setAttribute('jslog', `${VisualLogging.item('usage-breakdown')}`);
315
- usageBreakdownRow.appendChild(this.pieChart);
316
-
317
- const quotaOverrideCheckboxRow = quota.appendRow();
318
- quotaOverrideCheckboxRow.classList.add('quota-override-row');
319
- this.quotaOverrideCheckbox = UI.UIUtils.CheckboxLabel.create(i18nString(UIStrings.simulateCustomStorage), false);
320
- this.quotaOverrideCheckbox.setAttribute(
321
- 'jslog', `${VisualLogging.toggle('simulate-custom-quota').track({change: true})}`);
322
- quotaOverrideCheckboxRow.appendChild(this.quotaOverrideCheckbox);
323
- this.quotaOverrideCheckbox.addEventListener('click', this.onClickCheckbox.bind(this), false);
324
- this.quotaOverrideControlRow = quota.appendRow();
325
- this.quotaOverrideEditor = this.quotaOverrideControlRow.createChild('input', 'quota-override-notification-editor');
326
- this.quotaOverrideEditor.setAttribute('placeholder', i18nString(UIStrings.pleaseEnterANumber));
327
- this.quotaOverrideEditor.setAttribute(
328
- 'jslog', `${VisualLogging.textField('quota-override').track({change: true})}`);
329
- this.quotaOverrideControlRow.appendChild(UI.UIUtils.createLabel(i18nString(UIStrings.mb)));
330
- this.quotaOverrideEditor.addEventListener('keyup', event => {
331
- if (event.key === 'Enter') {
332
- void this.applyQuotaOverrideFromInputField();
333
- event.consume(true);
334
- }
335
- });
336
- this.quotaOverrideEditor.addEventListener('focusout', event => {
337
- void this.applyQuotaOverrideFromInputField();
338
- event.consume(true);
339
- });
340
-
341
- const errorMessageRow = quota.appendRow();
342
- this.quotaOverrideErrorMessage = errorMessageRow.createChild('div', 'quota-override-error');
343
-
344
400
  const cookiesSetting = this.settings.get(Protocol.Storage.StorageType.Cookies);
345
401
  this.onCookiesSettingChanged(Boolean(cookiesSetting?.get()));
346
402
  SDK.TargetManager.TargetManager.instance().observeTargets(this);
@@ -463,18 +519,18 @@ export class StorageView extends UI.Widget.VBox {
463
519
  this.requestUpdate();
464
520
  }
465
521
 
466
- private async applyQuotaOverrideFromInputField(): Promise<void> {
522
+ private async applyQuotaOverrideFromInputField(editorString: string): Promise<void> {
523
+ this.quotaOverrideFieldValue = editorString;
467
524
  if (!this.target || !this.securityOrigin) {
468
525
  this.quotaOverrideError = i18nString(UIStrings.internalError);
469
526
  this.requestUpdate();
470
527
  return;
471
528
  }
472
529
  this.quotaOverrideError = '';
473
- this.requestUpdate();
474
- const editorString = this.quotaOverrideEditor.value;
475
530
  if (editorString === '') {
476
531
  await this.clearQuotaForOrigin(this.target, this.securityOrigin);
477
532
  this.previousOverrideFieldValue = '';
533
+ this.requestUpdate();
478
534
  return;
479
535
  }
480
536
  const quota = parseFloat(editorString);
@@ -497,8 +553,9 @@ export class StorageView extends UI.Widget.VBox {
497
553
  const bytesPerMB = 1000 * 1000;
498
554
  const quotaInBytes = Math.round(quota * bytesPerMB);
499
555
  const quotaFieldValue = `${quotaInBytes / bytesPerMB}`;
500
- this.quotaOverrideEditor.value = quotaFieldValue;
501
556
  this.previousOverrideFieldValue = quotaFieldValue;
557
+ this.quotaOverrideFieldValue = quotaFieldValue;
558
+ this.requestUpdate();
502
559
  await this.target.storageAgent().invoke_overrideQuotaForOrigin(
503
560
  {origin: this.securityOrigin, quotaSize: quotaInBytes});
504
561
  }
@@ -510,10 +567,10 @@ export class StorageView extends UI.Widget.VBox {
510
567
  private async onClickCheckbox(): Promise<void> {
511
568
  if (!this.quotaOverrideEnabled) {
512
569
  this.quotaOverrideEnabled = true;
513
- this.quotaOverrideEditor.value = this.previousOverrideFieldValue;
570
+ this.quotaOverrideFieldValue = this.previousOverrideFieldValue;
514
571
  this.requestUpdate();
515
572
  await this.updateComplete;
516
- this.quotaOverrideEditor.focus();
573
+ this.#viewOutput.focusQuotaOverrideEditor?.();
517
574
  } else {
518
575
  this.quotaOverrideEnabled = false;
519
576
  this.quotaOverrideError = '';
@@ -551,7 +608,7 @@ export class StorageView extends UI.Widget.VBox {
551
608
  this.requestUpdate();
552
609
  await this.updateComplete;
553
610
  if (this.isShowing()) {
554
- this.clearSiteDataViewOutput.focusClearButton?.();
611
+ this.#viewOutput.focusClearButton?.();
555
612
  }
556
613
  }, 500);
557
614
 
@@ -675,67 +732,32 @@ export class StorageView extends UI.Widget.VBox {
675
732
  }
676
733
 
677
734
  override performUpdate(): void {
678
- if (this.subtitle !== null) {
679
- this.reportView.setSubtitle(this.subtitle);
680
- }
681
735
  const cookiesSetting = this.settings.get(Protocol.Storage.StorageType.Cookies);
682
- this.clearSiteDataView({
736
+ this.#view({
737
+ subtitle: this.subtitle,
683
738
  settings: this.settings,
684
739
  includeThirdPartyCookiesSetting: this.includeThirdPartyCookiesSetting,
685
740
  includeThirdPartyCookiesDisabled: !cookiesSetting?.get(),
686
741
  clearing: this.clearing,
742
+ quotaUsage: this.quotaUsage,
743
+ quotaQuota: this.quotaQuota,
744
+ quotaOverrideActive: this.quotaOverrideActive,
745
+ pieChartSlices: this.pieChartSlices,
746
+ quotaOverrideEnabled: this.quotaOverrideEnabled,
747
+ quotaOverrideValue: this.quotaOverrideFieldValue,
748
+ quotaOverrideError: this.quotaOverrideError,
687
749
  onClear: () => this.clear(),
750
+ onToggleQuotaOverride: () => {
751
+ void this.onClickCheckbox();
752
+ },
753
+ onQuotaOverrideInput: value => {
754
+ this.quotaOverrideFieldValue = value;
755
+ },
756
+ onApplyQuotaOverride: value => {
757
+ void this.applyQuotaOverrideFromInputField(value);
758
+ },
688
759
  },
689
- this.clearSiteDataViewOutput, this.clearSiteDataFieldList);
690
- this.renderQuotaRow();
691
- this.populatePieChart();
692
- this.quotaOverrideControlRow.classList.toggle('hidden', !this.quotaOverrideEnabled);
693
- this.quotaOverrideCheckbox.checked = this.quotaOverrideEnabled;
694
- this.quotaOverrideErrorMessage.textContent = this.quotaOverrideError;
695
- }
696
-
697
- private renderQuotaRow(): void {
698
- this.quotaRow.textContent = '';
699
- if (this.quotaUsage === null || this.quotaQuota === null) {
700
- return;
701
- }
702
- const quotaAsString = i18n.ByteUtilities.bytesToString(this.quotaQuota);
703
- const usageAsString = i18n.ByteUtilities.bytesToString(this.quotaUsage);
704
- const formattedQuotaAsString = i18nString(UIStrings.storageWithCustomMarker, {PH1: quotaAsString});
705
-
706
- let quota: string|HTMLElement = quotaAsString;
707
- if (this.quotaOverrideActive) {
708
- const element = document.createElement('b');
709
- element.textContent = formattedQuotaAsString;
710
- quota = element;
711
- }
712
-
713
- const element = uiI18n.getFormatLocalizedString(str_, UIStrings.storageQuotaUsed, {PH1: usageAsString, PH2: quota});
714
- this.quotaRow.appendChild(element);
715
- UI.Tooltip.Tooltip.install(
716
- this.quotaRow,
717
- i18nString(UIStrings.storageQuotaUsedWithBytes,
718
- {PH1: this.quotaUsage.toLocaleString(), PH2: this.quotaQuota.toLocaleString()}));
719
-
720
- if (!this.quotaOverrideActive && this.quotaQuota < 125829120) { // 120 MiB
721
- const icon = new Icon();
722
- icon.name = 'info';
723
- icon.style.color = 'var(--icon-info)';
724
- icon.classList.add('small');
725
- UI.Tooltip.Tooltip.install(icon, i18nString(UIStrings.storageQuotaIsLimitedIn));
726
- this.quotaRow.appendChild(icon);
727
- }
728
- }
729
-
730
- private populatePieChart(): void {
731
- this.pieChart.data = {
732
- chartName: i18nString(UIStrings.storageUsage),
733
- size: 110,
734
- formatter: i18n.ByteUtilities.bytesToString,
735
- showLegend: true,
736
- total: this.quotaUsage ?? 0,
737
- slices: this.pieChartSlices,
738
- };
760
+ this.#viewOutput, this.contentElement);
739
761
  }
740
762
 
741
763
  static getStorageTypeName(type: Protocol.Storage.StorageType): string {
@@ -18,11 +18,11 @@ const UIStrings = {
18
18
  /**
19
19
  * @description Heading label for Sub Apps view
20
20
  */
21
- subApps: 'Sub Apps',
21
+ subApps: 'Sub apps',
22
22
  /**
23
23
  * @description Heading label for Sibling Sub Apps view
24
24
  */
25
- siblingSubApps: 'Sibling Sub Apps',
25
+ siblingSubApps: 'Sibling sub apps',
26
26
  /**
27
27
  * @description Column header for the sub-app name
28
28
  */