chrome-devtools-frontend 1.0.1582745 → 1.0.1583146

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 (27) hide show
  1. package/front_end/core/root/Runtime.ts +0 -5
  2. package/front_end/core/sdk/NetworkManager.ts +63 -115
  3. package/front_end/entrypoint_template.html +1 -5
  4. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +15 -3
  5. package/front_end/panels/ai_assistance/components/ChatMessage.ts +4 -2
  6. package/front_end/panels/autofill/AutofillView.ts +4 -8
  7. package/front_end/panels/common/AiCodeGenerationTeaser.ts +27 -8
  8. package/front_end/panels/elements/ComputedStyleWidget.ts +41 -29
  9. package/front_end/panels/elements/ElementStatePaneWidget.ts +1 -1
  10. package/front_end/panels/elements/ElementsTreeElement.ts +487 -426
  11. package/front_end/panels/elements/EventListenersWidget.ts +2 -4
  12. package/front_end/panels/elements/PropertiesWidget.ts +1 -2
  13. package/front_end/panels/elements/StylePropertyTreeElement.ts +18 -2
  14. package/front_end/panels/elements/computedStyleWidget.css +30 -0
  15. package/front_end/panels/network/NetworkLogView.ts +64 -105
  16. package/front_end/panels/network/RequestConditionsDrawer.ts +40 -131
  17. package/front_end/panels/network/network-meta.ts +4 -27
  18. package/front_end/panels/settings/WorkspaceSettingsTab.ts +1 -1
  19. package/front_end/panels/sources/CallStackSidebarPane.ts +2 -2
  20. package/front_end/ui/components/text_editor/AiCodeCompletionProvider.ts +8 -0
  21. package/front_end/ui/components/text_editor/AiCodeGenerationProvider.ts +8 -0
  22. package/front_end/ui/components/text_editor/config.ts +6 -0
  23. package/front_end/ui/legacy/Toolbar.ts +12 -4
  24. package/front_end/ui/legacy/UIUtils.ts +26 -1
  25. package/front_end/ui/visual_logging/KnownContextValues.ts +1 -0
  26. package/package.json +1 -1
  27. package/front_end/panels/elements/computedStyleSidebarPane.css +0 -18
@@ -582,10 +582,6 @@ interface AiPromptApi {
582
582
  allowWithoutGpu: boolean;
583
583
  }
584
584
 
585
- interface DevToolsIndividualRequestThrottling {
586
- enabled: boolean;
587
- }
588
-
589
585
  export interface DevToolsEnableDurableMessages {
590
586
  enabled: boolean;
591
587
  }
@@ -631,7 +627,6 @@ export type HostConfig = Platform.TypeScriptUtilities.RecursivePartial<{
631
627
  devToolsAiCodeGeneration: HostConfigAiCodeGeneration,
632
628
  devToolsVeLogging: HostConfigVeLogging,
633
629
  devToolsWellKnown: HostConfigWellKnown,
634
- devToolsIndividualRequestThrottling: DevToolsIndividualRequestThrottling,
635
630
  /**
636
631
  * OffTheRecord here indicates that the user's profile is either incognito,
637
632
  * or guest mode, rather than a "normal" profile.
@@ -1687,19 +1687,8 @@ export class RequestCondition extends Common.ObjectWrapper.ObjectWrapper<Request
1687
1687
  (this.#pattern.upgradedPattern?.constructorString ?? this.#pattern.wildcardURL);
1688
1688
  }
1689
1689
 
1690
- set pattern(pattern: RequestURLPattern|string) {
1691
- if (typeof pattern === 'string') {
1692
- // TODO(pfaffe) Remove once the feature flag is no longer required
1693
- if (Root.Runtime.hostConfig.devToolsIndividualRequestThrottling?.enabled) {
1694
- throw new Error('Should not use wildcard urls');
1695
- }
1696
- this.#pattern = {
1697
- wildcardURL: pattern,
1698
- upgradedPattern: RequestURLPattern.upgradeFromWildcard(pattern) ?? undefined
1699
- };
1700
- } else {
1701
- this.#pattern = pattern;
1702
- }
1690
+ set pattern(pattern: RequestURLPattern) {
1691
+ this.#pattern = pattern;
1703
1692
  this.dispatchEventToListeners(RequestCondition.Events.REQUEST_CONDITION_CHANGED);
1704
1693
  }
1705
1694
 
@@ -1792,10 +1781,7 @@ export class RequestConditions extends Common.ObjectWrapper.ObjectWrapper<Reques
1792
1781
  }
1793
1782
 
1794
1783
  findCondition(pattern: string): RequestCondition|undefined {
1795
- if (Root.Runtime.hostConfig.devToolsIndividualRequestThrottling?.enabled) {
1796
- return this.#conditions.find(condition => condition.constructorString === pattern);
1797
- }
1798
- return this.#conditions.find(condition => condition.wildcardURL === pattern);
1784
+ return this.#conditions.find(condition => condition.constructorString === pattern);
1799
1785
  }
1800
1786
 
1801
1787
  has(url: string): boolean {
@@ -1862,84 +1848,72 @@ export class RequestConditions extends Common.ObjectWrapper.ObjectWrapper<Reques
1862
1848
  function isNonBlockingCondition(condition: ThrottlingConditions): condition is Conditions {
1863
1849
  return !('block' in condition);
1864
1850
  }
1865
- if (Root.Runtime.hostConfig.devToolsIndividualRequestThrottling?.enabled) {
1866
- const urlPatterns: Protocol.Network.BlockPattern[] = [];
1867
- // We store all this info out-of-band to prevent races with changing conditions while the promise is still pending
1868
- const matchedNetworkConditions: Array<{conditions: Conditions, ruleIds?: Set<string>, urlPattern?: string}> = [];
1869
- if (this.conditionsEnabled) {
1870
- for (const condition of this.#conditions) {
1871
- const urlPattern = condition.constructorString;
1872
- const conditions = condition.conditions;
1873
- if (!condition.enabled || !urlPattern || conditions === NoThrottlingConditions) {
1874
- continue;
1875
- }
1876
- const block = !isNonBlockingCondition(conditions);
1877
- urlPatterns.push({urlPattern, block});
1878
- if (!block) {
1879
- const {ruleIds} = condition;
1880
- matchedNetworkConditions.push({ruleIds, urlPattern, conditions});
1881
- }
1851
+ const urlPatterns: Protocol.Network.BlockPattern[] = [];
1852
+ // We store all this info out-of-band to prevent races with changing conditions while the promise is still pending
1853
+ const matchedNetworkConditions: Array<{conditions: Conditions, ruleIds?: Set<string>, urlPattern?: string}> = [];
1854
+ if (this.conditionsEnabled) {
1855
+ for (const condition of this.#conditions) {
1856
+ const urlPattern = condition.constructorString;
1857
+ const conditions = condition.conditions;
1858
+ if (!condition.enabled || !urlPattern || conditions === NoThrottlingConditions) {
1859
+ continue;
1860
+ }
1861
+ const block = !isNonBlockingCondition(conditions);
1862
+ urlPatterns.push({urlPattern, block});
1863
+ if (!block) {
1864
+ const {ruleIds} = condition;
1865
+ matchedNetworkConditions.push({ruleIds, urlPattern, conditions});
1882
1866
  }
1883
1867
  }
1868
+ }
1884
1869
 
1885
- if (globalConditions) {
1886
- matchedNetworkConditions.push({conditions: globalConditions});
1887
- }
1888
-
1889
- const promises: Array<Promise<unknown>> = [];
1890
-
1891
- for (const agent of agents) {
1892
- promises.push(agent.invoke_setBlockedURLs({urlPatterns}));
1893
- promises.push(agent
1894
- .invoke_emulateNetworkConditionsByRule({
1895
- offline,
1896
- matchedNetworkConditions: matchedNetworkConditions.map(
1897
- ({urlPattern, conditions}) => ({
1898
- urlPattern: urlPattern ?? '',
1899
- latency: conditions.latency,
1900
- downloadThroughput: conditions.download < 0 ? 0 : conditions.download,
1901
- uploadThroughput: conditions.upload < 0 ? 0 : conditions.upload,
1902
- packetLoss: (conditions.packetLoss ?? 0) < 0 ? 0 : conditions.packetLoss,
1903
- packetQueueLength: conditions.packetQueueLength,
1904
- packetReordering: conditions.packetReordering,
1905
- connectionType: NetworkManager.connectionType(conditions),
1906
- }))
1907
- })
1908
- .then(response => {
1909
- if (!response.getError()) {
1910
- for (let i = 0; i < response.ruleIds.length; ++i) {
1911
- const ruleId = response.ruleIds[i];
1912
- const {ruleIds, conditions, urlPattern} = matchedNetworkConditions[i];
1913
- if (ruleIds) {
1914
- this.#requestConditionsById.set(ruleId, {urlPattern, conditions});
1915
- matchedNetworkConditions[i].ruleIds?.add(ruleId);
1916
- }
1917
- }
1918
- }
1919
- }));
1920
- promises.push(agent.invoke_overrideNetworkState({
1921
- offline,
1922
- latency: globalConditions?.latency ?? 0,
1923
- downloadThroughput: globalConditions?.download ?? -1,
1924
- uploadThroughput: globalConditions?.upload ?? -1,
1925
- connectionType: globalConditions ? NetworkManager.connectionType(globalConditions) :
1926
- Protocol.Network.ConnectionType.None,
1927
- }));
1928
- }
1929
-
1930
- this.#conditionsAppliedForTestPromise = this.#conditionsAppliedForTestPromise.then(() => Promise.all(promises));
1931
- return urlPatterns.length > 0;
1870
+ if (globalConditions) {
1871
+ matchedNetworkConditions.push({conditions: globalConditions});
1932
1872
  }
1933
1873
 
1934
- const urls = this.conditionsEnabled ?
1935
- this.#conditions.filter(condition => condition.enabled && condition.wildcardURL)
1936
- .map(condition => condition.wildcardURL as string) :
1937
- [];
1874
+ const promises: Array<Promise<unknown>> = [];
1938
1875
 
1939
1876
  for (const agent of agents) {
1940
- void agent.invoke_setBlockedURLs({urls});
1877
+ promises.push(agent.invoke_setBlockedURLs({urlPatterns}));
1878
+ promises.push(agent
1879
+ .invoke_emulateNetworkConditionsByRule({
1880
+ offline,
1881
+ matchedNetworkConditions: matchedNetworkConditions.map(
1882
+ ({urlPattern, conditions}) => ({
1883
+ urlPattern: urlPattern ?? '',
1884
+ latency: conditions.latency,
1885
+ downloadThroughput: conditions.download < 0 ? 0 : conditions.download,
1886
+ uploadThroughput: conditions.upload < 0 ? 0 : conditions.upload,
1887
+ packetLoss: (conditions.packetLoss ?? 0) < 0 ? 0 : conditions.packetLoss,
1888
+ packetQueueLength: conditions.packetQueueLength,
1889
+ packetReordering: conditions.packetReordering,
1890
+ connectionType: NetworkManager.connectionType(conditions),
1891
+ }))
1892
+ })
1893
+ .then(response => {
1894
+ if (!response.getError()) {
1895
+ for (let i = 0; i < response.ruleIds.length; ++i) {
1896
+ const ruleId = response.ruleIds[i];
1897
+ const {ruleIds, conditions, urlPattern} = matchedNetworkConditions[i];
1898
+ if (ruleIds) {
1899
+ this.#requestConditionsById.set(ruleId, {urlPattern, conditions});
1900
+ matchedNetworkConditions[i].ruleIds?.add(ruleId);
1901
+ }
1902
+ }
1903
+ }
1904
+ }));
1905
+ promises.push(agent.invoke_overrideNetworkState({
1906
+ offline,
1907
+ latency: globalConditions?.latency ?? 0,
1908
+ downloadThroughput: globalConditions?.download ?? -1,
1909
+ uploadThroughput: globalConditions?.upload ?? -1,
1910
+ connectionType: globalConditions ? NetworkManager.connectionType(globalConditions) :
1911
+ Protocol.Network.ConnectionType.None,
1912
+ }));
1941
1913
  }
1942
- return urls.length > 0;
1914
+
1915
+ this.#conditionsAppliedForTestPromise = this.#conditionsAppliedForTestPromise.then(() => Promise.all(promises));
1916
+ return urlPatterns.length > 0;
1943
1917
  }
1944
1918
 
1945
1919
  conditionsAppliedForTest(): Promise<unknown> {
@@ -2082,9 +2056,6 @@ export class MultitargetNetworkManager extends Common.ObjectWrapper.ObjectWrappe
2082
2056
  }
2083
2057
  this.#networkAgents.add(networkAgent);
2084
2058
  this.#fetchAgents.add(fetchAgent);
2085
- if (this.isThrottling() && !Root.Runtime.hostConfig.devToolsIndividualRequestThrottling?.enabled) {
2086
- this.updateNetworkConditions(networkAgent);
2087
- }
2088
2059
  }
2089
2060
 
2090
2061
  modelRemoved(networkManager: NetworkManager): void {
@@ -2110,14 +2081,8 @@ export class MultitargetNetworkManager extends Common.ObjectWrapper.ObjectWrappe
2110
2081
 
2111
2082
  setNetworkConditions(conditions: Conditions): void {
2112
2083
  this.#networkConditions = conditions;
2113
- if (Root.Runtime.hostConfig.devToolsIndividualRequestThrottling?.enabled) {
2114
- this.#requestConditions.applyConditions(
2115
- this.isOffline(), this.isThrottling() ? this.#networkConditions : null, ...this.#networkAgents);
2116
- } else {
2117
- for (const agent of this.#networkAgents) {
2118
- this.updateNetworkConditions(agent);
2119
- }
2120
- }
2084
+ this.#requestConditions.applyConditions(
2085
+ this.isOffline(), this.isThrottling() ? this.#networkConditions : null, ...this.#networkAgents);
2121
2086
  this.dispatchEventToListeners(MultitargetNetworkManager.Events.CONDITIONS_CHANGED);
2122
2087
  }
2123
2088
 
@@ -2224,23 +2189,6 @@ export class MultitargetNetworkManager extends Common.ObjectWrapper.ObjectWrappe
2224
2189
  return this.#isBlocking && this.requestConditions.conditionsEnabled;
2225
2190
  }
2226
2191
 
2227
- /**
2228
- * @deprecated Kept for layout tests
2229
- * TODO(pfaffe) remove
2230
- */
2231
- private setBlockingEnabled(enabled: boolean): void {
2232
- this.requestConditions.conditionsEnabled = enabled;
2233
- }
2234
-
2235
- /**
2236
- * @deprecated Kept for layout tests
2237
- * TODO(pfaffe) remove
2238
- */
2239
- private setBlockedPatterns(patterns: Array<{url: string, enabled: boolean}>): void {
2240
- this.requestConditions.clear();
2241
- this.requestConditions.add(...patterns.map(pattern => RequestCondition.createFromSetting(pattern)));
2242
- }
2243
-
2244
2192
  private updateBlockedPatterns(): void {
2245
2193
  this.#isBlocking = this.#requestConditions.applyConditions(
2246
2194
  this.isOffline(), this.isThrottling() ? this.#networkConditions : null, ...this.#networkAgents);
@@ -14,11 +14,7 @@
14
14
  }
15
15
  }
16
16
  </style>
17
- <meta
18
- http-equiv="Content-Security-Policy"
19
- content="default-src 'self' devtools: data:; style-src 'self' 'unsafe-inline' devtools:; object-src 'none'; script-src
20
- 'self' https://chrome-devtools-frontend.appspot.com; img-src 'self' data:; frame-src * data:; connect-src data:
21
- https://chromeuxreport.googleapis.com 'self' devtools:;">
17
+ <meta http-equiv="Content-Security-Policy" content="object-src 'none'; script-src 'self' https://chrome-devtools-frontend.appspot.com">
22
18
  <meta name="referrer" content="no-referrer">
23
19
  <script type="module" src="./entrypoints/%ENTRYPOINT_NAME%/%ENTRYPOINT_NAME%.js"></script>
24
20
  <link href="./application_tokens.css" rel="stylesheet">
@@ -707,12 +707,24 @@ export class AiAssistancePanel extends UI.Panel.Panel {
707
707
  // We select the default agent based on the open panels if
708
708
  // there isn't any active conversation.
709
709
  #selectDefaultAgentIfNeeded(): void {
710
+ // We don't change the current agent when there is a message in flight.
711
+ if (this.#isLoading) {
712
+ return;
713
+ }
714
+
710
715
  // If there already is an agent and if it is not empty,
711
- // we don't automatically change the agent. In addition to this,
712
- // we don't change the current agent when there is a message in flight.
713
- if ((this.#conversation && !this.#conversation.isEmpty) || this.#isLoading) {
716
+ // we don't automatically change the agent.
717
+ if (this.#conversation && !this.#conversation.isEmpty) {
718
+ // If the context selection agent is enabled,
719
+ // we update the context of the current agent.
720
+ const context = this.#getConversationContext(this.#getDefaultConversationType());
721
+ if (context && isAiAssistanceContextSelectionAgentEnabled()) {
722
+ this.#conversation?.setContext(context);
723
+ this.requestUpdate();
724
+ }
714
725
  return;
715
726
  }
727
+
716
728
  const targetConversationType = this.#getDefaultConversationType();
717
729
  if (this.#conversation?.type === targetConversationType) {
718
730
  // The above if makes sure even if we have an active agent it's empty
@@ -221,6 +221,7 @@ export interface RatingViewInput {
221
221
  export interface ActionViewInput {
222
222
  onReportClick: () => void;
223
223
  onCopyResponseClick: () => void;
224
+ showActions: boolean;
224
225
  }
225
226
 
226
227
  export interface SuggestionViewInput {
@@ -330,7 +331,7 @@ export const DEFAULT_VIEW = (input: ChatMessageViewInput, output: ViewOutput, ta
330
331
  },
331
332
  )}
332
333
  ${renderError(message)}
333
- ${input.isLastMessage && !input.isLoading ? renderActions(input, output) : Lit.nothing}
334
+ ${input.showActions ? renderActions(input, output) : Lit.nothing}
334
335
  </section>
335
336
  `, target);
336
337
  // clang-format on
@@ -812,8 +813,9 @@ export class ChatMessage extends UI.Widget.Widget {
812
813
  onInputChange: this.#handleInputChange.bind(this),
813
814
  isSubmitButtonDisabled: this.#isSubmitButtonDisabled,
814
815
  // Props for actions logic
816
+ showActions: !(this.isLastMessage && this.isLoading),
815
817
  showRateButtons: this.message.entity === ChatMessageEntity.MODEL && !!this.message.rpcId,
816
- suggestions: (this.message.entity === ChatMessageEntity.MODEL && !this.isReadOnly &&
818
+ suggestions: (this.isLastMessage && this.message.entity === ChatMessageEntity.MODEL && !this.isReadOnly &&
817
819
  this.message.parts.at(-1)?.type === 'answer') ?
818
820
  (this.message.parts.at(-1) as AnswerPart).suggestions :
819
821
  undefined,
@@ -228,14 +228,12 @@ const DEFAULT_VIEW: View = (input: ViewInput, _output: ViewOutput, target: HTMLE
228
228
  <div class="top-left-corner">
229
229
  <devtools-checkbox
230
230
  ${bindToSetting(input.showTestAddressesInAutofillMenuSetting)}
231
- title=${i18nString(UIStrings.showTestAddressesInAutofillMenu)}
232
- jslog=${VisualLogging.toggle(input.showTestAddressesInAutofillMenuSetting.name).track({ change: true })}>
231
+ title=${i18nString(UIStrings.showTestAddressesInAutofillMenu)}>
233
232
  ${i18nString(UIStrings.showTestAddressesInAutofillMenu)}
234
233
  </devtools-checkbox>
235
234
  <devtools-checkbox
236
235
  ${bindToSetting(input.autoOpenViewSetting)}
237
- title=${i18nString(UIStrings.autoShowTooltip)}
238
- jslog=${VisualLogging.toggle(input.autoOpenViewSetting.name).track({ change: true })}>
236
+ title=${i18nString(UIStrings.autoShowTooltip)}>
239
237
  ${i18nString(UIStrings.autoShow)}
240
238
  </devtools-checkbox>
241
239
  <devtools-link href=${AUTOFILL_FEEDBACK_URL} class="feedback link" jslogcontext="feedback">${i18nString(UIStrings.sendFeedback)}</devtools-link>
@@ -267,16 +265,14 @@ const DEFAULT_VIEW: View = (input: ViewInput, _output: ViewOutput, target: HTMLE
267
265
  <div class="label-container">
268
266
  <devtools-checkbox
269
267
  ${bindToSetting(input.showTestAddressesInAutofillMenuSetting)}
270
- title=${i18nString(UIStrings.showTestAddressesInAutofillMenu)}
271
- jslog=${VisualLogging.toggle(input.showTestAddressesInAutofillMenuSetting.name).track({ change: true })}>
268
+ title=${i18nString(UIStrings.showTestAddressesInAutofillMenu)}>
272
269
  ${i18nString(UIStrings.showTestAddressesInAutofillMenu)}
273
270
  </devtools-checkbox>
274
271
  </div>
275
272
  <div class="label-container">
276
273
  <devtools-checkbox
277
274
  ${bindToSetting(input.autoOpenViewSetting)}
278
- title=${i18nString(UIStrings.autoShowTooltip)}
279
- jslog=${VisualLogging.toggle(input.autoOpenViewSetting.name).track({ change: true })}>
275
+ title=${i18nString(UIStrings.autoShowTooltip)}>
280
276
  ${i18nString(UIStrings.autoShow)}
281
277
  </devtools-checkbox>
282
278
  </div>
@@ -23,6 +23,14 @@ const UIStringsNotTranslate = {
23
23
  * @description Text for teaser to generate code in Mac.
24
24
  */
25
25
  cmdItoGenerateCode: 'cmd+i to generate code',
26
+ /**
27
+ * @description Text for teaser to learn how data is being used.
28
+ */
29
+ ctrlOneTimeDisclaimerToLearnHowYourDataIsBeingUsed: 'ctrl+. to learn how your data is being used.',
30
+ /**
31
+ * @description Text for teaser to learn how data is being used in Mac.
32
+ */
33
+ cmdOneTimeDisclaimerToLearnHowYourDataIsBeingUsed: 'cmd+. to learn how your data is being used.',
26
34
  /**
27
35
  * @description Aria label for teaser to generate code.
28
36
  */
@@ -109,6 +117,7 @@ export interface ViewInput {
109
117
  disclaimerTooltipId?: string;
110
118
  noLogging: boolean;
111
119
  onManageInSettingsTooltipClick: (event: Event) => void;
120
+ showDataUsageTeaser: boolean;
112
121
  // TODO(b/472268298): Remove ContextFlavor explicitly and pass required values
113
122
  panel?: AiCodeCompletion.AiCodeCompletion.ContextFlavor;
114
123
  }
@@ -136,18 +145,23 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
136
145
  }
137
146
  const toGenerateCode = Host.Platform.isMac() ? lockedString(UIStringsNotTranslate.cmdItoGenerateCode) :
138
147
  lockedString(UIStringsNotTranslate.ctrlItoGenerateCode);
139
- const toLearnHowYourDataIsBeingUsed = Host.Platform.isMac() ?
148
+ const toLearnHowYourDataIsBeingUsedScreenReaderOnly = Host.Platform.isMac() ?
140
149
  lockedString(UIStringsNotTranslate.pressCmdPeriodToLearnHowYourDataIsBeingUsed) :
141
150
  lockedString(UIStringsNotTranslate.pressCtrlPeriodToLearnHowYourDataIsBeingUsed);
151
+ const toLearnHowYourDataIsBeingUsedVisible = Host.Platform.isMac() ?
152
+ lockedString(UIStringsNotTranslate.cmdOneTimeDisclaimerToLearnHowYourDataIsBeingUsed) :
153
+ lockedString(UIStringsNotTranslate.ctrlOneTimeDisclaimerToLearnHowYourDataIsBeingUsed);
142
154
  const tooltipDisclaimerText = getTooltipDisclaimerText(input.noLogging, input.panel);
143
- // TODO(b/472291834): Disclaimer icon should match the placeholder's color
155
+
144
156
  // clang-format off
145
157
  teaserLabel = html`<div class="ai-code-generation-teaser-trigger">
146
- <span aria-atomic="true" aria-live="assertive">${toGenerateCode}&nbsp;</span>
147
- <div class="ai-code-generation-teaser-screen-reader-only" aria-atomic="true" aria-live="assertive">
148
- ${toLearnHowYourDataIsBeingUsed}
149
- </div>
150
- <devtools-button
158
+ <span aria-atomic="true" aria-live="assertive">${toGenerateCode}</span>
159
+ ${input.showDataUsageTeaser ?
160
+ html`<span aria-hidden="true">${'. ' + toLearnHowYourDataIsBeingUsedVisible}</span>` : nothing}
161
+ <span class="ai-code-generation-teaser-screen-reader-only" aria-atomic="true" aria-live="assertive">
162
+ ${toLearnHowYourDataIsBeingUsedScreenReaderOnly}
163
+ </span>
164
+ &nbsp;<devtools-button
151
165
  .data=${{
152
166
  title: lockedString(UIStringsNotTranslate.learnMoreAboutHowYourDataIsBeingUsed),
153
167
  size: Buttons.Button.Size.MICRO,
@@ -245,12 +259,13 @@ export class AiCodeGenerationTeaser extends UI.Widget.Widget {
245
259
  readonly #view: View;
246
260
  #viewOutput: ViewOutput = {};
247
261
 
248
- #displayState = AiCodeGenerationTeaserDisplayState.TRIGGER;
262
+ #displayState = AiCodeGenerationTeaserDisplayState.DISCOVERY;
249
263
  #disclaimerTooltipId?: string;
250
264
  #noLogging: boolean; // Whether the enterprise setting is `ALLOW_WITHOUT_LOGGING` or not.
251
265
  #panel?: AiCodeCompletion.AiCodeCompletion.ContextFlavor;
252
266
  #timerIntervalId?: number;
253
267
  #loadStartTime?: number;
268
+ static #showDataUsageTeaser = true;
254
269
 
255
270
  constructor(view?: View) {
256
271
  super();
@@ -268,6 +283,7 @@ export class AiCodeGenerationTeaser extends UI.Widget.Widget {
268
283
  onManageInSettingsTooltipClick: this.#onManageInSettingsTooltipClick.bind(this),
269
284
  disclaimerTooltipId: this.#disclaimerTooltipId,
270
285
  noLogging: this.#noLogging,
286
+ showDataUsageTeaser: AiCodeGenerationTeaser.#showDataUsageTeaser,
271
287
  panel: this.#panel,
272
288
  },
273
289
  this.#viewOutput, this.contentElement);
@@ -286,6 +302,9 @@ export class AiCodeGenerationTeaser extends UI.Widget.Widget {
286
302
  if (displayState === this.#displayState) {
287
303
  return;
288
304
  }
305
+ if (this.#displayState === AiCodeGenerationTeaserDisplayState.TRIGGER) {
306
+ AiCodeGenerationTeaser.#showDataUsageTeaser = false;
307
+ }
289
308
  this.#displayState = displayState;
290
309
  this.requestUpdate();
291
310
  if (this.#displayState === AiCodeGenerationTeaserDisplayState.LOADING) {
@@ -46,7 +46,7 @@ import * as UI from '../../ui/legacy/legacy.js';
46
46
  import * as Lit from '../../ui/lit/lit.js';
47
47
 
48
48
  import * as ElementsComponents from './components/components.js';
49
- import computedStyleSidebarPaneStyles from './computedStyleSidebarPane.css.js';
49
+ import computedStyleWidgetStyles from './computedStyleWidget.css.js';
50
50
  import {ImagePreviewPopover} from './ImagePreviewPopover.js';
51
51
  import {PlatformFontsWidget} from './PlatformFontsWidget.js';
52
52
  import {categorizePropertyName, type Category, DefaultCategoryOrder} from './PropertyNameCategories.js';
@@ -54,6 +54,7 @@ import {Renderer, rendererBase, type RenderingContext, StringRenderer, URLRender
54
54
  import {StylePropertiesSection} from './StylePropertiesSection.js';
55
55
 
56
56
  const {html, render} = Lit;
57
+ const {bindToSetting} = UI.UIUtils;
57
58
 
58
59
  const UIStrings = {
59
60
  /**
@@ -263,9 +264,12 @@ type ComputedStyleData = {
263
264
 
264
265
  interface ComputedStyleWidgetInput {
265
266
  computedStylesTree: TreeOutline.TreeOutline.TreeOutline<ComputedStyleData>;
266
- toolbar: HTMLElement;
267
267
  hasMatches: boolean;
268
268
  computedStyleModel: ComputedStyleModule.ComputedStyleModel.ComputedStyleModel;
269
+ showInheritedComputedStylePropertiesSetting: Common.Settings.Setting<boolean>;
270
+ groupComputedStylesSetting: Common.Settings.Setting<boolean>;
271
+ onFilterChanged: (event: CustomEvent<string>) => void;
272
+ filterText: string;
269
273
  }
270
274
 
271
275
  type View = (input: ComputedStyleWidgetInput, output: null, target: HTMLElement) => void;
@@ -273,14 +277,30 @@ type View = (input: ComputedStyleWidgetInput, output: null, target: HTMLElement)
273
277
  export const DEFAULT_VIEW: View = (input, _output, target) => {
274
278
  // clang-format off
275
279
  render(html`
276
- <div class="styles-sidebar-pane-toolbar">${input.toolbar}</div>
280
+ <style>${computedStyleWidgetStyles}</style>
281
+ <div class="styles-sidebar-pane-toolbar">
282
+ <devtools-toolbar class="styles-pane-toolbar" role="presentation">
283
+ <devtools-toolbar-input
284
+ type="filter"
285
+ autofocus
286
+ value=${input.filterText}
287
+ @change=${input.onFilterChanged}
288
+ ></devtools-toolbar-input>
289
+ <devtools-checkbox
290
+ title=${i18nString(UIStrings.showAll)}
291
+ ${bindToSetting(input.showInheritedComputedStylePropertiesSetting)}
292
+ >${i18nString(UIStrings.showAll)}</devtools-checkbox>
293
+ <devtools-checkbox
294
+ title=${i18nString(UIStrings.group)}
295
+ ${bindToSetting(input.groupComputedStylesSetting)}
296
+ >${i18nString(UIStrings.group)}</devtools-checkbox>
297
+ </devtools-toolbar>
298
+ </div>
277
299
  <div class="computed-style-tree-outline-container">
278
300
  ${input.computedStylesTree}
279
301
  </div>
280
302
  ${!input.hasMatches ? html`<div class="gray-info-message">${i18nString(UIStrings.noMatchingProperty)}</div>` : ''}
281
- <div class="platform-fonts-widget-container">
282
- <devtools-widget .widgetConfig=${UI.Widget.widgetConfig(PlatformFontsWidget, { sharedModel: input.computedStyleModel})}></devtools-widget>
283
- </div>
303
+ <devtools-widget .widgetConfig=${UI.Widget.widgetConfig(PlatformFontsWidget, { sharedModel: input.computedStyleModel})}></devtools-widget>
284
304
  `, target);
285
305
  // clang-format on
286
306
  };
@@ -289,7 +309,6 @@ export class ComputedStyleWidget extends UI.Widget.VBox {
289
309
  private computedStyleModel: ComputedStyleModule.ComputedStyleModel.ComputedStyleModel;
290
310
  private readonly showInheritedComputedStylePropertiesSetting: Common.Settings.Setting<boolean>;
291
311
  private readonly groupComputedStylesSetting: Common.Settings.Setting<boolean>;
292
- input: UI.Toolbar.ToolbarInput;
293
312
  private filterRegex: RegExp|null;
294
313
  private readonly linkifier: Components.Linkifier.Linkifier;
295
314
  private readonly imagePreviewPopover: ImagePreviewPopover;
@@ -297,12 +316,11 @@ export class ComputedStyleWidget extends UI.Widget.VBox {
297
316
  #computedStylesTree = new TreeOutline.TreeOutline.TreeOutline<ComputedStyleData>();
298
317
  #treeData?: TreeOutline.TreeOutline.TreeOutlineData<ComputedStyleData>;
299
318
  readonly #view: View;
300
- private readonly toolbarElement: HTMLElement;
319
+ #filterText = '';
301
320
 
302
321
  constructor(computedStyleModel: ComputedStyleModule.ComputedStyleModel.ComputedStyleModel) {
303
322
  super({useShadowDom: true});
304
323
  this.#view = DEFAULT_VIEW;
305
- this.registerRequiredCSS(computedStyleSidebarPaneStyles);
306
324
 
307
325
  this.contentElement.classList.add('styles-sidebar-computed-style-widget');
308
326
 
@@ -321,23 +339,8 @@ export class ComputedStyleWidget extends UI.Widget.VBox {
321
339
  this.requestUpdate();
322
340
  });
323
341
 
324
- this.toolbarElement = document.createElement('div');
325
- this.toolbarElement.classList.add('hbox', 'styles-sidebar-pane-toolbar');
326
- const toolbar = document.createElement('devtools-toolbar');
327
- toolbar.classList.add('styles-pane-toolbar');
328
- this.toolbarElement.appendChild(toolbar);
329
-
330
- const filterInput = new UI.Toolbar.ToolbarFilter(undefined, 1, 1, undefined, undefined, false);
331
- filterInput.addEventListener(UI.Toolbar.ToolbarInput.Event.TEXT_CHANGED, this.onFilterChanged, this);
332
- toolbar.appendToolbarItem(filterInput);
333
- this.input = filterInput;
334
342
  this.filterRegex = null;
335
343
 
336
- toolbar.appendToolbarItem(new UI.Toolbar.ToolbarSettingCheckbox(
337
- this.showInheritedComputedStylePropertiesSetting, undefined, i18nString(UIStrings.showAll)));
338
- toolbar.appendToolbarItem(
339
- new UI.Toolbar.ToolbarSettingCheckbox(this.groupComputedStylesSetting, undefined, i18nString(UIStrings.group)));
340
-
341
344
  this.linkifier = new Components.Linkifier.Linkifier(maxLinkLength);
342
345
 
343
346
  this.imagePreviewPopover = new ImagePreviewPopover(this.contentElement, event => {
@@ -373,9 +376,12 @@ export class ComputedStyleWidget extends UI.Widget.VBox {
373
376
  this.#view(
374
377
  {
375
378
  computedStylesTree: this.#computedStylesTree,
376
- toolbar: this.toolbarElement,
377
379
  hasMatches,
378
380
  computedStyleModel: this.computedStyleModel,
381
+ showInheritedComputedStylePropertiesSetting: this.showInheritedComputedStylePropertiesSetting,
382
+ groupComputedStylesSetting: this.groupComputedStylesSetting,
383
+ onFilterChanged: this.onFilterChanged.bind(this),
384
+ filterText: this.#filterText,
379
385
  },
380
386
  null, this.contentElement);
381
387
  }
@@ -628,13 +634,14 @@ export class ComputedStyleWidget extends UI.Widget.VBox {
628
634
  return result;
629
635
  }
630
636
 
631
- private async onFilterChanged(event: Common.EventTarget.EventTargetEvent<string>): Promise<void> {
637
+ private async onFilterChanged(event: CustomEvent<string>): Promise<void> {
638
+ this.#filterText = event.detail;
632
639
  await this.filterComputedStyles(
633
- event.data ? new RegExp(Platform.StringUtilities.escapeForRegExp(event.data), 'i') : null);
640
+ event.detail ? new RegExp(Platform.StringUtilities.escapeForRegExp(event.detail), 'i') : null);
634
641
 
635
- if (event.data && this.#computedStylesTree.data && this.#computedStylesTree.data.tree) {
642
+ if (event.detail && this.#computedStylesTree.data && this.#computedStylesTree.data.tree) {
636
643
  UI.ARIAUtils.LiveAnnouncer.alert(i18nString(
637
- UIStrings.filterUpdateAriaText, {PH1: event.data, PH2: this.#computedStylesTree.data.tree.length}));
644
+ UIStrings.filterUpdateAriaText, {PH1: event.detail, PH2: this.#computedStylesTree.data.tree.length}));
638
645
  }
639
646
  }
640
647
 
@@ -646,6 +653,11 @@ export class ComputedStyleWidget extends UI.Widget.VBox {
646
653
  return this.filterAlphabeticalList();
647
654
  }
648
655
 
656
+ setFilterInput(text: string): void {
657
+ this.#filterText = text;
658
+ this.requestUpdate();
659
+ }
660
+
649
661
  private nodeFilter(node: TreeOutline.TreeOutlineUtils.TreeNode<ComputedStyleData>): boolean {
650
662
  const regex = this.filterRegex;
651
663
  const data = node.treeNodeData;
@@ -106,7 +106,7 @@ export const DEFAULT_VIEW: View = (input, _output, target) => {
106
106
  jslog=${VisualLogging.pane('element-states')}>
107
107
  <div class="page-state-checkbox">
108
108
  <devtools-checkbox class="small" title=${i18nString(UIStrings.emulatesAFocusedPage)}
109
- jslog=${VisualLogging.toggle('emulate-page-focus').track({change: true})} ${bindToSetting('emulate-page-focus')}>${
109
+ ${bindToSetting('emulate-page-focus')}>${
110
110
  i18nString(UIStrings.emulateFocusedPage)}</devtools-checkbox>
111
111
  <devtools-button
112
112
  @click=${() => UIHelpers.openInNewTab('https://developer.chrome.com/docs/devtools/rendering/apply-effects#emulate_a_focused_page')}