chrome-devtools-frontend 1.0.1699061 → 1.0.1701636

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 (157) hide show
  1. package/front_end/core/root/Runtime.ts +5 -0
  2. package/front_end/core/sdk/CSSPropertyParserMatchers.ts +16 -11
  3. package/front_end/core/sdk/NetworkManager.ts +7 -0
  4. package/front_end/core/sdk/SecurityOrigin.ts +1 -0
  5. package/front_end/core/sdk/ServiceWorkerCacheModel.ts +3 -0
  6. package/front_end/core/sdk/SourceMap.ts +12 -1
  7. package/front_end/core/sdk/SourceMapCache.ts +12 -0
  8. package/front_end/core/sdk/SourceMapManager.ts +17 -8
  9. package/front_end/core/sdk/SourceMapScopeChainEntry.ts +2 -19
  10. package/front_end/core/sdk/SourceMapScopesInfo.ts +21 -0
  11. package/front_end/core/sdk/StorageBucketsModel.ts +2 -0
  12. package/front_end/entrypoints/formatter_worker/ScopeParser.ts +7 -3
  13. package/front_end/entrypoints/formatter_worker/Substitute.ts +90 -26
  14. package/front_end/entrypoints/formatter_worker/formatter_worker-entrypoint.ts +1 -1
  15. package/front_end/entrypoints/main/ExecutionContextSelector.ts +17 -4
  16. package/front_end/entrypoints/main/GlobalAiButton.ts +2 -6
  17. package/front_end/entrypoints/main/MainImpl.ts +8 -1
  18. package/front_end/generated/InspectorBackendCommands.ts +13 -5
  19. package/front_end/generated/SupportedCSSProperties.ts +14 -0
  20. package/front_end/generated/protocol-mapping.d.ts +48 -9
  21. package/front_end/generated/protocol-proxy-api.d.ts +37 -7
  22. package/front_end/generated/protocol.ts +135 -22
  23. package/front_end/models/ai_assistance/debug.ts +10 -2
  24. package/front_end/models/bindings/NetworkProject.ts +30 -0
  25. package/front_end/models/bindings/ResourceScriptMapping.ts +62 -0
  26. package/front_end/models/change_tracker/ChangeTracker.ts +1 -1
  27. package/front_end/models/comment_manager/CD4ABridge.ts +4 -4
  28. package/front_end/models/comment_manager/CommentManager.ts +21 -0
  29. package/front_end/models/extensions/ExtensionAPI.ts +4 -2
  30. package/front_end/models/formatter/FormatterWorkerPool.ts +2 -2
  31. package/front_end/models/issues_manager/CookieIssue.ts +0 -2
  32. package/front_end/models/javascript_metadata/NativeFunctions.ts +7 -2
  33. package/front_end/models/persistence/NetworkPersistenceManager.ts +29 -4
  34. package/front_end/models/source_map_scopes/NamesResolver.ts +65 -40
  35. package/front_end/models/source_map_scopes/ScopeChainModel.ts +21 -1
  36. package/front_end/panels/accessibility/AccessibilityAnnouncementRecordingView.ts +70 -1
  37. package/front_end/panels/ai_assistance/ai_assistance-meta.ts +5 -8
  38. package/front_end/panels/ai_assistance/components/ChatMessage.ts +1 -1
  39. package/front_end/panels/application/AppManifestView.ts +128 -134
  40. package/front_end/panels/application/CrashReportContextView.ts +5 -5
  41. package/front_end/panels/application/DeviceBoundSessionsTreeElement.ts +17 -17
  42. package/front_end/panels/application/DeviceBoundSessionsView.ts +136 -137
  43. package/front_end/panels/application/IndexedDBModel.ts +3 -0
  44. package/front_end/panels/application/OriginTrialTreeView.ts +18 -23
  45. package/front_end/panels/application/ReportingApiTreeElement.ts +3 -3
  46. package/front_end/panels/application/ReportingApiView.ts +6 -14
  47. package/front_end/panels/application/application-meta.ts +7 -7
  48. package/front_end/panels/common/CommentThreadWidget.ts +19 -6
  49. package/front_end/panels/common/CommentsOverlayWidget.ts +143 -10
  50. package/front_end/panels/common/CommentsStatusBarPill.ts +13 -1
  51. package/front_end/panels/common/ExtensionServer.ts +61 -42
  52. package/front_end/panels/common/GeminiRebrandPromoDialog.ts +1 -1
  53. package/front_end/panels/common/commentThreadWidget.css +18 -0
  54. package/front_end/panels/common/common-meta.ts +4 -1
  55. package/front_end/panels/console/ConsolePrompt.ts +1 -1
  56. package/front_end/panels/console/ConsoleViewMessage.ts +1 -1
  57. package/front_end/panels/elements/ClassesPaneWidget.ts +2 -1
  58. package/front_end/panels/elements/DOMTreeContextMenu.ts +1 -1
  59. package/front_end/panels/elements/{ElementsTreeOutline.ts → DOMTreeWidget.ts} +45 -31
  60. package/front_end/panels/elements/ElementsPanel.ts +1 -1
  61. package/front_end/panels/elements/ElementsTreeElement.ts +3 -1
  62. package/front_end/panels/elements/ShortcutTreeElement.ts +1 -1
  63. package/front_end/panels/elements/StylePropertyTreeElement.ts +1 -1
  64. package/front_end/panels/elements/StylesSidebarPane.ts +4 -6
  65. package/front_end/panels/elements/TopLayerContainer.ts +1 -1
  66. package/front_end/panels/elements/elements.ts +4 -3
  67. package/front_end/panels/elements/elementsTreeOutline.css +4 -0
  68. package/front_end/panels/event_listeners/EventListenersView.ts +9 -4
  69. package/front_end/panels/issues/IssuesPane.ts +34 -22
  70. package/front_end/panels/network/RequestPayloadView.ts +17 -15
  71. package/front_end/panels/profiler/HeapDetachedElementsDataGrid.ts +1 -1
  72. package/front_end/panels/profiler/HeapProfileView.ts +8 -6
  73. package/front_end/panels/profiler/HeapSnapshotDataGrids.ts +8 -1
  74. package/front_end/panels/profiler/HeapSnapshotView.ts +6 -4
  75. package/front_end/panels/recorder/RecordingView.ts +32 -53
  76. package/front_end/panels/recorder/controlButton.css +6 -0
  77. package/front_end/panels/recorder/recordingView.css +11 -2
  78. package/front_end/panels/security/SecurityPanel.ts +87 -99
  79. package/front_end/panels/sensors/SensorsView.ts +87 -0
  80. package/front_end/panels/sensors/sensors-meta.ts +69 -1
  81. package/front_end/panels/settings/keybindsSettingsTab.css +1 -1
  82. package/front_end/panels/sources/DebuggerPlugin.ts +136 -55
  83. package/front_end/panels/sources/ScopeChainSidebarPane.ts +17 -15
  84. package/front_end/panels/timeline/components/IgnoreListSetting.ts +0 -2
  85. package/front_end/panels/timeline/components/LiveMetricsView.ts +59 -64
  86. package/front_end/panels/timeline/components/liveMetricsView.css +1 -0
  87. package/front_end/third_party/chromium/README.chromium +1 -1
  88. package/front_end/third_party/lighthouse/README.chromium +2 -2
  89. package/front_end/third_party/lighthouse/lighthouse-dt-bundle.js +1580 -1524
  90. package/front_end/third_party/lighthouse/locales/ar-XB.json +111 -72
  91. package/front_end/third_party/lighthouse/locales/ar.json +113 -74
  92. package/front_end/third_party/lighthouse/locales/bg.json +112 -73
  93. package/front_end/third_party/lighthouse/locales/ca.json +112 -73
  94. package/front_end/third_party/lighthouse/locales/cs.json +112 -73
  95. package/front_end/third_party/lighthouse/locales/da.json +112 -73
  96. package/front_end/third_party/lighthouse/locales/de.json +112 -73
  97. package/front_end/third_party/lighthouse/locales/el.json +112 -73
  98. package/front_end/third_party/lighthouse/locales/en-GB.json +111 -72
  99. package/front_end/third_party/lighthouse/locales/en-US.json +102 -66
  100. package/front_end/third_party/lighthouse/locales/en-XA.json +111 -72
  101. package/front_end/third_party/lighthouse/locales/en-XL.json +102 -66
  102. package/front_end/third_party/lighthouse/locales/es-419.json +112 -73
  103. package/front_end/third_party/lighthouse/locales/es.json +112 -73
  104. package/front_end/third_party/lighthouse/locales/fi.json +112 -73
  105. package/front_end/third_party/lighthouse/locales/fil.json +112 -73
  106. package/front_end/third_party/lighthouse/locales/fr.json +112 -73
  107. package/front_end/third_party/lighthouse/locales/he.json +112 -73
  108. package/front_end/third_party/lighthouse/locales/hi.json +112 -73
  109. package/front_end/third_party/lighthouse/locales/hr.json +112 -73
  110. package/front_end/third_party/lighthouse/locales/hu.json +112 -73
  111. package/front_end/third_party/lighthouse/locales/id.json +112 -73
  112. package/front_end/third_party/lighthouse/locales/it.json +113 -74
  113. package/front_end/third_party/lighthouse/locales/ja.json +112 -73
  114. package/front_end/third_party/lighthouse/locales/ko.json +112 -73
  115. package/front_end/third_party/lighthouse/locales/lt.json +112 -73
  116. package/front_end/third_party/lighthouse/locales/lv.json +112 -73
  117. package/front_end/third_party/lighthouse/locales/nl.json +112 -73
  118. package/front_end/third_party/lighthouse/locales/no.json +112 -73
  119. package/front_end/third_party/lighthouse/locales/pl.json +112 -73
  120. package/front_end/third_party/lighthouse/locales/pt-PT.json +112 -73
  121. package/front_end/third_party/lighthouse/locales/pt.json +112 -73
  122. package/front_end/third_party/lighthouse/locales/ro.json +112 -73
  123. package/front_end/third_party/lighthouse/locales/ru.json +112 -73
  124. package/front_end/third_party/lighthouse/locales/sk.json +112 -73
  125. package/front_end/third_party/lighthouse/locales/sl.json +112 -73
  126. package/front_end/third_party/lighthouse/locales/sr-Latn.json +112 -73
  127. package/front_end/third_party/lighthouse/locales/sr.json +112 -73
  128. package/front_end/third_party/lighthouse/locales/sv.json +124 -85
  129. package/front_end/third_party/lighthouse/locales/ta.json +112 -73
  130. package/front_end/third_party/lighthouse/locales/te.json +112 -73
  131. package/front_end/third_party/lighthouse/locales/th.json +112 -73
  132. package/front_end/third_party/lighthouse/locales/tr.json +113 -74
  133. package/front_end/third_party/lighthouse/locales/uk.json +112 -73
  134. package/front_end/third_party/lighthouse/locales/vi.json +112 -73
  135. package/front_end/third_party/lighthouse/locales/zh-HK.json +112 -73
  136. package/front_end/third_party/lighthouse/locales/zh-TW.json +113 -74
  137. package/front_end/third_party/lighthouse/locales/zh.json +113 -74
  138. package/front_end/third_party/lighthouse/report/bundle.d.ts +4 -4
  139. package/front_end/third_party/lighthouse/report/bundle.js +10 -3
  140. package/front_end/third_party/lighthouse/report-assets/report-generator.mjs +2 -2
  141. package/front_end/third_party/lit/lit.ts +3 -0
  142. package/front_end/third_party/lit/package.json +3 -0
  143. package/front_end/third_party/lit/rebuild.sh +3 -2
  144. package/front_end/ui/comments/CommentAnchorResolver.ts +8 -2
  145. package/front_end/ui/comments/CommentOverlayManager.ts +2 -1
  146. package/front_end/ui/legacy/InspectorView.ts +4 -3
  147. package/front_end/ui/legacy/TabbedPane.ts +121 -80
  148. package/front_end/ui/legacy/Treeoutline.ts +37 -7
  149. package/front_end/ui/legacy/UIUtils.ts +7 -0
  150. package/front_end/ui/legacy/components/data_grid/DataGridElement.ts +1 -1
  151. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +135 -146
  152. package/front_end/ui/legacy/treeoutline.css +2 -2
  153. package/front_end/ui/lit/lit.ts +1 -1
  154. package/front_end/ui/visual_logging/KnownContextValues.ts +11 -0
  155. package/inspector_overlay/highlight_anchor.ts +197 -0
  156. package/inspector_overlay/tool_highlight.ts +8 -0
  157. package/package.json +1 -1
@@ -428,6 +428,9 @@ export class IndexedDBModel extends SDK.SDKModel.SDKModel<EventTypes> implements
428
428
 
429
429
  storageBucketDeleted(_event: Protocol.Storage.StorageBucketDeletedEvent): void {
430
430
  }
431
+
432
+ privateVerificationTokensUpdated(): void {
433
+ }
431
434
  }
432
435
 
433
436
  SDK.SDKModel.SDKModel.register(IndexedDBModel, {capabilities: SDK.Target.Capability.STORAGE, autostart: false});
@@ -20,53 +20,48 @@ const {widget} = UI.Widget;
20
20
 
21
21
  const UIStrings = {
22
22
  /**
23
- * @description Label for the 'origin' field in a parsed Origin Trial Token.
23
+ * @description Label for the origin field in an origin trial token.
24
24
  */
25
25
  origin: 'Origin',
26
26
  /**
27
- * @description Label for `trialName` field in a parsed Origin Trial Token.
28
- * This field is only shown when token has unknown trial name as the token
29
- * will be put into 'UNKNOWN' group.
27
+ * @description Label for the trial name field in an origin trial token.
30
28
  */
31
- trialName: 'Trial Name',
29
+ trialName: 'Trial name',
32
30
  /**
33
- * @description Label for `expiryTime` field in a parsed Origin Trial Token.
31
+ * @description Label for the expiry time field in an origin trial token.
34
32
  */
35
- expiryTime: 'Expiry Time',
33
+ expiryTime: 'Expiry time',
36
34
  /**
37
- * @description Label for `usageRestriction` field in a parsed Origin Trial Token.
35
+ * @description Label for the usage restriction field in an origin trial token.
38
36
  */
39
- usageRestriction: 'Usage Restriction',
37
+ usageRestriction: 'Usage restriction',
40
38
  /**
41
- * @description Label for `isThirdParty` field in a parsed Origin Trial Token.
39
+ * @description Label for the third party field in an origin trial token.
42
40
  */
43
- isThirdParty: 'Third Party',
41
+ isThirdParty: 'Third party',
44
42
  /**
45
- * @description Label for a field containing info about an Origin Trial Token's `matchSubDomains` field.
46
- *An Origin Trial Token contains an origin URL. The `matchSubDomains` field describes whether the token
47
- *only applies to the origin URL or to all subdomains of the origin URL as well.
48
- *The field contains either 'true' or 'false'.
43
+ * @description Label for the subdomain matching field in an origin trial token.
49
44
  */
50
- matchSubDomains: 'Subdomain Matching',
45
+ matchSubDomains: 'Subdomain matching',
51
46
  /**
52
- * @description Label for the raw(= encoded / not human-readable) Origin Trial Token.
47
+ * @description Label for the raw token text in an origin trial token.
53
48
  */
54
- rawTokenText: 'Raw Token',
49
+ rawTokenText: 'Raw token',
55
50
  /**
56
- * @description Label for `status` field in an Origin Trial Token.
51
+ * @description Label for the token status field in an origin trial token.
57
52
  */
58
- status: 'Token Status',
53
+ status: 'Token status',
59
54
  /**
60
- * @description Label for tokenWithStatus node.
55
+ * @description Label for a token node in the origin trials tree view.
61
56
  */
62
57
  token: 'Token',
63
58
  /**
64
- * @description Label for a badge showing the number of Origin Trial Tokens. This number is always greater than 1.
59
+ * @description Label for a badge showing the number of origin trial tokens.
65
60
  * @example {2} PH1
66
61
  */
67
62
  tokens: '{PH1} tokens',
68
63
  /**
69
- * @description Label shown when there are no Origin Trial Tokens in the Frame view of the Application panel.
64
+ * @description Label shown when there are no origin trial tokens in the frame details view of the Application panel.
70
65
  */
71
66
  noTrialTokens: 'No trial tokens',
72
67
  } as const;
@@ -14,13 +14,13 @@ import type {ResourcesPanel} from './ResourcesPanel.js';
14
14
 
15
15
  const UIStrings = {
16
16
  /**
17
- * @description Label for an item in the Application Panel Sidebar of the Application panel
17
+ * @description Label for an item in the sidebar of the Application panel.
18
18
  */
19
19
  reportingApi: 'Reporting API',
20
20
  /**
21
- * @description Label for the Crash Report Context child item in the Reporting API section.
21
+ * @description Label for the crash report context item in the sidebar of the Application panel.
22
22
  */
23
- crashReportContext: 'Crash Report Context',
23
+ crashReportContext: 'Crash report context',
24
24
  } as const;
25
25
  const str_ = i18n.i18n.registerUIStrings('panels/application/ReportingApiTreeElement.ts', UIStrings);
26
26
  export const i18nString: i18n.LocalizeString = i18n.i18n.getLocalizedString.bind(undefined, str_);
@@ -17,29 +17,21 @@ const {widget} = UI.Widget;
17
17
 
18
18
  const UIStrings = {
19
19
  /**
20
- * @description Placeholder text that shows if no report or endpoint was detected.
21
- * A report contains information on issues or events that were encountered by a web browser.
22
- * An endpoint is a URL where the report is sent to.
23
- * (https://developer.chrome.com/docs/capabilities/web-apis/reporting-api)
20
+ * @description Header text in an empty state view when no report or endpoint has been detected in the reporting API view of the Application panel.
24
21
  */
25
22
  noReportOrEndpoint: 'No report or endpoint',
26
23
  /**
27
- * @description Placeholder text that shows if no report or endpoint was detected.
28
- * A report contains information on issues or events that were encountered by a web browser.
29
- * An endpoint is a URL where the report is sent to.
30
- * (https://developer.chrome.com/docs/capabilities/web-apis/reporting-api)
24
+ * @description Explanatory text in an empty state view describing the reporting API view of the Application panel.
31
25
  */
32
- reportingApiDescription: 'On this page you will be able to inspect `Reporting API` reports and endpoints',
26
+ reportingApiDescription: 'Inspect `Reporting API` reports and endpoints',
33
27
  /**
34
- * @description Placeholder text that shows if no report was selected for viewing
35
- *report body (https://developers.google.com/web/updates/2018/09/reportingapi#sending).
28
+ * @description Header text in an empty state view when no report is selected in the reporting API view of the Application panel.
36
29
  */
37
30
  noReportSelected: 'No report selected',
38
31
  /**
39
- * @description Placeholder text instructing the user how to display a Reporting API
40
- *report body (https://developers.google.com/web/updates/2018/09/reportingapi#sending).
32
+ * @description Explanatory text instructing the user how to display a report body in the reporting API view of the Application panel.
41
33
  */
42
- clickToDisplayBody: 'Click on any report to display its body',
34
+ clickToDisplayBody: 'Click any report to display its body',
43
35
  } as const;
44
36
  const str_ = i18n.i18n.registerUIStrings('panels/application/ReportingApiView.ts', UIStrings);
45
37
  export const i18nString: i18n.LocalizeString = i18n.i18n.getLocalizedString.bind(undefined, str_);
@@ -12,31 +12,31 @@ import * as PreloadingHelper from './preloading/helper/helper.js';
12
12
 
13
13
  const UIStrings = {
14
14
  /**
15
- * @description Text in Application Panel Sidebar of the Application panel
15
+ * @description Title of the Application panel.
16
16
  */
17
17
  application: 'Application',
18
18
  /**
19
- * @description Command for showing the 'Application' tool
19
+ * @description Command in the command menu for showing the Application panel.
20
20
  */
21
21
  showApplication: 'Show Application',
22
22
  /**
23
- * @description A tag of Application Panel that can be searched in the command menu
23
+ * @description Search tag for the Application panel in the command menu.
24
24
  */
25
25
  pwa: 'pwa',
26
26
  /**
27
- * @description Text of button in Clear Storage View of the Application panel
27
+ * @description Title of an action in the Application panel to clear site data.
28
28
  */
29
29
  clearSiteData: 'Clear site data',
30
30
  /**
31
- * @description Title of an action that clears all site data including 3rd party cookies
31
+ * @description Title of an action in the Application panel to clear all site data including third-party cookies.
32
32
  */
33
33
  clearSiteDataIncludingThirdparty: 'Clear site data (including third-party cookies)',
34
34
  /**
35
- * @description Title of an action under the Background Services category that can be invoked through the Command Menu
35
+ * @description Title of an action under the background services category that can be invoked through the command menu.
36
36
  */
37
37
  startRecordingEvents: 'Start recording events',
38
38
  /**
39
- * @description Title of an action under the Background Services category that can be invoked through the Command Menu
39
+ * @description Title of an action under the background services category that can be invoked through the command menu.
40
40
  */
41
41
  stopRecordingEvents: 'Stop recording events',
42
42
  } as const;
@@ -5,6 +5,7 @@
5
5
  import '../../ui/components/tooltips/tooltips.js';
6
6
 
7
7
  import * as i18n from '../../core/i18n/i18n.js';
8
+ import type * as SDK from '../../core/sdk/sdk.js';
8
9
  import type * as CommentManager from '../../models/comment_manager/comment_manager.js';
9
10
  import * as Input from '../../ui/components/input/input.js';
10
11
  import * as MarkdownView from '../../ui/components/markdown_view/markdown_view.js';
@@ -12,8 +13,10 @@ import * as UI from '../../ui/legacy/legacy.js';
12
13
  import * as Lit from '../../ui/lit/lit.js';
13
14
 
14
15
  import commentThreadWidgetStyles from './commentThreadWidget.css.js';
16
+ import {DOMNodeLink} from './DOMLinkifier.js';
15
17
 
16
18
  const {html, render, Directives: {createRef, ref}} = Lit;
19
+ const {widget} = UI.Widget;
17
20
 
18
21
  const UIStrings = {
19
22
  /**
@@ -33,7 +36,7 @@ const UIStrings = {
33
36
  /**
34
37
  * @description Label for the aria-label of the add comment button.
35
38
  */
36
- addCommentButton: 'Add comment',
39
+ sendToAgent: 'Send to agent',
37
40
  /**
38
41
  * @description aria-label for the comment text area.
39
42
  */
@@ -52,8 +55,16 @@ const str_ = i18n.i18n.registerUIStrings('panels/common/CommentThreadWidget.ts',
52
55
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
53
56
  const lockedString = i18n.i18n.lockedString;
54
57
 
58
+ /**
59
+ * Either the DOM node the thread is anchored to, or a plain text label for anchors that are not
60
+ * DOM nodes (e.g. network requests).
61
+ */
62
+ export type Title = {
63
+ node: SDK.DOMModel.DOMNode,
64
+ }|{text: string};
65
+
55
66
  export interface ViewInput {
56
- title: string;
67
+ title: Title;
57
68
  comments: CommentManager.CommentManager.Comment[];
58
69
  commentText: string;
59
70
  textAreaRef: Lit.Directives.Ref<HTMLTextAreaElement>;
@@ -72,7 +83,9 @@ export const DEFAULT_VIEW = (input: ViewInput, _output: ViewOutput, target: HTML
72
83
  <div class="comment-thread-widget ${hasComment ? 'submitted' : ''}">
73
84
  <div class="header">
74
85
  <span class="selected-item">
75
- <span class="selected-item-text">${input.title}</span>
86
+ ${'node' in input.title ?
87
+ widget(DOMNodeLink, {node: input.title.node}) :
88
+ html`<span class="selected-item-text">${input.title.text}</span>`}
76
89
  </span>
77
90
  ${hasComment ? html`
78
91
  <div class="sent-status">
@@ -137,10 +150,10 @@ export const DEFAULT_VIEW = (input: ViewInput, _output: ViewOutput, target: HTML
137
150
  </div>
138
151
  </devtools-tooltip>
139
152
  <devtools-button
140
- aria-label=${i18nString(UIStrings.addCommentButton)}
153
+ aria-label=${i18nString(UIStrings.sendToAgent)}
141
154
  .disabled=${!input.commentText.trim()}
142
155
  @click=${() => input.onAddComment(input.commentText)}>
143
- ${i18nString(UIStrings.addCommentButton)}
156
+ ${i18nString(UIStrings.sendToAgent)}
144
157
  </devtools-button>
145
158
  </div>
146
159
  ` : Lit.nothing}
@@ -152,7 +165,7 @@ export const DEFAULT_VIEW = (input: ViewInput, _output: ViewOutput, target: HTML
152
165
  type View = typeof DEFAULT_VIEW;
153
166
 
154
167
  export class CommentThreadWidget extends UI.Widget.Widget {
155
- title = 'Comment Thread';
168
+ title: Title = {text: ''};
156
169
  #comments: CommentManager.CommentManager.Comment[] = [];
157
170
  #commentText = '';
158
171
  #textAreaRef = createRef<HTMLTextAreaElement>();
@@ -4,13 +4,15 @@
4
4
 
5
5
  import type * as Common from '../../core/common/common.js';
6
6
  import * as Root from '../../core/root/root.js';
7
+ import * as SDK from '../../core/sdk/sdk.js';
8
+ import type * as Protocol from '../../generated/protocol.js';
7
9
  import * as CommentManager from '../../models/comment_manager/comment_manager.js';
8
10
  import * as Comments from '../../ui/comments/comments.js';
9
11
  import * as UI from '../../ui/legacy/legacy.js';
10
12
  import * as Lit from '../../ui/lit/lit.js';
11
13
 
12
14
  import commentsOverlayStyles from './commentsOverlay.css.js';
13
- import {CommentThreadWidget} from './CommentThreadWidget.js';
15
+ import {CommentThreadWidget, type Title} from './CommentThreadWidget.js';
14
16
 
15
17
  const {
16
18
  html,
@@ -27,6 +29,7 @@ export interface ViewInput {
27
29
  onPinClick: (threadId: string) => void;
28
30
  activeThread: CommentManager.CommentManager.CommentThread|null;
29
31
  activePin: Comments.CommentOverlayManager.PinPositionData|null;
32
+ title: Title;
30
33
  onAddComment: (text: string) => void;
31
34
  }
32
35
 
@@ -40,6 +43,7 @@ const POPUP_MARGIN = 8;
40
43
  const PIN_HEIGHT = 30;
41
44
  const POPUP_WIDTH = 288;
42
45
  const POPUP_HEIGHT = 220;
46
+ const AUTO_CLOSE_DELAY_MS = 2000;
43
47
 
44
48
  const DEFAULT_VIEW: View = (input: ViewInput, _output: undefined, target: HTMLElement): void => {
45
49
  // clang-format off
@@ -96,6 +100,7 @@ const DEFAULT_VIEW: View = (input: ViewInput, _output: undefined, target: HTMLEl
96
100
  )}px`,
97
101
  })}>
98
102
  ${UI.Widget.widget(CommentThreadWidget, {
103
+ title: input.title,
99
104
  comments: [...item.thread.comments],
100
105
  onAddComment: input.onAddComment,
101
106
  })}
@@ -115,6 +120,9 @@ export class CommentsOverlayWidget extends UI.Widget.Widget {
115
120
  readonly #commentManager: CommentManager.CommentManager.CommentManager;
116
121
  #commentOverlayManager: Comments.CommentOverlayManager.CommentOverlayManager;
117
122
  #activeThreadId: string|null = null;
123
+ #closeTimeoutId: number|null = null;
124
+ #cachedTitle: Title = {text: ''};
125
+ #cachedTitleAnchor: CommentManager.CommentManager.CommentAnchorSignature|null = null;
118
126
 
119
127
  constructor(
120
128
  element: HTMLElement|undefined,
@@ -157,11 +165,17 @@ export class CommentsOverlayWidget extends UI.Widget.Widget {
157
165
  this.#onCommentModeChanged,
158
166
  this,
159
167
  );
168
+ this.#commentManager.addEventListener(
169
+ CommentManager.CommentManager.Events.AGENT_ATTACHED_CHANGED,
170
+ this.#onAgentAttachedChanged,
171
+ this,
172
+ );
160
173
 
161
174
  this.requestUpdate();
162
175
  }
163
176
 
164
177
  override willHide(): void {
178
+ this.#clearCloseTimeout();
165
179
  this.#commentOverlayManager.stop();
166
180
  this.#commentOverlayManager.removeEventListener(
167
181
  Comments.CommentOverlayManager.Events.POSITIONS_UPDATED,
@@ -184,10 +198,32 @@ export class CommentsOverlayWidget extends UI.Widget.Widget {
184
198
  this.#onCommentModeChanged,
185
199
  this,
186
200
  );
201
+ this.#commentManager.removeEventListener(
202
+ CommentManager.CommentManager.Events.AGENT_ATTACHED_CHANGED,
203
+ this.#onAgentAttachedChanged,
204
+ this,
205
+ );
187
206
 
188
207
  super.willHide();
189
208
  }
190
209
 
210
+ #clearCloseTimeout(): void {
211
+ if (this.#closeTimeoutId !== null) {
212
+ window.clearTimeout(this.#closeTimeoutId);
213
+ this.#closeTimeoutId = null;
214
+ }
215
+ }
216
+
217
+ #onAgentAttachedChanged(
218
+ event: Common.EventTarget.EventTargetEvent<
219
+ CommentManager.CommentManager.EventTypes[CommentManager.CommentManager.Events.AGENT_ATTACHED_CHANGED]>,
220
+ ): void {
221
+ if (!event.data) {
222
+ this.#activeThreadId = null;
223
+ }
224
+ this.requestUpdate();
225
+ }
226
+
191
227
  #onCommentModeChanged(
192
228
  event: Common.EventTarget.EventTargetEvent<
193
229
  CommentManager.CommentManager.EventTypes[CommentManager.CommentManager.Events.COMMENT_MODE_CHANGED]>,
@@ -213,6 +249,43 @@ export class CommentsOverlayWidget extends UI.Widget.Widget {
213
249
  this.requestUpdate();
214
250
  }
215
251
 
252
+ async #getOrComputeTitle(anchor: CommentManager.CommentManager.CommentAnchorSignature|null): Promise<Title> {
253
+ if (anchor === this.#cachedTitleAnchor) {
254
+ return this.#cachedTitle;
255
+ }
256
+ const title = anchor ? await this.#computeTitle(anchor) : {text: ''};
257
+ this.#cachedTitleAnchor = anchor;
258
+ this.#cachedTitle = title;
259
+ return title;
260
+ }
261
+
262
+ async #computeTitle(anchor: CommentManager.CommentManager.CommentAnchorSignature): Promise<Title> {
263
+ if (anchor.node) {
264
+ const target = SDK.TargetManager.TargetManager.instance().targetById(anchor.node.targetId);
265
+ if (target) {
266
+ const deferredNode = new SDK.DOMModel.DeferredDOMNode(
267
+ target,
268
+ anchor.node.backendNodeId as Protocol.DOM.BackendNodeId,
269
+ );
270
+ const node = await deferredNode.resolvePromise();
271
+ if (node) {
272
+ return {node};
273
+ }
274
+ }
275
+ return {text: ''};
276
+ }
277
+
278
+ if (anchor.networkRequestId) {
279
+ const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();
280
+ const request = target?.model(SDK.NetworkManager.NetworkManager)?.requestForId(anchor.networkRequestId);
281
+ if (request) {
282
+ return {text: request.name()};
283
+ }
284
+ }
285
+
286
+ return {text: anchor.textSignature || ''};
287
+ }
288
+
216
289
  #handlePinClick = (threadId: string): void => {
217
290
  const thread = this.#commentManager.getCommentThread(threadId);
218
291
  if (this.#activeThreadId === threadId) {
@@ -227,16 +300,34 @@ export class CommentsOverlayWidget extends UI.Widget.Widget {
227
300
  this.requestUpdate();
228
301
  };
229
302
 
230
- override performUpdate(): void {
303
+ override async performUpdate(signal?: AbortSignal): Promise<void> {
304
+ if (!this.#commentManager.isAgentAttached()) {
305
+ this.#view(
306
+ {
307
+ pins: [],
308
+ highlights: [],
309
+ hoverHighlight: null,
310
+ commentMode: false,
311
+ onPinClick: this.#handlePinClick,
312
+ activeThread: null,
313
+ activePin: null,
314
+ title: {text: ''},
315
+ onAddComment: () => {},
316
+ },
317
+ undefined,
318
+ this.contentElement,
319
+ );
320
+ return;
321
+ }
322
+
323
+ const activeThread =
324
+ this.#activeThreadId ? this.#commentManager.getCommentThread(this.#activeThreadId) ?? null : null;
325
+ const title = await this.#getOrComputeTitle(activeThread?.anchor ?? null);
326
+ signal?.throwIfAborted();
327
+
231
328
  const pins = this.#commentOverlayManager.getPinPositions();
232
329
  const highlights = this.#commentOverlayManager.getHighlightRects();
233
-
234
- let activePin: Comments.CommentOverlayManager.PinPositionData|null = null;
235
- let activeThread: CommentManager.CommentManager.CommentThread|null = null;
236
- if (this.#activeThreadId) {
237
- activePin = pins.find(p => p.id === this.#activeThreadId) ?? null;
238
- activeThread = this.#commentManager.getCommentThread(this.#activeThreadId) ?? null;
239
- }
330
+ const activePin = this.#activeThreadId ? pins.find(p => p.id === this.#activeThreadId) ?? null : null;
240
331
 
241
332
  const viewInput: ViewInput = {
242
333
  pins,
@@ -246,8 +337,20 @@ export class CommentsOverlayWidget extends UI.Widget.Widget {
246
337
  onPinClick: this.#handlePinClick,
247
338
  activeThread,
248
339
  activePin,
340
+ title,
249
341
  onAddComment: (text: string) => {
250
- activeThread?.save(text);
342
+ if (!activeThread) {
343
+ return;
344
+ }
345
+ activeThread.save(text);
346
+ const threadId = activeThread.id;
347
+ this.#closeTimeoutId = window.setTimeout(() => {
348
+ this.#closeTimeoutId = null;
349
+ if (this.#activeThreadId === threadId) {
350
+ this.#activeThreadId = null;
351
+ this.requestUpdate();
352
+ }
353
+ }, AUTO_CLOSE_DELAY_MS);
251
354
  },
252
355
  };
253
356
  this.#view(viewInput, undefined, this.contentElement);
@@ -268,6 +371,9 @@ export class ActionDelegate implements UI.ActionRegistration.ActionDelegate {
268
371
 
269
372
  handleAction(_context: UI.Context.Context, actionId: string): boolean {
270
373
  if (actionId === 'comments.toggle-comment-mode') {
374
+ if (!this.#commentManager.isAgentAttached()) {
375
+ return false;
376
+ }
271
377
  if (!widgetInstance) {
272
378
  widgetInstance = new CommentsOverlayWidget(
273
379
  undefined,
@@ -291,3 +397,30 @@ export class ActionDelegate implements UI.ActionRegistration.ActionDelegate {
291
397
  }
292
398
  }
293
399
  }
400
+
401
+ export class ButtonProvider implements UI.Toolbar.Provider {
402
+ readonly #button: UI.Toolbar.ToolbarButton;
403
+ readonly #commentManager: CommentManager.CommentManager.CommentManager;
404
+
405
+ constructor(commentManager?: CommentManager.CommentManager.CommentManager) {
406
+ this.#commentManager = commentManager ??
407
+ Root.DevToolsContext.globalInstance().get(
408
+ CommentManager.CommentManager.CommentManager,
409
+ );
410
+ const action = UI.ActionRegistry.ActionRegistry.instance().getAction('comments.toggle-comment-mode');
411
+ action.setEnabled(this.#commentManager.isAgentAttached());
412
+ this.#button = UI.Toolbar.Toolbar.createActionButton(action);
413
+ this.#button.setVisible(this.#commentManager.isAgentAttached());
414
+ this.#commentManager.addEventListener(
415
+ CommentManager.CommentManager.Events.AGENT_ATTACHED_CHANGED,
416
+ event => {
417
+ action.setEnabled(event.data);
418
+ this.#button.setVisible(event.data);
419
+ },
420
+ );
421
+ }
422
+
423
+ item(): UI.Toolbar.ToolbarItem|null {
424
+ return this.#button;
425
+ }
426
+ }
@@ -72,6 +72,11 @@ export class CommentsStatusBarPill extends UI.Widget.Widget {
72
72
  this.#onThreadsChanged,
73
73
  this,
74
74
  );
75
+ this.#commentManager.addEventListener(
76
+ CommentManager.CommentManager.Events.AGENT_ATTACHED_CHANGED,
77
+ this.#onThreadsChanged,
78
+ this,
79
+ );
75
80
  this.requestUpdate();
76
81
  }
77
82
 
@@ -81,12 +86,19 @@ export class CommentsStatusBarPill extends UI.Widget.Widget {
81
86
  this.#onThreadsChanged,
82
87
  this,
83
88
  );
89
+ this.#commentManager.removeEventListener(
90
+ CommentManager.CommentManager.Events.AGENT_ATTACHED_CHANGED,
91
+ this.#onThreadsChanged,
92
+ this,
93
+ );
84
94
  super.willHide();
85
95
  }
86
96
 
87
97
  override performUpdate(): void {
88
98
  const viewInput: ViewInput = {
89
- threads: this.#commentManager.getCommentThreads().filter(thread => thread.status !== 'DRAFT'),
99
+ threads: this.#commentManager.isAgentAttached() ?
100
+ this.#commentManager.getCommentThreads().filter(thread => thread.status !== 'DRAFT') :
101
+ [],
90
102
  onPillClick: this.#handlePillClick,
91
103
  };
92
104
  this.#view(viewInput, undefined, this.contentElement);