chrome-devtools-frontend 1.0.981537 → 1.0.982087

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 (30) hide show
  1. package/front_end/core/common/ParsedURL.ts +5 -0
  2. package/front_end/core/host/InspectorFrontendHost.ts +7 -6
  3. package/front_end/core/host/InspectorFrontendHostAPI.ts +8 -8
  4. package/front_end/core/i18n/locales/en-US.json +12 -0
  5. package/front_end/core/i18n/locales/en-XL.json +12 -0
  6. package/front_end/core/sdk/Target.ts +2 -1
  7. package/front_end/models/bindings/FileUtils.ts +3 -2
  8. package/front_end/models/workspace/FileManager.ts +9 -6
  9. package/front_end/panels/application/BackgroundServiceView.ts +2 -1
  10. package/front_end/panels/console/ConsoleView.ts +3 -1
  11. package/front_end/panels/coverage/CoverageView.ts +2 -1
  12. package/front_end/panels/emulation/DeviceModeToolbar.ts +2 -1
  13. package/front_end/panels/input/InputTimeline.ts +2 -1
  14. package/front_end/panels/lighthouse/LighthouseReportRenderer.ts +1 -1
  15. package/front_end/panels/network/NetworkLogView.ts +2 -2
  16. package/front_end/panels/profiler/HeapSnapshotView.ts +3 -2
  17. package/front_end/panels/profiler/ProfileView.ts +2 -2
  18. package/front_end/panels/protocol_monitor/ProtocolMonitor.ts +4 -2
  19. package/front_end/panels/screencast/ScreencastView.ts +4 -1
  20. package/front_end/panels/settings/SettingsScreen.ts +4 -1
  21. package/front_end/panels/sources/components/HeadersView.css +17 -2
  22. package/front_end/panels/sources/components/HeadersView.ts +102 -0
  23. package/front_end/panels/timeline/TimelinePanel.ts +2 -1
  24. package/front_end/ui/components/panel_feedback/FeedbackButton.ts +4 -1
  25. package/front_end/ui/legacy/XLink.ts +8 -3
  26. package/front_end/ui/legacy/components/color_picker/ContrastDetails.ts +3 -1
  27. package/front_end/ui/legacy/components/utils/ImagePreview.ts +6 -2
  28. package/front_end/ui/legacy/components/utils/Linkifier.ts +7 -2
  29. package/front_end/ui/legacy/tabbedPane.css +1 -0
  30. package/package.json +1 -1
@@ -254,6 +254,11 @@ export class ParsedURL {
254
254
  return devToolsPath.trim() as DevToolsPathType;
255
255
  }
256
256
 
257
+ static slice<DevToolsPathType extends BrandedPathString>(
258
+ devToolsPath: DevToolsPathType, start?: number, end?: number): DevToolsPathType {
259
+ return devToolsPath.slice(start, end) as DevToolsPathType;
260
+ }
261
+
257
262
  static join<DevToolsPathType extends Platform.DevToolsPath.UrlString|Platform.DevToolsPath.RawPathString|
258
263
  Platform.DevToolsPath.EncodedPathString>(
259
264
  devToolsPaths: DevToolsPathType[], separator?: string): DevToolsPathType {
@@ -53,7 +53,7 @@ const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
53
53
  const MAX_RECORDED_HISTOGRAMS_SIZE = 100;
54
54
 
55
55
  export class InspectorFrontendHostStub implements InspectorFrontendHostAPI {
56
- readonly #urlsBeingSaved: Map<string, string[]>;
56
+ readonly #urlsBeingSaved: Map<Platform.DevToolsPath.RawPathString|Platform.DevToolsPath.UrlString, string[]>;
57
57
  events!: Common.EventTarget.EventTarget<EventTypes>;
58
58
 
59
59
  recordedEnumeratedHistograms: {actionName: EnumeratedHistogram, actionCode: number}[] = [];
@@ -122,7 +122,7 @@ export class InspectorFrontendHostStub implements InspectorFrontendHostAPI {
122
122
  setInjectedScriptForOrigin(origin: string, script: string): void {
123
123
  }
124
124
 
125
- inspectedURLChanged(url: string): void {
125
+ inspectedURLChanged(url: Platform.DevToolsPath.UrlString): void {
126
126
  document.title = i18nString(UIStrings.devtoolsS, {PH1: url.replace(/^https?:\/\//, '')});
127
127
  }
128
128
 
@@ -133,7 +133,7 @@ export class InspectorFrontendHostStub implements InspectorFrontendHostAPI {
133
133
  void navigator.clipboard.writeText(text);
134
134
  }
135
135
 
136
- openInNewTab(url: string): void {
136
+ openInNewTab(url: Platform.DevToolsPath.UrlString): void {
137
137
  window.open(url, '_blank');
138
138
  }
139
139
 
@@ -142,7 +142,8 @@ export class InspectorFrontendHostStub implements InspectorFrontendHostAPI {
142
142
  'Show item in folder is not enabled in hosted mode. Please inspect using chrome://inspect');
143
143
  }
144
144
 
145
- save(url: string, content: string, forceSaveAs: boolean): void {
145
+ save(url: Platform.DevToolsPath.RawPathString|Platform.DevToolsPath.UrlString, content: string, forceSaveAs: boolean):
146
+ void {
146
147
  let buffer = this.#urlsBeingSaved.get(url);
147
148
  if (!buffer) {
148
149
  buffer = [];
@@ -152,7 +153,7 @@ export class InspectorFrontendHostStub implements InspectorFrontendHostAPI {
152
153
  this.events.dispatchEventToListeners(Events.SavedURL, {url, fileSystemPath: url});
153
154
  }
154
155
 
155
- append(url: string, content: string): void {
156
+ append(url: Platform.DevToolsPath.RawPathString|Platform.DevToolsPath.UrlString, content: string): void {
156
157
  const buffer = this.#urlsBeingSaved.get(url);
157
158
  if (buffer) {
158
159
  buffer.push(content);
@@ -160,7 +161,7 @@ export class InspectorFrontendHostStub implements InspectorFrontendHostAPI {
160
161
  }
161
162
  }
162
163
 
163
- close(url: string): void {
164
+ close(url: Platform.DevToolsPath.RawPathString|Platform.DevToolsPath.UrlString): void {
164
165
  const buffer = this.#urlsBeingSaved.get(url) || [];
165
166
  this.#urlsBeingSaved.delete(url);
166
167
  let fileName = '';
@@ -127,8 +127,8 @@ export interface RevealSourceLineEvent {
127
127
  }
128
128
 
129
129
  export interface SavedURLEvent {
130
- url: string;
131
- fileSystemPath: string;
130
+ url: Platform.DevToolsPath.RawPathString|Platform.DevToolsPath.UrlString;
131
+ fileSystemPath: Platform.DevToolsPath.RawPathString|Platform.DevToolsPath.UrlString;
132
132
  }
133
133
 
134
134
  export interface SearchCompletedEvent {
@@ -142,8 +142,8 @@ export interface SearchCompletedEvent {
142
142
  // Please note that the "dispatch" side can't be type-checked as the dispatch is
143
143
  // done dynamically.
144
144
  export type EventTypes = {
145
- [Events.AppendedToURL]: string,
146
- [Events.CanceledSaveURL]: string,
145
+ [Events.AppendedToURL]: Platform.DevToolsPath.RawPathString|Platform.DevToolsPath.UrlString,
146
+ [Events.CanceledSaveURL]: Platform.DevToolsPath.UrlString,
147
147
  [Events.ContextMenuCleared]: void,
148
148
  [Events.ContextMenuItemSelected]: number,
149
149
  [Events.DeviceCountUpdated]: number,
@@ -197,7 +197,7 @@ export interface InspectorFrontendHostAPI {
197
197
 
198
198
  inspectElementCompleted(): void;
199
199
 
200
- openInNewTab(url: string): void;
200
+ openInNewTab(url: Platform.DevToolsPath.UrlString): void;
201
201
 
202
202
  showItemInFolder(fileSystemPath: string): void;
203
203
 
@@ -205,11 +205,11 @@ export interface InspectorFrontendHostAPI {
205
205
 
206
206
  requestFileSystems(): void;
207
207
 
208
- save(url: string, content: string, forceSaveAs: boolean): void;
208
+ save(url: Platform.DevToolsPath.UrlString, content: string, forceSaveAs: boolean): void;
209
209
 
210
- append(url: string, content: string): void;
210
+ append(url: Platform.DevToolsPath.UrlString, content: string): void;
211
211
 
212
- close(url: string): void;
212
+ close(url: Platform.DevToolsPath.UrlString): void;
213
213
 
214
214
  searchInPath(requestId: number, fileSystemPath: string, query: string): void;
215
215
 
@@ -9245,12 +9245,24 @@
9245
9245
  "panels/sources/CallStackSidebarPane.ts | showMore": {
9246
9246
  "message": "Show more"
9247
9247
  },
9248
+ "panels/sources/components/HeadersView.ts | addHeader": {
9249
+ "message": "Add a header"
9250
+ },
9251
+ "panels/sources/components/HeadersView.ts | addHeaderOverride": {
9252
+ "message": "Add header override"
9253
+ },
9248
9254
  "panels/sources/components/HeadersView.ts | errorWhenParsing": {
9249
9255
  "message": "Error when parsing ''{PH1}''."
9250
9256
  },
9251
9257
  "panels/sources/components/HeadersView.ts | parsingErrorExplainer": {
9252
9258
  "message": "This is most likely due to a syntax error in ''{PH1}''. Try opening this file in an external editor to fix the error or delete the file and re-create the override."
9253
9259
  },
9260
+ "panels/sources/components/HeadersView.ts | removeBlock": {
9261
+ "message": "Remove this 'ApplyTo'-section"
9262
+ },
9263
+ "panels/sources/components/HeadersView.ts | removeHeader": {
9264
+ "message": "Remove this header"
9265
+ },
9254
9266
  "panels/sources/CoveragePlugin.ts | clickToShowCoveragePanel": {
9255
9267
  "message": "Click to show Coverage Panel"
9256
9268
  },
@@ -9245,12 +9245,24 @@
9245
9245
  "panels/sources/CallStackSidebarPane.ts | showMore": {
9246
9246
  "message": "Ŝh́ôẃ m̂ór̂é"
9247
9247
  },
9248
+ "panels/sources/components/HeadersView.ts | addHeader": {
9249
+ "message": "Âd́d̂ á ĥéâd́êŕ"
9250
+ },
9251
+ "panels/sources/components/HeadersView.ts | addHeaderOverride": {
9252
+ "message": "Âd́d̂ h́êád̂ér̂ óv̂ér̂ŕîd́ê"
9253
+ },
9248
9254
  "panels/sources/components/HeadersView.ts | errorWhenParsing": {
9249
9255
  "message": "Êŕr̂ór̂ ẃĥén̂ ṕâŕŝín̂ǵ ''{PH1}''."
9250
9256
  },
9251
9257
  "panels/sources/components/HeadersView.ts | parsingErrorExplainer": {
9252
9258
  "message": "T̂h́îś îś m̂óŝt́ l̂ík̂él̂ý d̂úê t́ô á ŝýn̂t́âx́ êŕr̂ór̂ ín̂ ''{PH1}''. T́r̂ý ôṕêńîńĝ t́ĥíŝ f́îĺê ín̂ án̂ éx̂t́êŕn̂ál̂ éd̂ít̂ór̂ t́ô f́îx́ t̂h́ê ér̂ŕôŕ ôŕ d̂él̂ét̂é t̂h́ê f́îĺê án̂d́ r̂é-ĉŕêát̂é t̂h́ê óv̂ér̂ŕîd́ê."
9253
9259
  },
9260
+ "panels/sources/components/HeadersView.ts | removeBlock": {
9261
+ "message": "R̂ém̂óv̂é t̂h́îś 'ApplyTo'-ŝéĉt́îón̂"
9262
+ },
9263
+ "panels/sources/components/HeadersView.ts | removeHeader": {
9264
+ "message": "R̂ém̂óv̂é t̂h́îś ĥéâd́êŕ"
9265
+ },
9254
9266
  "panels/sources/CoveragePlugin.ts | clickToShowCoveragePanel": {
9255
9267
  "message": "Ĉĺîćk̂ t́ô śĥóŵ Ćôv́êŕâǵê Ṕâńêĺ"
9256
9268
  },
@@ -175,7 +175,8 @@ export class Target extends ProtocolClient.InspectorBackend.TargetBase {
175
175
  const parsedURL = Common.ParsedURL.ParsedURL.fromString(inspectedURL);
176
176
  this.#inspectedURLName = parsedURL ? parsedURL.lastPathComponentWithFragment() : '#' + this.#idInternal;
177
177
  if (!this.parentTarget()) {
178
- Host.InspectorFrontendHost.InspectorFrontendHostInstance.inspectedURLChanged(inspectedURL || '');
178
+ Host.InspectorFrontendHost.InspectorFrontendHostInstance.inspectedURLChanged(
179
+ inspectedURL || Platform.DevToolsPath.EmptyUrlString);
179
180
  }
180
181
  this.#targetManagerInternal.onInspectedURLChange(this);
181
182
  if (!this.#nameInternal) {
@@ -29,6 +29,7 @@
29
29
  */
30
30
 
31
31
  import type * as Common from '../../core/common/common.js';
32
+ import type * as Platform from '../../core/platform/platform.js';
32
33
  import * as Workspace from '../workspace/workspace.js';
33
34
 
34
35
  export interface ChunkedReader {
@@ -206,13 +207,13 @@ export class ChunkedFileReader implements ChunkedReader {
206
207
 
207
208
  export class FileOutputStream implements Common.StringOutputStream.OutputStream {
208
209
  #writeCallbacks: (() => void)[];
209
- #fileName!: string;
210
+ #fileName!: Platform.DevToolsPath.RawPathString|Platform.DevToolsPath.UrlString;
210
211
  #closed?: boolean;
211
212
  constructor() {
212
213
  this.#writeCallbacks = [];
213
214
  }
214
215
 
215
- async open(fileName: string): Promise<boolean> {
216
+ async open(fileName: Platform.DevToolsPath.RawPathString|Platform.DevToolsPath.UrlString): Promise<boolean> {
216
217
  this.#closed = false;
217
218
  this.#writeCallbacks = [];
218
219
  this.#fileName = fileName;
@@ -30,15 +30,17 @@
30
30
 
31
31
  import * as Common from '../../core/common/common.js';
32
32
  import * as Host from '../../core/host/host.js';
33
+ import type * as Platform from '../../core/platform/platform.js';
33
34
 
34
35
  let fileManagerInstance: FileManager|null;
35
36
 
36
37
  interface SaveCallbackParam {
37
- fileSystemPath?: string;
38
+ fileSystemPath?: Platform.DevToolsPath.RawPathString|Platform.DevToolsPath.UrlString;
38
39
  }
39
40
 
40
41
  export class FileManager extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
41
- private readonly saveCallbacks: Map<string, (arg0: SaveCallbackParam|null) => void>;
42
+ private readonly saveCallbacks:
43
+ Map<Platform.DevToolsPath.RawPathString|Platform.DevToolsPath.UrlString, (arg0: SaveCallbackParam|null) => void>;
42
44
  private constructor() {
43
45
  super();
44
46
  this.saveCallbacks = new Map();
@@ -59,7 +61,8 @@ export class FileManager extends Common.ObjectWrapper.ObjectWrapper<EventTypes>
59
61
  return fileManagerInstance;
60
62
  }
61
63
 
62
- save(url: string, content: string, forceSaveAs: boolean): Promise<SaveCallbackParam|null> {
64
+ save(url: Platform.DevToolsPath.RawPathString|Platform.DevToolsPath.UrlString, content: string, forceSaveAs: boolean):
65
+ Promise<SaveCallbackParam|null> {
63
66
  // Remove this url from the saved URLs while it is being saved.
64
67
  const result = new Promise<SaveCallbackParam|null>(resolve => this.saveCallbacks.set(url, resolve));
65
68
  Host.InspectorFrontendHost.InspectorFrontendHostInstance.save(url, content, forceSaveAs);
@@ -75,7 +78,7 @@ export class FileManager extends Common.ObjectWrapper.ObjectWrapper<EventTypes>
75
78
  }
76
79
  }
77
80
 
78
- private canceledSavedURL({data: url}: Common.EventTarget.EventTargetEvent<string>): void {
81
+ private canceledSavedURL({data: url}: Common.EventTarget.EventTargetEvent<Platform.DevToolsPath.UrlString>): void {
79
82
  const callback = this.saveCallbacks.get(url);
80
83
  this.saveCallbacks.delete(url);
81
84
  if (callback) {
@@ -83,11 +86,11 @@ export class FileManager extends Common.ObjectWrapper.ObjectWrapper<EventTypes>
83
86
  }
84
87
  }
85
88
 
86
- append(url: string, content: string): void {
89
+ append(url: Platform.DevToolsPath.RawPathString|Platform.DevToolsPath.UrlString, content: string): void {
87
90
  Host.InspectorFrontendHost.InspectorFrontendHostInstance.append(url, content);
88
91
  }
89
92
 
90
- close(url: string): void {
93
+ close(url: Platform.DevToolsPath.RawPathString|Platform.DevToolsPath.UrlString): void {
91
94
  Host.InspectorFrontendHost.InspectorFrontendHostInstance.close(url);
92
95
  }
93
96
 
@@ -457,7 +457,8 @@ export class BackgroundServiceView extends UI.Widget.VBox {
457
457
  * Saves all currently displayed events in a file (JSON format).
458
458
  */
459
459
  private async saveToFile(): Promise<void> {
460
- const fileName = `${this.serviceName}-${Platform.DateUtilities.toISO8601Compact(new Date())}.json`;
460
+ const fileName = `${this.serviceName}-${Platform.DateUtilities.toISO8601Compact(new Date())}.json` as
461
+ Platform.DevToolsPath.RawPathString;
461
462
  const stream = new Bindings.FileUtils.FileOutputStream();
462
463
 
463
464
  const accepted = await stream.open(fileName);
@@ -1076,7 +1076,9 @@ export class ConsoleView extends UI.Widget.VBox implements UI.SearchableView.Sea
1076
1076
  private async saveConsole(): Promise<void> {
1077
1077
  const url = (SDK.TargetManager.TargetManager.instance().mainTarget() as SDK.Target.Target).inspectedURL();
1078
1078
  const parsedURL = Common.ParsedURL.ParsedURL.fromString(url);
1079
- const filename = Platform.StringUtilities.sprintf('%s-%d.log', parsedURL ? parsedURL.host : 'console', Date.now());
1079
+ const filename =
1080
+ Platform.StringUtilities.sprintf('%s-%d.log', parsedURL ? parsedURL.host : 'console', Date.now()) as
1081
+ Platform.DevToolsPath.RawPathString;
1080
1082
  const stream = new Bindings.FileUtils.FileOutputStream();
1081
1083
 
1082
1084
  const progressIndicator = new UI.ProgressIndicator.ProgressIndicator();
@@ -506,7 +506,8 @@ export class CoverageView extends UI.Widget.VBox {
506
506
 
507
507
  private async exportReport(): Promise<void> {
508
508
  const fos = new Bindings.FileUtils.FileOutputStream();
509
- const fileName = `Coverage-${Platform.DateUtilities.toISO8601Compact(new Date())}.json`;
509
+ const fileName =
510
+ `Coverage-${Platform.DateUtilities.toISO8601Compact(new Date())}.json` as Platform.DevToolsPath.RawPathString;
510
511
  const accepted = await fos.open(fileName);
511
512
  if (!accepted) {
512
513
  return;
@@ -6,6 +6,7 @@ import * as Common from '../../core/common/common.js';
6
6
  import * as Host from '../../core/host/host.js';
7
7
  import * as i18n from '../../core/i18n/i18n.js';
8
8
  import * as Root from '../../core/root/root.js';
9
+ import type * as Platform from '../../core/platform/platform.js';
9
10
  import * as EmulationModel from '../../models/emulation/emulation.js';
10
11
  import * as UI from '../../ui/legacy/legacy.js';
11
12
  import * as MobileThrottling from '../mobile_throttling/mobile_throttling.js';
@@ -389,7 +390,7 @@ export class DeviceModeToolbar {
389
390
 
390
391
  private experimentalClicked(): void {
391
392
  Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(
392
- 'chrome://flags/#enable-experimental-web-platform-features');
393
+ 'chrome://flags/#enable-experimental-web-platform-features' as Platform.DevToolsPath.UrlString);
393
394
  }
394
395
 
395
396
  private fillOptionsToolbar(toolbar: UI.Toolbar.Toolbar): void {
@@ -182,7 +182,8 @@ export class InputTimeline extends UI.Widget.VBox implements Timeline.TimelineLo
182
182
  return;
183
183
  }
184
184
 
185
- const fileName = `InputProfile-${Platform.DateUtilities.toISO8601Compact(new Date())}.json`;
185
+ const fileName = `InputProfile-${Platform.DateUtilities.toISO8601Compact(new Date())}.json` as
186
+ Platform.DevToolsPath.RawPathString;
186
187
  const stream = new Bindings.FileUtils.FileOutputStream();
187
188
 
188
189
  const accepted = await stream.open(fileName);
@@ -184,7 +184,7 @@ export class LighthouseReportUIFeatures extends LighthouseReport.ReportUIFeature
184
184
  const sanitizedDomain = domain.replace(/[^a-z0-9.-]+/gi, '_');
185
185
  const timestamp = Platform.DateUtilities.toISO8601Compact(new Date(this.json.fetchTime));
186
186
  const ext = blob.type.match('json') ? '.json' : '.html';
187
- const basename = `${sanitizedDomain}-${timestamp}${ext}`;
187
+ const basename = `${sanitizedDomain}-${timestamp}${ext}` as Platform.DevToolsPath.RawPathString;
188
188
  const text = await blob.text();
189
189
  void Workspace.FileManager.FileManager.instance().save(basename, text, true /* forceSaveAs */);
190
190
  }
@@ -1673,10 +1673,10 @@ export class NetworkLogView extends Common.ObjectWrapper.eventMixin<EventTypes,
1673
1673
  }
1674
1674
  const url = mainTarget.inspectedURL();
1675
1675
  const parsedURL = Common.ParsedURL.ParsedURL.fromString(url);
1676
- const filename = parsedURL ? parsedURL.host : 'network-log';
1676
+ const filename = (parsedURL ? parsedURL.host : 'network-log') as Platform.DevToolsPath.RawPathString;
1677
1677
  const stream = new Bindings.FileUtils.FileOutputStream();
1678
1678
 
1679
- if (!await stream.open(filename + '.har')) {
1679
+ if (!await stream.open(Common.ParsedURL.ParsedURL.concatenate(filename, '.har'))) {
1680
1680
  return;
1681
1681
  }
1682
1682
 
@@ -1557,7 +1557,7 @@ export class HeapProfileHeader extends ProfileHeader {
1557
1557
  onTempFileReady: (() => void)|null;
1558
1558
  failedToCreateTempFile?: boolean;
1559
1559
  wasDisposed?: boolean;
1560
- fileName?: string;
1560
+ fileName?: Platform.DevToolsPath.RawPathString;
1561
1561
 
1562
1562
  constructor(
1563
1563
  heapProfilerModel: SDK.HeapProfilerModel.HeapProfilerModel|null, type: HeapSnapshotProfileType, title?: string) {
@@ -1713,7 +1713,8 @@ export class HeapProfileHeader extends ProfileHeader {
1713
1713
  saveToFile(): void {
1714
1714
  const fileOutputStream = new Bindings.FileUtils.FileOutputStream();
1715
1715
  this.fileName = this.fileName ||
1716
- 'Heap-' + Platform.DateUtilities.toISO8601Compact(new Date()) + this.profileType().fileExtension();
1716
+ 'Heap-' + Platform.DateUtilities.toISO8601Compact(new Date()) + this.profileType().fileExtension() as
1717
+ Platform.DevToolsPath.RawPathString;
1717
1718
  const onOpen = async(accepted: boolean): Promise<void> => {
1718
1719
  if (!accepted) {
1719
1720
  return;
@@ -549,7 +549,7 @@ export const enum ViewTypes {
549
549
 
550
550
  export class WritableProfileHeader extends ProfileHeader implements Common.StringOutputStream.OutputStream {
551
551
  readonly debuggerModel: SDK.DebuggerModel.DebuggerModel|null;
552
- fileName?: string;
552
+ fileName?: Platform.DevToolsPath.RawPathString;
553
553
  jsonifiedProfile?: string|null;
554
554
  profile?: Protocol.Profiler.Profile;
555
555
  protocolProfileInternal?: Protocol.Profiler.Profile;
@@ -599,7 +599,7 @@ export class WritableProfileHeader extends ProfileHeader implements Common.Strin
599
599
  const now = Platform.DateUtilities.toISO8601Compact(new Date());
600
600
  const fileExtension = this.profileType().fileExtension();
601
601
 
602
- this.fileName = `${this.profileType().typeName()}-${now}${fileExtension}`;
602
+ this.fileName = `${this.profileType().typeName()}-${now}${fileExtension}` as Platform.DevToolsPath.RawPathString;
603
603
  }
604
604
 
605
605
  const accepted = await fileOutputStream.open(this.fileName);
@@ -247,7 +247,8 @@ export class ProtocolMonitorImpl extends UI.Widget.VBox {
247
247
  const [domain, method] = String(methodColumn.value).split('.');
248
248
  const type = typeColumn.value === 'sent' ? 'method' : 'event';
249
249
  Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(
250
- `https://chromedevtools.github.io/devtools-protocol/tot/${domain}#${type}-${method}`);
250
+ `https://chromedevtools.github.io/devtools-protocol/tot/${domain}#${type}-${method}` as
251
+ Platform.DevToolsPath.UrlString);
251
252
  });
252
253
  },
253
254
  },
@@ -466,7 +467,8 @@ export class ProtocolMonitorImpl extends UI.Widget.VBox {
466
467
 
467
468
  private async saveAsFile(): Promise<void> {
468
469
  const now = new Date();
469
- const fileName = 'ProtocolMonitor-' + Platform.DateUtilities.toISO8601Compact(now) + '.json';
470
+ const fileName = 'ProtocolMonitor-' + Platform.DateUtilities.toISO8601Compact(now) + '.json' as
471
+ Platform.DevToolsPath.RawPathString;
470
472
  const stream = new Bindings.FileUtils.FileOutputStream();
471
473
 
472
474
  const accepted = await stream.open(fileName);
@@ -32,6 +32,7 @@ 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 SDK from '../../core/sdk/sdk.js';
35
+ import type * as Platform from '../../core/platform/platform.js';
35
36
  import * as Protocol from '../../generated/protocol.js';
36
37
  import * as UI from '../../ui/legacy/legacy.js';
37
38
 
@@ -743,7 +744,9 @@ export class ScreencastView extends UI.Widget.VBox implements SDK.OverlayModel.H
743
744
  if (match) {
744
745
  url = match[1];
745
746
  }
746
- Host.InspectorFrontendHost.InspectorFrontendHostInstance.inspectedURLChanged(url);
747
+ // TODO(crbug.com/1253323): Cast to UrlString will be removed when migration to branded types is complete.
748
+ Host.InspectorFrontendHost.InspectorFrontendHostInstance.inspectedURLChanged(
749
+ url as Platform.DevToolsPath.UrlString);
747
750
  this.navigationUrl.value = decodeURI(url);
748
751
  }
749
752
 
@@ -32,6 +32,7 @@ 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 Root from '../../core/root/root.js';
35
+ import type * as Platform from '../../core/platform/platform.js';
35
36
  import * as IconButton from '../../ui/components/icon_button/icon_button.js';
36
37
  import * as Components from '../../ui/legacy/components/utils/utils.js';
37
38
  import * as UI from '../../ui/legacy/legacy.js';
@@ -508,9 +509,11 @@ export class ActionDelegate implements UI.ActionRegistration.ActionDelegate {
508
509
  case 'settings.show':
509
510
  void SettingsScreen.showSettingsScreen({focusTabHeader: true} as ShowSettingsScreenOptions);
510
511
  return true;
512
+ // TODO(crbug.com/1253323): Cast to UrlString will be removed when migration to branded types is complete.
511
513
  case 'settings.documentation':
512
514
  Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(
513
- UI.UIUtils.addReferrerToURL('https://developer.chrome.com/docs/devtools/'));
515
+ UI.UIUtils.addReferrerToURL('https://developer.chrome.com/docs/devtools/') as
516
+ Platform.DevToolsPath.UrlString);
514
517
  return true;
515
518
  case 'settings.shortcuts':
516
519
  void SettingsScreen.showSettingsScreen({name: 'keybinds', focusTabHeader: true});
@@ -16,8 +16,7 @@
16
16
  font-family: var(--monospace-font-family);
17
17
  font-size: var(--monospace-font-size);
18
18
  align-items: center;
19
- line-height: 18px;
20
- margin-top: 3px;
19
+ line-height: 24px;
21
20
  }
22
21
 
23
22
  .row devtools-button {
@@ -57,6 +56,18 @@
57
56
  border-radius: 2px;
58
57
  }
59
58
 
59
+ .row .inline-button {
60
+ opacity: 0%;
61
+ visibility: hidden;
62
+ transition: opacity 200ms;
63
+ }
64
+
65
+ .row:focus-within .inline-button,
66
+ .row:hover .inline-button {
67
+ opacity: 100%;
68
+ visibility: visible;
69
+ }
70
+
60
71
  .center-wrapper {
61
72
  height: 100%;
62
73
  display: flex;
@@ -79,3 +90,7 @@
79
90
  line-height: 1.5em;
80
91
  color: var(--color-text-secondary);
81
92
  }
93
+
94
+ .add-block {
95
+ margin-top: 3px;
96
+ }
@@ -5,6 +5,7 @@
5
5
  import * as i18n from '../../../core/i18n/i18n.js';
6
6
  import * as Persistence from '../../../models/persistence/persistence.js';
7
7
  import * as Workspace from '../../../models/workspace/workspace.js';
8
+ import * as Buttons from '../../../ui/components/buttons/buttons.js';
8
9
  import * as ComponentHelpers from '../../../ui/components/helpers/helpers.js';
9
10
  import * as UI from '../../../ui/legacy/legacy.js';
10
11
  import * as LitHtml from '../../../ui/lit-html/lit-html.js';
@@ -12,6 +13,18 @@ import * as LitHtml from '../../../ui/lit-html/lit-html.js';
12
13
  import HeadersViewStyles from './HeadersView.css.js';
13
14
 
14
15
  const UIStrings = {
16
+ /**
17
+ *@description The title of a button that adds a field to input a header in the editor form.
18
+ */
19
+ addHeader: 'Add a header',
20
+ /**
21
+ *@description The title of a button that removes a field to input a header in the editor form.
22
+ */
23
+ removeHeader: 'Remove this header',
24
+ /**
25
+ *@description The title of a button that removes a section for defining header overrides in the editor form.
26
+ */
27
+ removeBlock: 'Remove this \'`ApplyTo`\'-section',
15
28
  /**
16
29
  *@description Error message for files which cannot not be parsed.
17
30
  *@example {.headers} PH1
@@ -23,10 +36,17 @@ const UIStrings = {
23
36
  */
24
37
  parsingErrorExplainer:
25
38
  'This is most likely due to a syntax error in \'\'{PH1}\'\'. Try opening this file in an external editor to fix the error or delete the file and re-create the override.',
39
+ /**
40
+ *@description Button text for a button which adds an additional header override.
41
+ */
42
+ addHeaderOverride: 'Add header override',
26
43
  };
27
44
  const str_ = i18n.i18n.registerUIStrings('panels/sources/components/HeadersView.ts', UIStrings);
28
45
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
29
46
 
47
+ const plusIconUrl = new URL('../../../Images/plus_icon.svg', import.meta.url).toString();
48
+ const minusIconUrl = new URL('../../../Images/minus_icon.svg', import.meta.url).toString();
49
+
30
50
  export class HeadersView extends UI.View.SimpleView {
31
51
  readonly #headersViewComponent = new HeadersViewComponent();
32
52
  #uiSourceCode: Workspace.UISourceCode.UISourceCode;
@@ -96,6 +116,10 @@ export class HeadersView extends UI.View.SimpleView {
96
116
  this.#setComponentData(this.#uiSourceCode.workingCopy());
97
117
  }
98
118
 
119
+ getComponent(): HeadersViewComponent {
120
+ return this.#headersViewComponent;
121
+ }
122
+
99
123
  dispose(): void {
100
124
  this.#uiSourceCode.removeEventListener(
101
125
  Workspace.UISourceCode.Events.WorkingCopyChanged, this.#onWorkingCopyChanged, this);
@@ -127,11 +151,13 @@ export class HeadersViewComponent extends HTMLElement {
127
151
  #headerOverrides: HeaderOverride[] = [];
128
152
  #uiSourceCode: Workspace.UISourceCode.UISourceCode|null = null;
129
153
  #parsingError = false;
154
+ #focusElement: {blockIndex: number, headerIndex?: number}|null = null;
130
155
 
131
156
  constructor() {
132
157
  super();
133
158
  this.#shadow.addEventListener('focusin', this.#onFocusIn.bind(this));
134
159
  this.#shadow.addEventListener('focusout', this.#onFocusOut.bind(this));
160
+ this.#shadow.addEventListener('click', this.#onClick.bind(this));
135
161
  this.#shadow.addEventListener('input', this.#onInput.bind(this));
136
162
  this.#shadow.addEventListener('keydown', this.#onKeyDown.bind(this));
137
163
  }
@@ -187,6 +213,43 @@ export class HeadersViewComponent extends HTMLElement {
187
213
  selection?.removeAllRanges();
188
214
  }
189
215
 
216
+ #generateNextHeaderName(headers: Header[]): string {
217
+ const takenNames = new Set<string>(headers.map(header => header.name));
218
+ let idx = 1;
219
+ while (takenNames.has('headerName' + idx)) {
220
+ idx++;
221
+ }
222
+ return 'headerName' + idx;
223
+ }
224
+
225
+ #onClick(e: Event): void {
226
+ const target = e.target as HTMLButtonElement;
227
+ const rowElement = target.closest('.row') as HTMLElement | null;
228
+ const blockIndex = Number(rowElement?.dataset.blockIndex || 0);
229
+ const headerIndex = Number(rowElement?.dataset.headerIndex || 0);
230
+ if (target.matches('.add-header')) {
231
+ this.#headerOverrides[blockIndex].headers.splice(
232
+ headerIndex + 1, 0,
233
+ {name: this.#generateNextHeaderName(this.#headerOverrides[blockIndex].headers), value: 'headerValue'});
234
+ this.#focusElement = {blockIndex, headerIndex: headerIndex + 1};
235
+ this.#onHeadersChanged();
236
+ } else if (target.matches('.remove-header')) {
237
+ this.#headerOverrides[blockIndex].headers.splice(headerIndex, 1);
238
+ if (this.#headerOverrides[blockIndex].headers.length === 0) {
239
+ this.#headerOverrides[blockIndex].headers.push(
240
+ {name: this.#generateNextHeaderName(this.#headerOverrides[blockIndex].headers), value: 'headerValue'});
241
+ }
242
+ this.#onHeadersChanged();
243
+ } else if (target.matches('.add-block')) {
244
+ this.#headerOverrides.push({applyTo: '*', headers: [{name: 'headerName', value: 'headerValue'}]});
245
+ this.#focusElement = {blockIndex: this.#headerOverrides.length - 1};
246
+ this.#onHeadersChanged();
247
+ } else if (target.matches('.remove-block')) {
248
+ this.#headerOverrides.splice(blockIndex, 1);
249
+ this.#onHeadersChanged();
250
+ }
251
+ }
252
+
190
253
  #onInput(e: Event): void {
191
254
  const target = e.target as HTMLButtonElement;
192
255
  const rowElement = target.closest('.row') as HTMLElement;
@@ -252,8 +315,25 @@ export class HeadersViewComponent extends HTMLElement {
252
315
  )}
253
316
  `,
254
317
  )}
318
+ <${Buttons.Button.Button.litTagName} .variant=${Buttons.Button.Variant.SECONDARY} class="add-block">
319
+ ${i18nString(UIStrings.addHeaderOverride)}
320
+ </${Buttons.Button.Button.litTagName}>
255
321
  `, this.#shadow, {host: this});
256
322
  // clang-format on
323
+
324
+ if (this.#focusElement) {
325
+ let focusElement: Element|null = null;
326
+ if (this.#focusElement.headerIndex) {
327
+ focusElement = this.#shadow.querySelector(`[data-block-index="${
328
+ this.#focusElement.blockIndex}"][data-header-index="${this.#focusElement.headerIndex}"] .header-name`);
329
+ } else {
330
+ focusElement = this.#shadow.querySelector(`[data-block-index="${this.#focusElement.blockIndex}"] .apply-to`);
331
+ }
332
+ if (focusElement) {
333
+ (focusElement as HTMLElement).focus();
334
+ }
335
+ this.#focusElement = null;
336
+ }
257
337
  }
258
338
 
259
339
  #renderApplyToRow(pattern: string, blockIndex: number): LitHtml.TemplateResult {
@@ -263,6 +343,13 @@ export class HeadersViewComponent extends HTMLElement {
263
343
  <div>${i18n.i18n.lockedString('Apply to')}</div>
264
344
  <div class="separator">:</div>
265
345
  ${this.#renderEditable(pattern, 'apply-to')}
346
+ <${Buttons.Button.Button.litTagName}
347
+ title=${i18nString(UIStrings.removeBlock)}
348
+ .size=${Buttons.Button.Size.SMALL}
349
+ .iconUrl=${minusIconUrl}
350
+ .variant=${Buttons.Button.Variant.ROUND}
351
+ class="remove-block inline-button"
352
+ ></${Buttons.Button.Button.litTagName}>
266
353
  </div>
267
354
  `;
268
355
  // clang-format on
@@ -275,6 +362,21 @@ export class HeadersViewComponent extends HTMLElement {
275
362
  ${this.#renderEditable(header.name, 'header-name red')}
276
363
  <div class="separator">:</div>
277
364
  ${this.#renderEditable(header.value, 'header-value')}
365
+ <${Buttons.Button.Button.litTagName}
366
+ title=${i18nString(UIStrings.addHeader)}
367
+ .size=${Buttons.Button.Size.SMALL}
368
+ .iconUrl=${plusIconUrl}
369
+ .variant=${Buttons.Button.Variant.ROUND}
370
+ class="add-header inline-button"
371
+ ></${Buttons.Button.Button.litTagName}>
372
+ <${Buttons.Button.Button.litTagName}
373
+ title=${i18nString(UIStrings.removeHeader)}
374
+ .size=${Buttons.Button.Size.SMALL}
375
+ .iconUrl=${minusIconUrl}
376
+ .variant=${Buttons.Button.Variant.ROUND}
377
+ class="remove-header inline-button"
378
+ ></${Buttons.Button.Button.litTagName}>
379
+ </div>
278
380
  `;
279
381
  // clang-format on
280
382
  }
@@ -636,7 +636,8 @@ export class TimelinePanel extends UI.Panel.Panel implements Client, TimelineMod
636
636
  }
637
637
 
638
638
  const now = new Date();
639
- const fileName = 'Profile-' + Platform.DateUtilities.toISO8601Compact(now) + '.json';
639
+ const fileName =
640
+ 'Profile-' + Platform.DateUtilities.toISO8601Compact(now) + '.json' as Platform.DevToolsPath.RawPathString;
640
641
  const stream = new Bindings.FileUtils.FileOutputStream();
641
642
 
642
643
  const accepted = await stream.open(fileName);
@@ -4,6 +4,7 @@
4
4
 
5
5
  import * as Host from '../../../core/host/host.js';
6
6
  import * as i18n from '../../../core/i18n/i18n.js';
7
+ import type * as Platform from '../../../core/platform/platform.js';
7
8
  import * as ComponentHelpers from '../../components/helpers/helpers.js';
8
9
  import * as LitHtml from '../../lit-html/lit-html.js';
9
10
  import * as Buttons from '../buttons/buttons.js';
@@ -38,7 +39,9 @@ export class FeedbackButton extends HTMLElement {
38
39
  }
39
40
 
40
41
  #onFeedbackClick(): void {
41
- Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(this.#props.feedbackUrl);
42
+ // TODO(crbug.com/1253323): Cast to UrlString will be removed when migration to branded types is complete.
43
+ Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(
44
+ this.#props.feedbackUrl as Platform.DevToolsPath.UrlString);
42
45
  }
43
46
 
44
47
  #render(): void {
@@ -2,6 +2,8 @@
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
+ // TODO(crbug.com/1253323): Casts to UrlString will be removed from this file when migration to branded types is complete.
6
+
5
7
  import * as Host from '../../core/host/host.js';
6
8
  import * as Platform from '../../core/platform/platform.js';
7
9
  import * as ComponentHelpers from '../components/helpers/helpers.js';
@@ -47,13 +49,15 @@ export class XLink extends XElement {
47
49
 
48
50
  this.onClick = (event: Event): void => {
49
51
  event.consume(true);
50
- Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab((this.hrefInternal as string));
52
+ Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(
53
+ (this.hrefInternal as Platform.DevToolsPath.UrlString));
51
54
  this.dispatchEvent(new Event('x-link-invoke'));
52
55
  };
53
56
  this.onKeyDown = (event: Event): void => {
54
57
  if (isEnterOrSpaceKey(event)) {
55
58
  event.consume(true);
56
- Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab((this.hrefInternal as string));
59
+ Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(
60
+ (this.hrefInternal as Platform.DevToolsPath.UrlString));
57
61
  }
58
62
  this.dispatchEvent(new Event('x-link-invoke'));
59
63
  };
@@ -138,7 +142,8 @@ export class ContextMenuProvider implements Provider {
138
142
  const node: XLink = targetNode;
139
143
  contextMenu.revealSection().appendItem(openLinkExternallyLabel(), () => {
140
144
  if (node.href) {
141
- Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(node.href);
145
+ Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(
146
+ node.href as Platform.DevToolsPath.UrlString);
142
147
  }
143
148
  });
144
149
  contextMenu.revealSection().appendItem(copyLinkAddressLabel(), () => {
@@ -359,8 +359,10 @@ export class ContrastDetails extends Common.ObjectWrapper.ObjectWrapper<EventTyp
359
359
  }
360
360
 
361
361
  private static showHelp(): void {
362
+ // TODO(crbug.com/1253323): Cast to UrlString will be removed when migration to branded types is complete.
362
363
  Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(
363
- UI.UIUtils.addReferrerToURL('https://web.dev/color-and-contrast-accessibility/'));
364
+ UI.UIUtils.addReferrerToURL('https://web.dev/color-and-contrast-accessibility/') as
365
+ Platform.DevToolsPath.UrlString);
364
366
  }
365
367
 
366
368
  setVisible(visible: boolean): void {
@@ -2,6 +2,8 @@
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
+ // TODO(crbug.com/1253323): Casts to UrlString will be removed from this file when migration to branded types is complete.
6
+
5
7
  import * as Common from '../../../../core/common/common.js';
6
8
  import * as Host from '../../../../core/host/host.js';
7
9
  import * as i18n from '../../../../core/i18n/i18n.js';
@@ -113,7 +115,8 @@ export class ImagePreview {
113
115
 
114
116
  // Open image in new tab.
115
117
  link.addEventListener('click', () => {
116
- Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(imageURL);
118
+ Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(
119
+ imageURL as Platform.DevToolsPath.UrlString);
117
120
  });
118
121
 
119
122
  const intrinsicWidth = imageElement.naturalWidth;
@@ -158,7 +161,8 @@ export class ImagePreview {
158
161
  HTMLLinkElement);
159
162
  sourceLink.textContent = sourceText;
160
163
  sourceLink.addEventListener('click', () => {
161
- Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(imageURL);
164
+ Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(
165
+ imageURL as Platform.DevToolsPath.UrlString);
162
166
  });
163
167
  resolve(shadowBoundary);
164
168
  }
@@ -31,6 +31,7 @@
31
31
  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
+ import type * as Platform from '../../../../core/platform/platform.js';
34
35
  import * as SDK from '../../../../core/sdk/sdk.js';
35
36
  import * as Bindings from '../../../../models/bindings/bindings.js';
36
37
  import * as TextUtils from '../../../../models/text_utils/text_utils.js';
@@ -749,10 +750,12 @@ export class Linkifier implements SDK.TargetManager.Observer {
749
750
  }
750
751
  }
751
752
  if (resource || info.url) {
753
+ // TODO(crbug.com/1253323): Cast to UrlString will be removed when migration to branded types is complete.
752
754
  result.push({
753
755
  section: 'reveal',
754
756
  title: UI.UIUtils.openLinkExternallyLabel(),
755
- handler: (): void => Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(url),
757
+ handler: (): void => Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(
758
+ url as Platform.DevToolsPath.UrlString),
756
759
  });
757
760
  result.push({
758
761
  section: 'clipboard',
@@ -916,7 +919,9 @@ export class ContentProviderContextMenuProvider implements UI.ContextMenu.Provid
916
919
  contextMenu.revealSection().appendItem(
917
920
  UI.UIUtils.openLinkExternallyLabel(),
918
921
  () => Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(
919
- contentUrl.endsWith(':formatted') ? contentUrl.slice(0, contentUrl.lastIndexOf(':')) : contentUrl));
922
+ contentUrl.endsWith(':formatted') ?
923
+ Common.ParsedURL.ParsedURL.slice(contentUrl, 0, contentUrl.lastIndexOf(':')) :
924
+ contentUrl));
920
925
  for (const title of linkHandlers.keys()) {
921
926
  const handler = linkHandlers.get(title);
922
927
  if (!handler) {
@@ -98,6 +98,7 @@
98
98
  pointer-events: none;
99
99
  margin-left: 0;
100
100
  position: relative;
101
+ cursor: default;
101
102
  }
102
103
 
103
104
  .tabbed-pane-header-contents > * {
package/package.json CHANGED
@@ -54,5 +54,5 @@
54
54
  "unittest": "scripts/test/run_unittests.py --no-text-coverage",
55
55
  "watch": "third_party/node/node.py --output scripts/watch_build.js"
56
56
  },
57
- "version": "1.0.981537"
57
+ "version": "1.0.982087"
58
58
  }