chrome-devtools-frontend 1.0.1534717 → 1.0.1536371

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/docs/contributing/images/issues-nearestslo.png +0 -0
  2. package/docs/contributing/issues.md +32 -58
  3. package/eslint.config.mjs +1 -0
  4. package/front_end/core/common/Console.ts +1 -8
  5. package/front_end/core/common/ParsedURL.ts +10 -20
  6. package/front_end/core/common/SegmentedRange.ts +1 -2
  7. package/front_end/core/common/StringOutputStream.ts +1 -4
  8. package/front_end/core/host/InspectorFrontendHost.ts +6 -0
  9. package/front_end/core/host/UserMetrics.ts +5 -1
  10. package/front_end/core/i18n/i18nImpl.ts +0 -24
  11. package/front_end/core/protocol_client/CDPConnection.ts +53 -5
  12. package/front_end/core/protocol_client/protocol_client.ts +2 -0
  13. package/front_end/core/sdk/AnimationModel.ts +1 -2
  14. package/front_end/core/sdk/CSSMatchedStyles.ts +2 -2
  15. package/front_end/core/sdk/CSSModel.ts +1 -1
  16. package/front_end/core/sdk/CSSProperty.ts +3 -6
  17. package/front_end/core/sdk/CSSStyleDeclaration.ts +4 -4
  18. package/front_end/core/sdk/DebuggerModel.ts +1 -2
  19. package/front_end/core/sdk/EnhancedTracesParser.ts +4 -0
  20. package/front_end/core/sdk/SourceMap.ts +2 -3
  21. package/front_end/devtools_compatibility.js +32 -24
  22. package/front_end/entrypoints/node_app/NodeConnectionsPanel.ts +2 -1
  23. package/front_end/generated/InspectorBackendCommands.js +1 -2
  24. package/front_end/generated/SupportedCSSProperties.js +57 -0
  25. package/front_end/generated/protocol.ts +0 -27
  26. package/front_end/panels/accessibility/AccessibilityNodeView.ts +18 -17
  27. package/front_end/panels/accessibility/AccessibilitySidebarView.ts +9 -12
  28. package/front_end/panels/ai_assistance/PatchWidget.ts +39 -40
  29. package/front_end/panels/ai_assistance/components/ChatView.ts +5 -4
  30. package/front_end/panels/ai_assistance/components/ExploreWidget.ts +0 -2
  31. package/front_end/panels/application/AppManifestView.ts +7 -6
  32. package/front_end/panels/application/ApplicationPanelSidebar.ts +4 -4
  33. package/front_end/panels/application/OpenedWindowDetailsView.ts +6 -6
  34. package/front_end/panels/application/StorageView.ts +9 -8
  35. package/front_end/panels/application/components/BackForwardCacheView.ts +333 -314
  36. package/front_end/panels/application/components/ProtocolHandlersView.ts +3 -2
  37. package/front_end/panels/application/preloading/components/PreloadingDisabledInfobar.ts +2 -1
  38. package/front_end/panels/autofill/AutofillView.ts +2 -3
  39. package/front_end/panels/browser_debugger/ObjectEventListenersSidebarPane.ts +8 -8
  40. package/front_end/panels/changes/CombinedDiffView.ts +13 -14
  41. package/front_end/panels/common/BadgeNotification.ts +2 -1
  42. package/front_end/panels/common/GdpSignUpDialog.ts +2 -1
  43. package/front_end/panels/console/ConsoleInsightTeaser.ts +13 -2
  44. package/front_end/panels/console/ConsolePinPane.ts +12 -7
  45. package/front_end/panels/console/ConsoleView.ts +1 -0
  46. package/front_end/panels/console/consoleView.css +0 -1
  47. package/front_end/panels/developer_resources/DeveloperResourcesView.ts +9 -9
  48. package/front_end/panels/elements/ComputedStyleWidget.ts +7 -7
  49. package/front_end/panels/elements/ElementsTreeOutline.ts +1 -1
  50. package/front_end/panels/elements/EventListenersWidget.ts +9 -9
  51. package/front_end/panels/elements/NodeStackTraceWidget.ts +6 -6
  52. package/front_end/panels/elements/PlatformFontsWidget.ts +5 -5
  53. package/front_end/panels/elements/PropertiesWidget.ts +8 -8
  54. package/front_end/panels/layer_viewer/Layers3DView.ts +2 -1
  55. package/front_end/panels/layer_viewer/PaintProfilerView.ts +3 -3
  56. package/front_end/panels/network/RequestCookiesView.ts +2 -1
  57. package/front_end/panels/network/RequestTimingView.ts +2 -1
  58. package/front_end/panels/network/components/DirectSocketConnectionView.ts +4 -6
  59. package/front_end/panels/recorder/RecorderController.ts +34 -23
  60. package/front_end/panels/recorder/components/CreateRecordingView.ts +249 -240
  61. package/front_end/panels/security/CookieControlsView.ts +74 -67
  62. package/front_end/panels/security/CookieReportView.ts +18 -16
  63. package/front_end/panels/security/IPProtectionView.ts +1 -2
  64. package/front_end/panels/security/SecurityPanel.ts +19 -19
  65. package/front_end/panels/settings/AISettingsTab.ts +2 -1
  66. package/front_end/panels/settings/KeybindsSettingsTab.ts +6 -0
  67. package/front_end/panels/settings/components/SyncSection.ts +2 -1
  68. package/front_end/panels/sources/DebuggerPausedMessage.ts +4 -3
  69. package/front_end/panels/sources/ResourceOriginPlugin.ts +3 -2
  70. package/front_end/panels/sources/SourcesNavigator.ts +2 -1
  71. package/front_end/panels/sources/TabbedEditorContainer.ts +3 -2
  72. package/front_end/panels/sources/WatchExpressionsSidebarPane.ts +9 -9
  73. package/front_end/panels/timeline/TimelineSelectorStatsView.ts +36 -36
  74. package/front_end/panels/timeline/TimelineUIUtils.ts +3 -2
  75. package/front_end/panels/timeline/components/DetailsView.ts +5 -4
  76. package/front_end/panels/timeline/components/FieldSettingsDialog.ts +2 -1
  77. package/front_end/panels/timeline/components/LiveMetricsView.ts +5 -4
  78. package/front_end/panels/timeline/components/MetricCompareStrings.ts +25 -24
  79. package/front_end/panels/timeline/components/SidebarAnnotationsTab.ts +1 -2
  80. package/front_end/panels/timeline/components/insights/LCPDiscovery.ts +2 -1
  81. package/front_end/third_party/chromium/README.chromium +1 -1
  82. package/front_end/ui/components/docs/tooltip/basic.ts +1 -1
  83. package/front_end/ui/components/tooltips/Tooltip.ts +32 -17
  84. package/front_end/ui/i18n/i18n.ts +31 -0
  85. package/front_end/ui/legacy/SoftDropDown.ts +1 -12
  86. package/front_end/ui/legacy/ViewManager.ts +2 -4
  87. package/front_end/ui/legacy/Widget.ts +33 -17
  88. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +2 -1
  89. package/front_end/ui/legacy/legacy.ts +0 -2
  90. package/front_end/ui/visual_logging/KnownContextValues.ts +5 -0
  91. package/mcp/mcp.ts +1 -0
  92. package/package.json +1 -1
  93. package/front_end/ui/components/docs/recorder_create_recording_view/basic.html +0 -20
  94. package/front_end/ui/components/docs/recorder_create_recording_view/basic.ts +0 -27
  95. package/front_end/ui/legacy/ThrottledWidget.ts +0 -48
@@ -1,7 +1,6 @@
1
1
  // Copyright 2024 The Chromium Authors
2
2
  // Use of this source code is governed by a BSD-style license that can be
3
3
  // found in the LICENSE file.
4
- /* eslint-disable @devtools/no-lit-render-outside-of-view */
5
4
 
6
5
  import '../../ui/components/switch/switch.js';
7
6
  import '../../ui/components/cards/cards.js';
@@ -14,15 +13,15 @@ import type * as Platform from '../../core/platform/platform.js';
14
13
  import * as Root from '../../core/root/root.js';
15
14
  import * as SDK from '../../core/sdk/sdk.js';
16
15
  import * as Buttons from '../../ui/components/buttons/buttons.js';
17
- import * as ChromeLink from '../../ui/components/chrome_link/chrome_link.js';
18
16
  import * as Input from '../../ui/components/input/input.js';
17
+ import * as uiI18n from '../../ui/i18n/i18n.js';
19
18
  import * as UI from '../../ui/legacy/legacy.js';
20
- import * as Lit from '../../ui/lit/lit.js';
19
+ import {Directives, html, nothing, render, type TemplateResult} from '../../ui/lit/lit.js';
21
20
  import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
22
21
 
23
22
  import cookieControlsViewStyles from './cookieControlsView.css.js';
24
23
 
25
- const {render, html} = Lit;
24
+ const {ref} = Directives;
26
25
 
27
26
  const UIStrings = {
28
27
  /**
@@ -115,55 +114,53 @@ const UIStrings = {
115
114
 
116
115
  const str_ = i18n.i18n.registerUIStrings('panels/security/CookieControlsView.ts', UIStrings);
117
116
  export const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
118
- export const i18nFormatString = i18n.i18n.getFormatLocalizedString.bind(undefined, str_);
117
+ export const i18nFormatString = uiI18n.getFormatLocalizedString.bind(undefined, str_);
119
118
 
120
119
  export interface ViewInput {
120
+ thirdPartyControlsDict: Root.Runtime.HostConfig['thirdPartyCookieControls'];
121
+ isGracePeriodActive: boolean;
121
122
  inputChanged: (newValue: boolean, setting: Common.Settings.Setting<boolean>) => void;
122
123
  openChromeCookieSettings: () => void;
123
124
  }
124
125
 
125
126
  export type View = (input: ViewInput, output: object, target: HTMLElement) => void;
126
127
 
127
- export function showInfobar(): void {
128
- UI.InspectorView.InspectorView.instance().displayDebuggedTabReloadRequiredWarning(
129
- i18nString(UIStrings.siteReloadMessage));
128
+ function getChromeFlagsLink(flag: string): TemplateResult {
129
+ return html`
130
+ <devtools-chrome-link href="chrome://flags/#${flag}" tabindex="0">
131
+ ${flag}
132
+ </devtools-chrome-link>`;
130
133
  }
134
+ const DEFAULT_VIEW: View = (input: ViewInput, _output: object, target: HTMLElement): void => {
135
+ // createSetting() allows us to initialize the settings with the UI binding values the first
136
+ // time that the browser starts, and use the existing setting value for all subsequent uses.
137
+ const enterpriseEnabledSetting = Common.Settings.Settings.instance().createSetting(
138
+ 'enterprise-enabled',
139
+ input.thirdPartyControlsDict && input.thirdPartyControlsDict.managedBlockThirdPartyCookies &&
140
+ typeof input.thirdPartyControlsDict.managedBlockThirdPartyCookies === 'boolean' ?
141
+ input.thirdPartyControlsDict.managedBlockThirdPartyCookies :
142
+ false,
143
+ Common.Settings.SettingStorageType.GLOBAL);
144
+ const toggleEnabledSetting = Common.Settings.Settings.instance().createSetting(
145
+ 'cookie-control-override-enabled',
146
+ input.thirdPartyControlsDict?.thirdPartyCookieRestrictionEnabled ?
147
+ input.thirdPartyControlsDict.thirdPartyCookieRestrictionEnabled :
148
+ false,
149
+ Common.Settings.SettingStorageType.GLOBAL);
150
+ const gracePeriodDisabledSetting = Common.Settings.Settings.instance().createSetting(
151
+ 'grace-period-mitigation-disabled',
152
+ input.thirdPartyControlsDict?.thirdPartyCookieMetadataEnabled ?
153
+ input.thirdPartyControlsDict.thirdPartyCookieMetadataEnabled :
154
+ true,
155
+ Common.Settings.SettingStorageType.GLOBAL);
156
+ const heuristicsDisabledSetting = Common.Settings.Settings.instance().createSetting(
157
+ 'heuristic-mitigation-disabled',
158
+ input.thirdPartyControlsDict?.thirdPartyCookieHeuristicsEnabled ?
159
+ input.thirdPartyControlsDict.thirdPartyCookieHeuristicsEnabled :
160
+ true,
161
+ Common.Settings.SettingStorageType.GLOBAL);
131
162
 
132
- export class CookieControlsView extends UI.Widget.VBox {
133
- #view: View;
134
- #isGracePeriodActive: boolean;
135
- #thirdPartyControlsDict: Root.Runtime.HostConfig['thirdPartyCookieControls'];
136
-
137
- constructor(element?: HTMLElement, view: View = (input, _, target) => {
138
- // createSetting() allows us to initialize the settings with the UI binding values the first
139
- // time that the browser starts, and use the existing setting value for all subsequent uses.
140
- const enterpriseEnabledSetting = Common.Settings.Settings.instance().createSetting(
141
- 'enterprise-enabled',
142
- this.#thirdPartyControlsDict && this.#thirdPartyControlsDict.managedBlockThirdPartyCookies &&
143
- typeof this.#thirdPartyControlsDict.managedBlockThirdPartyCookies === 'boolean' ?
144
- this.#thirdPartyControlsDict.managedBlockThirdPartyCookies :
145
- false,
146
- Common.Settings.SettingStorageType.GLOBAL);
147
- const toggleEnabledSetting = Common.Settings.Settings.instance().createSetting(
148
- 'cookie-control-override-enabled',
149
- this.#thirdPartyControlsDict && this.#thirdPartyControlsDict.thirdPartyCookieRestrictionEnabled ?
150
- this.#thirdPartyControlsDict.thirdPartyCookieRestrictionEnabled :
151
- false,
152
- Common.Settings.SettingStorageType.GLOBAL);
153
- const gracePeriodDisabledSetting = Common.Settings.Settings.instance().createSetting(
154
- 'grace-period-mitigation-disabled',
155
- this.#thirdPartyControlsDict && this.#thirdPartyControlsDict.thirdPartyCookieMetadataEnabled ?
156
- this.#thirdPartyControlsDict.thirdPartyCookieMetadataEnabled :
157
- true,
158
- Common.Settings.SettingStorageType.GLOBAL);
159
- const heuristicsDisabledSetting = Common.Settings.Settings.instance().createSetting(
160
- 'heuristic-mitigation-disabled',
161
- this.#thirdPartyControlsDict && this.#thirdPartyControlsDict.thirdPartyCookieHeuristicsEnabled ?
162
- this.#thirdPartyControlsDict.thirdPartyCookieHeuristicsEnabled :
163
- true,
164
- Common.Settings.SettingStorageType.GLOBAL);
165
-
166
- // clang-format off
163
+ // clang-format off
167
164
  const cardHeader = html `
168
165
  <div class="card-header">
169
166
  <div class="lhs">
@@ -175,11 +172,11 @@ export class CookieControlsView extends UI.Widget.VBox {
175
172
  <devtools-icon
176
173
  tabindex="0"
177
174
  name="domain"
178
- ${Lit.Directives.ref((el: Element|undefined) => {
175
+ ${ref((el: Element|undefined) => {
179
176
  UI.Tooltip.Tooltip.install(el as HTMLElement, i18nString(UIStrings.enterpriseTooltip));
180
177
  (el as HTMLElement).role = 'img';
181
178
  })}>
182
- </devtools-icon>` : Lit.nothing
179
+ </devtools-icon>` : nothing
183
180
  }
184
181
  </div>
185
182
  <div>
@@ -197,8 +194,8 @@ export class CookieControlsView extends UI.Widget.VBox {
197
194
  `;
198
195
 
199
196
  const gracePeriodControlDisabled =
200
- (this.#thirdPartyControlsDict ? (!this.#thirdPartyControlsDict.thirdPartyCookieMetadataEnabled) : false) ||
201
- enterpriseEnabledSetting.get() || !toggleEnabledSetting.get() || !this.#isGracePeriodActive;
197
+ (input.thirdPartyControlsDict ? (!input.thirdPartyControlsDict.thirdPartyCookieMetadataEnabled) : false) ||
198
+ enterpriseEnabledSetting.get() || !toggleEnabledSetting.get() || !input.isGracePeriodActive;
202
199
  const gracePeriodControl = html`
203
200
  <div class="card-row">
204
201
  <label class='checkbox-label'>
@@ -215,11 +212,11 @@ export class CookieControlsView extends UI.Widget.VBox {
215
212
  i18nFormatString(UIStrings.gracePeriodExplanation, {
216
213
  PH1: i18nString(UIStrings.gracePeriod),
217
214
  }) :
218
- (this.#thirdPartyControlsDict ? !this.#thirdPartyControlsDict?.thirdPartyCookieMetadataEnabled: false) ?
215
+ (input.thirdPartyControlsDict ? !input.thirdPartyControlsDict?.thirdPartyCookieMetadataEnabled: false) ?
219
216
  i18nFormatString(UIStrings.enableFlag, {
220
- PH1: this.getChromeFlagsLink(UIStrings.tpcdMetadataGrants),
217
+ PH1: getChromeFlagsLink(UIStrings.tpcdMetadataGrants),
221
218
  }) :
222
- i18nFormatString(this.#isGracePeriodActive ? UIStrings.gracePeriodExplanation : UIStrings.enrollGracePeriod, {
219
+ i18nFormatString(input.isGracePeriodActive ? UIStrings.gracePeriodExplanation : UIStrings.enrollGracePeriod, {
223
220
  PH1: UI.Fragment.html`<x-link class="devtools-link" href="https://developers.google.com/privacy-sandbox/cookies/temporary-exceptions/grace-period" jslog=${VisualLogging.link('grace-period-link').track({click: true})}>${i18nString(UIStrings.gracePeriod)}</x-link>`,
224
221
  })
225
222
  }
@@ -230,7 +227,7 @@ export class CookieControlsView extends UI.Widget.VBox {
230
227
  `;
231
228
 
232
229
  const heuristicsControlDisabled =
233
- (this.#thirdPartyControlsDict ? (!this.#thirdPartyControlsDict.thirdPartyCookieHeuristicsEnabled) : false) ||
230
+ (input.thirdPartyControlsDict ? (!input.thirdPartyControlsDict.thirdPartyCookieHeuristicsEnabled) : false) ||
234
231
  enterpriseEnabledSetting.get() || !toggleEnabledSetting.get();
235
232
  const heuristicControl = html`
236
233
  <div class="card-row">
@@ -248,9 +245,9 @@ export class CookieControlsView extends UI.Widget.VBox {
248
245
  i18nFormatString(UIStrings.heuristicExplanation, {
249
246
  PH1: i18nString(UIStrings.scenarios),
250
247
  }) :
251
- (this.#thirdPartyControlsDict ? !this.#thirdPartyControlsDict.thirdPartyCookieHeuristicsEnabled: false) ?
248
+ (input.thirdPartyControlsDict ? !input.thirdPartyControlsDict.thirdPartyCookieHeuristicsEnabled: false) ?
252
249
  i18nFormatString(UIStrings.enableFlag, {
253
- PH1: this.getChromeFlagsLink(UIStrings.tpcdHeuristicsGrants),
250
+ PH1: getChromeFlagsLink(UIStrings.tpcdHeuristicsGrants),
254
251
  }) :
255
252
  i18nFormatString(UIStrings.heuristicExplanation, {
256
253
  PH1: UI.Fragment.html`<x-link class="devtools-link" href="https://developers.google.com/privacy-sandbox/cookies/temporary-exceptions/heuristics-based-exceptions" jslog=${VisualLogging.link('heuristic-link').track({click: true})}>${i18nString(UIStrings.scenarios)}</x-link>`,
@@ -300,12 +297,24 @@ export class CookieControlsView extends UI.Widget.VBox {
300
297
  </div>
301
298
  </div>
302
299
  </devtools-card>
303
- ${Boolean(enterpriseEnabledSetting.get()) ? enterpriseDisclaimer : Lit.nothing}
300
+ ${Boolean(enterpriseEnabledSetting.get()) ? enterpriseDisclaimer : nothing}
304
301
  </div>
305
302
  </div>
306
- `, target, {host: this});
307
- // clang-format on
308
- }) {
303
+ `, target);
304
+ // clang-format on
305
+ };
306
+
307
+ export function showInfobar(): void {
308
+ UI.InspectorView.InspectorView.instance().displayDebuggedTabReloadRequiredWarning(
309
+ i18nString(UIStrings.siteReloadMessage));
310
+ }
311
+
312
+ export class CookieControlsView extends UI.Widget.VBox {
313
+ #view: View;
314
+ #isGracePeriodActive: boolean;
315
+ #thirdPartyControlsDict: Root.Runtime.HostConfig['thirdPartyCookieControls'];
316
+
317
+ constructor(element?: HTMLElement, view: View = DEFAULT_VIEW) {
309
318
  super(element, {useShadowDom: true});
310
319
  this.#view = view;
311
320
  this.#isGracePeriodActive = false;
@@ -327,7 +336,14 @@ export class CookieControlsView extends UI.Widget.VBox {
327
336
  }
328
337
 
329
338
  override performUpdate(): void {
330
- this.#view(this, this, this.contentElement);
339
+ this.#view(
340
+ {
341
+ thirdPartyControlsDict: this.#thirdPartyControlsDict,
342
+ isGracePeriodActive: this.#isGracePeriodActive,
343
+ inputChanged: this.inputChanged.bind(this),
344
+ openChromeCookieSettings: this.openChromeCookieSettings.bind(this),
345
+ },
346
+ this, this.contentElement);
331
347
  }
332
348
 
333
349
  inputChanged(newValue: boolean, setting: Common.Settings.Setting<boolean>): void {
@@ -390,13 +406,4 @@ export class CookieControlsView extends UI.Widget.VBox {
390
406
  this.requestUpdate();
391
407
  }
392
408
  }
393
-
394
- getChromeFlagsLink(flag: string): Element {
395
- const link = new ChromeLink.ChromeLink.ChromeLink();
396
- link.textContent = flag;
397
- link.href = ('chrome://flags/' + flag) as Platform.DevToolsPath.UrlString;
398
- link.setAttribute('tabindex', '0');
399
-
400
- return link;
401
- }
402
409
  }
@@ -12,6 +12,7 @@ import * as SDK from '../../core/sdk/sdk.js';
12
12
  import * as Protocol from '../../generated/protocol.js';
13
13
  import * as IssuesManager from '../../models/issues_manager/issues_manager.js';
14
14
  import type * as TextUtils from '../../models/text_utils/text_utils.js';
15
+ import * as uiI18n from '../../ui/i18n/i18n.js';
15
16
  import * as UI from '../../ui/legacy/legacy.js';
16
17
  import * as Lit from '../../ui/lit/lit.js';
17
18
  import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
@@ -196,17 +197,8 @@ export interface CookieReportNodeData {
196
197
  }
197
198
 
198
199
  export type View = (input: ViewInput, output: ViewOutput, target: HTMLElement) => void;
199
-
200
- export class CookieReportView extends UI.Widget.VBox {
201
- #issuesManager?: IssuesManager.IssuesManager.IssuesManager;
202
- namedBitSetFilterUI?: UI.FilterBar.NamedBitSetFilterUI;
203
- #cookieRows = new Map<string, IssuesManager.CookieIssue.CookieReportInfo>();
204
- #view: View;
205
- filterItems: UI.FilterBar.Item[] = [];
206
- searchText: string;
207
-
208
- constructor(element?: HTMLElement, view: View = (input, output, target) => {
209
- // clang-format off
200
+ const DEFAULT_VIEW: View = (input, output, target) => {
201
+ // clang-format off
210
202
  render(html `
211
203
  <div class="report overflow-auto">
212
204
  <div class="header">
@@ -283,9 +275,19 @@ export class CookieReportView extends UI.Widget.VBox {
283
275
  }
284
276
 
285
277
  </div>
286
- `, target, {host: this});
287
- // clang-format on
288
- }) {
278
+ `, target);
279
+ // clang-format on
280
+ };
281
+
282
+ export class CookieReportView extends UI.Widget.VBox {
283
+ #issuesManager?: IssuesManager.IssuesManager.IssuesManager;
284
+ namedBitSetFilterUI?: UI.FilterBar.NamedBitSetFilterUI;
285
+ #cookieRows = new Map<string, IssuesManager.CookieIssue.CookieReportInfo>();
286
+ #view: View;
287
+ filterItems: UI.FilterBar.Item[] = [];
288
+ searchText: string;
289
+
290
+ constructor(element?: HTMLElement, view: View = DEFAULT_VIEW) {
289
291
  super(element, {useShadowDom: true});
290
292
  this.#view = view;
291
293
  this.registerRequiredCSS(cookieReportViewStyles);
@@ -447,7 +449,7 @@ export class CookieReportView extends UI.Widget.VBox {
447
449
  'https://github.com/privacysandbox/privacy-sandbox-dev-support/blob/main/3pc-migration-readiness.md',
448
450
  i18nString(UIStrings.guidance), undefined, undefined, 'readiness-list-link');
449
451
 
450
- return html`${i18n.i18n.getFormatLocalizedString(str_, UIStrings.gitHubResource, {
452
+ return html`${uiI18n.getFormatLocalizedString(str_, UIStrings.gitHubResource, {
451
453
  PH1: githubLink,
452
454
  })}`;
453
455
  }
@@ -460,7 +462,7 @@ export class CookieReportView extends UI.Widget.VBox {
460
462
  (domain.charAt(0) === '.' ? domain.substring(1) : domain),
461
463
  i18nString(UIStrings.reportedIssues), undefined, undefined, 'compatibility-lookup-link');
462
464
 
463
- return html`${i18n.i18n.getFormatLocalizedString(str_, UIStrings.gracePeriod, {
465
+ return html`${uiI18n.getFormatLocalizedString(str_, UIStrings.gracePeriod, {
464
466
  PH1: gracePeriodLink,
465
467
  })}`;
466
468
  }
@@ -1,7 +1,6 @@
1
1
  // Copyright 2025 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-lit-render-outside-of-view */
5
4
 
6
5
  import '../../ui/components/switch/switch.js';
7
6
  import '../../ui/components/cards/cards.js';
@@ -136,7 +135,7 @@ export interface ViewInput {
136
135
  }
137
136
  export type View = (input: ViewInput, output: object, target: HTMLElement) => void;
138
137
 
139
- export const DEFAULT_VIEW: View = (input, _, target) => {
138
+ export const DEFAULT_VIEW: View = (input, _output, target) => {
140
139
  const {status} = input;
141
140
  const statusText = status ? i18nString(UIStrings[status]) : i18nString(UIStrings.statusUnknown);
142
141
 
@@ -2,7 +2,6 @@
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
  /* eslint-disable @devtools/no-imperative-dom-api */
5
- /* eslint-disable @devtools/no-lit-render-outside-of-view */
6
5
 
7
6
  import * as Common from '../../core/common/common.js';
8
7
  import * as Host from '../../core/host/host.js';
@@ -549,6 +548,24 @@ export interface ViewOutput {
549
548
 
550
549
  export type View = (input: ViewInput, output: ViewOutput, target: HTMLElement) => void;
551
550
 
551
+ const DEFAULT_VIEW: View = (input: ViewInput, output: ViewOutput, target: HTMLElement): void => {
552
+ // clang-format off
553
+ render(html`
554
+ <devtools-split-view direction="column" name="security"
555
+ ${UI.Widget.widgetRef(UI.SplitWidget.SplitWidget, e => {output.splitWidget = e;})}>
556
+ <devtools-widget
557
+ slot="sidebar"
558
+ .widgetConfig=${widgetConfig(SecurityPanelSidebar)}
559
+ @showIPProtection=${() => output.setVisibleView(new IPProtectionView())}
560
+ @showCookieReport=${()=>output.setVisibleView(new CookieReportView())}
561
+ @showFlagControls=${() => output.setVisibleView(new CookieControlsView())}
562
+ ${UI.Widget.widgetRef(SecurityPanelSidebar, e => {output.sidebar = e;})}>
563
+ </devtools-widget>
564
+ </devtools-split-view>`,
565
+ target);
566
+ // clang-format on
567
+ };
568
+
552
569
  export class SecurityPanel extends UI.Panel.Panel implements SDK.TargetManager.SDKModelObserver<SecurityModel> {
553
570
  readonly mainView: SecurityMainView;
554
571
  readonly sidebar!: SecurityPanelSidebar;
@@ -560,24 +577,7 @@ export class SecurityPanel extends UI.Panel.Panel implements SDK.TargetManager.S
560
577
  private securityModel: SecurityModel|null;
561
578
  readonly splitWidget!: UI.SplitWidget.SplitWidget;
562
579
 
563
- constructor(private view: View = (_input, output, target) => {
564
- // clang-format off
565
- render(
566
- html`
567
- <devtools-split-view direction="column" name="security"
568
- ${UI.Widget.widgetRef(UI.SplitWidget.SplitWidget, e => {output.splitWidget = e;})}>
569
- <devtools-widget
570
- slot="sidebar"
571
- .widgetConfig=${widgetConfig(SecurityPanelSidebar)}
572
- @showIPProtection=${() => output.setVisibleView(new IPProtectionView())}
573
- @showCookieReport=${()=>output.setVisibleView(new CookieReportView())}
574
- @showFlagControls=${() => output.setVisibleView(new CookieControlsView())}
575
- ${UI.Widget.widgetRef(SecurityPanelSidebar, e => {output.sidebar = e;})}>
576
- </devtools-widget>
577
- </devtools-split-view>`,
578
- target, {host: this});
579
- // clang-format on
580
- }) {
580
+ constructor(private view: View = DEFAULT_VIEW) {
581
581
  super('security');
582
582
 
583
583
  this.update();
@@ -13,6 +13,7 @@ import * as Buttons from '../../ui/components/buttons/buttons.js';
13
13
  import * as Input from '../../ui/components/input/input.js';
14
14
  import * as LegacyWrapper from '../../ui/components/legacy_wrapper/legacy_wrapper.js';
15
15
  import * as Switch from '../../ui/components/switch/switch.js';
16
+ import * as uiI18n from '../../ui/i18n/i18n.js';
16
17
  import * as UI from '../../ui/legacy/legacy.js';
17
18
  import * as Lit from '../../ui/lit/lit.js';
18
19
  import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
@@ -515,7 +516,7 @@ export class AISettingsTab extends LegacyWrapper.LegacyWrapper.WrappableComponen
515
516
  },
516
517
  {
517
518
  icon: 'policy',
518
- text: html`${i18n.i18n.getFormatLocalizedString(str_, UIStrings.termsOfServicePrivacyNotice, {
519
+ text: html`${uiI18n.getFormatLocalizedString(str_, UIStrings.termsOfServicePrivacyNotice, {
519
520
  PH1: tosLink,
520
521
  PH2: privacyNoticeLink,
521
522
  })}`,
@@ -42,6 +42,11 @@ const UIStrings = {
42
42
  * @description Link text in the settings pane to add another shortcut for an action
43
43
  */
44
44
  addAShortcut: 'Add a shortcut',
45
+ /**
46
+ * @description Placeholder text in the settings pane when adding a new shortcut.
47
+ * Explaining that key strokes are going to be recoded.
48
+ */
49
+ recordingKeys: 'Recoding keys',
45
50
  /**
46
51
  * @description Label for a button in the settings pane that confirms changes to a keyboard shortcut
47
52
  */
@@ -446,6 +451,7 @@ export class ShortcutListItem {
446
451
  if (this.isEditing) {
447
452
  const shortcutInput = shortcutElement.createChild('input', 'harmony-input');
448
453
  shortcutInput.setAttribute('jslog', `${VisualLogging.textField().track({change: true})}`);
454
+ shortcutInput.setAttribute('placeholder', i18nString(UIStrings.recordingKeys));
449
455
  shortcutInput.spellcheck = false;
450
456
  shortcutInput.maxLength = 0;
451
457
  this.shortcutInputs.set(shortcut, shortcutInput);
@@ -16,6 +16,7 @@ import * as Badges from '../../../models/badges/badges.js';
16
16
  import * as Buttons from '../../../ui/components/buttons/buttons.js';
17
17
  import * as ComponentHelpers from '../../../ui/components/helpers/helpers.js';
18
18
  import type * as SettingsComponents from '../../../ui/components/settings/settings.js';
19
+ import * as uiI18n from '../../../ui/i18n/i18n.js';
19
20
  import * as Lit from '../../../ui/lit/lit.js';
20
21
  import * as VisualLogging from '../../../ui/visual_logging/visual_logging.js';
21
22
  import * as PanelCommon from '../../common/common.js';
@@ -112,7 +113,7 @@ function renderDataDisclaimer(): HTMLElement {
112
113
 
113
114
  const container = document.createElement('span');
114
115
  Lit.render(relevantDataTooltipTemplate, container);
115
- cachedTooltipElement = i18n.i18n.getFormatLocalizedString(str_, UIStrings.dataDisclaimer, {
116
+ cachedTooltipElement = uiI18n.getFormatLocalizedString(str_, UIStrings.dataDisclaimer, {
116
117
  PH1: container,
117
118
  });
118
119
  return cachedTooltipElement;
@@ -11,6 +11,7 @@ import * as Protocol from '../../generated/protocol.js';
11
11
  import type * as Bindings from '../../models/bindings/bindings.js';
12
12
  import type * as BreakpointManager from '../../models/breakpoints/breakpoints.js';
13
13
  import * as IconButton from '../../ui/components/icon_button/icon_button.js';
14
+ import * as uiI18n from '../../ui/i18n/i18n.js';
14
15
  import * as UI from '../../ui/legacy/legacy.js';
15
16
  import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
16
17
 
@@ -175,12 +176,12 @@ export class DebuggerPausedMessage {
175
176
  let messageElement;
176
177
  if (data.insertion) {
177
178
  if (data.targetNode === data.node) {
178
- messageElement = i18n.i18n.getFormatLocalizedString(str_, UIStrings.childSAdded, {PH1: targetNodeLink});
179
+ messageElement = uiI18n.getFormatLocalizedString(str_, UIStrings.childSAdded, {PH1: targetNodeLink});
179
180
  } else {
180
- messageElement = i18n.i18n.getFormatLocalizedString(str_, UIStrings.descendantSAdded, {PH1: targetNodeLink});
181
+ messageElement = uiI18n.getFormatLocalizedString(str_, UIStrings.descendantSAdded, {PH1: targetNodeLink});
181
182
  }
182
183
  } else {
183
- messageElement = i18n.i18n.getFormatLocalizedString(str_, UIStrings.descendantSRemoved, {PH1: targetNodeLink});
184
+ messageElement = uiI18n.getFormatLocalizedString(str_, UIStrings.descendantSRemoved, {PH1: targetNodeLink});
184
185
  }
185
186
  subElement.appendChild(document.createElement('br'));
186
187
  subElement.appendChild(messageElement);
@@ -6,6 +6,7 @@
6
6
  import * as i18n from '../../core/i18n/i18n.js';
7
7
  import * as Bindings from '../../models/bindings/bindings.js';
8
8
  import type * as Workspace from '../../models/workspace/workspace.js';
9
+ import * as uiI18n from '../../ui/i18n/i18n.js';
9
10
  import * as Components from '../../ui/legacy/components/utils/utils.js';
10
11
  import * as UI from '../../ui/legacy/legacy.js';
11
12
 
@@ -62,14 +63,14 @@ export class ResourceOriginPlugin extends Plugin {
62
63
  }
63
64
  element.append(link);
64
65
  });
65
- return [new UI.Toolbar.ToolbarItem(i18n.i18n.getFormatLocalizedString(str_, UIStrings.fromS, {PH1: element}))];
66
+ return [new UI.Toolbar.ToolbarItem(uiI18n.getFormatLocalizedString(str_, UIStrings.fromS, {PH1: element}))];
66
67
  }
67
68
 
68
69
  // Handle anonymous scripts with an originStackTrace.
69
70
  for (const script of debuggerWorkspaceBinding.scriptsForUISourceCode(this.uiSourceCode)) {
70
71
  if (script.originStackTrace?.callFrames.length) {
71
72
  const link = linkifier.linkifyStackTraceTopFrame(script.debuggerModel.target(), script.originStackTrace);
72
- return [new UI.Toolbar.ToolbarItem(i18n.i18n.getFormatLocalizedString(str_, UIStrings.fromS, {PH1: link}))];
73
+ return [new UI.Toolbar.ToolbarItem(uiI18n.getFormatLocalizedString(str_, UIStrings.fromS, {PH1: link}))];
73
74
  }
74
75
  }
75
76
 
@@ -15,6 +15,7 @@ import * as Bindings from '../../models/bindings/bindings.js';
15
15
  import * as Persistence from '../../models/persistence/persistence.js';
16
16
  import * as TextUtils from '../../models/text_utils/text_utils.js';
17
17
  import * as Workspace from '../../models/workspace/workspace.js';
18
+ import * as uiI18n from '../../ui/i18n/i18n.js';
18
19
  import * as UI from '../../ui/legacy/legacy.js';
19
20
  import * as Snippets from '../snippets/snippets.js';
20
21
 
@@ -190,7 +191,7 @@ export class FilesNavigatorView extends NavigatorView {
190
191
  const link =
191
192
  UI.XLink.XLink.create('https://goo.gle/devtools-automatic-workspace-folders', 'com.chrome.devtools.json');
192
193
  this.#automaticFileSystemNudge =
193
- i18n.i18n.getFormatLocalizedString(str_, UIStrings.automaticWorkspaceNudge, {PH1: link});
194
+ uiI18n.getFormatLocalizedString(str_, UIStrings.automaticWorkspaceNudge, {PH1: link});
194
195
  this.#automaticFileSystemNudge.classList.add('automatic-file-system-nudge');
195
196
  this.contentElement.insertBefore(this.#automaticFileSystemNudge, this.contentElement.firstChild);
196
197
 
@@ -12,6 +12,7 @@ import * as Workspace from '../../models/workspace/workspace.js';
12
12
  import type * as CodeMirror from '../../third_party/codemirror.next/codemirror.next.js';
13
13
  import * as IconButton from '../../ui/components/icon_button/icon_button.js';
14
14
  import * as Tooltips from '../../ui/components/tooltips/tooltips.js';
15
+ import * as uiI18n from '../../ui/i18n/i18n.js';
15
16
  import * as SourceFrame from '../../ui/legacy/components/source_frame/source_frame.js';
16
17
  import * as UI from '../../ui/legacy/legacy.js';
17
18
  import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
@@ -633,11 +634,11 @@ export class TabbedEditorContainer extends Common.ObjectWrapper.ObjectWrapper<Ev
633
634
  await UI.ViewManager.ViewManager.instance().showView('navigator-files');
634
635
  await automaticFileSystemManager.connectAutomaticFileSystem(/* addIfMissing= */ true);
635
636
  });
636
- tooltip.append(i18n.i18n.getFormatLocalizedString(
637
+ tooltip.append(uiI18n.getFormatLocalizedString(
637
638
  str_, UIStrings.changesWereNotSavedToFileSystemToSaveAddFolderToWorkspace, {PH1: link}));
638
639
  } else {
639
640
  const link = UI.XLink.XLink.create('https://developer.chrome.com/docs/devtools/workspaces/', 'Workspace');
640
- tooltip.append(i18n.i18n.getFormatLocalizedString(
641
+ tooltip.append(uiI18n.getFormatLocalizedString(
641
642
  str_, UIStrings.changesWereNotSavedToFileSystemToSaveSetUpYourWorkspace, {PH1: link}));
642
643
  }
643
644
  suffixElement.append(icon, tooltip);
@@ -94,7 +94,7 @@ const str_ = i18n.i18n.registerUIStrings('panels/sources/WatchExpressionsSidebar
94
94
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
95
95
  let watchExpressionsSidebarPaneInstance: WatchExpressionsSidebarPane;
96
96
 
97
- export class WatchExpressionsSidebarPane extends UI.ThrottledWidget.ThrottledWidget implements
97
+ export class WatchExpressionsSidebarPane extends UI.Widget.VBox implements
98
98
  UI.ActionRegistration.ActionDelegate, UI.Toolbar.ItemsProvider,
99
99
  UI.ContextMenu.Provider<ObjectUI.ObjectPropertiesSection.ObjectPropertyTreeElement|UISourceCodeFrame> {
100
100
  private watchExpressions: WatchExpression[];
@@ -106,7 +106,7 @@ export class WatchExpressionsSidebarPane extends UI.ThrottledWidget.ThrottledWid
106
106
  private readonly expandController: ObjectUI.ObjectPropertiesSection.ObjectPropertiesSectionsTreeExpandController;
107
107
  private readonly linkifier: Components.Linkifier.Linkifier;
108
108
  private constructor() {
109
- super(true);
109
+ super({useShadowDom: true});
110
110
  this.registerRequiredCSS(watchExpressionsSidebarPaneStyles, objectValueStyles);
111
111
 
112
112
  // TODO(szuend): Replace with a Set once the web test
@@ -125,7 +125,7 @@ export class WatchExpressionsSidebarPane extends UI.ThrottledWidget.ThrottledWid
125
125
  this.refreshButton = new UI.Toolbar.ToolbarButton(
126
126
  i18nString(UIStrings.refreshWatchExpressions), 'refresh', undefined, 'refresh-watch-expressions');
127
127
  this.refreshButton.setSize(Buttons.Button.Size.SMALL);
128
- this.refreshButton.addEventListener(UI.Toolbar.ToolbarButton.Events.CLICK, this.update, this);
128
+ this.refreshButton.addEventListener(UI.Toolbar.ToolbarButton.Events.CLICK, this.requestUpdate, this);
129
129
 
130
130
  this.contentElement.classList.add('watch-expressions');
131
131
  this.contentElement.setAttribute('jslog', `${VisualLogging.section('sources.watch')}`);
@@ -138,10 +138,10 @@ export class WatchExpressionsSidebarPane extends UI.ThrottledWidget.ThrottledWid
138
138
  this.expandController =
139
139
  new ObjectUI.ObjectPropertiesSection.ObjectPropertiesSectionsTreeExpandController(this.treeOutline);
140
140
 
141
- UI.Context.Context.instance().addFlavorChangeListener(SDK.RuntimeModel.ExecutionContext, this.update, this);
142
- UI.Context.Context.instance().addFlavorChangeListener(SDK.DebuggerModel.CallFrame, this.update, this);
141
+ UI.Context.Context.instance().addFlavorChangeListener(SDK.RuntimeModel.ExecutionContext, this.requestUpdate, this);
142
+ UI.Context.Context.instance().addFlavorChangeListener(SDK.DebuggerModel.CallFrame, this.requestUpdate, this);
143
143
  this.linkifier = new Components.Linkifier.Linkifier();
144
- this.update();
144
+ this.requestUpdate();
145
145
  }
146
146
 
147
147
  static instance(): WatchExpressionsSidebarPane {
@@ -182,7 +182,7 @@ export class WatchExpressionsSidebarPane extends UI.ThrottledWidget.ThrottledWid
182
182
  this.createWatchExpression(null).startEditing();
183
183
  }
184
184
 
185
- override async doUpdate(): Promise<void> {
185
+ override async performUpdate(): Promise<void> {
186
186
  this.linkifier.reset();
187
187
  this.contentElement.removeChildren();
188
188
  this.treeOutline.removeChildren();
@@ -265,14 +265,14 @@ export class WatchExpressionsSidebarPane extends UI.ThrottledWidget.ThrottledWid
265
265
  private deleteAllButtonClicked(): void {
266
266
  this.watchExpressions = [];
267
267
  this.saveExpressions();
268
- this.update();
268
+ this.requestUpdate();
269
269
  }
270
270
 
271
271
  private async focusAndAddExpressionToWatch(expression: string): Promise<void> {
272
272
  await UI.ViewManager.ViewManager.instance().showView('sources.watch');
273
273
  this.createWatchExpression(expression);
274
274
  this.saveExpressions();
275
- this.update();
275
+ this.requestUpdate();
276
276
  }
277
277
 
278
278
  handleAction(_context: UI.Context.Context, _actionId: string): boolean {