chrome-devtools-frontend 1.0.1597448 → 1.0.1597624

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 (81) hide show
  1. package/front_end/core/host/AidaClient.ts +4 -0
  2. package/front_end/core/sdk/CPUThrottlingManager.ts +5 -1
  3. package/front_end/core/sdk/CSSMatchedStyles.ts +2 -0
  4. package/front_end/core/sdk/CSSPropertyParserMatchers.ts +28 -0
  5. package/front_end/models/ai_assistance/AiConversation.ts +24 -8
  6. package/front_end/models/ai_assistance/ChangeManager.ts +16 -0
  7. package/front_end/models/ai_assistance/ExtensionScope.ts +11 -3
  8. package/front_end/models/ai_assistance/agents/AccessibilityAgent.ts +127 -0
  9. package/front_end/models/ai_assistance/agents/AiAgent.ts +22 -3
  10. package/front_end/models/ai_assistance/agents/ContextSelectionAgent.snapshot.txt +1 -1
  11. package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +11 -8
  12. package/front_end/models/ai_assistance/agents/StylingAgent.ts +34 -4
  13. package/front_end/models/ai_assistance/ai_assistance.ts +2 -0
  14. package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.ts +27 -0
  15. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +21 -0
  16. package/front_end/models/trace/Processor.ts +1 -0
  17. package/front_end/models/trace/handlers/PageLoadMetricsHandler.ts +33 -0
  18. package/front_end/models/trace/insights/CharacterSet.ts +172 -0
  19. package/front_end/models/trace/insights/Models.ts +1 -0
  20. package/front_end/models/trace/insights/types.ts +1 -0
  21. package/front_end/models/trace/types/TraceEvents.ts +17 -0
  22. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +16 -3
  23. package/front_end/panels/ai_assistance/components/ChatMessage.ts +90 -46
  24. package/front_end/panels/ai_assistance/components/MarkdownRendererWithCodeBlock.ts +18 -9
  25. package/front_end/panels/ai_assistance/components/chatMessage.css +11 -0
  26. package/front_end/panels/application/AppManifestView.ts +3 -4
  27. package/front_end/panels/application/DeviceBoundSessionsView.ts +18 -22
  28. package/front_end/panels/application/FrameDetailsView.ts +9 -15
  29. package/front_end/panels/application/OriginTrialTreeView.ts +2 -3
  30. package/front_end/panels/application/ReportingApiView.ts +13 -17
  31. package/front_end/panels/application/components/BackForwardCacheView.ts +3 -3
  32. package/front_end/panels/application/preloading/components/UsedPreloadingView.ts +2 -3
  33. package/front_end/panels/browser_debugger/DOMBreakpointsSidebarPane.ts +3 -2
  34. package/front_end/panels/changes/ChangesView.ts +6 -4
  35. package/front_end/panels/console/ConsolePinPane.ts +3 -3
  36. package/front_end/panels/coverage/CoverageListView.ts +1 -1
  37. package/front_end/panels/css_overview/CSSOverviewPanel.ts +11 -15
  38. package/front_end/panels/developer_resources/DeveloperResourcesView.ts +3 -5
  39. package/front_end/panels/elements/EventListenersWidget.ts +3 -2
  40. package/front_end/panels/elements/StandaloneStylesContainer.ts +21 -6
  41. package/front_end/panels/elements/StylePropertyTreeElement.ts +49 -4
  42. package/front_end/panels/layer_viewer/Layers3DView.ts +5 -4
  43. package/front_end/panels/linear_memory_inspector/components/LinearMemoryInspector.ts +5 -6
  44. package/front_end/panels/linear_memory_inspector/components/LinearMemoryValueInterpreter.ts +6 -11
  45. package/front_end/panels/network/RequestCookiesView.ts +3 -4
  46. package/front_end/panels/network/RequestInitiatorView.ts +7 -5
  47. package/front_end/panels/network/RequestResponseView.ts +10 -15
  48. package/front_end/panels/protocol_monitor/ProtocolMonitor.ts +3 -4
  49. package/front_end/panels/recorder/components/RecordingView.ts +31 -36
  50. package/front_end/panels/recorder/components/StepEditor.ts +6 -7
  51. package/front_end/panels/search/SearchView.ts +2 -3
  52. package/front_end/panels/settings/WorkspaceSettingsTab.ts +2 -5
  53. package/front_end/panels/timeline/components/LiveMetricsView.ts +5 -8
  54. package/front_end/panels/timeline/components/insights/Cache.ts +8 -10
  55. package/front_end/panels/timeline/components/insights/CharacterSet.ts +38 -0
  56. package/front_end/panels/timeline/components/insights/DOMSize.ts +16 -20
  57. package/front_end/panels/timeline/components/insights/DocumentLatency.ts +2 -6
  58. package/front_end/panels/timeline/components/insights/DuplicatedJavaScript.ts +3 -4
  59. package/front_end/panels/timeline/components/insights/FontDisplay.ts +3 -4
  60. package/front_end/panels/timeline/components/insights/ForcedReflow.ts +5 -7
  61. package/front_end/panels/timeline/components/insights/INPBreakdown.ts +3 -4
  62. package/front_end/panels/timeline/components/insights/ImageDelivery.ts +3 -4
  63. package/front_end/panels/timeline/components/insights/ImageRef.ts +2 -4
  64. package/front_end/panels/timeline/components/insights/InsightRenderer.ts +2 -0
  65. package/front_end/panels/timeline/components/insights/LCPBreakdown.ts +5 -7
  66. package/front_end/panels/timeline/components/insights/LCPDiscovery.ts +2 -4
  67. package/front_end/panels/timeline/components/insights/LegacyJavaScript.ts +3 -4
  68. package/front_end/panels/timeline/components/insights/ModernHTTP.ts +3 -4
  69. package/front_end/panels/timeline/components/insights/NetworkDependencyTree.ts +7 -11
  70. package/front_end/panels/timeline/components/insights/NodeLink.ts +2 -4
  71. package/front_end/panels/timeline/components/insights/RenderBlocking.ts +3 -4
  72. package/front_end/panels/timeline/components/insights/SlowCSSSelector.ts +7 -10
  73. package/front_end/panels/timeline/components/insights/ThirdParties.ts +5 -7
  74. package/front_end/panels/timeline/components/insights/insights.ts +2 -0
  75. package/front_end/panels/web_audio/WebAudioView.ts +3 -4
  76. package/front_end/ui/components/settings/SettingCheckbox.ts +2 -0
  77. package/front_end/ui/legacy/components/data_grid/DataGridElement.ts +3 -3
  78. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +8 -8
  79. package/front_end/ui/visual_logging/Debugging.ts +0 -32
  80. package/front_end/ui/visual_logging/KnownContextValues.ts +2 -0
  81. package/package.json +1 -1
@@ -203,6 +203,10 @@ export class PerformanceInsightFormatter {
203
203
  {title: 'Is my site polyfilling modern JavaScript features?'},
204
204
  {title: 'How can I reduce the amount of legacy JavaScript on my page?'},
205
205
  ];
206
+ case 'CharacterSet':
207
+ return [
208
+ {title: 'How do I declare a character encoding for my page?'},
209
+ ];
206
210
  default:
207
211
  throw new Error(`Unknown insight key '${this.#insight.insightKey}'`);
208
212
  }
@@ -881,6 +885,20 @@ ${requestSummary}`;
881
885
  * @param insight The Network Dependency Tree Insight Model to query.
882
886
  * @returns a string formatted for sending to Ask AI.
883
887
  */
888
+ formatCharacterSetInsight(insight: Trace.Insights.Models.CharacterSet.CharacterSetInsightModel): string {
889
+ let output = '';
890
+ if (insight.data) {
891
+ output += 'HTTP Content-Type header charset: ' + (insight.data.hasHttpCharset ? 'present' : 'missing') + '.\n';
892
+ output += 'HTML meta charset disposition: ' + (insight.data.metaCharsetDisposition ?? 'unknown') + '.\n';
893
+
894
+ if (!insight.data.hasHttpCharset && insight.data.metaCharsetDisposition !== 'found-in-first-1024-bytes') {
895
+ output +=
896
+ '\nThe page does not declare character encoding via HTTP header or a meta charset tag in the first 1024 bytes.\n';
897
+ }
898
+ }
899
+ return output;
900
+ }
901
+
884
902
  formatViewportInsight(insight: Trace.Insights.Models.Viewport.ViewportInsightModel): string {
885
903
  let output = '';
886
904
 
@@ -995,6 +1013,10 @@ ${this.#links()}`;
995
1013
  return this.formatViewportInsight(this.#insight);
996
1014
  }
997
1015
 
1016
+ if (Trace.Insights.Models.CharacterSet.isCharacterSetInsight(this.#insight)) {
1017
+ return this.formatCharacterSetInsight(this.#insight);
1018
+ }
1019
+
998
1020
  return '';
999
1021
  }
1000
1022
 
@@ -1074,6 +1096,9 @@ ${this.#links()}`;
1074
1096
  links.push('https://web.dev/articles/baseline-and-polyfills');
1075
1097
  links.push('https://philipwalton.com/articles/the-state-of-es5-on-the-web/');
1076
1098
  break;
1099
+ case 'CharacterSet':
1100
+ links.push('https://developer.chrome.com/docs/insights/charset/');
1101
+ break;
1077
1102
  }
1078
1103
 
1079
1104
  return links.map(link => '- ' + link).join('\n');
@@ -1158,6 +1183,8 @@ To pass this insight, ensure your server supports and prioritizes a modern HTTP
1158
1183
  return `This insight identified legacy JavaScript in your application's modules that may be creating unnecessary code.
1159
1184
 
1160
1185
  Polyfills and transforms enable older browsers to use new JavaScript features. However, many are not necessary for modern browsers. Consider modifying your JavaScript build process to not transpile Baseline features, unless you know you must support older browsers.`;
1186
+ case 'CharacterSet':
1187
+ return `This insight checks that the page declares a character encoding, ideally via the Content-Type HTTP response header. A missing or late charset declaration can force the browser to re-parse the document once it finally determines the encoding, delaying first contentful paint. Best practice: include charset=utf-8 in the Content-Type header and add <meta charset="utf-8"> as the very first element inside <head>.`;
1161
1188
  }
1162
1189
  }
1163
1190
  }
@@ -467,6 +467,7 @@ Here are all the insights that contain some related request from the given range
467
467
  - DocumentLatency: news.yahoo.com/ (news.yahoo.com) (eventKey: s-2116, ts: 157423489126)
468
468
  - ThirdParties: cmp.js (consent.cmp.oath.com) (eventKey: s-3382, ts: 157423742399), gpt.js (securepubads.g.doubleclick.net) (eventKey: s-6244, ts: 157423760529), loader.js (cdn.taboola.com) (eventKey: s-6352, ts: 157423761978)
469
469
  - Cache: prebid-2.0.js (s.yimg.com) (eventKey: s-6279, ts: 157423760925), cmp.js (consent.cmp.oath.com) (eventKey: s-3382, ts: 157423742399), d1irmdsmbztlvx.js (s.yimg.com) (eventKey: s-6185, ts: 157423759200), consent.js (s.yimg.com) (eventKey: s-3384, ts: 157423742450), wnsrvbjmeprtfrnfx.js (s.yimg.com) (eventKey: s-6273, ts: 157423760794)
470
+ - CharacterSet: news.yahoo.com/ (news.yahoo.com) (eventKey: s-2116, ts: 157423489126)
470
471
  - LegacyJavaScript: benji-2.2.99.js (s.yimg.com) (eventKey: s-3387, ts: 157423742567), 25fa214.caas-news_web.min.js (s.yimg.com) (eventKey: s-3412, ts: 157423743431), wnsrvbjmeprtfrnfx.js (s.yimg.com) (eventKey: s-6273, ts: 157423760794), consent.js (s.yimg.com) (eventKey: s-3384, ts: 157423742450), news.yahoo.com/ (news.yahoo.com) (eventKey: s-2116, ts: 157423489126)
471
472
  === end content
472
473
 
@@ -510,6 +511,10 @@ Available insights:
510
511
  description: 3rd party code can significantly impact load performance. [Reduce and defer loading of 3rd party code](https://developer.chrome.com/docs/performance/insights/third-parties) to prioritize your page's content.
511
512
  relevant trace bounds: {min: 1020034871372, max: 1020035171789}
512
513
  example question: Which third parties are having the largest impact on my page performance?
514
+ - insight name: CharacterSet
515
+ description: A character encoding declaration is required. It can be done with a meta charset tag in the first 1024 bytes of the HTML or in the Content-Type HTTP response header. [Learn more about declaring the character encoding](https://developer.chrome.com/docs/insights/charset/).
516
+ relevant trace bounds: {min: 1020034836013, max: 1020034892491}
517
+ example question: How do I declare a character encoding for my page?
513
518
  === end content
514
519
 
515
520
  Title: PerformanceTraceFormatter formatTraceSummary yahoo-news.json.gz
@@ -617,6 +622,10 @@ Available insights:
617
622
  relevant trace bounds: {min: 171608170438, max: 171608877165}
618
623
  example question: Show me the most impactful render-blocking requests that I should focus on
619
624
  example question: How can I reduce the number of render-blocking requests?
625
+ - insight name: CharacterSet
626
+ description: A character encoding declaration is required. It can be done with a meta charset tag in the first 1024 bytes of the HTML or in the Content-Type HTTP response header. [Learn more about declaring the character encoding](https://developer.chrome.com/docs/insights/charset/).
627
+ relevant trace bounds: {min: 171607584346, max: 171608171143}
628
+ example question: How do I declare a character encoding for my page?
620
629
 
621
630
  ## insight set id: NAVIGATION_1
622
631
 
@@ -641,6 +650,10 @@ Available insights:
641
650
  relevant trace bounds: {min: 171614330544, max: 171615043224}
642
651
  example question: Show me the most impactful render-blocking requests that I should focus on
643
652
  example question: How can I reduce the number of render-blocking requests?
653
+ - insight name: CharacterSet
654
+ description: A character encoding declaration is required. It can be done with a meta charset tag in the first 1024 bytes of the HTML or in the Content-Type HTTP response header. [Learn more about declaring the character encoding](https://developer.chrome.com/docs/insights/charset/).
655
+ relevant trace bounds: {min: 171613750986, max: 171614330870}
656
+ example question: How do I declare a character encoding for my page?
644
657
  === end content
645
658
 
646
659
  Title: PerformanceTraceFormatter formatTraceSummary deals with CrUX manager errors
@@ -714,6 +727,10 @@ Available insights:
714
727
  description: 3rd party code can significantly impact load performance. [Reduce and defer loading of 3rd party code](https://developer.chrome.com/docs/performance/insights/third-parties) to prioritize your page's content.
715
728
  relevant trace bounds: {min: 59728701403, max: 59729465969}
716
729
  example question: Which third parties are having the largest impact on my page performance?
730
+ - insight name: CharacterSet
731
+ description: A character encoding declaration is required. It can be done with a meta charset tag in the first 1024 bytes of the HTML or in the Content-Type HTTP response header. [Learn more about declaring the character encoding](https://developer.chrome.com/docs/insights/charset/).
732
+ relevant trace bounds: {min: 59728651057, max: 59728790724}
733
+ example question: How do I declare a character encoding for my page?
717
734
  === end content
718
735
 
719
736
  Title: PerformanceTraceFormatter formatTraceSummary image-delivery.json.gz
@@ -794,6 +811,10 @@ Available insights:
794
811
  description: 3rd party code can significantly impact load performance. [Reduce and defer loading of 3rd party code](https://developer.chrome.com/docs/performance/insights/third-parties) to prioritize your page's content.
795
812
  relevant trace bounds: {min: 59728701403, max: 59729465969}
796
813
  example question: Which third parties are having the largest impact on my page performance?
814
+ - insight name: CharacterSet
815
+ description: A character encoding declaration is required. It can be done with a meta charset tag in the first 1024 bytes of the HTML or in the Content-Type HTTP response header. [Learn more about declaring the character encoding](https://developer.chrome.com/docs/insights/charset/).
816
+ relevant trace bounds: {min: 59728651057, max: 59728790724}
817
+ example question: How do I declare a character encoding for my page?
797
818
  === end content
798
819
 
799
820
  Title: PerformanceTraceFormatter formatTraceSummary includes INP insight when there is no navigation
@@ -352,6 +352,7 @@ export class TraceProcessor extends EventTarget {
352
352
  SlowCSSSelector: null,
353
353
  ForcedReflow: null,
354
354
  Cache: null,
355
+ CharacterSet: null,
355
356
  ModernHTTP: null,
356
357
  LegacyJavaScript: null,
357
358
  };
@@ -40,11 +40,17 @@ let metricScoresByFrameId = new Map<FrameId, Map<AnyNavigationStart, Map<MetricN
40
40
  */
41
41
  let allMarkerEvents: Types.Events.PageLoadEvent[] = [];
42
42
 
43
+ // Grouped by navigation to make it easier for insights to scope checks.
44
+ let metaCharsetCheckEventsByNavigation = new Map<AnyNavigationStart, Types.Events.MetaCharsetCheck[]>();
45
+ let metaCharsetCheckEventsArray: Types.Events.MetaCharsetCheck[] = [];
46
+
43
47
  export function reset(): void {
44
48
  metricScoresByFrameId = new Map();
45
49
  pageLoadEventsArray = [];
46
50
  allMarkerEvents = [];
47
51
  selectedLCPCandidateEvents = new Set();
52
+ metaCharsetCheckEventsByNavigation = new Map();
53
+ metaCharsetCheckEventsArray = [];
48
54
  }
49
55
 
50
56
  let pageLoadEventsArray: Types.Events.PageLoadEvent[] = [];
@@ -60,6 +66,11 @@ let pageLoadEventsArray: Types.Events.PageLoadEvent[] = [];
60
66
  let selectedLCPCandidateEvents = new Set<Types.Events.AnyLargestContentfulPaintCandidate>();
61
67
 
62
68
  export function handleEvent(event: Types.Events.Event): void {
69
+ if (Types.Events.isMetaCharsetCheck(event)) {
70
+ metaCharsetCheckEventsArray.push(event);
71
+ return;
72
+ }
73
+
63
74
  if (!Types.Events.eventIsPageLoadEvent(event)) {
64
75
  return;
65
76
  }
@@ -393,6 +404,23 @@ export async function finalize(): Promise<void> {
393
404
  storePageLoadMetricAgainstNavigationId(navigation, pageLoadEvent);
394
405
  }
395
406
  }
407
+
408
+ const {navigationsByFrameId} = metaHandlerData();
409
+ metaCharsetCheckEventsArray.sort((a, b) => a.ts - b.ts);
410
+ for (const metaCharsetCheckEvent of metaCharsetCheckEventsArray) {
411
+ const frameId = metaCharsetCheckEvent.args.data?.frame;
412
+ if (!frameId) {
413
+ continue;
414
+ }
415
+ const navigation = Helpers.Trace.getNavigationForTraceEvent(metaCharsetCheckEvent, frameId, navigationsByFrameId);
416
+ if (!navigation) {
417
+ continue;
418
+ }
419
+ const eventsForNavigation =
420
+ Platform.MapUtilities.getWithDefault(metaCharsetCheckEventsByNavigation, navigation, () => []);
421
+ eventsForNavigation.push(metaCharsetCheckEvent);
422
+ }
423
+
396
424
  // NOTE: if you are looking for the TBT calculation, it has temporarily been
397
425
  // removed. See crbug.com/1424335 for details.
398
426
  const allFinalLCPEvents = gatherFinalLCPEvents();
@@ -421,12 +449,17 @@ export interface PageLoadMetricsData {
421
449
  * main frame.
422
450
  */
423
451
  allMarkerEvents: Types.Events.PageLoadEvent[];
452
+ /**
453
+ * MetaCharsetCheck events grouped by navigation.
454
+ */
455
+ metaCharsetCheckEventsByNavigation: Map<AnyNavigationStart, Types.Events.MetaCharsetCheck[]>;
424
456
  }
425
457
 
426
458
  export function data(): PageLoadMetricsData {
427
459
  return {
428
460
  metricScoresByFrameId,
429
461
  allMarkerEvents,
462
+ metaCharsetCheckEventsByNavigation,
430
463
  };
431
464
  }
432
465
 
@@ -0,0 +1,172 @@
1
+ // Copyright 2026 The Chromium Authors
2
+ // Use of this source code is governed by a BSD-style license that can be
3
+ // found in the LICENSE file.
4
+
5
+ import * as i18n from '../../../core/i18n/i18n.js';
6
+ import type * as Handlers from '../handlers/handlers.js';
7
+ import type * as Types from '../types/types.js';
8
+
9
+ import {
10
+ type Checklist,
11
+ InsightCategory,
12
+ InsightKeys,
13
+ type InsightModel,
14
+ type InsightSetContext,
15
+ InsightWarning,
16
+ type PartialInsightModel,
17
+ } from './types.js';
18
+
19
+ export const UIStrings = {
20
+ /**
21
+ * @description Title of an insight that checks whether the page declares a character encoding early enough.
22
+ */
23
+ title: 'Declare a character encoding',
24
+ /**
25
+ * @description Description of an insight that checks whether the page has a proper character encoding declaration via HTTP header or early meta tag.
26
+ */
27
+ description:
28
+ 'A character encoding declaration is required. It can be done with a meta charset tag in the first 1024 bytes of the HTML or in the Content-Type HTTP response header. [Learn more about declaring the character encoding](https://developer.chrome.com/docs/insights/charset/).',
29
+ /**
30
+ * @description Text to tell the user that the charset is declared in the Content-Type HTTP response header.
31
+ */
32
+ passingHttpHeader: 'Declares charset in HTTP header',
33
+ /**
34
+ * @description Text to tell the user that the charset is NOT declared in the Content-Type HTTP response header.
35
+ */
36
+ failedHttpHeader: 'Does not declare charset in HTTP header',
37
+ /**
38
+ * @description Text to tell the user that a meta charset tag was found in the first 1024 bytes of the HTML.
39
+ */
40
+ passingMetaCharsetEarly: 'Declares charset using a meta tag in the first 1024 bytes',
41
+ /**
42
+ * @description Text to tell the user that a meta charset tag was found, but too late in the HTML.
43
+ */
44
+ failedMetaCharsetLate: 'Declares charset using a meta tag after the first 1024 bytes',
45
+ /**
46
+ * @description Text to tell the user that no meta charset tag was found in the HTML.
47
+ */
48
+ failedMetaCharsetMissing: 'Does not declare charset using a meta tag',
49
+ /**
50
+ * @description Text to tell the user that trace data did not include the Blink signal for meta charset.
51
+ */
52
+ failedMetaCharsetUnknown: 'Could not determine meta charset declaration from trace',
53
+ } as const;
54
+
55
+ const str_ = i18n.i18n.registerUIStrings('models/trace/insights/CharacterSet.ts', UIStrings);
56
+ export const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
57
+
58
+ const CHARSET_HTTP_REGEX = /charset\s*=\s*[a-zA-Z0-9\-_:.()]{2,}/i;
59
+
60
+ export type CharacterSetInsightModel = InsightModel<typeof UIStrings, {
61
+ data?: {
62
+ hasHttpCharset: boolean,
63
+ checklist: Checklist<'httpCharset'|'metaCharset'>,
64
+ metaCharsetDisposition?: Types.Events.MetaCharsetDisposition,
65
+ documentRequest?: Types.Events.SyntheticNetworkRequest,
66
+ },
67
+ }>;
68
+
69
+ export function isCharacterSetInsight(model: InsightModel): model is CharacterSetInsightModel {
70
+ return model.insightKey === InsightKeys.CHARACTER_SET;
71
+ }
72
+
73
+ function finalize(partialModel: PartialInsightModel<CharacterSetInsightModel>): CharacterSetInsightModel {
74
+ let hasFailure = false;
75
+ if (partialModel.data) {
76
+ hasFailure = !partialModel.data.checklist.httpCharset.value && !partialModel.data.checklist.metaCharset.value;
77
+ }
78
+
79
+ return {
80
+ insightKey: InsightKeys.CHARACTER_SET,
81
+ strings: UIStrings,
82
+ title: i18nString(UIStrings.title),
83
+ description: i18nString(UIStrings.description),
84
+ docs: 'https://developer.chrome.com/docs/insights/charset/',
85
+ category: InsightCategory.ALL,
86
+ state: hasFailure ? 'fail' : 'pass',
87
+ ...partialModel,
88
+ };
89
+ }
90
+
91
+ function hasCharsetInContentType(request: Types.Events.SyntheticNetworkRequest): boolean {
92
+ if (!request.args.data.responseHeaders) {
93
+ return false;
94
+ }
95
+ for (const header of request.args.data.responseHeaders) {
96
+ if (header.name.toLowerCase() === 'content-type') {
97
+ return CHARSET_HTTP_REGEX.test(header.value);
98
+ }
99
+ }
100
+ return false;
101
+ }
102
+
103
+ function findMetaCharsetDisposition(
104
+ data: Handlers.Types.HandlerData,
105
+ context: InsightSetContext,
106
+ ): Types.Events.MetaCharsetDisposition|undefined {
107
+ if (!context.navigation) {
108
+ return undefined;
109
+ }
110
+ return data.PageLoadMetrics.metaCharsetCheckEventsByNavigation.get(context.navigation)
111
+ ?.at(-1)
112
+ ?.args.data?.disposition;
113
+ }
114
+
115
+ function metaCharsetLabel(disposition: Types.Events.MetaCharsetDisposition|undefined): ReturnType<typeof i18nString> {
116
+ switch (disposition) {
117
+ case 'found-in-first-1024-bytes':
118
+ return i18nString(UIStrings.passingMetaCharsetEarly);
119
+ case 'found-after-first-1024-bytes':
120
+ return i18nString(UIStrings.failedMetaCharsetLate);
121
+ case 'not-found':
122
+ return i18nString(UIStrings.failedMetaCharsetMissing);
123
+ default:
124
+ return i18nString(UIStrings.failedMetaCharsetUnknown);
125
+ }
126
+ }
127
+
128
+ export function generateInsight(
129
+ data: Handlers.Types.HandlerData, context: InsightSetContext): CharacterSetInsightModel {
130
+ if (!context.navigation) {
131
+ return finalize({});
132
+ }
133
+
134
+ const documentRequest = data.NetworkRequests.byId.get(context.navigationId);
135
+ if (!documentRequest) {
136
+ return finalize({warnings: [InsightWarning.NO_DOCUMENT_REQUEST]});
137
+ }
138
+
139
+ const hasHttpCharset = hasCharsetInContentType(documentRequest);
140
+ const metaCharsetDisposition = findMetaCharsetDisposition(data, context);
141
+ const hasMetaCharsetInFirst1024Bytes = metaCharsetDisposition === 'found-in-first-1024-bytes';
142
+
143
+ return finalize({
144
+ relatedEvents: [documentRequest],
145
+ data: {
146
+ hasHttpCharset,
147
+ metaCharsetDisposition,
148
+ documentRequest,
149
+ checklist: {
150
+ httpCharset: {
151
+ label: hasHttpCharset ? i18nString(UIStrings.passingHttpHeader) : i18nString(UIStrings.failedHttpHeader),
152
+ value: hasHttpCharset,
153
+ },
154
+ metaCharset: {
155
+ label: metaCharsetLabel(metaCharsetDisposition),
156
+ value: hasMetaCharsetInFirst1024Bytes,
157
+ },
158
+ },
159
+ },
160
+ });
161
+ }
162
+
163
+ export function createOverlays(model: CharacterSetInsightModel): Types.Overlays.Overlay[] {
164
+ if (!model.data?.documentRequest) {
165
+ return [];
166
+ }
167
+
168
+ return [{
169
+ type: 'ENTRY_SELECTED',
170
+ entry: model.data.documentRequest,
171
+ }];
172
+ }
@@ -3,6 +3,7 @@
3
3
  // found in the LICENSE file.
4
4
 
5
5
  export * as Cache from './Cache.js';
6
+ export * as CharacterSet from './CharacterSet.js';
6
7
  export * as CLSCulprits from './CLSCulprits.js';
7
8
  export * as DocumentLatency from './DocumentLatency.js';
8
9
  export * as DOMSize from './DOMSize.js';
@@ -164,4 +164,5 @@ export const enum InsightKeys {
164
164
  VIEWPORT = 'Viewport',
165
165
  MODERN_HTTP = 'ModernHTTP',
166
166
  CACHE = 'Cache',
167
+ CHARACTER_SET = 'CharacterSet',
167
168
  }
@@ -1360,6 +1360,22 @@ export function isParseMetaViewport(event: Event): event is ParseMetaViewport {
1360
1360
  return event.name === Name.PARSE_META_VIEWPORT;
1361
1361
  }
1362
1362
 
1363
+ export type MetaCharsetDisposition = 'found-in-first-1024-bytes'|'found-after-first-1024-bytes'|'not-found';
1364
+
1365
+ export interface MetaCharsetCheck extends Instant {
1366
+ name: Name.META_CHARSET_CHECK;
1367
+ args: Args&{
1368
+ data: {
1369
+ frame: string,
1370
+ disposition: MetaCharsetDisposition,
1371
+ },
1372
+ };
1373
+ }
1374
+
1375
+ export function isMetaCharsetCheck(event: Event): event is MetaCharsetCheck {
1376
+ return event.name === Name.META_CHARSET_CHECK;
1377
+ }
1378
+
1363
1379
  export interface LinkPreconnect extends Instant {
1364
1380
  name: Name.LINK_PRECONNECT;
1365
1381
  args: Args&{
@@ -3110,6 +3126,7 @@ export const enum Name {
3110
3126
  SELECTOR_STATS = 'SelectorStats',
3111
3127
  BEGIN_COMMIT_COMPOSITOR_FRAME = 'BeginCommitCompositorFrame',
3112
3128
  PARSE_META_VIEWPORT = 'ParseMetaViewport',
3129
+ META_CHARSET_CHECK = 'MetaCharsetCheck',
3113
3130
 
3114
3131
  /* Paint */
3115
3132
  SCROLL_LAYER = 'ScrollLayer',
@@ -1699,8 +1699,14 @@ export class AiAssistancePanel extends UI.Panel.Panel {
1699
1699
  parts: [],
1700
1700
  };
1701
1701
  this.#messages.push(systemMessage);
1702
- if (Greendev.Prototypes.instance().isEnabled('breakpointDebuggerAgent') &&
1703
- this.#conversation?.type === AiAssistanceModel.AiHistoryStorage.ConversationType.BREAKPOINT) {
1702
+ // If the walkthrough is currently expanded in the sidebar, we want to
1703
+ // automatically swap it to the newly created message's walkthrough.
1704
+ // This ensures that when a user asks a new question, the sidebar updates
1705
+ // immediately to show the "loading" state of the new walkthrough.
1706
+ const isSidebarWalkthroughOpen = this.#walkthrough.isExpanded && !this.#walkthrough.isInlined;
1707
+ if (isSidebarWalkthroughOpen ||
1708
+ (Greendev.Prototypes.instance().isEnabled('breakpointDebuggerAgent') &&
1709
+ this.#conversation?.type === AiAssistanceModel.AiHistoryStorage.ConversationType.BREAKPOINT)) {
1704
1710
  this.#openWalkthrough(systemMessage);
1705
1711
  }
1706
1712
  break;
@@ -1788,6 +1794,13 @@ export class AiAssistancePanel extends UI.Panel.Panel {
1788
1794
  systemMessage.parts.push(newPart);
1789
1795
  }
1790
1796
 
1797
+ if (data.widgets && Root.Runtime.hostConfig.devToolsAiAssistanceV2?.enabled) {
1798
+ systemMessage.parts.push({
1799
+ type: 'widget',
1800
+ widgets: data.widgets,
1801
+ });
1802
+ }
1803
+
1791
1804
  // When there is an answer without any thinking steps, we don't want to show the thinking step.
1792
1805
  // TODO(crbug.com/463323934): Remove specially handling this case.
1793
1806
  if (systemMessage.parts.length > 1) {
@@ -1881,7 +1894,7 @@ export function getResponseMarkdown(message: ModelChatMessage): string {
1881
1894
  for (const part of message.parts) {
1882
1895
  if (part.type === 'answer') {
1883
1896
  contentParts.push(`### Answer\n\n${part.text}`);
1884
- } else {
1897
+ } else if (part.type === 'step') {
1885
1898
  const step = part.step;
1886
1899
  if (step.title) {
1887
1900
  contentParts.push(`### ${step.title}`);