chrome-devtools-frontend 1.0.1611825 → 1.0.1613465

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 (39) hide show
  1. package/front_end/Images/src/flowsheet.svg +1 -0
  2. package/front_end/core/common/Color.ts +3 -2
  3. package/front_end/core/platform/StringUtilities.ts +5 -0
  4. package/front_end/core/sdk/NetworkManager.ts +7 -0
  5. package/front_end/generated/InspectorBackendCommands.ts +2 -2
  6. package/front_end/generated/protocol.ts +12 -2
  7. package/front_end/models/greendev/Prototypes.ts +7 -4
  8. package/front_end/models/har/HARFormat.ts +30 -0
  9. package/front_end/models/har/Importer.ts +12 -1
  10. package/front_end/models/har/Log.ts +28 -0
  11. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +62 -22
  12. package/front_end/panels/ai_assistance/PatchWidget.ts +7 -23
  13. package/front_end/panels/ai_assistance/SelectWorkspaceDialog.ts +3 -3
  14. package/front_end/panels/ai_assistance/ai_assistance-meta.ts +7 -0
  15. package/front_end/panels/ai_assistance/ai_assistance.ts +1 -0
  16. package/front_end/panels/ai_assistance/components/ChatView.ts +4 -0
  17. package/front_end/panels/ai_assistance/components/ExportForAgentsDialog.ts +12 -6
  18. package/front_end/panels/ai_assistance/components/OptInChangeDialog.ts +179 -0
  19. package/front_end/panels/ai_assistance/components/optInChangeDialog.css +95 -0
  20. package/front_end/panels/ai_assistance/components/walkthroughView.css +1 -1
  21. package/front_end/panels/application/CookieItemsView.ts +3 -2
  22. package/front_end/panels/changes/ChangesView.ts +0 -12
  23. package/front_end/panels/common/common.ts +0 -1
  24. package/front_end/panels/console/ConsolePrompt.ts +2 -2
  25. package/front_end/panels/elements/StylePropertyTreeElement.ts +2 -1
  26. package/front_end/panels/elements/StylesSidebarPane.ts +3 -1
  27. package/front_end/panels/elements/elements-meta.ts +14 -0
  28. package/front_end/panels/network/NetworkLogView.ts +58 -28
  29. package/front_end/panels/recorder/RecorderController.ts +4 -4
  30. package/front_end/panels/settings/AISettingsTab.ts +39 -3
  31. package/front_end/panels/settings/SettingsScreen.ts +2 -2
  32. package/front_end/third_party/chromium/README.chromium +1 -1
  33. package/front_end/ui/legacy/SplitWidget.ts +9 -6
  34. package/front_end/ui/legacy/components/settings_ui/SettingsUI.ts +3 -3
  35. package/front_end/ui/legacy/components/source_frame/FontView.ts +101 -88
  36. package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +4 -4
  37. package/front_end/ui/visual_logging/KnownContextValues.ts +6 -0
  38. package/package.json +1 -1
  39. package/front_end/panels/common/CopyChangesToPrompt.ts +0 -233
@@ -0,0 +1,179 @@
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 * as Root from '../../../core/root/root.js';
7
+ import * as Buttons from '../../../ui/components/buttons/buttons.js';
8
+ import * as UI from '../../../ui/legacy/legacy.js';
9
+ import * as Lit from '../../../ui/lit/lit.js';
10
+ import * as VisualLogging from '../../../ui/visual_logging/visual_logging.js';
11
+
12
+ import styles from './optInChangeDialog.css.js';
13
+
14
+ const {html, render} = Lit;
15
+
16
+ const UIStrings = {
17
+ /**
18
+ * @description Title for the opt-in change dialog.
19
+ */
20
+ title: 'AI assistance just got better',
21
+ /**
22
+ * @description First point in the opt-in change dialog, describing the new integration.
23
+ */
24
+ integrationPoint:
25
+ 'AI assistance is now integrated with Application and Lighthouse panels, and pulls context from data sources simultaneously',
26
+ /**
27
+ * @description Second point in the opt-in change dialog, describing the new widgets.
28
+ */
29
+ widgetPoint: 'Use widgets to verify results or jump to source data for select debugging cases',
30
+ /**
31
+ * @description Third point in the opt-in change dialog (disclaimer) for regular users.
32
+ */
33
+ privacyDisclaimer:
34
+ 'Chat messages, data accessible for this site via DevTools panels and Web APIs, and items you select such as network requests, files, and performance traces are sent to Google and may be seen by human reviewers to improve this feature. This is an experimental AI feature and won’t always get it right.',
35
+ /**
36
+ * @description Third point in the opt-in change dialog (disclaimer) for enterprise users with logging disabled.
37
+ */
38
+ privacyDisclaimerEnterpriseNoLogging:
39
+ 'Chat messages, data accessible for this site via DevTools panels and Web APIs, and items you select such as network requests, files, and performance traces are sent to Google. The content submitted to and generated by this feature will not be used to improve Google’s AI models. This is an experimental AI feature and won’t always get it right.',
40
+ /**
41
+ * @description Button text for managing settings.
42
+ */
43
+ manageSettings: 'Manage in settings',
44
+ /**
45
+ * @description Button text for acknowledging the changes.
46
+ */
47
+ gotIt: 'Got it',
48
+ } as const;
49
+
50
+ const str_ = i18n.i18n.registerUIStrings('panels/ai_assistance/components/OptInChangeDialog.ts', UIStrings);
51
+ const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
52
+
53
+ interface ViewInput {
54
+ onGotIt: () => void;
55
+ onManageSettings: () => void;
56
+ loggingEnabled: boolean;
57
+ }
58
+
59
+ type View = (input: ViewInput, output: undefined, target: HTMLElement) => void;
60
+
61
+ export const DEFAULT_VIEW: View = (input, _output, target): void => {
62
+ const disclaimer = input.loggingEnabled ? i18nString(UIStrings.privacyDisclaimer) :
63
+ i18nString(UIStrings.privacyDisclaimerEnterpriseNoLogging);
64
+ // clang-format off
65
+ render(html`
66
+ <style>${styles}</style>
67
+ <div class="opt-in-change-dialog" jslog=${VisualLogging.dialog('ai-v2-opt-in-change-dialog')}>
68
+ <header>
69
+ <div class="header-icon-container">
70
+ <devtools-icon name="smart-assistant" role="presentation"></devtools-icon>
71
+ </div>
72
+ <h1 tabindex="-1">
73
+ ${i18nString(UIStrings.title)}
74
+ </h1>
75
+ </header>
76
+ <main>
77
+ <div class="item">
78
+ <devtools-icon name="lightbulb-spark" role="presentation"></devtools-icon>
79
+ <div class="text">${i18nString(UIStrings.integrationPoint)}</div>
80
+ </div>
81
+ <div class="item">
82
+ <devtools-icon name="flowsheet" role="presentation"></devtools-icon>
83
+ <div class="text">${i18nString(UIStrings.widgetPoint)}</div>
84
+ </div>
85
+ <div class="item">
86
+ <devtools-icon name="google" role="presentation"></devtools-icon>
87
+ <div class="text">${disclaimer}</div>
88
+ </div>
89
+ </main>
90
+ <footer>
91
+ <div class="right-buttons">
92
+ <devtools-button
93
+ @click=${input.onManageSettings}
94
+ .jslogContext=${'ai-assistance-v2-opt-in.manage-settings'}
95
+ .variant=${Buttons.Button.Variant.OUTLINED}
96
+ .accessibleLabel=${i18nString(UIStrings.manageSettings)}
97
+ >
98
+ ${i18nString(UIStrings.manageSettings)}
99
+ </devtools-button>
100
+ <devtools-button
101
+ @click=${input.onGotIt}
102
+ .jslogContext=${'ai-assistance-v2-opt-in.got-it'}
103
+ .variant=${Buttons.Button.Variant.PRIMARY}
104
+ .accessibleLabel=${i18nString(UIStrings.gotIt)}
105
+ >
106
+ ${i18nString(UIStrings.gotIt)}
107
+ </devtools-button>
108
+ </div>
109
+ </footer>
110
+ </div>
111
+ `, target);
112
+ // clang-format on
113
+ };
114
+
115
+ export class OptInChangeDialog extends UI.Widget.VBox {
116
+ readonly #view: View;
117
+ readonly #onGotIt: () => void;
118
+ readonly #onManageSettings: () => void;
119
+
120
+ constructor(
121
+ options: {
122
+ onGotIt: () => void,
123
+ onManageSettings: () => void,
124
+ },
125
+ view: View = DEFAULT_VIEW) {
126
+ super();
127
+ this.#onGotIt = options.onGotIt;
128
+ this.#onManageSettings = options.onManageSettings;
129
+ this.#view = view;
130
+
131
+ this.requestUpdate();
132
+ }
133
+
134
+ override performUpdate(): void {
135
+ const loggingEnabled = Root.Runtime.hostConfig.aidaAvailability?.enterprisePolicyValue !==
136
+ Root.Runtime.GenAiEnterprisePolicyValue.ALLOW_WITHOUT_LOGGING;
137
+
138
+ const viewInput = {
139
+ onGotIt: this.#onGotIt,
140
+ onManageSettings: this.#onManageSettings,
141
+ loggingEnabled,
142
+ };
143
+
144
+ this.#view(viewInput, undefined, this.contentElement);
145
+ }
146
+
147
+ focusTitle(): void {
148
+ this.contentElement.querySelector('h1')?.focus();
149
+ }
150
+
151
+ static show(options: {
152
+ onGotIt: () => void,
153
+ onManageSettings: () => void,
154
+ }): void {
155
+ const dialog = new UI.Dialog.Dialog();
156
+ dialog.setAriaLabel(i18nString(UIStrings.title));
157
+ dialog.setOutsideClickCallback(event => event.consume(true));
158
+ dialog.setCloseOnEscape(false);
159
+ dialog.setSizeBehavior(UI.GlassPane.SizeBehavior.MEASURE_CONTENT);
160
+ dialog.setDimmed(true);
161
+
162
+ const optInChangeDialog = new OptInChangeDialog({
163
+ onGotIt: () => {
164
+ dialog.hide();
165
+ options.onGotIt();
166
+ },
167
+ onManageSettings: () => {
168
+ dialog.hide();
169
+ options.onManageSettings();
170
+ },
171
+ });
172
+ optInChangeDialog.show(dialog.contentElement);
173
+
174
+ void optInChangeDialog.updateComplete.then(() => {
175
+ dialog.show();
176
+ optInChangeDialog.focusTitle();
177
+ });
178
+ }
179
+ }
@@ -0,0 +1,95 @@
1
+ /*
2
+ * Copyright 2026 The Chromium Authors
3
+ * Use of this source code is governed by a BSD-style license that can be
4
+ * found in the LICENSE file.
5
+ */
6
+
7
+ @scope to (devtools-widget > *) {
8
+ :scope {
9
+ width: 100%;
10
+ box-shadow: none;
11
+ padding: var(--sys-size-8);
12
+ background-color: var(--sys-color-surface);
13
+ border-radius: var(--sys-shape-corner-medium);
14
+ }
15
+
16
+ .opt-in-change-dialog {
17
+ width: var(--sys-size-33);
18
+ max-width: 100%;
19
+ }
20
+
21
+ header {
22
+ display: flex;
23
+ flex-direction: row;
24
+ align-items: center;
25
+ gap: var(--sys-size-8);
26
+ margin-bottom: var(--sys-size-8);
27
+
28
+ h2 {
29
+ margin: 0;
30
+ color: var(--sys-color-on-surface);
31
+ font: var(--sys-typescale-headline5);
32
+ }
33
+
34
+ .header-icon-container {
35
+ background: linear-gradient(
36
+ 135deg,
37
+ var(--sys-color-gradient-primary),
38
+ var(--sys-color-gradient-tertiary)
39
+ );
40
+ border-radius: var(--sys-size-4);
41
+ height: var(--sys-size-14);
42
+ width: var(--sys-size-14);
43
+ display: flex;
44
+ align-items: center;
45
+ justify-content: center;
46
+
47
+ devtools-icon {
48
+ width: var(--sys-size-9);
49
+ height: var(--sys-size-9);
50
+ color: var(--sys-color-on-primary);
51
+ }
52
+ }
53
+ }
54
+
55
+ main {
56
+ background-color: var(--sys-color-surface4);
57
+ border-radius: var(--sys-shape-corner-medium-small);
58
+ padding: var(--sys-size-8);
59
+ display: flex;
60
+ flex-direction: column;
61
+ gap: var(--sys-size-6);
62
+ margin-bottom: var(--sys-size-8);
63
+
64
+ .item {
65
+ display: flex;
66
+ flex-direction: row;
67
+ align-items: center;
68
+ gap: var(--sys-size-8);
69
+
70
+ devtools-icon {
71
+ width: var(--sys-size-8);
72
+ height: var(--sys-size-8);
73
+ flex-shrink: 0;
74
+ color: var(--sys-color-on-surface-subtle);
75
+ }
76
+
77
+ .text {
78
+ font: var(--sys-typescale-body4);
79
+ color: var(--sys-color-on-surface);
80
+ }
81
+ }
82
+ }
83
+
84
+ footer {
85
+ display: flex;
86
+ flex-direction: row;
87
+ align-items: center;
88
+ justify-content: flex-end;
89
+
90
+ .right-buttons {
91
+ display: flex;
92
+ gap: var(--sys-size-5);
93
+ }
94
+ }
95
+ }
@@ -99,7 +99,7 @@
99
99
 
100
100
  .inline-wrapper {
101
101
  display: flex;
102
- align-items: center;
102
+ align-items: flex-start;
103
103
  gap: var(--sys-size-2);
104
104
  justify-content: flex-start;
105
105
 
@@ -375,9 +375,10 @@ export class CookieItemsView extends UI.Widget.VBox {
375
375
  }
376
376
 
377
377
  deleteSelectedItem(): void {
378
- if (this.selectedCookie) {
378
+ const cookie = this.selectedCookie;
379
+ if (cookie) {
379
380
  this.showPreview(null);
380
- void this.model.deleteCookie(this.selectedCookie);
381
+ void this.model.deleteCookie(cookie);
381
382
  }
382
383
  }
383
384
 
@@ -6,13 +6,11 @@ import '../../ui/legacy/legacy.js';
6
6
 
7
7
  import * as i18n from '../../core/i18n/i18n.js';
8
8
  import type * as Platform from '../../core/platform/platform.js';
9
- import * as GreenDev from '../../models/greendev/greendev.js';
10
9
  import type * as Workspace from '../../models/workspace/workspace.js';
11
10
  import * as WorkspaceDiff from '../../models/workspace_diff/workspace_diff.js';
12
11
  import * as UI from '../../ui/legacy/legacy.js';
13
12
  import * as Lit from '../../ui/lit/lit.js';
14
13
  import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
15
- import * as PanelsCommon from '../common/common.js';
16
14
 
17
15
  import {ChangesSidebar, Events} from './ChangesSidebar.js';
18
16
  import changesViewStyles from './changesView.css.js';
@@ -48,8 +46,6 @@ export const DEFAULT_VIEW: View = (input, _output, target) => {
48
46
  Events.SELECTED_UI_SOURCE_CODE_CHANGED, () => input.onSelect(sidebar.selectedUISourceCode()));
49
47
  };
50
48
 
51
- const hasCopyToPrompt = GreenDev.Prototypes.instance().isEnabled('copyToGemini');
52
-
53
49
  render(
54
50
  // clang-format off
55
51
  html`
@@ -70,14 +66,6 @@ export const DEFAULT_VIEW: View = (input, _output, target) => {
70
66
  workspaceDiff: input.workspaceDiff
71
67
  })}
72
68
  </div>
73
- ${hasCopyToPrompt ? html`
74
- <devtools-widget class="copy-to-prompt"
75
- ${widget(PanelsCommon.CopyChangesToPrompt, {
76
- workspaceDiff: input.workspaceDiff,
77
- patchAgentCSSChange: null,
78
- })}
79
- ></devtools-widget>
80
- ` : Lit.nothing}
81
69
  </div>
82
70
  <devtools-widget slot="sidebar" ${widget(ChangesSidebar, {workspaceDiff: input.workspaceDiff})}
83
71
  ${UI.Widget.widgetRef(ChangesSidebar, onSidebar)}>
@@ -111,4 +111,3 @@ export * as PersistenceUtils from './PersistenceUtils.js';
111
111
  export * as DOMLinkifier from './DOMLinkifier.js';
112
112
  export * as ThrottlingUtils from './ThrottlingUtils.js';
113
113
  export * as ExtensionIframe from './ExtensionView.js';
114
- export {CopyChangesToPrompt} from './CopyChangesToPrompt.js';
@@ -29,11 +29,11 @@ const UIStrings = {
29
29
  */
30
30
  consolePrompt: 'Console prompt',
31
31
  /**
32
- * @description Warning shown to users when pasting text into the DevTools console.
32
+ * @description Warning shown to users when pasting text into the DevTools console. IMPORTANT: keep double quotes around PH1 and do not use single quotes.
33
33
  * @example {allow pasting} PH1
34
34
  */
35
35
  selfXssWarning:
36
- 'Warning: Don’t paste code into the DevTools Console that you don’t understand or haven’t reviewed yourself. This could allow attackers to steal your identity or take control of your computer. Please type {PH1} below and press Enter to allow pasting.',
36
+ 'Warning: Don’t paste code into the DevTools Console that you don’t understand or haven’t reviewed yourself. This could allow attackers to steal your identity or take control of your computer. Please type {PH1} below and press Enter to allow pasting.',
37
37
  /**
38
38
  * @description Text a user needs to type in order to confirm that they are aware of the danger of pasting code into the DevTools console.
39
39
  */
@@ -2782,7 +2782,8 @@ export class StylePropertyTreeElement extends UI.TreeOutline.TreeElement {
2782
2782
  existingElement?.remove();
2783
2783
  }
2784
2784
 
2785
- if (!this.overriddenByAnimation() || UI.ViewManager.ViewManager.instance().isViewVisible('animations')) {
2785
+ if (!this.overriddenByAnimation() || UI.ViewManager.ViewManager.instance().isViewVisible('animations') ||
2786
+ !Common.Settings.Settings.instance().moduleSetting('css-animations-only-when-animations-tab-open').get()) {
2786
2787
  return;
2787
2788
  }
2788
2789
 
@@ -1096,10 +1096,12 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
1096
1096
  // the matched styles we reenable the button.
1097
1097
  LayersWidget.ButtonProvider.instance().item().setVisible(false);
1098
1098
  const animationsPanelVisible = UI.ViewManager.ViewManager.instance().isViewVisible('animations');
1099
+ const cssAnimationsOnlyWhenAnimationsTabOpen =
1100
+ Common.Settings.Settings.instance().moduleSetting('css-animations-only-when-animations-tab-open').get();
1099
1101
  for (const style of matchedStyles.nodeStyles()) {
1100
1102
  const isTransitionOrAnimationStyle = style.type === SDK.CSSStyleDeclaration.Type.Transition ||
1101
1103
  style.type === SDK.CSSStyleDeclaration.Type.Animation;
1102
- if (isTransitionOrAnimationStyle && !animationsPanelVisible) {
1104
+ if (isTransitionOrAnimationStyle && cssAnimationsOnlyWhenAnimationsTabOpen && !animationsPanelVisible) {
1103
1105
  continue;
1104
1106
  }
1105
1107
 
@@ -163,6 +163,10 @@ const UIStrings = {
163
163
  * @description Command for toggling the eye dropper when the color picker is open
164
164
  */
165
165
  toggleEyeDropper: 'Toggle eye dropper',
166
+ /**
167
+ * @description Title of a setting under the Elements category.
168
+ */
169
+ cssAnimationsOnlyWhenAnimationsTabOpen: 'Show animation styles only when the Animations tab is open',
166
170
  } as const;
167
171
  const str_ = i18n.i18n.registerUIStrings('panels/elements/elements-meta.ts', UIStrings);
168
172
  const i18nLazyString = i18n.i18n.getLazilyComputedLocalizedString.bind(undefined, str_);
@@ -569,6 +573,16 @@ Common.Settings.registerSettingExtension({
569
573
  defaultValue: true,
570
574
  });
571
575
 
576
+ Common.Settings.registerSettingExtension({
577
+ category: Common.Settings.SettingCategory.ELEMENTS,
578
+ storageType: Common.Settings.SettingStorageType.SYNCED,
579
+ order: 6,
580
+ title: i18nLazyString(UIStrings.cssAnimationsOnlyWhenAnimationsTabOpen),
581
+ settingName: 'css-animations-only-when-animations-tab-open',
582
+ settingType: Common.Settings.SettingType.BOOLEAN,
583
+ defaultValue: true,
584
+ });
585
+
572
586
  Common.Settings.registerSettingExtension({
573
587
  settingName: 'show-event-listeners-for-ancestors',
574
588
  settingType: Common.Settings.SettingType.BOOLEAN,
@@ -1880,10 +1880,30 @@ export class NetworkLogView extends Common.ObjectWrapper.eventMixin<EventTypes,
1880
1880
  const throttlingMenu =
1881
1881
  contextMenu.debugSection().appendSubMenuItem(i18nString(UIStrings.throttleRequests), /* disabled=*/ true);
1882
1882
 
1883
- const urlWithoutScheme = request.parsedURL.urlWithoutScheme();
1884
- const urlPattern = urlWithoutScheme &&
1883
+ const parsed = request.parsedURL;
1884
+ let urlPatternString = '';
1885
+ if (parsed.isValid) {
1886
+ // We cannot escape parsed.urlWithoutScheme() directly. If we escaped the first '?'
1887
+ // URLPattern would treat the entire string as the pathname and fail to match the query string.
1888
+ // Thus, we must escape the components individually and reconstruct the pattern string.
1889
+ urlPatternString = '*://' + Platform.StringUtilities.escapeForURLPattern(parsed.host);
1890
+ if (parsed.port) {
1891
+ urlPatternString += ':' + Platform.StringUtilities.escapeForURLPattern(parsed.port);
1892
+ }
1893
+ urlPatternString += Platform.StringUtilities.escapeForURLPattern(parsed.path);
1894
+ if (parsed.queryParams) {
1895
+ urlPatternString += '?' + Platform.StringUtilities.escapeForURLPattern(parsed.queryParams);
1896
+ }
1897
+ if (parsed.fragment) {
1898
+ urlPatternString += '#' + Platform.StringUtilities.escapeForURLPattern(parsed.fragment);
1899
+ }
1900
+ } else if (parsed.urlWithoutScheme()) {
1901
+ urlPatternString = '*://' + Platform.StringUtilities.escapeForURLPattern(parsed.urlWithoutScheme());
1902
+ }
1903
+
1904
+ const urlPattern = urlPatternString &&
1885
1905
  SDK.NetworkManager.RequestURLPattern.create(
1886
- `*://${urlWithoutScheme}` as SDK.NetworkManager.URLPatternConstructorString);
1906
+ urlPatternString as SDK.NetworkManager.URLPatternConstructorString);
1887
1907
  if (urlPattern) {
1888
1908
  throttlingMenu.setEnabled(true);
1889
1909
  blockingMenu.setEnabled(true);
@@ -1906,30 +1926,39 @@ export class NetworkLogView extends Common.ObjectWrapper.eventMixin<EventTypes,
1906
1926
  {jslogContext: 'throttle-request-url'});
1907
1927
  }
1908
1928
 
1909
- const domain = request.parsedURL.domain();
1910
- const domainPattern = domain &&
1911
- SDK.NetworkManager.RequestURLPattern.create(
1912
- `*://${domain}` as SDK.NetworkManager.URLPatternConstructorString);
1913
- if (domainPattern) {
1914
- throttlingMenu.setEnabled(true);
1915
- blockingMenu.setEnabled(true);
1916
- const existingConditions = manager.requestConditions.findCondition(domainPattern.constructorString);
1917
- const isBlocking = existingConditions?.conditions === SDK.NetworkManager.BlockingConditions;
1918
- const isThrottling = existingConditions &&
1919
- existingConditions.conditions !== SDK.NetworkManager.BlockingConditions &&
1920
- existingConditions.conditions !== SDK.NetworkManager.NoThrottlingConditions;
1921
- const croppedURL = Platform.StringUtilities.trimMiddle(domainPattern.constructorString, maxBlockedURLLength);
1922
- blockingMenu.debugSection().appendItem(
1923
- isBlocking ? i18nString(UIStrings.unblockS, {PH1: croppedURL}) : i18nString(UIStrings.blockRequestDomain),
1924
- () => isBlocking ? removeRequestCondition(domainPattern) :
1925
- addRequestCondition(domainPattern, SDK.NetworkManager.BlockingConditions),
1926
- {jslogContext: 'block-request-domain'});
1927
- throttlingMenu.debugSection().appendItem(
1928
- isThrottling ? i18nString(UIStrings.unthrottleS, {PH1: croppedURL}) :
1929
- i18nString(UIStrings.throttleRequestDomain),
1930
- () => isThrottling ? removeRequestCondition(domainPattern) :
1931
- addRequestCondition(domainPattern, SDK.NetworkManager.Slow3GConditions),
1932
- {jslogContext: 'throttle-request-domain'});
1929
+ let domainPatternString = '';
1930
+ if (parsed.isValid) {
1931
+ domainPatternString = '*://' + Platform.StringUtilities.escapeForURLPattern(parsed.host);
1932
+ if (parsed.port) {
1933
+ domainPatternString += ':' + Platform.StringUtilities.escapeForURLPattern(parsed.port);
1934
+ }
1935
+ } else if (parsed.domain()) {
1936
+ domainPatternString = '*://' + Platform.StringUtilities.escapeForURLPattern(parsed.domain());
1937
+ }
1938
+
1939
+ const domainPattern = domainPatternString &&
1940
+ SDK.NetworkManager.RequestURLPattern.create(
1941
+ domainPatternString as SDK.NetworkManager.URLPatternConstructorString);
1942
+ if (domainPattern) {
1943
+ throttlingMenu.setEnabled(true);
1944
+ blockingMenu.setEnabled(true);
1945
+ const existingConditions = manager.requestConditions.findCondition(domainPattern.constructorString);
1946
+ const isBlocking = existingConditions?.conditions === SDK.NetworkManager.BlockingConditions;
1947
+ const isThrottling = existingConditions &&
1948
+ existingConditions.conditions !== SDK.NetworkManager.BlockingConditions &&
1949
+ existingConditions.conditions !== SDK.NetworkManager.NoThrottlingConditions;
1950
+ const croppedURL = Platform.StringUtilities.trimMiddle(domainPattern.constructorString, maxBlockedURLLength);
1951
+ blockingMenu.debugSection().appendItem(
1952
+ isBlocking ? i18nString(UIStrings.unblockS, {PH1: croppedURL}) : i18nString(UIStrings.blockRequestDomain),
1953
+ () => isBlocking ? removeRequestCondition(domainPattern) :
1954
+ addRequestCondition(domainPattern, SDK.NetworkManager.BlockingConditions),
1955
+ {jslogContext: 'block-request-domain'});
1956
+ throttlingMenu.debugSection().appendItem(
1957
+ isThrottling ? i18nString(UIStrings.unthrottleS, {PH1: croppedURL}) :
1958
+ i18nString(UIStrings.throttleRequestDomain),
1959
+ () => isThrottling ? removeRequestCondition(domainPattern) :
1960
+ addRequestCondition(domainPattern, SDK.NetworkManager.Slow3GConditions),
1961
+ {jslogContext: 'throttle-request-domain'});
1933
1962
  }
1934
1963
 
1935
1964
  if (SDK.NetworkManager.NetworkManager.canReplayRequest(request)) {
@@ -1944,7 +1973,8 @@ export class NetworkLogView extends Common.ObjectWrapper.eventMixin<EventTypes,
1944
1973
  const requests = Logs.NetworkLog.NetworkLog.instance().requests().filter(request => this.applyFilter(request));
1945
1974
  return requests.filter(NetworkLogView.getHTTPRequestsFilter).filter(request => {
1946
1975
  return request.finished ||
1947
- (request.resourceType() === Common.ResourceType.resourceTypes.WebSocket && request.responseReceivedTime);
1976
+ (request.resourceType() === Common.ResourceType.resourceTypes.WebSocket && request.responseReceivedTime) ||
1977
+ Boolean(request.eventSourceMessages()?.length);
1948
1978
  });
1949
1979
  }
1950
1980
 
@@ -133,21 +133,21 @@ const UIStrings = {
133
133
  */
134
134
  doYouTrustThisCode: 'Do you trust this recording?',
135
135
  /**
136
- * @description Warning shown to users when imports code into DevTools Recorder.
136
+ * @description Warning shown to users when imports code into DevTools Recorder. IMPORTANT: keep double quotes around PH1 and do not use single quotes.
137
137
  * @example {allow importing} PH1
138
138
  */
139
139
  doNotImport:
140
- 'Don\'t import recordings you do not understand or have not reviewed yourself into DevTools. This could allow attackers to steal your identity or take control of your computer. Please type \'\'{PH1}\'\' below to allow importing.',
140
+ 'Don\'t import recordings you do not understand or have not reviewed yourself into DevTools. This could allow attackers to steal your identity or take control of your computer. Please type {PH1} below to allow importing.',
141
141
  /**
142
142
  * @description Text a user needs to type in order to confirm that they
143
143
  *are aware of the danger of import code into the DevTools Recorder.
144
144
  */
145
145
  allowImporting: 'allow importing',
146
146
  /**
147
- * @description Input box placeholder which instructs the user to type 'allow importing' into the input box.
147
+ * @description Input box placeholder which instructs the user to type 'allow importing' into the input box. IMPORTANT: keep double quotes around PH1 and do not use single quotes.
148
148
  * @example {allow importing} PH1
149
149
  */
150
- typeAllowImporting: 'Type \'\'{PH1}\'\'',
150
+ typeAllowImporting: 'Type {PH1}',
151
151
  } as const;
152
152
  const str_ = i18n.i18n.registerUIStrings('panels/recorder/RecorderController.ts', UIStrings);
153
153
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
@@ -120,6 +120,29 @@ const UIStrings = {
120
120
  */
121
121
  helpUnderstandStylingNetworkPerformanceAndFile:
122
122
  'Get help with understanding CSS styles, network requests, performance, and files',
123
+ /**
124
+ * @description Text describing the 'AI assistance' feature when V2 is enabled
125
+ */
126
+ aiAssistanceDescriptionV2: 'Get context-aware help on the inspected page',
127
+ /**
128
+ * @description First item in the description of the AI assistance feature when V2 is enabled
129
+ */
130
+ aiAssistanceWhenOnItem1V2:
131
+ 'Debug styling, network, performance, source code, accessibility and storage issues with DevTools AI assistance',
132
+ /**
133
+ * @description Second item in the description of the AI assistance feature when V2 is enabled
134
+ */
135
+ aiAssistanceWhenOnItem2V2: 'Follow the agent\'s reasoning step-by-step and quickly jump to the relevant source data',
136
+ /**
137
+ * @description Explainer for which data is being sent by the AI assistance feature when V2 is enabled
138
+ */
139
+ aiAssistanceThingsToConsiderV2:
140
+ 'To generate explanations, chat messages, data accessible for this site via DevTools panels and Web APIs, and items you select such as network requests, files, and performance traces are sent to Google and may be seen by human reviewers to improve this feature. This is an experimental AI feature and won’t always get it right.',
141
+ /**
142
+ * @description Explainer for which data is being sent by the AI assistance feature when V2 is enabled and logging is disabled
143
+ */
144
+ aiAssistanceThingsToConsiderNoLoggingV2:
145
+ 'To generate explanations, chat messages, data accessible for this site via DevTools panels and Web APIs, and items you select such as network requests, files, and performance traces are sent to Google. The content you submit and that is generated by this feature will not be used to improve Google’s AI models. This is an experimental AI feature and won’t always get it right.',
123
146
  /**
124
147
  * @description Text describing the 'Code suggestions' feature
125
148
  */
@@ -480,6 +503,7 @@ export class AISettingsTab extends UI.Widget.VBox {
480
503
  }
481
504
 
482
505
  if (this.#aiAssistanceSetting) {
506
+ const isV2 = Root.Runtime.hostConfig.devToolsAiAssistanceV2?.enabled;
483
507
  const aiAssistanceData: AiSettingParams = {
484
508
  settingName: i18n.i18n.lockedString(
485
509
  AiAssistanceModel.AiUtils.isGeminiBranding() ? 'Gemini in Chrome DevTools' : 'AI assistance'),
@@ -488,12 +512,18 @@ export class AISettingsTab extends UI.Widget.VBox {
488
512
  enableSettingText: i18nString(UIStrings.enableAiAssistance),
489
513
  settingItems: [
490
514
  {iconName: 'info', text: this.#getAiAssistanceSettingInfo()},
491
- {iconName: 'pen-spark', text: i18nString(UIStrings.receiveStylingSuggestions)}
515
+ {
516
+ iconName: 'pen-spark',
517
+ text: isV2 ? i18nString(UIStrings.aiAssistanceWhenOnItem2V2) :
518
+ i18nString(UIStrings.receiveStylingSuggestions),
519
+ },
492
520
  ],
493
521
  toConsiderSettingItems: [{
494
522
  iconName: 'google',
495
- text: noLogging ? i18nString(UIStrings.freestylerSendsDataNoLogging) :
496
- i18nString(UIStrings.freestylerSendsData)
523
+ text: isV2 ? (noLogging ? i18nString(UIStrings.aiAssistanceThingsToConsiderNoLoggingV2) :
524
+ i18nString(UIStrings.aiAssistanceThingsToConsiderV2)) :
525
+ (noLogging ? i18nString(UIStrings.freestylerSendsDataNoLogging) :
526
+ i18nString(UIStrings.freestylerSendsData)),
497
527
  }],
498
528
  learnMoreLink: {
499
529
  url: 'https://developer.chrome.com/docs/devtools/ai-assistance',
@@ -581,6 +611,9 @@ export class AISettingsTab extends UI.Widget.VBox {
581
611
 
582
612
  #getAiAssistanceSettingDescription(): Platform.UIString.LocalizedString {
583
613
  const {hostConfig} = Root.Runtime;
614
+ if (hostConfig.devToolsAiAssistanceV2?.enabled) {
615
+ return i18nString(UIStrings.aiAssistanceDescriptionV2);
616
+ }
584
617
  if (hostConfig.devToolsAiAssistancePerformanceAgent?.enabled) {
585
618
  return i18nString(UIStrings.helpUnderstandStylingNetworkPerformanceAndFile);
586
619
  }
@@ -595,6 +628,9 @@ export class AISettingsTab extends UI.Widget.VBox {
595
628
 
596
629
  #getAiAssistanceSettingInfo(): Platform.UIString.LocalizedString {
597
630
  const {hostConfig} = Root.Runtime;
631
+ if (hostConfig.devToolsAiAssistanceV2?.enabled) {
632
+ return i18nString(UIStrings.aiAssistanceWhenOnItem1V2);
633
+ }
598
634
  if (hostConfig.devToolsAiAssistancePerformanceAgent?.enabled) {
599
635
  return i18nString(UIStrings.explainStylingNetworkPerformanceAndFile);
600
636
  }
@@ -636,7 +636,7 @@ const GREENDEV_VIEW: View = (input, _output, target) => {
636
636
  <span>${i18nString(UIStrings.greenDevUnstable)}</span>
637
637
  </div>
638
638
  <div class="settings-experiments-block">
639
- ${renderPrototypeCheckboxes(input.settings, ['aiAnnotations', 'copyToGemini', 'breakpointDebuggerAgent', 'emulationCapabilities'])}
639
+ ${renderPrototypeCheckboxes(input.settings, ['aiAnnotations', 'beyondStyling', 'breakpointDebuggerAgent', 'emulationCapabilities'])}
640
640
  </div>
641
641
  </devtools-card>
642
642
  </div>
@@ -646,7 +646,7 @@ const GREENDEV_VIEW: View = (input, _output, target) => {
646
646
 
647
647
  const GREENDEV_PROTOTYPE_NAMES: Record<keyof GreenDev.GreenDevSettings, string> = {
648
648
  aiAnnotations: 'AI auto-annotations',
649
- copyToGemini: 'Copy changes to AI Prompt',
649
+ beyondStyling: 'Beyond Styling',
650
650
  breakpointDebuggerAgent: 'Breakpoint Debugger Agent',
651
651
  emulationCapabilities: 'Emulation Capabilities',
652
652
  };
@@ -1,7 +1,7 @@
1
1
  Name: Dependencies sourced from the upstream `chromium` repository
2
2
  URL: Internal
3
3
  Version: N/A
4
- Revision: ba9b7fcecd6da792b29305cac5a406adc76fc1e5
4
+ Revision: a287ca9049cc3727d680078c1d9275b32f721c2d
5
5
  Update Mechanism: Manual (https://crbug.com/428069060)
6
6
  License: BSD-3-Clause
7
7
  License File: LICENSE