chrome-devtools-frontend 1.0.1034999 → 1.0.1036501

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 (31) hide show
  1. package/AUTHORS +1 -0
  2. package/config/gni/devtools_grd_files.gni +2 -0
  3. package/docs/workflows.md +4 -5
  4. package/front_end/core/i18n/locales/en-US.json +21 -6
  5. package/front_end/core/i18n/locales/en-XL.json +21 -6
  6. package/front_end/core/root/Runtime.ts +8 -3
  7. package/front_end/entrypoints/main/MainImpl.ts +6 -5
  8. package/front_end/generated/InspectorBackendCommands.js +2 -2
  9. package/front_end/generated/SupportedCSSProperties.js +8 -4
  10. package/front_end/generated/protocol.ts +7 -1
  11. package/front_end/models/persistence/NetworkPersistenceManager.ts +25 -14
  12. package/front_end/panels/application/components/Prerender2.ts +5 -7
  13. package/front_end/panels/elements/CSSRuleValidator.ts +1 -1
  14. package/front_end/panels/elements/StylePropertiesSection.ts +12 -0
  15. package/front_end/panels/elements/StylePropertyTreeElement.ts +1 -1
  16. package/front_end/panels/elements/StylesSidebarPane.ts +1 -0
  17. package/front_end/panels/network/NetworkLogView.ts +13 -5
  18. package/front_end/panels/settings/SettingsScreen.ts +12 -0
  19. package/front_end/panels/settings/settingsScreen.css +6 -0
  20. package/front_end/panels/sources/NavigatorView.ts +0 -7
  21. package/front_end/panels/sources/ScopeChainSidebarPane.ts +4 -3
  22. package/front_end/panels/sources/SourcesNavigator.ts +0 -37
  23. package/front_end/panels/sources/SourcesPanel.ts +34 -22
  24. package/front_end/panels/sources/components/BreakpointsView.ts +206 -0
  25. package/front_end/panels/sources/components/HeadersView.ts +8 -41
  26. package/front_end/panels/sources/components/breakpointsView.css +95 -0
  27. package/front_end/panels/sources/components/components.ts +2 -0
  28. package/front_end/ui/components/linear_memory_inspector/LinearMemoryHighlightChipList.ts +11 -9
  29. package/front_end/ui/components/linear_memory_inspector/linearMemoryHighlightChipList.css +48 -30
  30. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +2 -2
  31. package/package.json +1 -1
@@ -1034,17 +1034,10 @@ export class NavigatorView extends UI.Widget.VBox implements SDK.TargetManager.O
1034
1034
  }
1035
1035
  }
1036
1036
 
1037
- /**
1038
- * Subclasses can override to listen to grouping changes.
1039
- */
1040
- onGroupingChanged(): void {
1041
- }
1042
-
1043
1037
  private groupingChanged(): void {
1044
1038
  this.reset(true);
1045
1039
  this.initGrouping();
1046
1040
  // Reset the workspace to repopulate filesystem folders.
1047
- this.onGroupingChanged();
1048
1041
  this.resetWorkspace(Workspace.Workspace.WorkspaceImpl.instance());
1049
1042
  this.workspaceInternal.uiSourceCodes().forEach(this.addUISourceCode.bind(this));
1050
1043
  }
@@ -317,16 +317,17 @@ export class OpenLinearMemoryInspector extends UI.Widget.VBox implements UI.Cont
317
317
  if (target instanceof ObjectUI.ObjectPropertiesSection.ObjectPropertyTreeElement) {
318
318
  if (target.property && target.property.value &&
319
319
  LinearMemoryInspector.LinearMemoryInspectorController.isMemoryObjectProperty(target.property.value)) {
320
+ const expression = target.path();
320
321
  contextMenu.debugSection().appendItem(
321
322
  i18nString(UIStrings.revealInMemoryInspectorPanel),
322
- this.openMemoryInspector.bind(this, target.property.name, target.property.value));
323
+ this.openMemoryInspector.bind(this, expression, target.property.value));
323
324
  }
324
325
  }
325
326
  }
326
327
 
327
- private async openMemoryInspector(name: string, obj: SDK.RemoteObject.RemoteObject): Promise<void> {
328
+ private async openMemoryInspector(expression: string, obj: SDK.RemoteObject.RemoteObject): Promise<void> {
328
329
  const controller = LinearMemoryInspector.LinearMemoryInspectorController.LinearMemoryInspectorController.instance();
329
330
  Host.userMetrics.linearMemoryInspectorRevealedFrom(Host.UserMetrics.LinearMemoryInspectorRevealedFrom.ContextMenu);
330
- void controller.openInspectorView(obj, undefined /* address */, name);
331
+ void controller.openInspectorView(obj, /* address */ undefined, expression);
331
332
  }
332
333
  }
@@ -32,11 +32,9 @@ import * as Common from '../../core/common/common.js';
32
32
  import * as Host from '../../core/host/host.js';
33
33
  import * as i18n from '../../core/i18n/i18n.js';
34
34
  import * as Platform from '../../core/platform/platform.js';
35
- import * as Root from '../../core/root/root.js';
36
35
  import * as SDK from '../../core/sdk/sdk.js';
37
36
  import * as Persistence from '../../models/persistence/persistence.js';
38
37
  import * as Workspace from '../../models/workspace/workspace.js';
39
- import * as Feedback from '../../ui/components/panel_feedback/panel_feedback.js';
40
38
  import * as UI from '../../ui/legacy/legacy.js';
41
39
  import * as Snippets from '../snippets/snippets.js';
42
40
 
@@ -102,61 +100,26 @@ const UIStrings = {
102
100
  *@description Text to save content as a specific file type
103
101
  */
104
102
  saveAs: 'Save as...',
105
- /**
106
- *@description Description of the new experimental Authored/Deployed view
107
- */
108
- authoredDescription: 'Group files by Authored/Deployed',
109
103
  };
110
104
  const str_ = i18n.i18n.registerUIStrings('panels/sources/SourcesNavigator.ts', UIStrings);
111
105
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
112
106
  let networkNavigatorViewInstance: NetworkNavigatorView;
113
107
 
114
108
  export class NetworkNavigatorView extends NavigatorView {
115
- private previewToggle: Feedback.PreviewToggle.PreviewToggle;
116
109
  private constructor() {
117
110
  super(true);
118
111
  SDK.TargetManager.TargetManager.instance().addEventListener(
119
112
  SDK.TargetManager.Events.InspectedURLChanged, this.inspectedURLChanged, this);
120
113
 
121
- this.previewToggle = new Feedback.PreviewToggle.PreviewToggle();
122
- this.onGroupingChanged();
123
-
124
- const div = UI.Fragment.html`<div class="border-container"></div>`;
125
- div.append(this.previewToggle);
126
- this.contentElement.prepend(div);
127
-
128
114
  // Record the sources tool load time after the file navigator has loaded.
129
115
  Host.userMetrics.panelLoaded('sources', 'DevTools.Launch.Sources');
130
116
  }
131
117
 
132
- onGroupingChanged(): void {
133
- // Setting the data will re-render it.
134
- this.previewToggle.data = {
135
- name: i18nString(UIStrings.authoredDescription),
136
- helperText: null,
137
- experiment: Root.Runtime.ExperimentName.AUTHORED_DEPLOYED_GROUPING,
138
- learnMoreURL: 'https://goo.gle/authored-deployed',
139
- feedbackURL: 'https://goo.gle/authored-deployed-feedback',
140
- onChangeCallback: this.onAuthoredDeployedChanged,
141
- };
142
- }
143
-
144
118
  wasShown(): void {
145
119
  this.registerCSSFiles([sourcesNavigatorStyles]);
146
120
  super.wasShown();
147
121
  }
148
122
 
149
- private onAuthoredDeployedChanged(checked: boolean): void {
150
- Host.userMetrics.experimentChanged(Root.Runtime.ExperimentName.AUTHORED_DEPLOYED_GROUPING, checked);
151
- // Need to signal to the NavigatorView that grouping has changed. Unfortunately,
152
- // it can't listen to an experiment, and this class doesn't directly interact
153
- // with it, so we will convince it a different grouping setting changed. When we switch
154
- // from using an experiment to a setting, it will listen to that setting and we
155
- // won't need to do this.
156
- const groupByFolderSetting = Common.Settings.Settings.instance().moduleSetting('navigatorGroupByFolder');
157
- groupByFolderSetting.set(groupByFolderSetting.get());
158
- }
159
-
160
123
  static instance(opts: {
161
124
  forceNew: boolean|null,
162
125
  } = {forceNew: null}): NetworkNavigatorView {
@@ -112,6 +112,10 @@ const UIStrings = {
112
112
  */
113
113
  groupByAuthored: 'Group by Authored/Deployed',
114
114
  /**
115
+ *@description Text in Sources Panel of the Sources panel
116
+ */
117
+ hideIgnoreListed: 'Hide ignore-listed sources',
118
+ /**
115
119
  *@description Text for pausing the debugger on exceptions
116
120
  */
117
121
  pauseOnExceptions: 'Pause on exceptions',
@@ -563,36 +567,44 @@ export class SourcesPanel extends UI.Panel.Panel implements UI.ContextMenu.Provi
563
567
  }
564
568
  }
565
569
 
566
- private toggleAuthoredDeployedExperiment(): void {
567
- const experiment = Root.Runtime.ExperimentName.AUTHORED_DEPLOYED_GROUPING;
568
- const checked = Root.Runtime.experiments.isEnabled(experiment);
569
- Root.Runtime.experiments.setEnabled(experiment, !checked);
570
- Host.userMetrics.experimentChanged(experiment, checked);
571
- // Need to signal to the NavigatorView that grouping has changed. Unfortunately,
572
- // it can't listen to an experiment, and this class doesn't directly interact
573
- // with it, so we will convince it a different grouping setting changed. When we switch
574
- // from using an experiment to a setting, it will listen to that setting and we
575
- // won't need to do this.
576
- const groupByFolderSetting = Common.Settings.Settings.instance().moduleSetting('navigatorGroupByFolder');
577
- groupByFolderSetting.set(groupByFolderSetting.get());
578
- }
570
+ private addExperimentMenuItem(
571
+ menuSection: UI.ContextMenu.Section, experiment: string, menuItem: Common.UIString.LocalizedString): void {
572
+ // menu handler
573
+ function toggleExperiment(): void {
574
+ const checked = Root.Runtime.experiments.isEnabled(experiment);
575
+ Root.Runtime.experiments.setEnabled(experiment, !checked);
576
+ Host.userMetrics.experimentChanged(experiment, checked);
577
+ // Need to signal to the NavigatorView that grouping has changed. Unfortunately,
578
+ // it can't listen to an experiment, and this class doesn't directly interact
579
+ // with it, so we will convince it a different grouping setting changed. When we switch
580
+ // from using an experiment to a setting, it will listen to that setting and we
581
+ // won't need to do this.
582
+ const groupByFolderSetting = Common.Settings.Settings.instance().moduleSetting('navigatorGroupByFolder');
583
+ groupByFolderSetting.set(groupByFolderSetting.get());
584
+ }
579
585
 
580
- private populateNavigatorMenu(contextMenu: UI.ContextMenu.ContextMenu): void {
581
- const groupByFolderSetting = Common.Settings.Settings.instance().moduleSetting('navigatorGroupByFolder');
582
- contextMenu.appendItemsAtLocation('navigatorMenu');
583
- contextMenu.viewSection().appendCheckboxItem(
584
- i18nString(UIStrings.groupByFolder), () => groupByFolderSetting.set(!groupByFolderSetting.get()),
585
- groupByFolderSetting.get());
586
586
  const previewIcon = new IconButton.Icon.Icon();
587
- const experiment = Root.Runtime.ExperimentName.AUTHORED_DEPLOYED_GROUPING;
588
587
  previewIcon.data = {
589
588
  iconName: 'ic_preview_feature',
590
589
  color: 'var(--icon-color)',
591
590
  width: '14px',
592
591
  };
592
+ menuSection.appendCheckboxItem(
593
+ menuItem, toggleExperiment, Root.Runtime.experiments.isEnabled(experiment), false, previewIcon);
594
+ }
595
+
596
+ private populateNavigatorMenu(contextMenu: UI.ContextMenu.ContextMenu): void {
597
+ const groupByFolderSetting = Common.Settings.Settings.instance().moduleSetting('navigatorGroupByFolder');
598
+ contextMenu.appendItemsAtLocation('navigatorMenu');
593
599
  contextMenu.viewSection().appendCheckboxItem(
594
- i18nString(UIStrings.groupByAuthored), this.toggleAuthoredDeployedExperiment,
595
- Root.Runtime.experiments.isEnabled(experiment), false, previewIcon);
600
+ i18nString(UIStrings.groupByFolder), () => groupByFolderSetting.set(!groupByFolderSetting.get()),
601
+ groupByFolderSetting.get());
602
+
603
+ this.addExperimentMenuItem(
604
+ contextMenu.viewSection(), Root.Runtime.ExperimentName.AUTHORED_DEPLOYED_GROUPING,
605
+ i18nString(UIStrings.groupByAuthored));
606
+ this.addExperimentMenuItem(
607
+ contextMenu.viewSection(), Root.Runtime.ExperimentName.JUST_MY_CODE, i18nString(UIStrings.hideIgnoreListed));
596
608
  }
597
609
 
598
610
  setIgnoreExecutionLineEvents(ignoreExecutionLineEvents: boolean): void {
@@ -0,0 +1,206 @@
1
+ // Copyright (c) 2022 The Chromium Authors. All rights reserved.
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 Platform from '../../../core/platform/platform.js';
7
+ import * as ComponentHelpers from '../../../ui/components/helpers/helpers.js';
8
+ import * as IconButton from '../../../ui/components/icon_button/icon_button.js';
9
+ import * as LitHtml from '../../../ui/lit-html/lit-html.js';
10
+
11
+ import breakpointsViewStyles from './breakpointsView.css.js';
12
+
13
+ const UIStrings = {
14
+ /**
15
+ *@description Text exposed to screen readers on checked items.
16
+ */
17
+ checked: 'checked',
18
+ /**
19
+ *@description Accessible text exposed to screen readers when the screen reader encounters an unchecked checkbox.
20
+ */
21
+ unchecked: 'unchecked',
22
+ /**
23
+ *@description Accessible text for a breakpoint collection with a combination of checked states.
24
+ */
25
+ indeterminate: 'mixed',
26
+ /**
27
+ *@description Accessibility label for hit breakpoints in the Sources panel.
28
+ *@example {checked} PH1
29
+ */
30
+ breakpointHit: '{PH1} breakpoint hit',
31
+
32
+ };
33
+ const str_ = i18n.i18n.registerUIStrings('panels/sources/components/BreakpointsView.ts', UIStrings);
34
+ const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
35
+
36
+ const MAX_SNIPPET_LENGTH = 200;
37
+
38
+ export interface BreakpointsViewData {
39
+ groups: BreakpointGroup[];
40
+ }
41
+
42
+ export interface BreakpointGroup {
43
+ name: string;
44
+ url: Platform.DevToolsPath.UrlString;
45
+ expanded: boolean;
46
+ breakpointItems: BreakpointItem[];
47
+ }
48
+
49
+ export interface BreakpointItem {
50
+ location: string;
51
+ codeSnippet: string;
52
+ isHit: boolean;
53
+ status: BreakpointStatus;
54
+ hoverText?: string;
55
+ }
56
+
57
+ export const enum BreakpointStatus {
58
+ ENABLED = 'ENABLED',
59
+ DISABLED = 'DISABLED',
60
+ INDETERMINATE = 'INDETERMINATE',
61
+ }
62
+
63
+ export class CheckboxToggledEvent extends Event {
64
+ static readonly eventName = 'checkboxtoggled';
65
+ data: {breakpointItem: BreakpointItem, checked: boolean};
66
+
67
+ constructor(breakpointItem: BreakpointItem, checked: boolean) {
68
+ super(CheckboxToggledEvent.eventName);
69
+ this.data = {breakpointItem: breakpointItem, checked};
70
+ }
71
+ }
72
+
73
+ export class ExpandedStateChangedEvent extends Event {
74
+ static readonly eventName = 'expandedstatechanged';
75
+ data: {url: Platform.DevToolsPath.UrlString, expanded: boolean};
76
+
77
+ constructor(url: Platform.DevToolsPath.UrlString, expanded: boolean) {
78
+ super(ExpandedStateChangedEvent.eventName);
79
+ this.data = {url, expanded};
80
+ }
81
+ }
82
+
83
+ export class BreakpointSelectedEvent extends Event {
84
+ static readonly eventName = 'breakpointselected';
85
+ data: {breakpointItem: BreakpointItem};
86
+
87
+ constructor(breakpointItem: BreakpointItem) {
88
+ super(BreakpointSelectedEvent.eventName);
89
+ this.data = {breakpointItem: breakpointItem};
90
+ }
91
+ }
92
+
93
+ export class BreakpointsView extends HTMLElement {
94
+ static readonly litTagName = LitHtml.literal`devtools-breakpoint-view`;
95
+ readonly #shadow = this.attachShadow({mode: 'open'});
96
+ readonly #boundRender = this.#render.bind(this);
97
+
98
+ #breakpointGroups: BreakpointGroup[] = [];
99
+
100
+ set data(data: BreakpointsViewData) {
101
+ this.#breakpointGroups = data.groups;
102
+ void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);
103
+ }
104
+
105
+ connectedCallback(): void {
106
+ this.#shadow.adoptedStyleSheets = [breakpointsViewStyles];
107
+ void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);
108
+ }
109
+
110
+ #render(): void {
111
+ const renderedGroups = this.#breakpointGroups.map((group, index) => {
112
+ const out = this.#renderBreakpointGroup(group);
113
+ if (index === this.#breakpointGroups.length - 1) {
114
+ return out;
115
+ }
116
+ return LitHtml.html`${out}<div class='divider'></div>`;
117
+ });
118
+ LitHtml.render(LitHtml.html`${renderedGroups}`, this.#shadow, {host: this});
119
+ }
120
+
121
+ #renderBreakpointGroup(group: BreakpointGroup): LitHtml.TemplateResult {
122
+ const groupClassMap = {
123
+ 'expanded': group.expanded,
124
+ };
125
+ // clang-format off
126
+ return LitHtml.html`
127
+ <div data-group='true' class=${LitHtml.Directives.classMap(groupClassMap)}>
128
+ <div class='group-header' @click=${(): void => this.#onGroupExpandToggled(group)}>
129
+ <span class='triangle'></span>
130
+ ${this.#renderFileIcon()}
131
+ <span class='group-header-title'>${group.name}</span>
132
+ </div>
133
+ ${group.expanded? LitHtml.html`
134
+ ${group.breakpointItems.map(entry => this.#renderBreakpointEntry(entry))}` : LitHtml.nothing}
135
+ </div>
136
+ `;
137
+ // clang-format on
138
+ }
139
+
140
+ #renderFileIcon(): LitHtml.TemplateResult {
141
+ return LitHtml.html`
142
+ <${IconButton.Icon.Icon.litTagName} .data=${
143
+ {iconName: 'ic_file_script', color: 'var(--color-ic-file-script)', width: '16px', height: '16px'} as
144
+ IconButton.Icon.IconWithName}></${IconButton.Icon.Icon.litTagName}>
145
+ `;
146
+ }
147
+
148
+ #renderBreakpointEntry(breakpointItem: BreakpointItem): LitHtml.TemplateResult {
149
+ const classMap = {
150
+ 'breakpoint-item': true,
151
+ 'hit': breakpointItem.isHit,
152
+ };
153
+ const breakpointItemDescription = this.#getBreakpointItemDescription(breakpointItem);
154
+ const codeSnippet = Platform.StringUtilities.trimEndWithMaxLength(breakpointItem.codeSnippet, MAX_SNIPPET_LENGTH);
155
+
156
+ // clang-format off
157
+ return LitHtml.html`
158
+ <div class=${LitHtml.Directives.classMap(classMap)} aria-label=${breakpointItemDescription} tabIndex=${breakpointItem.isHit ? 0 : 1}>
159
+ <label class='checkbox-label'>
160
+ <input type='checkbox' aria-label=${breakpointItem.location} ?indeterminate=${breakpointItem.status === BreakpointStatus.INDETERMINATE} ?checked=${breakpointItem.status === BreakpointStatus.ENABLED} @change=${(e: Event): void => this.#onCheckboxToggled(e, breakpointItem)}>
161
+ </label>
162
+ <span class='code-snippet' @click=${():void => {this.dispatchEvent(new BreakpointSelectedEvent(breakpointItem));}}>${codeSnippet}</span>
163
+ <span class='location'>${breakpointItem.location}</span>
164
+ </div>
165
+ `;
166
+ // clang-format on
167
+ }
168
+
169
+ #getBreakpointItemDescription(breakpointItem: BreakpointItem): Platform.UIString.LocalizedString {
170
+ let checkboxDescription;
171
+ switch (breakpointItem.status) {
172
+ case BreakpointStatus.ENABLED:
173
+ checkboxDescription = i18nString(UIStrings.checked);
174
+ break;
175
+ case BreakpointStatus.DISABLED:
176
+ checkboxDescription = i18nString(UIStrings.unchecked);
177
+ break;
178
+ case BreakpointStatus.INDETERMINATE:
179
+ checkboxDescription = i18nString(UIStrings.indeterminate);
180
+ break;
181
+ }
182
+ if (!breakpointItem.isHit) {
183
+ return checkboxDescription;
184
+ }
185
+ return i18nString(UIStrings.breakpointHit, {PH1: checkboxDescription});
186
+ }
187
+
188
+ #onGroupExpandToggled(group: BreakpointGroup): void {
189
+ group.expanded = !group.expanded;
190
+ this.dispatchEvent(new ExpandedStateChangedEvent(group.url, group.expanded));
191
+ void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);
192
+ }
193
+
194
+ #onCheckboxToggled(e: Event, item: BreakpointItem): void {
195
+ const element = e.target as HTMLInputElement;
196
+ this.dispatchEvent(new CheckboxToggledEvent(item, element.checked));
197
+ }
198
+ }
199
+
200
+ ComponentHelpers.CustomElements.defineComponent('devtools-breakpoint-view', BreakpointsView);
201
+
202
+ declare global {
203
+ interface HTMLElementTagNameMap {
204
+ 'devtools-breakpoint-view': BreakpointsView;
205
+ }
206
+ }
@@ -9,6 +9,7 @@ import * as Buttons from '../../../ui/components/buttons/buttons.js';
9
9
  import * as ComponentHelpers from '../../../ui/components/helpers/helpers.js';
10
10
  import * as UI from '../../../ui/legacy/legacy.js';
11
11
  import * as LitHtml from '../../../ui/lit-html/lit-html.js';
12
+ import type * as Protocol from '../../../generated/protocol.js';
12
13
 
13
14
  import HeadersViewStyles from './HeadersView.css.js';
14
15
 
@@ -81,23 +82,8 @@ export class HeadersView extends UI.View.SimpleView {
81
82
  parsingError = true;
82
83
  }
83
84
 
84
- // Header overrides are stored as the key-value pairs of a JSON object on
85
- // disk. For the editor we want them as an array instead, so that we can
86
- // access/add/remove entries by their index.
87
- const arrayOfHeaderOverrideArrays: HeaderOverride[] = headerOverrides.map(headerOverride => {
88
- return {
89
- applyTo: headerOverride.applyTo,
90
- headers: Object.entries(headerOverride.headers).map(([headerName, headerValue]) => {
91
- return {
92
- name: headerName,
93
- value: headerValue,
94
- };
95
- }),
96
- };
97
- });
98
-
99
85
  this.#headersViewComponent.data = {
100
- headerOverrides: arrayOfHeaderOverrideArrays,
86
+ headerOverrides,
101
87
  uiSourceCode: this.#uiSourceCode,
102
88
  parsingError,
103
89
  };
@@ -128,18 +114,8 @@ export class HeadersView extends UI.View.SimpleView {
128
114
  }
129
115
  }
130
116
 
131
- type Header = {
132
- name: string,
133
- value: string,
134
- };
135
-
136
- type HeaderOverride = {
137
- applyTo: string,
138
- headers: Header[],
139
- };
140
-
141
117
  export interface HeadersViewComponentData {
142
- headerOverrides: HeaderOverride[];
118
+ headerOverrides: Persistence.NetworkPersistenceManager.HeaderOverride[];
143
119
  uiSourceCode: Workspace.UISourceCode.UISourceCode;
144
120
  parsingError: boolean;
145
121
  }
@@ -148,7 +124,7 @@ export class HeadersViewComponent extends HTMLElement {
148
124
  static readonly litTagName = LitHtml.literal`devtools-sources-headers-view`;
149
125
  readonly #shadow = this.attachShadow({mode: 'open'});
150
126
  readonly #boundRender = this.#render.bind(this);
151
- #headerOverrides: HeaderOverride[] = [];
127
+ #headerOverrides: Persistence.NetworkPersistenceManager.HeaderOverride[] = [];
152
128
  #uiSourceCode: Workspace.UISourceCode.UISourceCode|null = null;
153
129
  #parsingError = false;
154
130
  #focusElement: {blockIndex: number, headerIndex?: number}|null = null;
@@ -213,7 +189,7 @@ export class HeadersViewComponent extends HTMLElement {
213
189
  selection?.removeAllRanges();
214
190
  }
215
191
 
216
- #generateNextHeaderName(headers: Header[]): string {
192
+ #generateNextHeaderName(headers: Protocol.Fetch.HeaderEntry[]): string {
217
193
  const takenNames = new Set<string>(headers.map(header => header.name));
218
194
  let idx = 1;
219
195
  while (takenNames.has('headerName' + idx)) {
@@ -270,17 +246,7 @@ export class HeadersViewComponent extends HTMLElement {
270
246
  }
271
247
 
272
248
  #onHeadersChanged(): void {
273
- // In the editor header overrides are represented by items in an array, so
274
- // that we can access/add/remove entries by their index. On disk, they are
275
- // stored as key-value pairs of a JSON object instead.
276
- const arrayOfHeaderOverrideObjects: Persistence.NetworkPersistenceManager.HeaderOverride[] =
277
- this.#headerOverrides.map(headerOverride => {
278
- return {
279
- applyTo: headerOverride.applyTo,
280
- headers: headerOverride.headers.reduce((a, v) => ({...a, [v.name]: v.value}), {}),
281
- };
282
- });
283
- this.#uiSourceCode?.setWorkingCopy(JSON.stringify(arrayOfHeaderOverrideObjects, null, 2));
249
+ this.#uiSourceCode?.setWorkingCopy(JSON.stringify(this.#headerOverrides, null, 2));
284
250
  }
285
251
 
286
252
  #render(): void {
@@ -355,7 +321,8 @@ export class HeadersViewComponent extends HTMLElement {
355
321
  // clang-format on
356
322
  }
357
323
 
358
- #renderHeaderRow(header: Header, blockIndex: number, headerIndex: number): LitHtml.TemplateResult {
324
+ #renderHeaderRow(header: Protocol.Fetch.HeaderEntry, blockIndex: number, headerIndex: number):
325
+ LitHtml.TemplateResult {
359
326
  // clang-format off
360
327
  return LitHtml.html`
361
328
  <div class="row padded" data-block-index=${blockIndex} data-header-index=${headerIndex}>
@@ -0,0 +1,95 @@
1
+ /*
2
+ * Copyright 2022 The Chromium Authors. All rights reserved.
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
+ :host {
8
+ flex: auto;
9
+ display: flex;
10
+ flex-direction: column;
11
+ }
12
+
13
+ .divider {
14
+ height: 1px;
15
+ width: inherit;
16
+ background-color: var(--color-details-hairline);
17
+ }
18
+
19
+ .code-snippet {
20
+ width: 100%;
21
+ padding-left: 6px;
22
+ font-family: var(--source-code-font-family);
23
+ font-size: var(--source-code-font-size);
24
+ color: var(--color-text-secondary);
25
+ text-overflow: ellipsis;
26
+ overflow: hidden;
27
+ white-space: nowrap;
28
+ flex-shrink: 100;
29
+ }
30
+
31
+ input {
32
+ height: 12px;
33
+ width: 12px;
34
+ flex-shrink: 0;
35
+ margin: 3px 0;
36
+ }
37
+
38
+ .triangle {
39
+ margin-left: 6px;
40
+ margin-right: 4px;
41
+ display: inline-block;
42
+ -webkit-mask-image: var(--image-file-treeoutlineTriangles);
43
+ -webkit-mask-size: 32px 24px;
44
+ -webkit-mask-position: 0 0;
45
+ background-color: var(--color-text-primary);
46
+ height: 12px;
47
+ width: 8px;
48
+ }
49
+
50
+ .group-header {
51
+ display: flex;
52
+ align-items: center;
53
+ height: 18px;
54
+ }
55
+
56
+ .expanded > .group-header > .triangle {
57
+ -webkit-mask-position: -16px 0;
58
+ }
59
+
60
+ .group-header-title {
61
+ margin-left: 4px;
62
+ font-weight: 500;
63
+ font-size: var(--source-code-font-size);
64
+ text-overflow: ellipsis;
65
+ overflow: hidden;
66
+ white-space: nowrap;
67
+ }
68
+
69
+ .breakpoint-item {
70
+ display: flex;
71
+ align-items: center;
72
+ line-height: 13px;
73
+ height: 18px;
74
+ }
75
+
76
+ .breakpoint-item:hover {
77
+ background-color: var(--color-background-elevation-1);
78
+ }
79
+
80
+ .breakpoint-item.hit {
81
+ --override-breakpoint-hit-background: rgb(255 255 194);
82
+
83
+ background-color: var(--override-breakpoint-hit-background);
84
+ }
85
+
86
+ .checkbox-label {
87
+ padding-left: 24px;
88
+ display: flex;
89
+ align-items: center;
90
+ }
91
+
92
+ .location {
93
+ line-height: 14px;
94
+ margin: 0 8px;
95
+ }
@@ -2,8 +2,10 @@
2
2
  // Use of this source code is governed by a BSD-style license that can be
3
3
  // found in the LICENSE file.
4
4
 
5
+ import * as BreakpointsView from './BreakpointsView.js';
5
6
  import * as HeadersView from './HeadersView.js';
6
7
 
7
8
  export {
9
+ BreakpointsView,
8
10
  HeadersView,
9
11
  };
@@ -95,15 +95,17 @@ export class LinearMemoryHighlightChipList extends HTMLElement {
95
95
  <span class="value">${expressionName}</span><span class="separator">: </span><span>${expressionType}</span>
96
96
  </span>
97
97
  </button>
98
- <button class="delete-highlight-button" title=${
99
- i18nString(UIStrings.deleteHighlight)} @click=${():void => this.#onDeleteHighlightClick(highlightInfo)}>
100
- <${IconButton.Icon.Icon.litTagName} .data=${{
101
- iconName: 'close-icon',
102
- color: 'black',
103
- width: '7px',
104
- } as IconButton.Icon.IconData}>
105
- </${IconButton.Icon.Icon.litTagName}>
106
- </button>
98
+ <div class="delete-highlight-container">
99
+ <button class="delete-highlight-button" title=${
100
+ i18nString(UIStrings.deleteHighlight)} @click=${():void => this.#onDeleteHighlightClick(highlightInfo)}>
101
+ <${IconButton.Icon.Icon.litTagName} .data=${{
102
+ iconName: 'close-icon',
103
+ color: 'var(--color-text-primary)',
104
+ width: '7px',
105
+ } as IconButton.Icon.IconData}>
106
+ </${IconButton.Icon.Icon.litTagName}>
107
+ </button>
108
+ </div>
107
109
  </div>
108
110
  `;
109
111
  // clang-format off