chrome-devtools-frontend 1.0.971140 → 1.0.973253

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 (107) hide show
  1. package/config/gni/devtools_grd_files.gni +10 -8
  2. package/front_end/core/common/ParsedURL.ts +9 -3
  3. package/front_end/core/host/UserMetrics.ts +2 -1
  4. package/front_end/core/i18n/locales/en-US.json +24 -0
  5. package/front_end/core/i18n/locales/en-XL.json +24 -0
  6. package/front_end/core/sdk/CSSModel.ts +21 -0
  7. package/front_end/core/sdk/CSSStyleSheetHeader.ts +10 -10
  8. package/front_end/core/sdk/CompilerSourceMappingContentProvider.ts +6 -4
  9. package/front_end/core/sdk/DOMDebuggerModel.ts +4 -3
  10. package/front_end/core/sdk/DebuggerModel.ts +17 -16
  11. package/front_end/core/sdk/NetworkManager.ts +17 -9
  12. package/front_end/core/sdk/NetworkRequest.ts +18 -16
  13. package/front_end/core/sdk/Resource.ts +10 -10
  14. package/front_end/core/sdk/ResourceTreeModel.ts +16 -13
  15. package/front_end/core/sdk/Script.ts +10 -10
  16. package/front_end/core/sdk/SourceMap.ts +8 -6
  17. package/front_end/entrypoints/lighthouse_worker/{LighthouseService.ts → LighthouseWorkerService.ts} +69 -38
  18. package/front_end/entrypoints/lighthouse_worker/lighthouse_worker.ts +1 -1
  19. package/front_end/entrypoints/main/MainImpl.ts +5 -0
  20. package/front_end/generated/InspectorBackendCommands.js +14 -8
  21. package/front_end/generated/SupportedCSSProperties.js +2 -0
  22. package/front_end/generated/protocol-mapping.d.ts +5 -0
  23. package/front_end/generated/protocol-proxy-api.d.ts +5 -0
  24. package/front_end/generated/protocol.ts +20 -12
  25. package/front_end/models/bindings/BreakpointManager.ts +7 -5
  26. package/front_end/models/bindings/CSSWorkspaceBinding.ts +2 -16
  27. package/front_end/models/bindings/DebuggerLanguagePlugins.ts +2 -1
  28. package/front_end/models/bindings/ResourceMapping.ts +2 -1
  29. package/front_end/models/bindings/ResourceScriptMapping.ts +2 -1
  30. package/front_end/models/bindings/SASSSourceMapping.ts +4 -3
  31. package/front_end/models/bindings/StylesSourceMapping.ts +2 -1
  32. package/front_end/models/har/HARFormat.ts +4 -2
  33. package/front_end/models/har/Importer.ts +0 -1
  34. package/front_end/models/issues_manager/FederatedAuthRequestIssue.ts +12 -12
  35. package/front_end/models/issues_manager/descriptions/{federatedAuthRequestClientIdMetadataHttpNotFound.md → federatedAuthRequestClientMetadataHttpNotFound.md} +0 -0
  36. package/front_end/models/issues_manager/descriptions/{federatedAuthRequestClientIdMetadataInvalidResponse.md → federatedAuthRequestClientMetadataInvalidResponse.md} +0 -0
  37. package/front_end/models/issues_manager/descriptions/{federatedAuthRequestClientIdMetadataNoResponse.md → federatedAuthRequestClientMetadataNoResponse.md} +0 -0
  38. package/front_end/models/issues_manager/descriptions/federatedAuthRequestManifestHttpNotFound.md +1 -0
  39. package/front_end/models/issues_manager/descriptions/federatedAuthRequestManifestInvalidResponse.md +1 -0
  40. package/front_end/models/issues_manager/descriptions/federatedAuthRequestManifestNoResponse.md +1 -0
  41. package/front_end/models/persistence/FileSystemWorkspaceBinding.ts +5 -5
  42. package/front_end/models/persistence/IsolatedFileSystem.ts +10 -13
  43. package/front_end/models/persistence/PersistenceActions.ts +1 -4
  44. package/front_end/models/persistence/PlatformFileSystem.ts +3 -3
  45. package/front_end/{panels/sources/SourceMapNamesResolver.ts → models/source_map_scopes/NamesResolver.ts} +5 -5
  46. package/front_end/models/source_map_scopes/source_map_scopes.ts +7 -0
  47. package/front_end/models/text_utils/ContentProvider.ts +2 -1
  48. package/front_end/models/text_utils/StaticContentProvider.ts +7 -5
  49. package/front_end/models/workspace/UISourceCode.ts +7 -7
  50. package/front_end/models/workspace/WorkspaceImpl.ts +1 -3
  51. package/front_end/models/workspace_diff/WorkspaceDiff.ts +20 -8
  52. package/front_end/panels/application/ServiceWorkerCacheViews.ts +3 -2
  53. package/front_end/panels/changes/ChangesView.ts +4 -4
  54. package/front_end/panels/console/ConsolePrompt.ts +25 -2
  55. package/front_end/panels/console/ConsoleViewMessage.ts +41 -8
  56. package/front_end/panels/coverage/CoverageModel.ts +1 -1
  57. package/front_end/panels/elements/ElementsTreeElement.ts +0 -6
  58. package/front_end/panels/elements/StylesSidebarPane.ts +43 -33
  59. package/front_end/panels/elements/components/LayoutPane.ts +1 -1
  60. package/front_end/panels/issues/AffectedResourcesView.ts +1 -1
  61. package/front_end/panels/issues/AffectedSourcesView.ts +1 -1
  62. package/front_end/panels/lighthouse/LighthouseController.ts +13 -2
  63. package/front_end/panels/lighthouse/LighthousePanel.ts +57 -8
  64. package/front_end/panels/lighthouse/LighthouseProtocolService.ts +94 -30
  65. package/front_end/panels/lighthouse/LighthouseReportRenderer.ts +0 -5
  66. package/front_end/panels/lighthouse/LighthouseStartView.ts +6 -2
  67. package/front_end/panels/lighthouse/LighthouseStartViewFR.ts +61 -0
  68. package/front_end/panels/lighthouse/LighthouseTimespanView.ts +99 -0
  69. package/front_end/panels/network/NetworkDataGridNode.ts +1 -1
  70. package/front_end/panels/profiler/CPUProfileView.ts +1 -1
  71. package/front_end/panels/profiler/HeapProfileView.ts +0 -2
  72. package/front_end/panels/profiler/HeapSnapshotGridNodes.ts +0 -1
  73. package/front_end/panels/profiler/HeapSnapshotView.ts +2 -3
  74. package/front_end/panels/snippets/ScriptSnippetFileSystem.ts +1 -1
  75. package/front_end/panels/sources/DebuggerPlugin.ts +5 -4
  76. package/front_end/panels/sources/NavigatorView.ts +5 -5
  77. package/front_end/panels/sources/ScopeChainSidebarPane.ts +6 -3
  78. package/front_end/panels/sources/SourcesNavigator.ts +7 -1
  79. package/front_end/panels/sources/sources-legacy.ts +5 -3
  80. package/front_end/panels/sources/sources.ts +0 -2
  81. package/front_end/panels/timeline/TimelineUIUtils.ts +4 -47
  82. package/front_end/third_party/codemirror.next/bundle.ts +1 -1
  83. package/front_end/third_party/codemirror.next/chunk/codemirror.js +1 -1
  84. package/front_end/third_party/codemirror.next/chunk/json.js +2 -1
  85. package/front_end/third_party/codemirror.next/codemirror.next.d.ts +28 -2
  86. package/front_end/third_party/codemirror.next/codemirror.next.js +1 -1
  87. package/front_end/third_party/codemirror.next/package.json +10 -10
  88. package/front_end/third_party/lighthouse/lighthouse-dt-bundle.js +1047 -1158
  89. package/front_end/third_party/lighthouse/locales/en-US.json +7 -1
  90. package/front_end/third_party/lighthouse/locales/en-XL.json +7 -1
  91. package/front_end/third_party/lighthouse/report/bundle.d.ts +0 -3
  92. package/front_end/third_party/lighthouse/report/bundle.js +38 -24
  93. package/front_end/third_party/lighthouse/report-assets/report-generator.mjs +1 -1
  94. package/front_end/ui/components/expandable_list/expandableList.css +1 -1
  95. package/front_end/ui/components/text_editor/config.ts +1 -0
  96. package/front_end/ui/legacy/ViewManager.ts +2 -1
  97. package/front_end/ui/legacy/components/source_frame/BinaryResourceViewFactory.ts +7 -4
  98. package/front_end/ui/legacy/components/source_frame/FontView.ts +1 -1
  99. package/front_end/ui/legacy/components/source_frame/ImageView.ts +1 -1
  100. package/front_end/ui/legacy/components/utils/JSPresentationUtils.ts +2 -3
  101. package/front_end/ui/legacy/components/utils/Linkifier.ts +20 -59
  102. package/front_end/ui/legacy/tabbedPane.css +1 -0
  103. package/package.json +1 -1
  104. package/scripts/hosted_mode/server.js +13 -0
  105. package/front_end/models/issues_manager/descriptions/federatedAuthRequestWellKnownHttpNotFound.md +0 -1
  106. package/front_end/models/issues_manager/descriptions/federatedAuthRequestWellKnownInvalidResponse.md +0 -1
  107. package/front_end/models/issues_manager/descriptions/federatedAuthRequestWellKnownNoResponse.md +0 -1
@@ -14,6 +14,7 @@ import * as Emulation from '../emulation/emulation.js';
14
14
  import type {AuditProgressChangedEvent, PageAuditabilityChangedEvent, PageWarningsChangedEvent} from './LighthouseController.js';
15
15
  import {Events, LighthouseController} from './LighthouseController.js';
16
16
  import lighthousePanelStyles from './lighthousePanel.css.js';
17
+ import type {LighthouseRun} from './LighthouseProtocolService.js';
17
18
  import {ProtocolService} from './LighthouseProtocolService.js';
18
19
 
19
20
  import type {ReportJSON, RunnerResultArtifacts} from './LighthouseReporterTypes.js';
@@ -23,6 +24,7 @@ import {Item, ReportSelector} from './LighthouseReportSelector.js';
23
24
  import {StartView} from './LighthouseStartView.js';
24
25
  import {StartViewFR} from './LighthouseStartViewFR.js';
25
26
  import {StatusView} from './LighthouseStatusView.js';
27
+ import {TimespanView} from './LighthouseTimespanView.js';
26
28
 
27
29
  const UIStrings = {
28
30
  /**
@@ -65,6 +67,7 @@ export class LighthousePanel extends UI.Panel.Panel {
65
67
  private readonly controller: LighthouseController;
66
68
  private readonly startView: StartView;
67
69
  private readonly statusView: StatusView;
70
+ private readonly timespanView: TimespanView|null;
68
71
  private warningText: Nullable<string>;
69
72
  private unauditableExplanation: Nullable<string>;
70
73
  private readonly cachedRenderedReports: Map<ReportJSON, HTMLElement>;
@@ -81,6 +84,7 @@ export class LighthousePanel extends UI.Panel.Panel {
81
84
  network: {conditions: SDK.NetworkManager.Conditions},
82
85
  };
83
86
  private isLHAttached?: boolean;
87
+ private currentLighthouseRun?: LighthouseRun;
84
88
 
85
89
  private constructor() {
86
90
  super('lighthouse');
@@ -89,8 +93,10 @@ export class LighthousePanel extends UI.Panel.Panel {
89
93
  this.controller = new LighthouseController(this.protocolService);
90
94
  if (Root.Runtime.experiments.isEnabled('lighthousePanelFR')) {
91
95
  this.startView = new StartViewFR(this.controller);
96
+ this.timespanView = new TimespanView(this.controller);
92
97
  } else {
93
98
  this.startView = new StartView(this.controller);
99
+ this.timespanView = null;
94
100
  }
95
101
  this.statusView = new StatusView(this.controller);
96
102
 
@@ -105,12 +111,10 @@ export class LighthousePanel extends UI.Panel.Panel {
105
111
  this.controller.addEventListener(Events.PageAuditabilityChanged, this.refreshStartAuditUI.bind(this));
106
112
  this.controller.addEventListener(Events.PageWarningsChanged, this.refreshWarningsUI.bind(this));
107
113
  this.controller.addEventListener(Events.AuditProgressChanged, this.refreshStatusUI.bind(this));
108
- this.controller.addEventListener(Events.RequestLighthouseStart, _event => {
109
- void this.startLighthouse();
110
- });
111
- this.controller.addEventListener(Events.RequestLighthouseCancel, _event => {
112
- void this.cancelLighthouse();
113
- });
114
+ this.controller.addEventListener(Events.RequestLighthouseTimespanStart, this.onLighthouseTimespanStart.bind(this));
115
+ this.controller.addEventListener(Events.RequestLighthouseTimespanEnd, this.onLighthouseTimespanEnd.bind(this));
116
+ this.controller.addEventListener(Events.RequestLighthouseStart, this.onLighthouseStart.bind(this));
117
+ this.controller.addEventListener(Events.RequestLighthouseCancel, this.onLighthouseCancel.bind(this));
114
118
 
115
119
  this.renderToolbar();
116
120
  this.auditResultsElement = this.contentElement.createChild('div', 'lighthouse-results-container');
@@ -132,6 +136,27 @@ export class LighthousePanel extends UI.Panel.Panel {
132
136
  return Events;
133
137
  }
134
138
 
139
+ private async onLighthouseTimespanStart(): Promise<void> {
140
+ this.timespanView?.show(this.contentElement);
141
+ await this.startLighthouse();
142
+ this.timespanView?.ready();
143
+ }
144
+
145
+ private async onLighthouseTimespanEnd(): Promise<void> {
146
+ this.timespanView?.hide();
147
+ await this.collectLighthouseResults();
148
+ }
149
+
150
+ private async onLighthouseStart(): Promise<void> {
151
+ await this.startLighthouse();
152
+ await this.collectLighthouseResults();
153
+ }
154
+
155
+ private async onLighthouseCancel(): Promise<void> {
156
+ this.timespanView?.hide();
157
+ void this.cancelLighthouse();
158
+ }
159
+
135
160
  private refreshWarningsUI(evt: Common.EventTarget.EventTargetEvent<PageWarningsChangedEvent>): void {
136
161
  // PageWarningsChanged fires multiple times during an audit, which we want to ignore.
137
162
  if (this.isLHAttached) {
@@ -148,6 +173,8 @@ export class LighthousePanel extends UI.Panel.Panel {
148
173
  return;
149
174
  }
150
175
 
176
+ this.startView.updateStartButton();
177
+
151
178
  this.unauditableExplanation = evt.data.helpText;
152
179
  this.startView.setUnauditableExplanation(evt.data.helpText);
153
180
  this.startView.setStartButtonEnabled(!evt.data.helpText);
@@ -348,11 +375,30 @@ export class LighthousePanel extends UI.Panel.Panel {
348
375
  const categoryIDs = this.controller.getCategoryIDs();
349
376
  const flags = this.controller.getFlags();
350
377
 
378
+ this.currentLighthouseRun = {inspectedURL, categoryIDs, flags};
379
+
351
380
  await this.setupEmulationAndProtocolConnection();
352
381
 
353
- this.renderStatusView(inspectedURL);
382
+ if (flags.mode === 'timespan') {
383
+ await this.protocolService.startTimespan(this.currentLighthouseRun);
384
+ }
385
+
386
+ } catch (err) {
387
+ await this.resetEmulationAndProtocolConnection();
388
+ if (err instanceof Error) {
389
+ this.statusView.renderBugReport(err);
390
+ }
391
+ }
392
+ }
393
+
394
+ private async collectLighthouseResults(): Promise<void> {
395
+ try {
396
+ if (!this.currentLighthouseRun) {
397
+ throw new Error('Lighthouse is not started');
398
+ }
399
+ this.renderStatusView(this.currentLighthouseRun.inspectedURL);
354
400
 
355
- const lighthouseResponse = await this.protocolService.startLighthouse(inspectedURL, categoryIDs, flags);
401
+ const lighthouseResponse = await this.protocolService.collectLighthouseResults(this.currentLighthouseRun);
356
402
 
357
403
  if (lighthouseResponse && lighthouseResponse.fatal) {
358
404
  const error = new Error(lighthouseResponse.message);
@@ -375,10 +421,13 @@ export class LighthousePanel extends UI.Panel.Panel {
375
421
  if (err instanceof Error) {
376
422
  this.statusView.renderBugReport(err);
377
423
  }
424
+ } finally {
425
+ this.currentLighthouseRun = undefined;
378
426
  }
379
427
  }
380
428
 
381
429
  private async cancelLighthouse(): Promise<void> {
430
+ this.currentLighthouseRun = undefined;
382
431
  this.statusView.updateStatus(i18nString(UIStrings.cancelling));
383
432
  await this.resetEmulationAndProtocolConnection();
384
433
  this.renderStartView();
@@ -8,15 +8,58 @@ import * as SDK from '../../core/sdk/sdk.js';
8
8
 
9
9
  import type * as ReportRenderer from './LighthouseReporterTypes.js';
10
10
 
11
+ /**
12
+ * @overview
13
+ ┌────────────┐
14
+ │CDP Backend │
15
+ └────────────┘
16
+ │ ▲
17
+ │ │ parallelConnection
18
+ ┌┐ ▼ │ ┌┐
19
+ ││ dispatchProtocolMessage sendProtocolMessage ││
20
+ ││ │ ▲ ││
21
+ ProtocolService ││ | │ ││
22
+ ││ sendWithResponse ▼ │ ││
23
+ ││ │ send onWorkerMessage ││
24
+ └┘ │ │ ▲ └┘
25
+ worker boundary - - - - - - - - ┼ - -│- - - - - - - - -│- - - - - - - - - - - -
26
+ ┌┐ ▼ ▼ │ ┌┐
27
+ ││ onFrontendMessage notifyFrontendViaWorkerMessage ││
28
+ ││ │ ▲ ││
29
+ ││ ▼ │ ││
30
+ LighthouseWorkerService ││ Either ConnectionProxy or LegacyPort ││
31
+ ││ │ ▲ ││
32
+ ││ ┌─────────────────────┼─┼───────────────────────┐ ││
33
+ ││ │ Lighthouse ┌────▼──────┐ │ ││
34
+ ││ │ │connection │ │ ││
35
+ ││ │ └───────────┘ │ ││
36
+ └┘ └───────────────────────────────────────────────┘ └┘
37
+
38
+ * All messages traversing the worker boundary are action-wrapped.
39
+ * All messages over the parallelConnection speak pure CDP.
40
+ * All messages within ConnectionProxy/LegacyPort speak pure CDP.
41
+ * The foundational CDP connection is `parallelConnection`.
42
+ * All connections within the worker are not actual ParallelConnection's.
43
+ */
44
+
11
45
  let lastId = 1;
12
46
 
47
+ export interface LighthouseRun {
48
+ inspectedURL: string;
49
+ categoryIDs: string[];
50
+ flags: Record<string, Object|undefined>;
51
+ }
52
+
53
+ /**
54
+ * ProtocolService manages a connection between the frontend (Lighthouse panel) and the Lighthouse worker.
55
+ */
13
56
  export class ProtocolService {
14
57
  private targetInfo?: {
15
58
  mainSessionId: string,
16
59
  mainTargetId: string,
17
60
  mainFrameId: string,
18
61
  };
19
- private rawConnection?: ProtocolClient.InspectorBackend.Connection;
62
+ private parallelConnection?: ProtocolClient.InspectorBackend.Connection;
20
63
  private lighthouseWorkerPromise?: Promise<Worker>;
21
64
  private lighthouseMessageUpdateCallback?: ((arg0: string) => void);
22
65
 
@@ -46,7 +89,7 @@ export class ProtocolService {
46
89
  this.dispatchProtocolMessage(message);
47
90
  });
48
91
 
49
- this.rawConnection = connection;
92
+ this.parallelConnection = connection;
50
93
  this.targetInfo = {
51
94
  mainTargetId: await childTargetManager.getParentTargetId(),
52
95
  mainFrameId: mainFrame.id,
@@ -58,19 +101,36 @@ export class ProtocolService {
58
101
  return [i18n.DevToolsLocale.DevToolsLocale.instance().locale];
59
102
  }
60
103
 
61
- async startLighthouse(auditURL: string, categoryIDs: string[], flags: Record<string, Object|undefined>):
62
- Promise<ReportRenderer.RunnerResult> {
104
+ async startTimespan(currentLighthouseRun: LighthouseRun): Promise<void> {
105
+ const {inspectedURL, categoryIDs, flags} = currentLighthouseRun;
106
+
107
+ if (!this.targetInfo) {
108
+ throw new Error('Unable to get target info required for Lighthouse');
109
+ }
110
+
111
+ await this.sendWithResponse('startTimespan', {
112
+ url: inspectedURL,
113
+ categoryIDs,
114
+ flags,
115
+ locales: this.getLocales(),
116
+ target: this.targetInfo,
117
+ });
118
+ }
119
+
120
+ async collectLighthouseResults(currentLighthouseRun: LighthouseRun): Promise<ReportRenderer.RunnerResult> {
121
+ const {inspectedURL, categoryIDs, flags} = currentLighthouseRun;
122
+
63
123
  if (!this.targetInfo) {
64
124
  throw new Error('Unable to get target info required for Lighthouse');
65
125
  }
66
126
 
67
127
  let mode = flags.mode as string;
68
- if (mode === 'navigation' && flags.legacyNavigation) {
69
- mode = 'legacyNavigation';
128
+ if (mode === 'timespan') {
129
+ mode = 'endTimespan';
70
130
  }
71
131
 
72
132
  return this.sendWithResponse(mode, {
73
- url: auditURL,
133
+ url: inspectedURL,
74
134
  categoryIDs,
75
135
  flags,
76
136
  locales: this.getLocales(),
@@ -80,20 +140,20 @@ export class ProtocolService {
80
140
 
81
141
  async detach(): Promise<void> {
82
142
  const oldLighthouseWorker = this.lighthouseWorkerPromise;
83
- const oldRawConnection = this.rawConnection;
143
+ const oldParallelConnection = this.parallelConnection;
84
144
 
85
145
  // When detaching, make sure that we remove the old promises, before we
86
146
  // perform any async cleanups. That way, if there is a message coming from
87
147
  // lighthouse while we are in the process of cleaning up, we shouldn't deliver
88
148
  // them to the backend.
89
149
  this.lighthouseWorkerPromise = undefined;
90
- this.rawConnection = undefined;
150
+ this.parallelConnection = undefined;
91
151
 
92
152
  if (oldLighthouseWorker) {
93
153
  (await oldLighthouseWorker).terminate();
94
154
  }
95
- if (oldRawConnection) {
96
- await oldRawConnection.disconnect();
155
+ if (oldParallelConnection) {
156
+ await oldParallelConnection.disconnect();
97
157
  }
98
158
  await SDK.TargetManager.TargetManager.instance().resumeAllTargets();
99
159
  }
@@ -117,7 +177,7 @@ export class ProtocolService {
117
177
  method?: string,
118
178
  };
119
179
  if (protocolMessage.sessionId || (protocolMessage.method && protocolMessage.method.startsWith('Target'))) {
120
- void this.sendWithoutResponse('dispatchProtocolMessage', {message: JSON.stringify(message)});
180
+ void this.send('dispatchProtocolMessage', {message: JSON.stringify(message)});
121
181
  }
122
182
  }
123
183
 
@@ -137,18 +197,7 @@ export class ProtocolService {
137
197
  return;
138
198
  }
139
199
 
140
- const lighthouseMessage = JSON.parse(event.data);
141
-
142
- if (lighthouseMessage.method === 'statusUpdate') {
143
- if (this.lighthouseMessageUpdateCallback && lighthouseMessage.params &&
144
- 'message' in lighthouseMessage.params) {
145
- this.lighthouseMessageUpdateCallback(lighthouseMessage.params.message as string);
146
- }
147
- } else if (lighthouseMessage.method === 'sendProtocolMessage') {
148
- if (lighthouseMessage.params && 'message' in lighthouseMessage.params) {
149
- this.sendProtocolMessage(lighthouseMessage.params.message as string);
150
- }
151
- }
200
+ this.onWorkerMessage(event);
152
201
  });
153
202
  });
154
203
  return this.lighthouseWorkerPromise;
@@ -164,19 +213,34 @@ export class ProtocolService {
164
213
  return worker;
165
214
  }
166
215
 
216
+ private onWorkerMessage(event: MessageEvent): void {
217
+ const lighthouseMessage = JSON.parse(event.data);
218
+
219
+ if (lighthouseMessage.action === 'statusUpdate') {
220
+ if (this.lighthouseMessageUpdateCallback && lighthouseMessage.args && 'message' in lighthouseMessage.args) {
221
+ this.lighthouseMessageUpdateCallback(lighthouseMessage.args.message as string);
222
+ }
223
+ } else if (lighthouseMessage.action === 'sendProtocolMessage') {
224
+ if (lighthouseMessage.args && 'message' in lighthouseMessage.args) {
225
+ this.sendProtocolMessage(lighthouseMessage.args.message as string);
226
+ }
227
+ }
228
+ }
229
+
167
230
  private sendProtocolMessage(message: string): void {
168
- if (this.rawConnection) {
169
- this.rawConnection.sendRawMessage(message);
231
+ if (this.parallelConnection) {
232
+ this.parallelConnection.sendRawMessage(message);
170
233
  }
171
234
  }
172
235
 
173
- private async sendWithoutResponse(method: string, params: {[x: string]: string|string[]|Object} = {}): Promise<void> {
236
+ private async send(action: string, args: {[x: string]: string|string[]|Object} = {}): Promise<void> {
174
237
  const worker = await this.ensureWorkerExists();
175
238
  const messageId = lastId++;
176
- worker.postMessage(JSON.stringify({id: messageId, method, params: {...params, id: messageId}}));
239
+ worker.postMessage(JSON.stringify({id: messageId, action, args: {...args, id: messageId}}));
177
240
  }
178
241
 
179
- private async sendWithResponse(method: string, params: {[x: string]: string|string[]|Object} = {}):
242
+ /** sendWithResponse currently only handles the original startLighthouse request and LHR-filled response. */
243
+ private async sendWithResponse(action: string, args: {[x: string]: string|string[]|Object} = {}):
180
244
  Promise<ReportRenderer.RunnerResult> {
181
245
  const worker = await this.ensureWorkerExists();
182
246
  const messageId = lastId++;
@@ -191,7 +255,7 @@ export class ProtocolService {
191
255
  };
192
256
  worker.addEventListener('message', workerListener);
193
257
  });
194
- worker.postMessage(JSON.stringify({id: messageId, method, params: {...params, id: messageId}}));
258
+ worker.postMessage(JSON.stringify({id: messageId, action, args: {...args, id: messageId}}));
195
259
 
196
260
  return messageResult;
197
261
  }
@@ -127,11 +127,6 @@ export class LighthouseReportRenderer extends LighthouseReport.ReportRenderer {
127
127
  showColumnNumber: false,
128
128
  inlineFrameIndex: 0,
129
129
  maxLength: MaxLengthForLinks,
130
- bypassURLTrimming: undefined,
131
- className: undefined,
132
- preventClick: undefined,
133
- tabStop: undefined,
134
- text: undefined,
135
130
  });
136
131
  UI.Tooltip.Tooltip.install(origHTMLElement, '');
137
132
  origHTMLElement.textContent = '';
@@ -41,9 +41,9 @@ const UIStrings = {
41
41
  const str_ = i18n.i18n.registerUIStrings('panels/lighthouse/LighthouseStartView.ts', UIStrings);
42
42
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
43
43
  export class StartView extends UI.Widget.Widget {
44
- private controller: LighthouseController;
44
+ protected controller: LighthouseController;
45
45
  private readonly settingsToolbarInternal: UI.Toolbar.Toolbar;
46
- private startButton!: HTMLButtonElement;
46
+ protected startButton!: HTMLButtonElement;
47
47
  private helpText?: Element;
48
48
  private warningText?: Element;
49
49
  private shouldConfirm?: boolean;
@@ -173,6 +173,10 @@ export class StartView extends UI.Widget.Widget {
173
173
  this.contentElement.style.overflow = 'auto';
174
174
  }
175
175
 
176
+ updateStartButton(): void {
177
+ // Do nothing in default case.
178
+ }
179
+
176
180
  onResize(): void {
177
181
  const useNarrowLayout = this.contentElement.offsetWidth < 560;
178
182
  const startViewEl = this.contentElement.querySelector('.lighthouse-start-view');
@@ -4,14 +4,28 @@
4
4
 
5
5
  import * as i18n from '../../core/i18n/i18n.js';
6
6
  import * as UI from '../../ui/legacy/legacy.js';
7
+ import type * as Platform from '../../core/platform/platform.js';
7
8
 
8
9
  import {StartView} from './LighthouseStartView.js';
10
+ import {Events} from './LighthouseController.js';
9
11
 
10
12
  const UIStrings = {
11
13
  /**
12
14
  * @description Text that refers to the Lighthouse mode
13
15
  */
14
16
  mode: 'Mode',
17
+ /**
18
+ * @description Label for a button to start analyzing a page navigation with Lighthouse
19
+ */
20
+ analyzeNavigation: 'Analyze navigation',
21
+ /**
22
+ * @description Label for a button to start analyzing the current page state with Lighthouse
23
+ */
24
+ analyzeSnapshot: 'Analyze snapshot',
25
+ /**
26
+ * @description Label for a button that ends a Lighthouse timespan
27
+ */
28
+ startTimespan: 'Start timespan',
15
29
  };
16
30
 
17
31
  const str_ = i18n.i18n.registerUIStrings('panels/lighthouse/LighthouseStartViewFR.ts', UIStrings);
@@ -35,5 +49,52 @@ export class StartViewFR extends StartView {
35
49
 
36
50
  const form = this.contentElement.querySelector('form');
37
51
  form?.appendChild(fragment.element());
52
+ this.updateStartButton();
53
+ }
54
+
55
+ updateStartButton(): void {
56
+ const {mode} = this.controller.getFlags();
57
+
58
+ let label: Platform.UIString.LocalizedString;
59
+ let callback: () => void;
60
+
61
+ if (mode === 'timespan') {
62
+ label = i18nString(UIStrings.startTimespan);
63
+ callback = (): void => {
64
+ this.controller.dispatchEventToListeners(
65
+ Events.RequestLighthouseTimespanStart,
66
+ /* keyboardInitiated */ this.startButton.matches(':focus-visible'),
67
+ );
68
+ };
69
+ } else if (mode === 'snapshot') {
70
+ label = i18nString(UIStrings.analyzeSnapshot);
71
+ callback = (): void => {
72
+ this.controller.dispatchEventToListeners(
73
+ Events.RequestLighthouseStart,
74
+ /* keyboardInitiated */ this.startButton.matches(':focus-visible'),
75
+ );
76
+ };
77
+ } else {
78
+ label = i18nString(UIStrings.analyzeNavigation);
79
+ callback = (): void => {
80
+ this.controller.dispatchEventToListeners(
81
+ Events.RequestLighthouseStart,
82
+ /* keyboardInitiated */ this.startButton.matches(':focus-visible'),
83
+ );
84
+ };
85
+ }
86
+
87
+ this.startButton = UI.UIUtils.createTextButton(
88
+ label,
89
+ callback,
90
+ /* className */ '',
91
+ /* primary */ true,
92
+ );
93
+
94
+ const startButtonContainer = this.contentElement.querySelector('.lighthouse-start-button-container');
95
+ if (startButtonContainer) {
96
+ startButtonContainer.textContent = '';
97
+ startButtonContainer.appendChild(this.startButton);
98
+ }
38
99
  }
39
100
  }
@@ -0,0 +1,99 @@
1
+ // Copyright 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 UI from '../../ui/legacy/legacy.js';
7
+
8
+ import type {LighthouseController} from './LighthouseController.js';
9
+ import {Events} from './LighthouseController.js';
10
+ import lighthouseDialogStyles from './lighthouseDialog.css.js';
11
+
12
+ const UIStrings = {
13
+ /**
14
+ * @description Header indicating that a Lighthouse timespan is starting.
15
+ */
16
+ timespanStarting: 'Timespan starting…',
17
+ /**
18
+ * @description Header indicating that a Lighthouse timespan has started.
19
+ */
20
+ timespanStarted: 'Timespan started, interact with the page',
21
+ /**
22
+ * @description Label for a button that ends a Lighthouse timespan.
23
+ */
24
+ endTimespan: 'End timespan',
25
+ /**
26
+ * @description Label for a button that cancels a Lighthouse timespan.
27
+ */
28
+ cancel: 'Cancel',
29
+ };
30
+
31
+ const str_ = i18n.i18n.registerUIStrings('panels/lighthouse/LighthouseTimespanView.ts', UIStrings);
32
+ const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
33
+
34
+ export class TimespanView extends UI.Dialog.Dialog {
35
+ private controller: LighthouseController;
36
+ private statusHeader: Element|null;
37
+ private endButton: HTMLButtonElement|null;
38
+
39
+ constructor(controller: LighthouseController) {
40
+ super();
41
+ this.controller = controller;
42
+ this.statusHeader = null;
43
+ this.endButton = null;
44
+ this.setDimmed(true);
45
+ this.setCloseOnEscape(false);
46
+ this.setOutsideClickCallback(event => event.consume(true));
47
+ this.render();
48
+ }
49
+
50
+ show(dialogRenderElement: Element): void {
51
+ this.reset();
52
+ super.show(dialogRenderElement);
53
+ }
54
+
55
+ reset(): void {
56
+ if (this.statusHeader && this.endButton) {
57
+ this.statusHeader.textContent = i18nString(UIStrings.timespanStarting);
58
+ this.endButton.disabled = true;
59
+ }
60
+ }
61
+
62
+ ready(): void {
63
+ if (this.statusHeader && this.endButton) {
64
+ this.statusHeader.textContent = i18nString(UIStrings.timespanStarted);
65
+ this.endButton.disabled = false;
66
+ this.endButton.focus();
67
+ }
68
+ }
69
+
70
+ render(): void {
71
+ const dialogRoot = UI.Utils.createShadowRootWithCoreStyles(
72
+ this.contentElement, {cssFile: [lighthouseDialogStyles], delegatesFocus: undefined});
73
+
74
+ this.endButton = UI.UIUtils.createTextButton(i18nString(UIStrings.endTimespan), this.endTimespan.bind(this));
75
+ const cancelButton = UI.UIUtils.createTextButton(i18nString(UIStrings.cancel), this.cancel.bind(this));
76
+ const fragment = UI.Fragment.Fragment.build`
77
+ <div class="lighthouse-view vbox">
78
+ <h2 $="status-header"></h2>
79
+ ${this.endButton}
80
+ ${cancelButton}
81
+ </div>
82
+ `;
83
+
84
+ this.statusHeader = fragment.$('status-header');
85
+ dialogRoot.appendChild(fragment.element());
86
+
87
+ this.setSizeBehavior(UI.GlassPane.SizeBehavior.SetExactWidthMaxHeight);
88
+ this.setMaxContentSize(new UI.Geometry.Size(500, 400));
89
+ this.reset();
90
+ }
91
+
92
+ private endTimespan(): void {
93
+ this.controller.dispatchEventToListeners(Events.RequestLighthouseTimespanEnd, false);
94
+ }
95
+
96
+ private cancel(): void {
97
+ this.controller.dispatchEventToListeners(Events.RequestLighthouseCancel);
98
+ }
99
+ }
@@ -1216,7 +1216,7 @@ export class NetworkRequestNode extends NetworkNode {
1216
1216
  } else {
1217
1217
  this.linkifiedInitiatorAnchor = linkifier.linkifyScriptLocation(
1218
1218
  networkManager.target(), initiator.scriptId, initiator.url, initiator.lineNumber,
1219
- {columnNumber: initiator.columnNumber, inlineFrameIndex: 0, className: undefined, tabStop: undefined});
1219
+ {columnNumber: initiator.columnNumber, inlineFrameIndex: 0});
1220
1220
  }
1221
1221
  UI.Tooltip.Tooltip.install((this.linkifiedInitiatorAnchor), '');
1222
1222
  cell.appendChild(this.linkifiedInitiatorAnchor);
@@ -310,7 +310,7 @@ export class NodeFormatter implements Formatter {
310
310
  linkifyNode(node: ProfileDataGridNode): Element|null {
311
311
  const cpuProfilerModel = this.profileView.profileHeader.cpuProfilerModel;
312
312
  const target = cpuProfilerModel ? cpuProfilerModel.target() : null;
313
- const options = {className: 'profile-node-file', columnNumber: undefined, inlineFrameIndex: 0, tabStop: undefined};
313
+ const options = {className: 'profile-node-file', inlineFrameIndex: 0};
314
314
  return this.profileView.linkifier().maybeLinkifyConsoleCallFrame(target, node.profileNode.callFrame, options);
315
315
  }
316
316
  }
@@ -620,9 +620,7 @@ export class NodeFormatter implements Formatter {
620
620
  const target = heapProfilerModel ? heapProfilerModel.target() : null;
621
621
  const options = {
622
622
  className: 'profile-node-file',
623
- columnNumber: undefined,
624
623
  inlineFrameIndex: 0,
625
- tabStop: undefined,
626
624
  };
627
625
  return this.profileView.linkifier().maybeLinkifyConsoleCallFrame(target, node.profileNode.callFrame, options);
628
626
  }
@@ -1301,7 +1301,6 @@ export class AllocationGridNode extends HeapSnapshotGridNode {
1301
1301
  columnNumber: allocationNode.column - 1,
1302
1302
  inlineFrameIndex: 0,
1303
1303
  className: 'profile-node-file',
1304
- tabStop: undefined,
1305
1304
  });
1306
1305
  urlElement.style.maxWidth = '75%';
1307
1306
  cell.insertBefore(urlElement, cell.firstChild);
@@ -1887,10 +1887,9 @@ export class HeapAllocationStackView extends UI.Widget.Widget {
1887
1887
  continue;
1888
1888
  }
1889
1889
  const target = this.heapProfilerModel ? this.heapProfilerModel.target() : null;
1890
- const options = {columnNumber: frame.column - 1};
1890
+ const options = {columnNumber: frame.column - 1, inlineFrameIndex: 0};
1891
1891
  const urlElement = this.linkifier.linkifyScriptLocation(
1892
- target, String(frame.scriptId) as Protocol.Runtime.ScriptId, frame.scriptName, frame.line - 1,
1893
- (options as Components.Linkifier.LinkifyOptions));
1892
+ target, String(frame.scriptId) as Protocol.Runtime.ScriptId, frame.scriptName, frame.line - 1, options);
1894
1893
  frameDiv.appendChild(urlElement);
1895
1894
  stackFrameToURLElement.set(frameDiv, urlElement);
1896
1895
  frameDiv.addEventListener('contextmenu', this.onContextMenu.bind(this, urlElement));
@@ -126,7 +126,7 @@ export class SnippetFileSystem extends Persistence.PlatformFileSystem.PlatformFi
126
126
  return Common.ResourceType.resourceTypes.Script;
127
127
  }
128
128
 
129
- tooltipForURL(url: string): string {
129
+ tooltipForURL(url: Platform.DevToolsPath.UrlString): string {
130
130
  return i18nString(UIStrings.linkedTo, {PH1: unescapeSnippetName(url.substring(this.path().length))});
131
131
  }
132
132