chrome-devtools-frontend 1.0.1548870 → 1.0.1549484

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 (188) hide show
  1. package/docs/contributing/settings-experiments-features.md +35 -0
  2. package/docs/styleguide/ux/patterns.md +27 -0
  3. package/eslint.config.mjs +1 -0
  4. package/front_end/Tests.js +2 -0
  5. package/front_end/core/host/InspectorFrontendHost.ts +26 -558
  6. package/front_end/core/host/InspectorFrontendHostAPI.ts +6 -3
  7. package/front_end/core/host/InspectorFrontendHostStub.ts +558 -0
  8. package/front_end/core/host/ResourceLoader.ts +9 -23
  9. package/front_end/core/host/UserMetrics.ts +4 -4
  10. package/front_end/core/root/DevToolsContext.ts +4 -0
  11. package/front_end/core/root/Runtime.ts +10 -0
  12. package/front_end/core/sdk/CSSMatchedStyles.ts +2 -2
  13. package/front_end/core/sdk/CSSModel.ts +24 -24
  14. package/front_end/core/sdk/CSSPropertyParserMatchers.ts +11 -11
  15. package/front_end/core/sdk/CSSQuery.ts +1 -1
  16. package/front_end/core/sdk/CSSRule.ts +2 -2
  17. package/front_end/core/sdk/CSSStyleDeclaration.ts +1 -1
  18. package/front_end/core/sdk/CSSStyleSheetHeader.ts +1 -1
  19. package/front_end/core/sdk/DOMModel.ts +3 -0
  20. package/front_end/core/sdk/NetworkManager.ts +29 -31
  21. package/front_end/core/sdk/NetworkRequest.ts +4 -0
  22. package/front_end/core/sdk/OverlayModel.ts +2 -2
  23. package/front_end/core/sdk/PageResourceLoader.ts +63 -37
  24. package/front_end/core/sdk/SourceMap.ts +6 -0
  25. package/front_end/core/sdk/SourceMapCache.ts +21 -0
  26. package/front_end/core/sdk/SourceMapManager.ts +7 -6
  27. package/front_end/core/sdk/SourceMapScopesInfo.ts +6 -2
  28. package/front_end/core/sdk/TargetManager.ts +14 -2
  29. package/front_end/core/sdk/sdk-meta.ts +13 -0
  30. package/front_end/entrypoints/formatter_worker/FormatterActions.ts +1 -0
  31. package/front_end/entrypoints/formatter_worker/ScopeParser.ts +1 -1
  32. package/front_end/entrypoints/main/MainImpl.ts +13 -3
  33. package/front_end/foundation/Universe.ts +1 -1
  34. package/front_end/generated/Deprecation.ts +18 -4
  35. package/front_end/generated/InspectorBackendCommands.ts +33 -31
  36. package/front_end/generated/SupportedCSSProperties.js +41 -41
  37. package/front_end/generated/protocol-mapping.d.ts +12 -0
  38. package/front_end/generated/protocol-proxy-api.d.ts +11 -0
  39. package/front_end/generated/protocol.ts +70 -35
  40. package/front_end/models/ai_assistance/AiConversation.ts +5 -4
  41. package/front_end/models/ai_assistance/ChangeManager.ts +4 -4
  42. package/front_end/models/ai_assistance/ConversationHandler.ts +0 -15
  43. package/front_end/models/ai_assistance/agents/AiAgent.ts +9 -6
  44. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +135 -3
  45. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.ts +24 -0
  46. package/front_end/models/bindings/CompilerScriptMapping.ts +43 -0
  47. package/front_end/models/bindings/DebuggerWorkspaceBinding.ts +19 -0
  48. package/front_end/models/bindings/ResourceMapping.ts +73 -0
  49. package/front_end/models/bindings/ResourceScriptMapping.ts +50 -0
  50. package/front_end/models/issues_manager/GenericIssue.ts +17 -0
  51. package/front_end/models/issues_manager/descriptions/genericNavigationEntryMarkedSkippable.md +7 -0
  52. package/front_end/models/javascript_metadata/NativeFunctions.js +7 -3
  53. package/front_end/models/source_map_scopes/FunctionCodeResolver.snapshot.txt +98 -0
  54. package/front_end/models/source_map_scopes/FunctionCodeResolver.ts +270 -0
  55. package/front_end/models/source_map_scopes/source_map_scopes.ts +2 -0
  56. package/front_end/models/workspace/UISourceCode.ts +51 -44
  57. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +76 -34
  58. package/front_end/panels/ai_assistance/aiAssistancePanel.css +1 -0
  59. package/front_end/panels/ai_assistance/components/ChatView.ts +23 -11
  60. package/front_end/panels/application/AppManifestView.ts +3 -2
  61. package/front_end/panels/application/FrameDetailsView.ts +5 -6
  62. package/front_end/panels/application/ServiceWorkersView.ts +2 -2
  63. package/front_end/panels/application/TrustTokensTreeElement.ts +2 -6
  64. package/front_end/panels/application/components/PermissionsPolicySection.ts +201 -157
  65. package/front_end/panels/application/components/ProtocolHandlersView.ts +117 -80
  66. package/front_end/panels/application/components/ServiceWorkerRouterView.ts +47 -41
  67. package/front_end/panels/application/components/StorageMetadataView.ts +31 -34
  68. package/front_end/panels/application/components/TrustTokensView.ts +76 -68
  69. package/front_end/panels/console/ConsoleView.ts +3 -2
  70. package/front_end/panels/console/ConsoleViewMessage.ts +6 -4
  71. package/front_end/panels/console/console-meta.ts +0 -13
  72. package/front_end/panels/developer_resources/DeveloperResourcesView.ts +3 -1
  73. package/front_end/panels/elements/CSSRuleValidator.ts +7 -7
  74. package/front_end/panels/elements/CSSRuleValidatorHelper.ts +2 -2
  75. package/front_end/panels/elements/ElementsTreeElement.ts +16 -13
  76. package/front_end/panels/elements/ElementsTreeOutline.ts +2 -1
  77. package/front_end/panels/elements/LayoutPane.ts +12 -10
  78. package/front_end/panels/elements/StylePropertyTreeElement.ts +12 -12
  79. package/front_end/panels/elements/components/AdornerManager.ts +3 -3
  80. package/front_end/panels/elements/components/StylePropertyEditor.ts +6 -6
  81. package/front_end/panels/linear_memory_inspector/components/LinearMemoryHighlightChipList.ts +27 -49
  82. package/front_end/panels/linear_memory_inspector/components/LinearMemoryInspector.ts +15 -11
  83. package/front_end/panels/media/PlayerListView.ts +100 -73
  84. package/front_end/panels/media/playerListView.css +5 -0
  85. package/front_end/panels/mobile_throttling/ThrottlingSettingsTab.ts +3 -3
  86. package/front_end/panels/network/RequestConditionsDrawer.ts +5 -5
  87. package/front_end/panels/network/components/DirectSocketConnectionView.ts +17 -0
  88. package/front_end/panels/network/resourceChunkView.css +4 -0
  89. package/front_end/panels/security/CookieControlsView.ts +1 -1
  90. package/front_end/panels/sensors/LocationsSettingsTab.ts +1 -1
  91. package/front_end/panels/settings/FrameworkIgnoreListSettingsTab.ts +1 -1
  92. package/front_end/panels/settings/KeybindsSettingsTab.ts +1 -1
  93. package/front_end/panels/settings/SettingsScreen.ts +6 -6
  94. package/front_end/panels/settings/WorkspaceSettingsTab.ts +1 -1
  95. package/front_end/panels/settings/emulation/DevicesSettingsTab.ts +1 -1
  96. package/front_end/panels/snippets/SnippetsQuickOpen.ts +4 -2
  97. package/front_end/panels/sources/CSSPlugin.ts +1 -1
  98. package/front_end/panels/sources/FilteredUISourceCodeListProvider.ts +13 -5
  99. package/front_end/panels/sources/GoToLineQuickOpen.ts +4 -2
  100. package/front_end/panels/sources/NavigatorView.ts +2 -2
  101. package/front_end/panels/sources/OpenFileQuickOpen.ts +7 -8
  102. package/front_end/panels/sources/OutlineQuickOpen.ts +6 -3
  103. package/front_end/panels/sources/ProfilePlugin.ts +21 -12
  104. package/front_end/panels/sources/UISourceCodeFrame.ts +0 -1
  105. package/front_end/panels/sources/filteredUISourceCodeListProvider.css +41 -0
  106. package/front_end/panels/timeline/TimelinePanel.ts +17 -18
  107. package/front_end/panels/timeline/TimelineSelectorStatsView.ts +3 -3
  108. package/front_end/panels/timeline/components/insights/SlowCSSSelector.ts +2 -2
  109. package/front_end/panels/timeline/docs/flame_chart_migration.md +11 -16
  110. package/front_end/panels/utils/utils.ts +17 -3
  111. package/front_end/panels/whats_new/ReleaseNoteText.ts +10 -20
  112. package/front_end/panels/whats_new/resources/WNDT.md +8 -8
  113. package/front_end/third_party/chromium/README.chromium +1 -1
  114. package/front_end/third_party/puppeteer/third_party/mitt/README.chromium +1 -0
  115. package/front_end/third_party/puppeteer/third_party/parsel/README.chromium +1 -0
  116. package/front_end/third_party/puppeteer/third_party/rxjs/README.chromium +1 -0
  117. package/front_end/ui/components/adorners/Adorner.ts +1 -1
  118. package/front_end/ui/components/annotations/AnnotationRepository.ts +98 -0
  119. package/front_end/ui/components/annotations/AnnotationType.ts +10 -0
  120. package/front_end/ui/components/annotations/annotations.ts +6 -0
  121. package/front_end/ui/components/buttons/Button.ts +1 -1
  122. package/front_end/ui/components/buttons/FloatingButton.ts +1 -1
  123. package/front_end/ui/components/chrome_link/ChromeLink.ts +1 -1
  124. package/front_end/ui/components/dialogs/ButtonDialog.ts +1 -1
  125. package/front_end/ui/components/dialogs/Dialog.ts +1 -1
  126. package/front_end/ui/components/dialogs/ShortcutDialog.ts +1 -0
  127. package/front_end/ui/components/diff_view/DiffView.ts +1 -1
  128. package/front_end/ui/components/expandable_list/ExpandableList.ts +1 -1
  129. package/front_end/ui/components/highlighting/HighlightElement.ts +1 -0
  130. package/front_end/ui/components/highlighting/MarkupHighlight.ts +162 -0
  131. package/front_end/ui/components/highlighting/highlighting.ts +7 -0
  132. package/front_end/ui/components/icon_button/FileSourceIcon.ts +1 -1
  133. package/front_end/ui/components/icon_button/Icon.ts +4 -2
  134. package/front_end/ui/components/icon_button/IconButton.ts +1 -1
  135. package/front_end/ui/components/issue_counter/IssueCounter.ts +1 -1
  136. package/front_end/ui/components/issue_counter/IssueLinkIcon.ts +1 -1
  137. package/front_end/ui/components/legacy_wrapper/LegacyWrapper.ts +1 -1
  138. package/front_end/ui/components/linkifier/LinkifierImpl.ts +1 -1
  139. package/front_end/ui/components/list/List.ts +184 -0
  140. package/front_end/ui/components/list/list.css +90 -0
  141. package/front_end/ui/components/{cards/cards.ts → list/lists.ts} +3 -3
  142. package/front_end/ui/components/markdown_view/CodeBlock.ts +1 -1
  143. package/front_end/ui/components/markdown_view/MarkdownImage.ts +1 -1
  144. package/front_end/ui/components/markdown_view/MarkdownLink.ts +1 -1
  145. package/front_end/ui/components/markdown_view/MarkdownView.ts +1 -1
  146. package/front_end/ui/components/menus/Menu.ts +1 -1
  147. package/front_end/ui/components/menus/SelectMenu.ts +1 -1
  148. package/front_end/ui/components/node_text/NodeText.ts +1 -1
  149. package/front_end/ui/components/panel_feedback/FeedbackButton.ts +1 -1
  150. package/front_end/ui/components/panel_feedback/PanelFeedback.ts +1 -1
  151. package/front_end/ui/components/panel_feedback/PreviewToggle.ts +1 -1
  152. package/front_end/ui/components/panel_introduction_steps/PanelIntroductionSteps.ts +1 -1
  153. package/front_end/ui/components/report_view/ReportView.ts +1 -1
  154. package/front_end/ui/components/request_link_icon/RequestLinkIcon.ts +1 -1
  155. package/front_end/ui/components/settings/SettingCheckbox.ts +1 -1
  156. package/front_end/ui/components/settings/SettingDeprecationWarning.ts +1 -1
  157. package/front_end/ui/components/snackbars/Snackbar.ts +1 -1
  158. package/front_end/ui/components/spinners/Spinner.ts +1 -1
  159. package/front_end/ui/components/srgb_overlay/SrgbOverlay.ts +1 -1
  160. package/front_end/ui/components/suggestion_input/SuggestionInput.ts +1 -0
  161. package/front_end/ui/components/survey_link/SurveyLink.ts +1 -1
  162. package/front_end/ui/components/switch/SwitchImpl.ts +1 -1
  163. package/front_end/ui/components/text_editor/TextEditor.ts +1 -0
  164. package/front_end/ui/components/text_prompt/TextPrompt.ts +1 -1
  165. package/front_end/ui/components/tooltips/Tooltip.ts +1 -1
  166. package/front_end/ui/components/tree_outline/TreeOutline.ts +1 -1
  167. package/front_end/ui/kit/kit.ts +5 -0
  168. package/front_end/ui/legacy/TabbedPane.ts +98 -0
  169. package/front_end/ui/legacy/UIUtils.ts +0 -184
  170. package/front_end/ui/legacy/ViewManager.ts +23 -8
  171. package/front_end/ui/legacy/ViewRegistration.ts +21 -22
  172. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +5 -4
  173. package/front_end/ui/legacy/components/perf_ui/LineLevelProfile.ts +73 -35
  174. package/front_end/ui/legacy/components/perf_ui/LiveHeapProfile.ts +11 -2
  175. package/front_end/ui/legacy/components/quick_open/CommandMenu.ts +12 -13
  176. package/front_end/ui/legacy/components/quick_open/FilteredListWidget.ts +7 -16
  177. package/front_end/ui/legacy/components/quick_open/HelpQuickOpen.ts +5 -6
  178. package/front_end/ui/legacy/components/quick_open/filteredListWidget.css +18 -65
  179. package/front_end/ui/legacy/components/source_frame/JSONView.ts +2 -1
  180. package/front_end/ui/legacy/tabbedPane.css +10 -0
  181. package/front_end/ui/visual_logging/KnownContextValues.ts +3 -0
  182. package/inspector_overlay/README.md +3 -3
  183. package/mcp/HostBindings.ts +310 -0
  184. package/mcp/mcp.ts +17 -0
  185. package/mcp/tsconfig.json +6 -1
  186. package/package.json +26 -24
  187. /package/front_end/ui/{components → kit}/cards/Card.ts +0 -0
  188. /package/front_end/ui/{components → kit}/cards/card.css +0 -0
@@ -517,7 +517,7 @@ export class AppManifestView extends Common.ObjectWrapper.eventMixin<EventTypes,
517
517
  this.protocolHandlersSection =
518
518
  this.reportView.appendSection(i18nString(UIStrings.protocolHandlers), 'undefined,protocol-handlers');
519
519
  this.protocolHandlersView = new ApplicationComponents.ProtocolHandlersView.ProtocolHandlersView();
520
- this.protocolHandlersSection.appendFieldWithCustomView(this.protocolHandlersView);
520
+ this.protocolHandlersView.show(this.protocolHandlersSection.getFieldElement());
521
521
  this.iconsSection = this.reportView.appendSection(i18nString(UIStrings.icons), 'report-section-icons', 'icons');
522
522
  this.windowControlsSection =
523
523
  this.reportView.appendSection(UIStrings.windowControlsOverlay, undefined, 'window-controls-overlay');
@@ -753,7 +753,8 @@ export class AppManifestView extends Common.ObjectWrapper.eventMixin<EventTypes,
753
753
  }
754
754
 
755
755
  const protocolHandlers = parsedManifest['protocol_handlers'] || [];
756
- this.protocolHandlersView.data = {protocolHandlers, manifestLink: url};
756
+ this.protocolHandlersView.protocolHandlers = protocolHandlers;
757
+ this.protocolHandlersView.manifestLink = url;
757
758
 
758
759
  const icons = parsedManifest['icons'] || [];
759
760
  this.iconsSection.clearContent();
@@ -297,12 +297,11 @@ const DEFAULT_VIEW: View = (input, _output, target) => {
297
297
  ${renderIsolationSection(input)}
298
298
  ${renderApiAvailabilitySection(input.frame)}
299
299
  ${renderOriginTrial(input.trials)}
300
- ${input.permissionsPolicies ?
301
- html`
302
- <devtools-resources-permissions-policy-section
303
- .data=${{policies: input.permissionsPolicies, showDetails: false} as ApplicationComponents.PermissionsPolicySection.PermissionsPolicySectionData}>
304
- </devtools-resources-permissions-policy-section>
305
- ` : nothing}
300
+ ${input.permissionsPolicies ? html`
301
+ <devtools-widget .widgetConfig=${widgetConfig(ApplicationComponents.PermissionsPolicySection.PermissionsPolicySection, {
302
+ policies: input.permissionsPolicies,
303
+ showDetails: false})}>
304
+ </devtools-widget>` : nothing}
306
305
  ${input.protocolMonitorExperimentEnabled ? renderAdditionalInfoSection(input.frame) : nothing}
307
306
  </devtools-report>
308
307
  `, target);
@@ -706,9 +706,9 @@ export class Section {
706
706
  this.routerField = this.wrapWidget(this.section.appendField(title));
707
707
  }
708
708
  if (!this.routerField.lastElementChild) {
709
- this.routerField.appendChild(this.routerView);
709
+ this.routerView.show(this.routerField);
710
710
  }
711
- this.routerView.update(active.routerRules);
711
+ this.routerView.rules = active.routerRules;
712
712
  } else {
713
713
  // If no active worker or no registered rules, remove the field.
714
714
  this.section.removeField(title);
@@ -6,8 +6,6 @@ import * as Host from '../../core/host/host.js';
6
6
  import * as i18n from '../../core/i18n/i18n.js';
7
7
  import type * as Platform from '../../core/platform/platform.js';
8
8
  import * as IconButton from '../../ui/components/icon_button/icon_button.js';
9
- import * as LegacyWrapper from '../../ui/components/legacy_wrapper/legacy_wrapper.js';
10
- import * as UI from '../../ui/legacy/legacy.js';
11
9
 
12
10
  import {ApplicationPanelTreeElement} from './ApplicationPanelTreeElement.js';
13
11
  import * as ApplicationComponents from './components/components.js';
@@ -24,8 +22,7 @@ const str_ = i18n.i18n.registerUIStrings('panels/application/TrustTokensTreeElem
24
22
  export const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
25
23
 
26
24
  export class TrustTokensTreeElement extends ApplicationPanelTreeElement {
27
- private view?: LegacyWrapper.LegacyWrapper
28
- .LegacyWrapper<UI.Widget.Widget, ApplicationComponents.TrustTokensView.TrustTokensView>;
25
+ private view?: ApplicationComponents.TrustTokensView.TrustTokensView;
29
26
 
30
27
  constructor(storagePanel: ResourcesPanel) {
31
28
  super(storagePanel, i18nString(UIStrings.trustTokens), false, 'private-state-tokens');
@@ -40,8 +37,7 @@ export class TrustTokensTreeElement extends ApplicationPanelTreeElement {
40
37
  override onselect(selectedByUser?: boolean): boolean {
41
38
  super.onselect(selectedByUser);
42
39
  if (!this.view) {
43
- this.view = LegacyWrapper.LegacyWrapper.legacyWrapper(
44
- UI.Widget.Widget, new ApplicationComponents.TrustTokensView.TrustTokensView(), 'trust-tokens');
40
+ this.view = new ApplicationComponents.TrustTokensView.TrustTokensView();
45
41
  }
46
42
  this.showView(this.view);
47
43
  Host.userMetrics.panelShown('trust-tokens');
@@ -1,7 +1,6 @@
1
1
  // Copyright 2021 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/icon_button/icon_button.js';
7
6
  import '../../../ui/components/report_view/report_view.js';
@@ -13,14 +12,12 @@ import * as SDK from '../../../core/sdk/sdk.js';
13
12
  import * as Protocol from '../../../generated/protocol.js';
14
13
  import * as NetworkForward from '../../../panels/network/forward/forward.js';
15
14
  import * as Buttons from '../../../ui/components/buttons/buttons.js';
16
- import * as RenderCoordinator from '../../../ui/components/render_coordinator/render_coordinator.js';
17
- import * as Lit from '../../../ui/lit/lit.js';
15
+ import * as UI from '../../../ui/legacy/legacy.js';
16
+ import {html, type LitTemplate, nothing, render, type TemplateResult} from '../../../ui/lit/lit.js';
18
17
  import * as VisualLogging from '../../../ui/visual_logging/visual_logging.js';
19
18
 
20
19
  import permissionsPolicySectionStyles from './permissionsPolicySection.css.js';
21
20
 
22
- const {html} = Lit;
23
-
24
21
  const UIStrings = {
25
22
  /**
26
23
  * @description Label for a button. When clicked more details (for the content this button refers to) will be shown.
@@ -72,179 +69,226 @@ export interface PermissionsPolicySectionData {
72
69
 
73
70
  export function renderIconLink(
74
71
  iconName: string, title: Platform.UIString.LocalizedString, clickHandler: (() => void)|(() => Promise<void>),
75
- jsLogContext: string): Lit.TemplateResult {
72
+ jsLogContext: string): TemplateResult {
76
73
  // Disabled until https://crbug.com/1079231 is fixed.
77
74
  // clang-format off
78
75
  return html`
79
- <devtools-button
80
- .iconName=${iconName}
81
- title=${title}
82
- aria-label=${title}
83
- .variant=${Buttons.Button.Variant.ICON}
84
- .size=${Buttons.Button.Size.SMALL}
85
- @click=${clickHandler}
86
- jslog=${VisualLogging.action().track({click: true}).context(jsLogContext)}></devtools-button>
87
- `;
76
+ <devtools-button
77
+ .iconName=${iconName}
78
+ title=${title}
79
+ aria-label=${title}
80
+ .variant=${Buttons.Button.Variant.ICON}
81
+ .size=${Buttons.Button.Size.SMALL}
82
+ @click=${clickHandler}
83
+ jslog=${VisualLogging.action().track({click: true}).context(jsLogContext)}>
84
+ </devtools-button>`;
88
85
  // clang-format on
89
86
  }
90
87
 
91
- export class PermissionsPolicySection extends HTMLElement {
92
- readonly #shadow = this.attachShadow({mode: 'open'});
93
- #permissionsPolicySectionData: PermissionsPolicySectionData = {policies: [], showDetails: false};
94
-
95
- set data(data: PermissionsPolicySectionData) {
96
- this.#permissionsPolicySectionData = data;
97
- void this.#render();
88
+ function renderAllowed(allowed: Protocol.Page.PermissionsPolicyFeatureState[]): LitTemplate {
89
+ if (!allowed.length) {
90
+ return nothing;
98
91
  }
92
+ return html`
93
+ <devtools-report-key>${i18nString(UIStrings.allowedFeatures)}</devtools-report-key>
94
+ <devtools-report-value>${allowed.map(({feature}) => feature).join(', ')}</devtools-report-value>`;
95
+ }
99
96
 
100
- #toggleShowPermissionsDisallowedDetails(): void {
101
- this.#permissionsPolicySectionData.showDetails = !this.#permissionsPolicySectionData.showDetails;
102
- void this.#render();
97
+ function renderDisallowed(
98
+ data: Array<{
99
+ policy: Protocol.Page.PermissionsPolicyFeatureState,
100
+ blockReason?: Protocol.Page.PermissionsPolicyBlockReason,
101
+ linkTargetDOMNode?: SDK.DOMModel.DOMNode,
102
+ linkTargetRequest?: SDK.NetworkRequest.NetworkRequest,
103
+ }>,
104
+ showDetails: boolean,
105
+ onToggleShowDetails: () => void,
106
+ onRevealDOMNode: (linkTargetDOMNode: SDK.DOMModel.DOMNode) => Promise<void>,
107
+ onRevealHeader: (linkTargetRequest: SDK.NetworkRequest.NetworkRequest) => Promise<void>,
108
+ ): LitTemplate {
109
+ if (!data.length) {
110
+ return nothing;
103
111
  }
104
-
105
- #renderAllowed(): Lit.LitTemplate {
106
- const allowed = this.#permissionsPolicySectionData.policies.filter(p => p.allowed).map(p => p.feature).sort();
107
- if (!allowed.length) {
108
- return Lit.nothing;
109
- }
112
+ if (!showDetails) {
113
+ // clang-format off
110
114
  return html`
111
- <devtools-report-key>${i18nString(UIStrings.allowedFeatures)}</devtools-report-key>
115
+ <devtools-report-key>${i18nString(UIStrings.disabledFeatures)}</devtools-report-key>
112
116
  <devtools-report-value>
113
- ${allowed.join(', ')}
114
- </devtools-report-value>
115
- `;
116
- }
117
-
118
- async #renderDisallowed(): Promise<Lit.LitTemplate> {
119
- const disallowed = this.#permissionsPolicySectionData.policies.filter(p => !p.allowed)
120
- .sort((a, b) => a.feature.localeCompare(b.feature));
121
- if (!disallowed.length) {
122
- return Lit.nothing;
123
- }
124
- if (!this.#permissionsPolicySectionData.showDetails) {
125
- return html`
126
- <devtools-report-key>${i18nString(UIStrings.disabledFeatures)}</devtools-report-key>
127
- <devtools-report-value>
128
- ${disallowed.map(p => p.feature).join(', ')}
129
- <devtools-button
130
- class="disabled-features-button"
131
- .variant=${Buttons.Button.Variant.OUTLINED}
132
- @click=${() => this.#toggleShowPermissionsDisallowedDetails()}
133
- jslog=${VisualLogging.action('show-disabled-features-details').track({
134
- click: true,
135
- })}>${i18nString(UIStrings.showDetails)}
117
+ ${data.map(({policy}) => policy.feature).join(', ')}
118
+ <devtools-button
119
+ class="disabled-features-button"
120
+ .variant=${Buttons.Button.Variant.OUTLINED}
121
+ @click=${onToggleShowDetails}
122
+ jslog=${VisualLogging.action('show-disabled-features-details').track({click: true})}>
123
+ ${i18nString(UIStrings.showDetails)}
136
124
  </devtools-button>
137
- </devtools-report-value>
138
- `;
139
- }
125
+ </devtools-report-value>`;
126
+ // clang-format on
127
+ }
140
128
 
141
- const frameManager = SDK.FrameManager.FrameManager.instance();
142
- const featureRows = await Promise.all(disallowed.map(async policy => {
143
- const frame = policy.locator ? frameManager.getFrame(policy.locator.frameId) : null;
144
- const blockReason = policy.locator?.blockReason;
145
- const linkTargetDOMNode = await (blockReason === Protocol.Page.PermissionsPolicyBlockReason.IframeAttribute &&
146
- frame?.getOwnerDOMNodeOrDocument());
147
- const resource = frame?.resourceForURL(frame.url);
148
- const linkTargetRequest = blockReason === Protocol.Page.PermissionsPolicyBlockReason.Header && resource?.request;
149
- const blockReasonText = (() => {
150
- switch (blockReason) {
151
- case Protocol.Page.PermissionsPolicyBlockReason.IframeAttribute:
152
- return i18nString(UIStrings.disabledByIframe);
153
- case Protocol.Page.PermissionsPolicyBlockReason.Header:
154
- return i18nString(UIStrings.disabledByHeader);
155
- case Protocol.Page.PermissionsPolicyBlockReason.InFencedFrameTree:
156
- return i18nString(UIStrings.disabledByFencedFrame);
157
- default:
158
- return '';
159
- }
160
- })();
161
- const revealHeader = async(): Promise<void> => {
162
- if (!linkTargetRequest) {
163
- return;
164
- }
165
- const headerName =
166
- linkTargetRequest.responseHeaderValue('permissions-policy') ? 'permissions-policy' : 'feature-policy';
167
- const requestLocation = NetworkForward.UIRequestLocation.UIRequestLocation.responseHeaderMatch(
168
- linkTargetRequest,
169
- {name: headerName, value: ''},
170
- );
171
- await Common.Revealer.reveal(requestLocation);
172
- };
173
-
174
- // Disabled until https://crbug.com/1079231 is fixed.
175
- // clang-format off
176
- return html`
177
- <div class="permissions-row">
178
- <div>
179
- <devtools-icon class="allowed-icon extra-large" name="cross-circle">
180
- </devtools-icon>
181
- </div>
182
- <div class="feature-name text-ellipsis">
183
- ${policy.feature}
184
- </div>
185
- <div class="block-reason">${blockReasonText}</div>
186
- <div>
187
- ${
188
- linkTargetDOMNode ? renderIconLink(
189
- 'code-circle', i18nString(UIStrings.clickToShowIframe),
190
- () => Common.Revealer.reveal(linkTargetDOMNode), 'reveal-in-elements') :
191
- Lit.nothing}
192
- ${
193
- linkTargetRequest ? renderIconLink(
194
- 'arrow-up-down-circle',
195
- i18nString(UIStrings.clickToShowHeader),
196
- revealHeader,
197
- 'reveal-in-network') :
198
- Lit.nothing}
199
- </div>
129
+ const featureRows = data.map(({policy, blockReason, linkTargetDOMNode, linkTargetRequest}) => {
130
+ const blockReasonText = (() => {
131
+ switch (blockReason) {
132
+ case Protocol.Page.PermissionsPolicyBlockReason.IframeAttribute:
133
+ return i18nString(UIStrings.disabledByIframe);
134
+ case Protocol.Page.PermissionsPolicyBlockReason.Header:
135
+ return i18nString(UIStrings.disabledByHeader);
136
+ case Protocol.Page.PermissionsPolicyBlockReason.InFencedFrameTree:
137
+ return i18nString(UIStrings.disabledByFencedFrame);
138
+ default:
139
+ return '';
140
+ }
141
+ })();
142
+ // Disabled until https://crbug.com/1079231 is fixed.
143
+ // clang-format off
144
+ return html`
145
+ <div class="permissions-row">
146
+ <div>
147
+ <devtools-icon class="allowed-icon extra-large" name="cross-circle">
148
+ </devtools-icon>
200
149
  </div>
201
- `;
202
- // clang-format on
203
- }));
150
+ <div class="feature-name text-ellipsis">${policy.feature}</div>
151
+ <div class="block-reason">${blockReasonText}</div>
152
+ <div>
153
+ ${linkTargetDOMNode ?
154
+ renderIconLink('code-circle', i18nString(UIStrings.clickToShowIframe),
155
+ () => onRevealDOMNode(linkTargetDOMNode), 'reveal-in-elements') :
156
+ nothing}
157
+ ${linkTargetRequest ?
158
+ renderIconLink('arrow-up-down-circle', i18nString(UIStrings.clickToShowHeader),
159
+ () => onRevealHeader(linkTargetRequest), 'reveal-in-network') :
160
+ nothing}
161
+ </div>
162
+ </div>`;
163
+ // clang-format on
164
+ });
204
165
 
205
- return html`
206
- <devtools-report-key>${i18nString(UIStrings.disabledFeatures)}</devtools-report-key>
207
- <devtools-report-value class="policies-list">
208
- ${featureRows}
209
- <div class="permissions-row">
166
+ // clang-format off
167
+ return html`
168
+ <devtools-report-key>${i18nString(UIStrings.disabledFeatures)}</devtools-report-key>
169
+ <devtools-report-value class="policies-list">
170
+ ${featureRows}
171
+ <div class="permissions-row">
210
172
  <devtools-button
211
- .variant=${Buttons.Button.Variant.OUTLINED}
212
- @click=${() => this.#toggleShowPermissionsDisallowedDetails()}
213
- jslog=${VisualLogging.action('hide-disabled-features-details').track({
214
- click: true,
215
- })}>${i18nString(UIStrings.hideDetails)}
173
+ .variant=${Buttons.Button.Variant.OUTLINED}
174
+ @click=${onToggleShowDetails}
175
+ jslog=${VisualLogging.action('hide-disabled-features-details').track({click: true})}>
176
+ ${i18nString(UIStrings.hideDetails)}
216
177
  </devtools-button>
217
- </div>
218
- </devtools-report-value>
219
- `;
178
+ </div>
179
+ </devtools-report-value>`;
180
+ // clang-format on
181
+ }
182
+
183
+ interface ViewInput {
184
+ allowed: Protocol.Page.PermissionsPolicyFeatureState[];
185
+ disallowed: Array<{
186
+ policy: Protocol.Page.PermissionsPolicyFeatureState,
187
+ blockReason?: Protocol.Page.PermissionsPolicyBlockReason,
188
+ linkTargetDOMNode?: SDK.DOMModel.DOMNode,
189
+ linkTargetRequest?: SDK.NetworkRequest.NetworkRequest,
190
+ }>;
191
+ showDetails: boolean;
192
+ onToggleShowDetails: () => void;
193
+ onRevealDOMNode: (linkTargetDOMNode: SDK.DOMModel.DOMNode) => Promise<void>;
194
+ onRevealHeader: (linkTargetRequest: SDK.NetworkRequest.NetworkRequest) => Promise<void>;
195
+ }
196
+
197
+ type View = (input: ViewInput, output: undefined, target: HTMLElement) => void;
198
+
199
+ const DEFAULT_VIEW: View = (input, output, target) => {
200
+ // clang-format off
201
+ render(html`
202
+ <style>${permissionsPolicySectionStyles}</style>
203
+ <devtools-report-section-header>
204
+ ${i18n.i18n.lockedString('Permissions Policy')}
205
+ </devtools-report-section-header>
206
+ ${renderAllowed(input.allowed)}
207
+ ${(input.allowed.length > 0 && input.disallowed.length > 0) ?
208
+ html`<devtools-report-divider class="subsection-divider"></devtools-report-divider>` : nothing}
209
+ ${renderDisallowed(
210
+ input.disallowed, input.showDetails,
211
+ input.onToggleShowDetails, input.onRevealDOMNode, input.onRevealHeader)}
212
+ <devtools-report-divider></devtools-report-divider>`, target);
213
+ // clang-format on
214
+ };
215
+
216
+ export class PermissionsPolicySection extends UI.Widget.Widget {
217
+ #policies: Protocol.Page.PermissionsPolicyFeatureState[] = [];
218
+ #showDetails = false;
219
+ #view: View;
220
+
221
+ constructor(element?: HTMLElement, view = DEFAULT_VIEW) {
222
+ super(element, {useShadowDom: true});
223
+ this.#view = view;
220
224
  }
221
225
 
222
- async #render(): Promise<void> {
223
- await RenderCoordinator.write('PermissionsPolicySection render', () => {
224
- // Disabled until https://crbug.com/1079231 is fixed.
225
- // clang-format off
226
- Lit.render(
227
- html`
228
- <style>${permissionsPolicySectionStyles}</style>
229
- <devtools-report-section-header>${i18n.i18n.lockedString('Permissions Policy')}</devtools-report-section-header>
230
- ${this.#renderAllowed()}
231
- ${(this.#permissionsPolicySectionData.policies.findIndex(p => p.allowed) > 0 ||
232
- this.#permissionsPolicySectionData.policies.findIndex(p => !p.allowed) > 0) ?
233
- html`<devtools-report-divider class="subsection-divider"></devtools-report-divider>` : Lit.nothing}
234
- ${Lit.Directives.until(this.#renderDisallowed(), Lit.nothing)}
235
- <devtools-report-divider></devtools-report-divider>
236
- `,
237
- this.#shadow, {host: this},
238
- );
239
- // clang-format on
240
- });
226
+ set policies(policies: Protocol.Page.PermissionsPolicyFeatureState[]) {
227
+ this.#policies = policies;
228
+ this.requestUpdate();
229
+ }
230
+
231
+ get policies(): Protocol.Page.PermissionsPolicyFeatureState[] {
232
+ return this.#policies;
233
+ }
234
+
235
+ set showDetails(showDetails: boolean) {
236
+ this.#showDetails = showDetails;
237
+ this.requestUpdate();
241
238
  }
242
- }
243
239
 
244
- customElements.define('devtools-resources-permissions-policy-section', PermissionsPolicySection);
240
+ get showDetails(): boolean {
241
+ return this.#showDetails;
242
+ }
243
+
244
+ #toggleShowPermissionsDisallowedDetails(): void {
245
+ this.showDetails = !this.showDetails;
246
+ }
247
+
248
+ async #revealDOMNode(linkTargetDOMNode: SDK.DOMModel.DOMNode): Promise<void> {
249
+ await Common.Revealer.reveal(linkTargetDOMNode);
250
+ }
251
+
252
+ async #revealHeader(linkTargetRequest: SDK.NetworkRequest.NetworkRequest): Promise<void> {
253
+ if (!linkTargetRequest) {
254
+ return;
255
+ }
256
+ const headerName =
257
+ linkTargetRequest.responseHeaderValue('permissions-policy') ? 'permissions-policy' : 'feature-policy';
258
+ const requestLocation = NetworkForward.UIRequestLocation.UIRequestLocation.responseHeaderMatch(
259
+ linkTargetRequest,
260
+ {name: headerName, value: ''},
261
+ );
262
+ await Common.Revealer.reveal(requestLocation);
263
+ }
264
+
265
+ override async performUpdate(): Promise<void> {
266
+ const frameManager = SDK.FrameManager.FrameManager.instance();
267
+ const policies = this.#policies.sort((a, b) => a.feature.localeCompare(b.feature));
268
+ const allowed = policies.filter(p => p.allowed).sort((a, b) => a.feature.localeCompare(b.feature));
269
+ const disallowed = policies.filter(p => !p.allowed).sort((a, b) => a.feature.localeCompare(b.feature));
270
+ const disallowedData = this.#showDetails ? await Promise.all(disallowed.map(async policy => {
271
+ const frame = policy.locator ? frameManager.getFrame(policy.locator.frameId) : undefined;
272
+ const blockReason = policy.locator?.blockReason;
273
+ const linkTargetDOMNode = await ((blockReason === Protocol.Page.PermissionsPolicyBlockReason.IframeAttribute &&
274
+ frame?.getOwnerDOMNodeOrDocument()) ||
275
+ undefined);
276
+ const resource = frame?.resourceForURL(frame.url);
277
+ const linkTargetRequest =
278
+ (blockReason === Protocol.Page.PermissionsPolicyBlockReason.Header && resource?.request) || undefined;
279
+ return {policy, blockReason, linkTargetDOMNode, linkTargetRequest};
280
+ })) :
281
+ disallowed.map(policy => ({policy}));
245
282
 
246
- declare global {
247
- interface HTMLElementTagNameMap {
248
- 'devtools-resources-permissions-policy-section': PermissionsPolicySection;
283
+ this.#view(
284
+ {
285
+ allowed,
286
+ disallowed: disallowedData,
287
+ showDetails: this.#showDetails,
288
+ onToggleShowDetails: this.#toggleShowPermissionsDisallowedDetails.bind(this),
289
+ onRevealDOMNode: this.#revealDOMNode.bind(this),
290
+ onRevealHeader: this.#revealHeader.bind(this),
291
+ },
292
+ undefined, this.contentElement);
249
293
  }
250
294
  }