blob: 542be042800ebb7447d9b6415b5d09c548c00ea4 [file] [log] [blame]
Blink Reformat4c46d092018-04-07 15:32:371// Copyright 2016 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
Jan Schefflerc5a400f2021-01-22 16:41:475/* eslint-disable rulesdir/no_underscored_properties */
6
Tim van der Lippe76961572021-04-06 10:48:077import * as Common from '../../core/common/common.js';
Tim van der Lippee0247312021-04-01 14:25:308import * as Host from '../../core/host/host.js';
Tim van der Lippebb352e62021-04-01 17:57:289import * as i18n from '../../core/i18n/i18n.js';
Tim van der Lipped8caac42021-03-31 14:40:4410import * as Root from '../../core/root/root.js';
Tim van der Lippee00b92f2021-03-31 16:52:1711import * as SDK from '../../core/sdk/sdk.js';
Tim van der Lippeaa61faf2021-04-07 15:32:0712import * as UI from '../../ui/legacy/legacy.js';
Tim van der Lippe7a077eb2021-03-23 18:02:1113import * as Emulation from '../emulation/emulation.js';
Tim van der Lippec02a97c2020-02-14 14:39:2714
Connor Clark2bc3be22020-02-14 22:34:1915import {Events, LighthouseController} from './LighthouseController.js';
16import {ProtocolService} from './LighthouseProtocolService.js';
Tim van der Lippe12fed692021-03-24 11:45:2417
Tim van der Lippe5f62c6f2021-02-25 16:39:2618import type * as ReportRenderer from './LighthouseReporterTypes.js';
Connor Clark2bc3be22020-02-14 22:34:1919import {LighthouseReportRenderer, LighthouseReportUIFeatures} from './LighthouseReportRenderer.js';
20import {Item, ReportSelector} from './LighthouseReportSelector.js';
21import {StartView} from './LighthouseStartView.js';
22import {StatusView} from './LighthouseStatusView.js';
Paul Lewis51474192020-01-09 16:02:2223
Simon Zünd6f95e842021-03-01 07:41:5524const UIStrings = {
vidorteg06840022020-11-21 05:18:0325 /**
26 *@description Text that appears when user drag and drop something (for example, a file) in Lighthouse Panel
27 */
28 dropLighthouseJsonHere: 'Drop `Lighthouse` JSON here',
29 /**
30 *@description Tooltip text that appears when hovering over the largeicon add button in the Lighthouse Panel
31 */
32 performAnAudit: 'Perform an audit…',
33 /**
34 *@description Text to clear everything
35 */
36 clearAll: 'Clear all',
37 /**
38 *@description Tooltip text that appears when hovering over the largeicon settings gear in show settings pane setting in start view of the audits panel
39 */
40 lighthouseSettings: '`Lighthouse` settings',
41 /**
42 *@description Status header in the Lighthouse panel
43 */
44 printing: 'Printing',
45 /**
46 *@description Status text in the Lighthouse panel
47 */
48 thePrintPopupWindowIsOpenPlease: 'The print popup window is open. Please close it to continue.',
49 /**
50 *@description Text in Lighthouse Panel
51 */
52 cancelling: 'Cancelling',
53};
Tim van der Lippe7a077eb2021-03-23 18:02:1154const str_ = i18n.i18n.registerUIStrings('panels/lighthouse/LighthousePanel.ts', UIStrings);
vidorteg06840022020-11-21 05:18:0355const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
Andres Olivaresfe256672021-01-19 16:14:0356
Jan Schefflerc5a400f2021-01-22 16:41:4757let lighthousePanelInstace: LighthousePanel;
Andres Olivaresfe256672021-01-19 16:14:0358
Paul Lewisdaac1062020-03-05 14:37:1059export class LighthousePanel extends UI.Panel.Panel {
Jan Schefflerc5a400f2021-01-22 16:41:4760 _protocolService: ProtocolService;
61 _controller: LighthouseController;
62 _startView: StartView;
63 _statusView: StatusView;
64 _warningText: null;
65 _unauditableExplanation: null;
66 _cachedRenderedReports: Map<ReportRenderer.ReportJSON, HTMLElement>;
67 _dropTarget: UI.DropTarget.DropTarget;
68 _auditResultsElement: HTMLElement;
69 _clearButton!: UI.Toolbar.ToolbarButton;
70 _newButton!: UI.Toolbar.ToolbarButton;
71 _reportSelector!: ReportSelector;
72 _settingsPane!: UI.Widget.Widget;
73 _rightToolbar!: UI.Toolbar.Toolbar;
74 _showSettingsPaneSetting!: Common.Settings.Setting<boolean>;
75 _stateBefore?: {
Sigurd Schneider15761862021-02-04 08:05:3676 emulation: {enabled: boolean, outlineEnabled: boolean, toolbarControlsEnabled: boolean},
77 network: {conditions: SDK.NetworkManager.Conditions},
Jan Schefflerc5a400f2021-01-22 16:41:4778 };
79 _isLHAttached?: boolean;
80
81 private constructor() {
Connor Clark2bc3be22020-02-14 22:34:1982 super('lighthouse');
Jack Franklin0ca983b2020-12-14 10:22:3283 this.registerRequiredCSS('third_party/lighthouse/report-assets/report.css', {enableLegacyPatching: false});
Tim van der Lippe7a077eb2021-03-23 18:02:1184 this.registerRequiredCSS('panels/lighthouse/lighthousePanel.css', {enableLegacyPatching: false});
Blink Reformat4c46d092018-04-07 15:32:3785
Paul Lewis51474192020-01-09 16:02:2286 this._protocolService = new ProtocolService();
Connor Clark2bc3be22020-02-14 22:34:1987 this._controller = new LighthouseController(this._protocolService);
Paul Lewis51474192020-01-09 16:02:2288 this._startView = new StartView(this._controller);
89 this._statusView = new StatusView(this._controller);
Blink Reformat4c46d092018-04-07 15:32:3790
Adam Raine3226e932020-10-08 14:42:2191 this._warningText = null;
Patrick Hulcea087f622018-05-18 00:37:5392 this._unauditableExplanation = null;
93 this._cachedRenderedReports = new Map();
Blink Reformat4c46d092018-04-07 15:32:3794
Paul Lewisdaac1062020-03-05 14:37:1095 this._dropTarget = new UI.DropTarget.DropTarget(
vidorteg06840022020-11-21 05:18:0396 this.contentElement, [UI.DropTarget.Type.File], i18nString(UIStrings.dropLighthouseJsonHere),
Blink Reformat4c46d092018-04-07 15:32:3797 this._handleDrop.bind(this));
98
Paul Lewis51474192020-01-09 16:02:2299 this._controller.addEventListener(Events.PageAuditabilityChanged, this._refreshStartAuditUI.bind(this));
Adam Raine3226e932020-10-08 14:42:21100 this._controller.addEventListener(Events.PageWarningsChanged, this._refreshWarningsUI.bind(this));
Paul Lewis51474192020-01-09 16:02:22101 this._controller.addEventListener(Events.AuditProgressChanged, this._refreshStatusUI.bind(this));
Tim van der Lippe37a35ff2020-03-03 13:49:02102 this._controller.addEventListener(Events.RequestLighthouseStart, event => {
103 this._startLighthouse(event);
104 });
Jan Schefflerc5a400f2021-01-22 16:41:47105 this._controller.addEventListener(Events.RequestLighthouseCancel, _event => {
Tim van der Lippe37a35ff2020-03-03 13:49:02106 this._cancelLighthouse();
107 });
Blink Reformat4c46d092018-04-07 15:32:37108
Patrick Hulcea087f622018-05-18 00:37:53109 this._renderToolbar();
Connor Clark2bc3be22020-02-14 22:34:19110 this._auditResultsElement = this.contentElement.createChild('div', 'lighthouse-results-container');
Patrick Hulcea087f622018-05-18 00:37:53111 this._renderStartView();
112
113 this._controller.recomputePageAuditability();
Blink Reformat4c46d092018-04-07 15:32:37114 }
115
Jan Schefflerc5a400f2021-01-22 16:41:47116 static instance(opts = {forceNew: null}): LighthousePanel {
Andres Olivaresfe256672021-01-19 16:14:03117 const {forceNew} = opts;
118 if (!lighthousePanelInstace || forceNew) {
119 lighthousePanelInstace = new LighthousePanel();
120 }
121
122 return lighthousePanelInstace;
123 }
Jan Schefflerc5a400f2021-01-22 16:41:47124
125 static getEvents(): typeof Events {
Adam Raine3226e932020-10-08 14:42:21126 return Events;
127 }
128
Jan Schefflerc5a400f2021-01-22 16:41:47129 _refreshWarningsUI(evt: Common.EventTarget.EventTargetEvent): void {
Adam Raine3226e932020-10-08 14:42:21130 // PageWarningsChanged fires multiple times during an audit, which we want to ignore.
131 if (this._isLHAttached) {
132 return;
133 }
134
135 this._warningText = evt.data.warning;
136 this._startView.setWarningText(evt.data.warning);
137 }
138
Jan Schefflerc5a400f2021-01-22 16:41:47139 _refreshStartAuditUI(evt: Common.EventTarget.EventTargetEvent): void {
Connor Clarkca8905e2019-08-23 18:35:10140 // PageAuditabilityChanged fires multiple times during an audit, which we want to ignore.
Tim van der Lippe1d6e57a2019-09-30 11:55:34141 if (this._isLHAttached) {
Connor Clarkca8905e2019-08-23 18:35:10142 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34143 }
Connor Clarkca8905e2019-08-23 18:35:10144
Patrick Hulcea087f622018-05-18 00:37:53145 this._unauditableExplanation = evt.data.helpText;
146 this._startView.setUnauditableExplanation(evt.data.helpText);
147 this._startView.setStartButtonEnabled(!evt.data.helpText);
Blink Reformat4c46d092018-04-07 15:32:37148 }
149
Jan Schefflerc5a400f2021-01-22 16:41:47150 _refreshStatusUI(evt: Common.EventTarget.EventTargetEvent): void {
Patrick Hulcea087f622018-05-18 00:37:53151 this._statusView.updateStatus(evt.data.message);
Blink Reformat4c46d092018-04-07 15:32:37152 }
153
Jan Schefflerc5a400f2021-01-22 16:41:47154 _refreshToolbarUI(): void {
Blink Reformat4c46d092018-04-07 15:32:37155 this._clearButton.setEnabled(this._reportSelector.hasItems());
156 }
157
Jan Schefflerc5a400f2021-01-22 16:41:47158 _clearAll(): void {
Blink Reformat4c46d092018-04-07 15:32:37159 this._reportSelector.clearAll();
Patrick Hulcea087f622018-05-18 00:37:53160 this._renderStartView();
Blink Reformat4c46d092018-04-07 15:32:37161 this._refreshToolbarUI();
162 }
163
Jan Schefflerc5a400f2021-01-22 16:41:47164 _renderToolbar(): void {
Connor Clark2bc3be22020-02-14 22:34:19165 const lighthouseToolbarContainer = this.element.createChild('div', 'lighthouse-toolbar-container');
Connor Clarke66080e2019-11-07 00:35:51166
Paul Lewisdaac1062020-03-05 14:37:10167 const toolbar = new UI.Toolbar.Toolbar('', lighthouseToolbarContainer);
Blink Reformat4c46d092018-04-07 15:32:37168
vidorteg06840022020-11-21 05:18:03169 this._newButton = new UI.Toolbar.ToolbarButton(i18nString(UIStrings.performAnAudit), 'largeicon-add');
Blink Reformat4c46d092018-04-07 15:32:37170 toolbar.appendToolbarItem(this._newButton);
Paul Lewisdaac1062020-03-05 14:37:10171 this._newButton.addEventListener(UI.Toolbar.ToolbarButton.Events.Click, this._renderStartView.bind(this));
Blink Reformat4c46d092018-04-07 15:32:37172
Blink Reformat4c46d092018-04-07 15:32:37173 toolbar.appendSeparator();
174
Paul Lewis51474192020-01-09 16:02:22175 this._reportSelector = new ReportSelector(() => this._renderStartView());
Blink Reformat4c46d092018-04-07 15:32:37176 toolbar.appendToolbarItem(this._reportSelector.comboBox());
177
vidorteg06840022020-11-21 05:18:03178 this._clearButton = new UI.Toolbar.ToolbarButton(i18nString(UIStrings.clearAll), 'largeicon-clear');
Blink Reformat4c46d092018-04-07 15:32:37179 toolbar.appendToolbarItem(this._clearButton);
Paul Lewisdaac1062020-03-05 14:37:10180 this._clearButton.addEventListener(UI.Toolbar.ToolbarButton.Events.Click, this._clearAll.bind(this));
Blink Reformat4c46d092018-04-07 15:32:37181
Paul Lewisdaac1062020-03-05 14:37:10182 this._settingsPane = new UI.Widget.HBox();
Connor Clarke66080e2019-11-07 00:35:51183 this._settingsPane.show(this.contentElement);
Connor Clark2bc3be22020-02-14 22:34:19184 this._settingsPane.element.classList.add('lighthouse-settings-pane');
Connor Clarke66080e2019-11-07 00:35:51185 this._settingsPane.element.appendChild(this._startView.settingsToolbar().element);
Paul Lewis2d7d65c2020-03-16 17:26:30186 this._showSettingsPaneSetting =
187 Common.Settings.Settings.instance().createSetting('lighthouseShowSettingsToolbar', false);
Connor Clarke66080e2019-11-07 00:35:51188
Paul Lewisdaac1062020-03-05 14:37:10189 this._rightToolbar = new UI.Toolbar.Toolbar('', lighthouseToolbarContainer);
Connor Clarke66080e2019-11-07 00:35:51190 this._rightToolbar.appendSeparator();
Paul Lewisdaac1062020-03-05 14:37:10191 this._rightToolbar.appendToolbarItem(new UI.Toolbar.ToolbarSettingToggle(
vidorteg06840022020-11-21 05:18:03192 this._showSettingsPaneSetting, 'largeicon-settings-gear', i18nString(UIStrings.lighthouseSettings)));
Connor Clarke66080e2019-11-07 00:35:51193 this._showSettingsPaneSetting.addChangeListener(this._updateSettingsPaneVisibility.bind(this));
194 this._updateSettingsPaneVisibility();
195
Patrick Hulcea087f622018-05-18 00:37:53196 this._refreshToolbarUI();
197 }
Blink Reformat4c46d092018-04-07 15:32:37198
Jan Schefflerc5a400f2021-01-22 16:41:47199 _updateSettingsPaneVisibility(): void {
Connor Clarke66080e2019-11-07 00:35:51200 this._settingsPane.element.classList.toggle('hidden', !this._showSettingsPaneSetting.get());
201 }
202
Jan Schefflerc5a400f2021-01-22 16:41:47203 _toggleSettingsDisplay(show: boolean): void {
Connor Clarke66080e2019-11-07 00:35:51204 this._rightToolbar.element.classList.toggle('hidden', !show);
205 this._settingsPane.element.classList.toggle('hidden', !show);
206 this._updateSettingsPaneVisibility();
207 }
208
Jan Schefflerc5a400f2021-01-22 16:41:47209 _renderStartView(): void {
Patrick Hulcea087f622018-05-18 00:37:53210 this._auditResultsElement.removeChildren();
211 this._statusView.hide();
212
Connor Clark2bc3be22020-02-14 22:34:19213 this._reportSelector.selectNewReport();
Patrick Hulcea087f622018-05-18 00:37:53214 this.contentElement.classList.toggle('in-progress', false);
215
216 this._startView.show(this.contentElement);
Connor Clarke66080e2019-11-07 00:35:51217 this._toggleSettingsDisplay(true);
Patrick Hulcea087f622018-05-18 00:37:53218 this._startView.setUnauditableExplanation(this._unauditableExplanation);
219 this._startView.setStartButtonEnabled(!this._unauditableExplanation);
Tim van der Lippe1d6e57a2019-09-30 11:55:34220 if (!this._unauditableExplanation) {
Patrick Hulce8d387f12018-05-29 18:54:54221 this._startView.focusStartButton();
Tim van der Lippe1d6e57a2019-09-30 11:55:34222 }
Adam Raine3226e932020-10-08 14:42:21223 this._startView.setWarningText(this._warningText);
Patrick Hulce8d387f12018-05-29 18:54:54224
Patrick Hulce05c18ce2018-05-24 00:34:56225 this._newButton.setEnabled(false);
Patrick Hulcea087f622018-05-18 00:37:53226 this._refreshToolbarUI();
Patrick Hulce05c18ce2018-05-24 00:34:56227 this.setDefaultFocusedChild(this._startView);
Patrick Hulcea087f622018-05-18 00:37:53228 }
229
Jan Schefflerc5a400f2021-01-22 16:41:47230 _renderStatusView(inspectedURL: string): void {
Patrick Hulcea087f622018-05-18 00:37:53231 this.contentElement.classList.toggle('in-progress', true);
232 this._statusView.setInspectedURL(inspectedURL);
233 this._statusView.show(this.contentElement);
234 }
235
Jan Schefflerc5a400f2021-01-22 16:41:47236 _beforePrint(): void {
Connor Clark99508362019-08-20 19:52:23237 this._statusView.show(this.contentElement);
238 this._statusView.toggleCancelButton(false);
vidorteg06840022020-11-21 05:18:03239 this._statusView.renderText(i18nString(UIStrings.printing), i18nString(UIStrings.thePrintPopupWindowIsOpenPlease));
Connor Clark99508362019-08-20 19:52:23240 }
241
Jan Schefflerc5a400f2021-01-22 16:41:47242 _afterPrint(): void {
Connor Clark99508362019-08-20 19:52:23243 this._statusView.hide();
244 this._statusView.toggleCancelButton(true);
245 }
246
Jan Schefflerc5a400f2021-01-22 16:41:47247 _renderReport(lighthouseResult: ReportRenderer.ReportJSON, artifacts?: ReportRenderer.RunnerResultArtifacts): void {
Connor Clarke66080e2019-11-07 00:35:51248 this._toggleSettingsDisplay(false);
Patrick Hulcea087f622018-05-18 00:37:53249 this.contentElement.classList.toggle('in-progress', false);
250 this._startView.hideWidget();
251 this._statusView.hide();
252 this._auditResultsElement.removeChildren();
Patrick Hulce05c18ce2018-05-24 00:34:56253 this._newButton.setEnabled(true);
Patrick Hulcea087f622018-05-18 00:37:53254 this._refreshToolbarUI();
255
256 const cachedRenderedReport = this._cachedRenderedReports.get(lighthouseResult);
257 if (cachedRenderedReport) {
258 this._auditResultsElement.appendChild(cachedRenderedReport);
259 return;
Blink Reformat4c46d092018-04-07 15:32:37260 }
261
Patrick Hulcea087f622018-05-18 00:37:53262 const reportContainer = this._auditResultsElement.createChild('div', 'lh-vars lh-root lh-devtools');
Blink Reformat4c46d092018-04-07 15:32:37263
Jan Schefflerc5a400f2021-01-22 16:41:47264 const dom = new DOM(this._auditResultsElement.ownerDocument as Document);
265 const renderer = new LighthouseReportRenderer(dom) as ReportRenderer.ReportRenderer;
Patrick Hulcea087f622018-05-18 00:37:53266
Tim van der Lippe5df64b22020-09-11 12:04:24267 const templatesHTML = Root.Runtime.cachedResources.get('third_party/lighthouse/report-assets/templates.html');
Tim van der Lippe4df32c92020-11-06 12:35:05268 if (!templatesHTML) {
269 return;
270 }
Patrick Hulcea087f622018-05-18 00:37:53271 const templatesDOM = new DOMParser().parseFromString(templatesHTML, 'text/html');
Tim van der Lippe1d6e57a2019-09-30 11:55:34272 if (!templatesDOM) {
Blink Reformat4c46d092018-04-07 15:32:37273 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34274 }
Blink Reformat4c46d092018-04-07 15:32:37275
Patrick Hulcea087f622018-05-18 00:37:53276 renderer.setTemplateContext(templatesDOM);
Paul Irish8f1e33d2018-05-31 02:29:50277 const el = renderer.renderReport(lighthouseResult, reportContainer);
Connor Clark2bc3be22020-02-14 22:34:19278 LighthouseReportRenderer.addViewTraceButton(el, artifacts);
[email protected]c5214af2019-06-25 20:31:21279 // Linkifying requires the target be loaded. Do not block the report
280 // from rendering, as this is just an embellishment and the main target
281 // could take awhile to load.
282 this._waitForMainTargetLoad().then(() => {
Connor Clark2bc3be22020-02-14 22:34:19283 LighthouseReportRenderer.linkifyNodeDetails(el);
284 LighthouseReportRenderer.linkifySourceLocationDetails(el);
[email protected]c5214af2019-06-25 20:31:21285 });
Connor Clark2bc3be22020-02-14 22:34:19286 LighthouseReportRenderer.handleDarkMode(el);
[email protected]f2f8c092019-05-30 22:01:56287
Jan Schefflerc5a400f2021-01-22 16:41:47288 // eslint-disable-next-line @typescript-eslint/no-explicit-any
289 const features = new LighthouseReportUIFeatures(dom) as any;
Connor Clark99508362019-08-20 19:52:23290 features.setBeforePrint(this._beforePrint.bind(this));
291 features.setAfterPrint(this._afterPrint.bind(this));
[email protected]f2f8c092019-05-30 22:01:56292 features.setTemplateContext(templatesDOM);
293 features.initFeatures(lighthouseResult);
Blink Reformat4c46d092018-04-07 15:32:37294
Patrick Hulcea087f622018-05-18 00:37:53295 this._cachedRenderedReports.set(lighthouseResult, reportContainer);
Blink Reformat4c46d092018-04-07 15:32:37296 }
297
Jan Schefflerc5a400f2021-01-22 16:41:47298 async _waitForMainTargetLoad(): Promise<void> {
Paul Lewisdaac1062020-03-05 14:37:10299 const mainTarget = SDK.SDKModel.TargetManager.instance().mainTarget();
Tim van der Lippe4df32c92020-11-06 12:35:05300 if (!mainTarget) {
301 return;
302 }
Paul Lewisdaac1062020-03-05 14:37:10303 const resourceTreeModel = mainTarget.model(SDK.ResourceTreeModel.ResourceTreeModel);
Tim van der Lippe4df32c92020-11-06 12:35:05304 if (!resourceTreeModel) {
305 return;
306 }
[email protected]c5214af2019-06-25 20:31:21307 return resourceTreeModel.once(SDK.ResourceTreeModel.Events.Load);
308 }
309
Jan Schefflerc5a400f2021-01-22 16:41:47310 _buildReportUI(lighthouseResult: ReportRenderer.ReportJSON, artifacts?: ReportRenderer.RunnerResultArtifacts): void {
Tim van der Lippe1d6e57a2019-09-30 11:55:34311 if (lighthouseResult === null) {
Blink Reformat4c46d092018-04-07 15:32:37312 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34313 }
Blink Reformat4c46d092018-04-07 15:32:37314
Paul Lewis51474192020-01-09 16:02:22315 const optionElement = new Item(
Paul Irish8f1e33d2018-05-31 02:29:50316 lighthouseResult, () => this._renderReport(lighthouseResult, artifacts), this._renderStartView.bind(this));
Blink Reformat4c46d092018-04-07 15:32:37317 this._reportSelector.prepend(optionElement);
Blink Reformat4c46d092018-04-07 15:32:37318 this._refreshToolbarUI();
Patrick Hulcea087f622018-05-18 00:37:53319 this._renderReport(lighthouseResult);
Blink Reformat4c46d092018-04-07 15:32:37320 }
321
Jan Schefflerc5a400f2021-01-22 16:41:47322 _handleDrop(dataTransfer: DataTransfer): void {
Blink Reformat4c46d092018-04-07 15:32:37323 const items = dataTransfer.items;
Tim van der Lippe1d6e57a2019-09-30 11:55:34324 if (!items.length) {
Blink Reformat4c46d092018-04-07 15:32:37325 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34326 }
Blink Reformat4c46d092018-04-07 15:32:37327 const item = items[0];
328 if (item.kind === 'file') {
329 const entry = items[0].webkitGetAsEntry();
Tim van der Lippe1d6e57a2019-09-30 11:55:34330 if (!entry.isFile) {
Blink Reformat4c46d092018-04-07 15:32:37331 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34332 }
Jan Schefflerc5a400f2021-01-22 16:41:47333 entry.file((file: Blob) => {
334 const reader = new FileReader();
335 reader.onload = (): void => this._loadedFromFile(reader.result as string);
336 reader.readAsText(file);
337 });
Blink Reformat4c46d092018-04-07 15:32:37338 }
339 }
340
Jan Schefflerc5a400f2021-01-22 16:41:47341 _loadedFromFile(report: string): void {
Patrick Hulcea087f622018-05-18 00:37:53342 const data = JSON.parse(report);
Tim van der Lippe1d6e57a2019-09-30 11:55:34343 if (!data['lighthouseVersion']) {
Blink Reformat4c46d092018-04-07 15:32:37344 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34345 }
Jan Schefflerc5a400f2021-01-22 16:41:47346 this._buildReportUI(data as ReportRenderer.ReportJSON);
Blink Reformat4c46d092018-04-07 15:32:37347 }
Blink Reformat4c46d092018-04-07 15:32:37348
Jan Schefflerc5a400f2021-01-22 16:41:47349 async _startLighthouse(_event: Common.EventTarget.EventTargetEvent): Promise<void> {
Tim van der Lippe4df32c92020-11-06 12:35:05350 Host.userMetrics.actionTaken(Host.UserMetrics.Action.LighthouseStarted);
Blink Reformat4c46d092018-04-07 15:32:37351
Patrick Hulcea087f622018-05-18 00:37:53352 try {
353 const inspectedURL = await this._controller.getInspectedURL({force: true});
354 const categoryIDs = this._controller.getCategoryIDs();
355 const flags = this._controller.getFlags();
Blink Reformat4c46d092018-04-07 15:32:37356
Patrick Hulcea087f622018-05-18 00:37:53357 await this._setupEmulationAndProtocolConnection();
Blink Reformat4c46d092018-04-07 15:32:37358
Patrick Hulcea087f622018-05-18 00:37:53359 this._renderStatusView(inspectedURL);
Blink Reformat4c46d092018-04-07 15:32:37360
Paul Irish8f1e33d2018-05-31 02:29:50361 const lighthouseResponse = await this._protocolService.startLighthouse(inspectedURL, categoryIDs, flags);
Blink Reformat4c46d092018-04-07 15:32:37362
Paul Irish8f1e33d2018-05-31 02:29:50363 if (lighthouseResponse && lighthouseResponse.fatal) {
364 const error = new Error(lighthouseResponse.message);
365 error.stack = lighthouseResponse.stack;
Patrick Hulcea087f622018-05-18 00:37:53366 throw error;
367 }
Blink Reformat4c46d092018-04-07 15:32:37368
Tim van der Lippe1d6e57a2019-09-30 11:55:34369 if (!lighthouseResponse) {
Patrick Hulcea087f622018-05-18 00:37:53370 throw new Error('Auditing failed to produce a result');
Tim van der Lippe1d6e57a2019-09-30 11:55:34371 }
Blink Reformat4c46d092018-04-07 15:32:37372
Tim van der Lippe4df32c92020-11-06 12:35:05373 Host.userMetrics.actionTaken(Host.UserMetrics.Action.LighthouseFinished);
Blink Reformat4c46d092018-04-07 15:32:37374
Patrick Hulcea087f622018-05-18 00:37:53375 await this._resetEmulationAndProtocolConnection();
Paul Irish8f1e33d2018-05-31 02:29:50376 this._buildReportUI(lighthouseResponse.lhr, lighthouseResponse.artifacts);
Brandon Goddard04d5ba92019-12-19 16:31:55377 // Give focus to the new audit button when completed
378 this._newButton.element.focus();
Patrick Hulcea087f622018-05-18 00:37:53379 } catch (err) {
Paul Irishdca01d02019-03-25 20:17:56380 await this._resetEmulationAndProtocolConnection();
Tim van der Lippe1d6e57a2019-09-30 11:55:34381 if (err instanceof Error) {
Patrick Hulcea087f622018-05-18 00:37:53382 this._statusView.renderBugReport(err);
Tim van der Lippe1d6e57a2019-09-30 11:55:34383 }
Blink Reformat4c46d092018-04-07 15:32:37384 }
385 }
Blink Reformat4c46d092018-04-07 15:32:37386
Jan Schefflerc5a400f2021-01-22 16:41:47387 async _cancelLighthouse(): Promise<void> {
vidorteg06840022020-11-21 05:18:03388 this._statusView.updateStatus(i18nString(UIStrings.cancelling));
Patrick Hulcea087f622018-05-18 00:37:53389 await this._resetEmulationAndProtocolConnection();
390 this._renderStartView();
Blink Reformat4c46d092018-04-07 15:32:37391 }
392
Paul Irishd8495012019-07-16 23:51:47393 /**
394 * We set the device emulation on the DevTools-side for two reasons:
395 * 1. To workaround some odd device metrics emulation bugs like occuluding viewports
396 * 2. To get the attractive device outline
Connor Clarkca8905e2019-08-23 18:35:10397 *
Connor Clark3ee5ac72019-11-07 23:11:58398 * We also set flags.internalDisableDeviceScreenEmulation = true to let LH only apply UA emulation
Paul Irishd8495012019-07-16 23:51:47399 */
Jan Schefflerc5a400f2021-01-22 16:41:47400 async _setupEmulationAndProtocolConnection(): Promise<void> {
Patrick Hulcea087f622018-05-18 00:37:53401 const flags = this._controller.getFlags();
Blink Reformat4c46d092018-04-07 15:32:37402
Jack Franklin6f3ee6c2020-10-22 12:54:10403 const emulationModel = Emulation.DeviceModeModel.DeviceModeModel.instance();
Connor Clarkca8905e2019-08-23 18:35:10404 this._stateBefore = {
405 emulation: {
406 enabled: emulationModel.enabledSetting().get(),
407 outlineEnabled: emulationModel.deviceOutlineSetting().get(),
Jan Schefflerc5a400f2021-01-22 16:41:47408 toolbarControlsEnabled: emulationModel.toolbarControlsEnabledSetting().get(),
Connor Clarkca8905e2019-08-23 18:35:10409 },
Jan Schefflerc5a400f2021-01-22 16:41:47410 network: {conditions: SDK.NetworkManager.MultitargetNetworkManager.instance().networkConditions()},
Connor Clarkca8905e2019-08-23 18:35:10411 };
Patrick Hulcea087f622018-05-18 00:37:53412
Connor Clarkca8905e2019-08-23 18:35:10413 emulationModel.toolbarControlsEnabledSetting().set(false);
Tim van der Lippe4df32c92020-11-06 12:35:05414 if ('emulatedFormFactor' in flags && flags.emulatedFormFactor === 'desktop') {
Patrick Hulcea087f622018-05-18 00:37:53415 emulationModel.enabledSetting().set(false);
Patrick Hulcea087f622018-05-18 00:37:53416 emulationModel.emulate(Emulation.DeviceModeModel.Type.None, null, null);
Connor Clark3f700342019-07-25 02:10:41417 } else if (flags.emulatedFormFactor === 'mobile') {
Patrick Hulcea087f622018-05-18 00:37:53418 emulationModel.enabledSetting().set(true);
419 emulationModel.deviceOutlineSetting().set(true);
420
Paul Lewisdaac1062020-03-05 14:37:10421 for (const device of Emulation.EmulatedDevices.EmulatedDevicesList.instance().standard()) {
Paul Irishac18cd02020-05-13 00:57:44422 if (device.title === 'Moto G4') {
Patrick Hulcea087f622018-05-18 00:37:53423 emulationModel.emulate(Emulation.DeviceModeModel.Type.Device, device, device.modes[0], 1);
Tim van der Lippe1d6e57a2019-09-30 11:55:34424 }
Patrick Hulcea087f622018-05-18 00:37:53425 }
Blink Reformat4c46d092018-04-07 15:32:37426 }
427
Patrick Hulcea087f622018-05-18 00:37:53428 await this._protocolService.attach();
429 this._isLHAttached = true;
430 }
Blink Reformat4c46d092018-04-07 15:32:37431
Jan Schefflerc5a400f2021-01-22 16:41:47432 async _resetEmulationAndProtocolConnection(): Promise<void> {
Tim van der Lippe1d6e57a2019-09-30 11:55:34433 if (!this._isLHAttached) {
Blink Reformat4c46d092018-04-07 15:32:37434 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34435 }
Blink Reformat4c46d092018-04-07 15:32:37436
Patrick Hulcea087f622018-05-18 00:37:53437 this._isLHAttached = false;
438 await this._protocolService.detach();
Blink Reformat4c46d092018-04-07 15:32:37439
Connor Clarkca8905e2019-08-23 18:35:10440 if (this._stateBefore) {
Jack Franklin6f3ee6c2020-10-22 12:54:10441 const emulationModel = Emulation.DeviceModeModel.DeviceModeModel.instance();
Connor Clarkca8905e2019-08-23 18:35:10442 emulationModel.enabledSetting().set(this._stateBefore.emulation.enabled);
443 emulationModel.deviceOutlineSetting().set(this._stateBefore.emulation.outlineEnabled);
444 emulationModel.toolbarControlsEnabledSetting().set(this._stateBefore.emulation.toolbarControlsEnabled);
Tim van der Lippecd0bb372020-05-01 13:53:21445 SDK.NetworkManager.MultitargetNetworkManager.instance().setNetworkConditions(
446 this._stateBefore.network.conditions);
Connor Clarkca8905e2019-08-23 18:35:10447 delete this._stateBefore;
448 }
449
Jack Franklindb9cb272020-10-15 13:11:26450 Emulation.InspectedPagePlaceholder.InspectedPagePlaceholder.instance().update(true);
Blink Reformat4c46d092018-04-07 15:32:37451
Tim van der Lippe4df32c92020-11-06 12:35:05452 const mainTarget = SDK.SDKModel.TargetManager.instance().mainTarget();
453 if (!mainTarget) {
454 return;
455 }
456 const resourceTreeModel = mainTarget.model(SDK.ResourceTreeModel.ResourceTreeModel);
457 if (!resourceTreeModel) {
458 return;
459 }
Patrick Hulcea087f622018-05-18 00:37:53460 // reload to reset the page state
461 const inspectedURL = await this._controller.getInspectedURL();
462 await resourceTreeModel.navigate(inspectedURL);
Blink Reformat4c46d092018-04-07 15:32:37463 }
Paul Lewiscf2ef222019-11-22 14:55:35464}