| OLD | NEW |
| 1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 /** | 5 /** |
| 6 * @unrestricted | 6 * @unrestricted |
| 7 */ | 7 */ |
| 8 Audits2.Audits2Panel = class extends UI.Panel { | 8 Audits2.Audits2Panel = class extends UI.PanelWithSidebar { |
| 9 constructor() { | 9 constructor() { |
| 10 super('audits2'); | 10 super('audits2'); |
| 11 this.setHideOnDetach(); | 11 this.setHideOnDetach(); |
| 12 this.registerRequiredCSS('audits2/audits2Panel.css'); | 12 this.registerRequiredCSS('audits2/audits2Panel.css'); |
| 13 this.registerRequiredCSS('audits2/lighthouse/report-styles.css'); | 13 this.registerRequiredCSS('audits2/lighthouse/report-styles.css'); |
| 14 | 14 |
| 15 this._protocolService = new Audits2.ProtocolService(); | 15 this._protocolService = new Audits2.ProtocolService(); |
| 16 this._protocolService.registerStatusCallback(msg => this._updateStatus(Commo
n.UIString(msg))); | 16 this._protocolService.registerStatusCallback(msg => this._updateStatus(Commo
n.UIString(msg))); |
| 17 | 17 |
| 18 this._settings = Audits2.Audits2Panel.Presets.map(preset => { | 18 var toolbar = new UI.Toolbar('', this.panelSidebarElement()); |
| 19 const setting = Common.settings.createSetting(preset.id, true); | |
| 20 setting.setTitle(Common.UIString(preset.description)); | |
| 21 return setting; | |
| 22 }); | |
| 23 | 19 |
| 24 var auditsViewElement = this.contentElement.createChild('div', 'hbox audits2
-view'); | 20 var newButton = new UI.ToolbarButton(Common.UIString('New audit\u2026'), 'la
rgeicon-add'); |
| 25 this._resultsView = this.contentElement.createChild('div', 'vbox results-vie
w'); | 21 toolbar.appendToolbarItem(newButton); |
| 26 this._createLauncherUI(auditsViewElement); | 22 newButton.addEventListener(UI.ToolbarButton.Events.Click, this._showLauncher
UI.bind(this)); |
| 23 |
| 24 var deleteButton = new UI.ToolbarButton(Common.UIString('Delete audit'), 'la
rgeicon-delete'); |
| 25 toolbar.appendToolbarItem(deleteButton); |
| 26 deleteButton.addEventListener(UI.ToolbarButton.Events.Click, this._deleteSel
ected.bind(this)); |
| 27 |
| 28 toolbar.appendSeparator(); |
| 29 |
| 30 var clearButton = new UI.ToolbarButton(Common.UIString('Clear all'), 'largei
con-clear'); |
| 31 toolbar.appendToolbarItem(clearButton); |
| 32 clearButton.addEventListener(UI.ToolbarButton.Events.Click, this._clearAll.b
ind(this)); |
| 33 |
| 34 this._treeOutline = new UI.TreeOutlineInShadow(); |
| 35 this._treeOutline.registerRequiredCSS('audits2/lighthouse/report-styles.css'
); |
| 36 this._treeOutline.registerRequiredCSS('audits2/audits2Tree.css'); |
| 37 this.panelSidebarElement().appendChild(this._treeOutline.element); |
| 38 |
| 39 this._dropTarget = new UI.DropTarget( |
| 40 this.contentElement, [UI.DropTarget.Types.Files], |
| 41 Common.UIString('Drop audit file here'), this._handleDrop.bind(this)); |
| 42 |
| 43 this._showLandingPage(); |
| 27 } | 44 } |
| 28 | 45 |
| 29 _reset() { | 46 _clearAll() { |
| 30 this.contentElement.classList.remove('show-results'); | 47 this._treeOutline.removeChildren(); |
| 31 this._resultsView.removeChildren(); | 48 if (!this._treeOutline.rootElement().childCount()) |
| 49 this._showLandingPage(); |
| 32 } | 50 } |
| 33 | 51 |
| 34 /** | 52 _deleteSelected() { |
| 35 * @param {!Element} auditsViewElement | 53 var selection = this._treeOutline.selectedTreeElement; |
| 36 */ | 54 if (selection) |
| 37 _createLauncherUI(auditsViewElement) { | 55 this._treeOutline.removeChild(selection); |
| 38 auditsViewElement.createChild('div', 'audits2-logo'); | 56 if (!this._treeOutline.rootElement().childCount()) |
| 57 this._showLandingPage(); |
| 58 } |
| 59 |
| 60 _showLandingPage() { |
| 61 this.mainElement().removeChildren(); |
| 62 var landingPage = this.mainElement().createChild('div', 'vbox audits2-landin
g-page'); |
| 63 var landingCenter = landingPage.createChild('div', 'vbox audits2-landing-cen
ter'); |
| 64 landingCenter.createChild('div', 'audits2-logo'); |
| 65 var text = landingCenter.createChild('div', 'audits2-landing-text'); |
| 66 text.createChild('span', 'audits2-landing-bold-text').textContent = Common.U
IString('Audits'); |
| 67 text.createChild('span').textContent = Common.UIString(' help you identify a
nd fix common problems that affect' + |
| 68 ' your site\'s performance, accessibility, and user experience. '); |
| 69 var link = text.createChild('span', 'link'); |
| 70 link.textContent = Common.UIString('Learn more'); |
| 71 link.addEventListener( |
| 72 'click', () => InspectorFrontendHost.openInNewTab('https://developers.go
ogle.com/web/tools/lighthouse/')); |
| 73 |
| 74 var newButton = UI.createTextButton( |
| 75 Common.UIString('Perform an audit\u2026'), this._showLauncherUI.bind(thi
s), 'material-button default'); |
| 76 landingCenter.appendChild(newButton); |
| 77 } |
| 78 |
| 79 _showLauncherUI() { |
| 80 this._dialog = new UI.Dialog(); |
| 81 this._dialog.setOutsideClickCallback(event => event.consume(true)); |
| 82 var root = UI.createShadowRootWithCoreStyles(this._dialog.contentElement, 'a
udits2/audits2Dialog.css'); |
| 83 var auditsViewElement = root.createChild('div', 'audits2-view'); |
| 39 var uiElement = auditsViewElement.createChild('div'); | 84 var uiElement = auditsViewElement.createChild('div'); |
| 40 var headerElement = uiElement.createChild('header'); | 85 var headerElement = uiElement.createChild('header'); |
| 41 headerElement.createChild('p').textContent = Common.UIString( | 86 headerElement.createChild('p').textContent = Common.UIString('Audits to perf
orm'); |
| 42 'Audits will analyze the page against modern development best practices
and collect useful performance metrics and diagnostics. Select audits to collect
:'); | |
| 43 uiElement.appendChild(headerElement); | 87 uiElement.appendChild(headerElement); |
| 44 | 88 |
| 45 var auditSelectorForm = uiElement.createChild('form', 'audits2-form'); | 89 var auditSelectorForm = uiElement.createChild('form', 'audits2-form'); |
| 46 | 90 |
| 47 this._settings | 91 for (var preset of Audits2.Audits2Panel.Presets) { |
| 48 .map(setting => new UI.ToolbarSettingCheckbox(setting)) | 92 preset.setting.setTitle(preset.title); |
| 49 .forEach(checkbox => auditSelectorForm.appendChild(checkbox.element)); | 93 var checkbox = new UI.ToolbarSettingCheckbox(preset.setting); |
| 94 var row = auditSelectorForm.createChild('div', 'vbox audits2-launcher-row'
); |
| 95 row.appendChild(checkbox.element); |
| 96 row.createChild('span', 'audits2-launcher-description dimmed').textContent
= preset.description; |
| 97 } |
| 50 | 98 |
| 51 this._startButton = UI.createTextButton( | 99 this._startButton = |
| 52 Common.UIString('Audit this page'), this._startButtonClicked.bind(this),
'run-audit audit-btn'); | 100 UI.createTextButton(Common.UIString('Run audit'), this._start.bind(this)
, 'material-button default'); |
| 53 auditSelectorForm.appendChild(this._startButton); | 101 auditSelectorForm.appendChild(this._startButton); |
| 102 this._cancelButton = UI.createTextButton(Common.UIString('Cancel'), this._ca
ncel.bind(this), 'material-button'); |
| 103 auditSelectorForm.appendChild(this._cancelButton); |
| 54 | 104 |
| 55 this._statusView = this._createStatusView(uiElement); | 105 this._statusView = this._createStatusView(uiElement); |
| 106 |
| 107 this._dialog.setSizeBehavior(UI.GlassPane.SizeBehavior.SetExactWidthMaxHeigh
t); |
| 108 this._dialog.setMaxContentSize(new UI.Size(600, 400)); |
| 109 this._dialog.show(this.mainElement()); |
| 110 auditsViewElement.tabIndex = 0; |
| 111 auditsViewElement.focus(); |
| 56 } | 112 } |
| 57 | 113 |
| 58 /** | 114 /** |
| 59 * @param {!Element} launcherUIElement | 115 * @param {!Element} launcherUIElement |
| 60 * @return {!Element} | 116 * @return {!Element} |
| 61 */ | 117 */ |
| 62 _createStatusView(launcherUIElement) { | 118 _createStatusView(launcherUIElement) { |
| 63 var statusView = launcherUIElement.createChild('div', 'audits2-status hbox h
idden'); | 119 var statusView = launcherUIElement.createChild('div', 'audits2-status hbox h
idden'); |
| 64 this._statusIcon = statusView.createChild('span', 'icon'); | 120 this._statusIcon = statusView.createChild('span', 'icon'); |
| 65 this._statusElement = statusView.createChild('p'); | 121 this._statusElement = statusView.createChild('p'); |
| 66 this._updateStatus(Common.UIString('Loading...')); | 122 this._updateStatus(Common.UIString('Loading...')); |
| 67 return statusView; | 123 return statusView; |
| 68 } | 124 } |
| 69 | 125 |
| 70 _start() { | 126 _start() { |
| 127 this._dialog.setCloseOnEscape(false); |
| 71 this._inspectedURL = SDK.targetManager.mainTarget().inspectedURL(); | 128 this._inspectedURL = SDK.targetManager.mainTarget().inspectedURL(); |
| 72 | 129 |
| 73 const categoryIDs = this._settings.map(setting => { | 130 var categoryIDs = []; |
| 74 const preset = Audits2.Audits2Panel.Presets.find(preset => preset.id === s
etting.name); | 131 for (var preset of Audits2.Audits2Panel.Presets) { |
| 75 return {configID: preset.configID, value: setting.get()}; | 132 if (preset.setting.get()) |
| 76 }).filter(agg => !!agg.value).map(agg => agg.configID); | 133 categoryIDs.push(preset.configID); |
| 134 } |
| 77 | 135 |
| 78 return Promise.resolve() | 136 return Promise.resolve() |
| 79 .then(_ => this._protocolService.attach()) | 137 .then(_ => this._protocolService.attach()) |
| 80 .then(_ => { | 138 .then(_ => { |
| 81 this._auditRunning = true; | 139 this._auditRunning = true; |
| 82 this._updateButton(); | 140 this._updateButton(); |
| 83 this._updateStatus(Common.UIString('Loading...')); | 141 this._updateStatus(Common.UIString('Loading\u2026')); |
| 84 }) | 142 }) |
| 85 .then(_ => this._protocolService.startLighthouse(this._inspectedURL, cat
egoryIDs)) | 143 .then(_ => this._protocolService.startLighthouse(this._inspectedURL, cat
egoryIDs)) |
| 86 .then(lighthouseResult => { | 144 .then(lighthouseResult => { |
| 87 this._finish(lighthouseResult); | 145 this._finish(lighthouseResult); |
| 88 return this._stop(); | 146 return this._stop(); |
| 89 }).catch(err => { | 147 }) |
| 90 if (err instanceof Error) this._renderBugReport(err); | 148 .catch(err => { |
| 149 if (err instanceof Error) |
| 150 this._renderBugReport(err); |
| 91 }); | 151 }); |
| 92 } | 152 } |
| 93 | 153 |
| 94 /** | 154 _hideDialog() { |
| 95 * @param {!Event} event | 155 if (!this._dialog) |
| 96 */ | 156 return; |
| 97 _startButtonClicked(event) { | 157 this._dialog.hide(); |
| 158 delete this._dialog; |
| 159 delete this._statusView; |
| 160 delete this._statusIcon; |
| 161 delete this._statusElement; |
| 162 delete this._startButton; |
| 163 delete this._cancelButton; |
| 164 } |
| 165 |
| 166 _cancel() { |
| 98 if (this._auditRunning) { | 167 if (this._auditRunning) { |
| 99 this._updateStatus(Common.UIString('Cancelling...')); | 168 this._updateStatus(Common.UIString('Cancelling\u2026')); |
| 100 this._stop(); | 169 this._stop(); |
| 101 return; | 170 } else { |
| 171 this._hideDialog(); |
| 102 } | 172 } |
| 103 this._start(); | |
| 104 } | 173 } |
| 105 | 174 |
| 106 _updateButton() { | 175 _updateButton() { |
| 107 this._startButton.textContent = | 176 if (!this._dialog) |
| 108 this._auditRunning ? Common.UIString('Cancel audit') : Common.UIString('
Audit this page'); | 177 return; |
| 109 this._startButton.classList.toggle('started', this._auditRunning); | 178 this._startButton.classList.toggle('default', !this._auditRunning); |
| 179 this._startButton.disabled = this._auditRunning; |
| 110 this._statusView.classList.toggle('hidden', !this._auditRunning); | 180 this._statusView.classList.toggle('hidden', !this._auditRunning); |
| 111 } | 181 } |
| 112 | 182 |
| 113 /** | 183 /** |
| 114 * @param {string} statusMessage | 184 * @param {string} statusMessage |
| 115 */ | 185 */ |
| 116 _updateStatus(statusMessage) { | 186 _updateStatus(statusMessage) { |
| 187 if (!this._dialog) |
| 188 return; |
| 117 this._statusElement.textContent = statusMessage; | 189 this._statusElement.textContent = statusMessage; |
| 118 } | 190 } |
| 119 | 191 |
| 120 /** | 192 /** |
| 121 * @return {!Promise<undefined>} | 193 * @return {!Promise<undefined>} |
| 122 */ | 194 */ |
| 123 _stop() { | 195 _stop() { |
| 124 return this._protocolService.detach().then(_ => { | 196 return this._protocolService.detach().then(_ => { |
| 125 this._auditRunning = false; | 197 this._auditRunning = false; |
| 126 this._updateButton(); | 198 this._updateButton(); |
| 127 var resourceTreeModel = SDK.targetManager.mainTarget().model(SDK.ResourceT
reeModel); | 199 var resourceTreeModel = SDK.targetManager.mainTarget().model(SDK.ResourceT
reeModel); |
| 128 if (resourceTreeModel && this._inspectedURL !== SDK.targetManager.mainTarg
et().inspectedURL()) | 200 if (resourceTreeModel && this._inspectedURL !== SDK.targetManager.mainTarg
et().inspectedURL()) |
| 129 resourceTreeModel.navigate(this._inspectedURL); | 201 resourceTreeModel.navigate(this._inspectedURL).then(() => this._hideDial
og()); |
| 130 | 202 else |
| 203 this._hideDialog(); |
| 131 }); | 204 }); |
| 132 } | 205 } |
| 133 | 206 |
| 134 /** | 207 /** |
| 135 * @param {!ReportRenderer.ReportJSON} lighthouseResult | 208 * @param {!ReportRenderer.ReportJSON} lighthouseResult |
| 136 */ | 209 */ |
| 137 _finish(lighthouseResult) { | 210 _finish(lighthouseResult) { |
| 138 if (lighthouseResult === null) { | 211 if (lighthouseResult === null) { |
| 139 this._updateStatus(Common.UIString('Auditing failed.')); | 212 this._updateStatus(Common.UIString('Auditing failed.')); |
| 140 return; | 213 return; |
| 141 } | 214 } |
| 142 this._resultsView.removeChildren(); | 215 var treeElement = new Audits2.Audits2Panel.TreeElement(lighthouseResult, thi
s.mainElement()); |
| 143 | 216 this._treeOutline.appendChild(treeElement); |
| 144 var url = lighthouseResult.url; | 217 treeElement._populate(); |
| 145 var timestamp = lighthouseResult.generatedTime; | 218 treeElement.select(); |
| 146 this._createResultsBar(this._resultsView, url, timestamp); | 219 this._hideDialog(); |
| 147 this._renderReport(this._resultsView, lighthouseResult); | |
| 148 this.contentElement.classList.add('show-results'); | |
| 149 } | 220 } |
| 150 | 221 |
| 151 /** | 222 /** |
| 152 * @param {!Error} err | 223 * @param {!Error} err |
| 153 */ | 224 */ |
| 154 _renderBugReport(err) { | 225 _renderBugReport(err) { |
| 155 console.error(err); | 226 console.error(err); |
| 156 this._statusElement.textContent = ''; | 227 this._statusElement.textContent = ''; |
| 157 this._statusIcon.classList.add('error'); | 228 this._statusIcon.classList.add('error'); |
| 158 this._statusElement.createTextChild(Common.UIString('We ran into an error. '
)); | 229 this._statusElement.createTextChild(Common.UIString('We ran into an error. '
)); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 172 qsBody += '**Stack Trace**:\n ```' + err.stack + '```'; | 243 qsBody += '**Stack Trace**:\n ```' + err.stack + '```'; |
| 173 var body = '&body=' + encodeURI(qsBody); | 244 var body = '&body=' + encodeURI(qsBody); |
| 174 | 245 |
| 175 var reportErrorEl = parentElem.createChild('a', 'audits2-link audits2-report
-error'); | 246 var reportErrorEl = parentElem.createChild('a', 'audits2-link audits2-report
-error'); |
| 176 reportErrorEl.href = baseURI + title + body; | 247 reportErrorEl.href = baseURI + title + body; |
| 177 reportErrorEl.textContent = Common.UIString('Report this bug'); | 248 reportErrorEl.textContent = Common.UIString('Report this bug'); |
| 178 reportErrorEl.target = '_blank'; | 249 reportErrorEl.target = '_blank'; |
| 179 } | 250 } |
| 180 | 251 |
| 181 /** | 252 /** |
| 182 * @param {!Element} resultsView | 253 * @param {!DataTransfer} dataTransfer |
| 183 * @param {!ReportRenderer.ReportJSON} lighthouseResult | |
| 184 * @suppressGlobalPropertiesCheck | |
| 185 */ | 254 */ |
| 186 _renderReport(resultsView, lighthouseResult) { | 255 _handleDrop(dataTransfer) { |
| 187 var reportContainer = resultsView.createChild('div', 'report-container lh-ro
ot'); | 256 var items = dataTransfer.items; |
| 188 | 257 if (!items.length) |
| 189 var dom = new DOM(document); | |
| 190 var detailsRenderer = new DetailsRenderer(dom); | |
| 191 var categoryRenderer = new CategoryRenderer(dom, detailsRenderer); | |
| 192 var renderer = new Audits2.ReportRenderer(dom, categoryRenderer); | |
| 193 | |
| 194 var templatesHTML = Runtime.cachedResources['audits2/lighthouse/templates.ht
ml']; | |
| 195 var templatesDOM = new DOMParser().parseFromString(templatesHTML, 'text/html
'); | |
| 196 if (!templatesDOM) | |
| 197 return; | 258 return; |
| 198 | 259 var item = items[0]; |
| 199 renderer.setTemplateContext(templatesDOM); | 260 if (item.kind === 'file') { |
| 200 renderer.renderReport(lighthouseResult, reportContainer); | 261 var entry = items[0].webkitGetAsEntry(); |
| 262 if (!entry.isFile) |
| 263 return; |
| 264 entry.file(file => { |
| 265 var reader = new FileReader(); |
| 266 reader.onload = () => this._loadedFromFile(/** @type {string} */ (reader
.result)); |
| 267 reader.readAsText(file); |
| 268 }); |
| 269 } |
| 201 } | 270 } |
| 202 | 271 |
| 203 /** | 272 /** |
| 204 * @param {!Element} resultsView | 273 * @param {string} profile |
| 205 * @param {string} url | |
| 206 * @param {string} timestamp | |
| 207 */ | 274 */ |
| 208 _createResultsBar(resultsView, url, timestamp) { | 275 _loadedFromFile(profile) { |
| 209 var elem = resultsView.createChild('div', 'results-bar hbox'); | 276 var data = JSON.parse(profile); |
| 210 elem.createChild('div', 'audits2-logo audits2-logo-small'); | 277 if (!data['lighthouseVersion']) |
| 211 | 278 return; |
| 212 var summaryElem = elem.createChild('div', 'audits2-summary'); | 279 this._finish(/** @type {!ReportRenderer.ReportJSON} */(data)); |
| 213 var reportFor = summaryElem.createChild('span'); | |
| 214 reportFor.createTextChild('Report for '); | |
| 215 var urlElem = reportFor.createChild('b'); | |
| 216 urlElem.textContent = url; | |
| 217 var timeElem = summaryElem.createChild('span'); | |
| 218 timeElem.textContent = | |
| 219 `Generated at ${new Date(timestamp).toLocaleDateString()} ${new Date(tim
estamp).toLocaleTimeString()}`; | |
| 220 | |
| 221 var newAuditButton = | |
| 222 UI.createTextButton(Common.UIString('New Audit'), this._reset.bind(this)
, 'new-audit audit-btn'); | |
| 223 elem.appendChild(newAuditButton); | |
| 224 } | 280 } |
| 225 }; | 281 }; |
| 226 | 282 |
| 227 /** | 283 /** |
| 228 * @override | 284 * @override |
| 229 */ | 285 */ |
| 230 Audits2.ReportRenderer = class extends ReportRenderer { | 286 Audits2.Audits2Panel.ReportRenderer = class extends ReportRenderer { |
| 231 /** | 287 /** |
| 232 * Provides empty element for left nav | 288 * Provides empty element for left nav |
| 233 * @override | 289 * @override |
| 234 * @returns {!DocumentFragment} | 290 * @returns {!DocumentFragment} |
| 235 */ | 291 */ |
| 236 _renderReportNav() { | 292 _renderReportNav() { |
| 237 return createDocumentFragment(); | 293 return createDocumentFragment(); |
| 238 } | 294 } |
| 295 |
| 296 /** |
| 297 * @param {!ReportRenderer.ReportJSON} report |
| 298 * @override |
| 299 * @return {!DocumentFragment} |
| 300 */ |
| 301 _renderReportHeader(report) { |
| 302 return createDocumentFragment(); |
| 303 } |
| 239 }; | 304 }; |
| 240 | 305 |
| 241 | |
| 242 class ReportUIFeatures { | 306 class ReportUIFeatures { |
| 243 /** | 307 /** |
| 244 * @param {!ReportRenderer.ReportJSON} report | 308 * @param {!ReportRenderer.ReportJSON} report |
| 245 */ | 309 */ |
| 246 initFeatures(report) {} | 310 initFeatures(report) { |
| 311 } |
| 247 } | 312 } |
| 248 | 313 |
| 249 /** @typedef {{id: string, configID: string, description: string}} */ | 314 /** @typedef {{setting: !Common.Setting, configID: string, title: string, descri
ption: string}} */ |
| 250 Audits2.Audits2Panel.Preset; | 315 Audits2.Audits2Panel.Preset; |
| 251 | 316 |
| 252 /** @type {!Array.<!Audits2.Audits2Panel.Preset>} */ | 317 /** @type {!Array.<!Audits2.Audits2Panel.Preset>} */ |
| 253 Audits2.Audits2Panel.Presets = [ | 318 Audits2.Audits2Panel.Presets = [ |
| 254 // configID maps to Lighthouse's Object.keys(config.categories)[0] value | 319 // configID maps to Lighthouse's Object.keys(config.categories)[0] value |
| 255 {id: 'audits2_cat_pwa', configID: 'pwa', description: 'Progressive Web App'}, | 320 { |
| 256 {id: 'audits2_cat_perf', configID: 'performance', description: 'Performance me
trics and diagnostics'}, | 321 setting: Common.settings.createSetting('audits2.cat_pwa', true), |
| 257 {id: 'audits2_cat_a11y', configID: 'accessibility', description: 'Accessibilit
y'}, | 322 configID: 'pwa', |
| 258 {id: 'audits2_cat_best_practices', configID: 'best-practices', description: 'M
odern best practices'}, | 323 title: 'Progressive Web App', |
| 324 description: 'Does this page meet the standard of a Progressive Web App' |
| 325 }, |
| 326 { |
| 327 setting: Common.settings.createSetting('audits2.cat_perf', true), |
| 328 configID: 'performance', |
| 329 title: 'Performance', |
| 330 description: 'How long does this app take to show content and become usable' |
| 331 }, |
| 332 { |
| 333 setting: Common.settings.createSetting('audits2.cat_best_practices', true), |
| 334 configID: 'best-practices', |
| 335 title: 'Best practices', |
| 336 description: 'Does this page follow best practices for modern web developmen
t' |
| 337 }, |
| 338 { |
| 339 setting: Common.settings.createSetting('audits2.cat_a11y', true), |
| 340 configID: 'accessibility', |
| 341 title: 'Accessibility', |
| 342 description: 'Is this page usable by people with disabilities or impairments
' |
| 343 }, |
| 259 ]; | 344 ]; |
| 260 | 345 |
| 261 Audits2.ProtocolService = class extends Common.Object { | 346 Audits2.ProtocolService = class extends Common.Object { |
| 262 constructor() { | 347 constructor() { |
| 263 super(); | 348 super(); |
| 264 /** @type {?Protocol.InspectorBackend.Connection} */ | 349 /** @type {?Protocol.InspectorBackend.Connection} */ |
| 265 this._rawConnection = null; | 350 this._rawConnection = null; |
| 266 /** @type {?Services.ServiceManager.Service} */ | 351 /** @type {?Services.ServiceManager.Service} */ |
| 267 this._backend = null; | 352 this._backend = null; |
| 268 /** @type {?Promise} */ | 353 /** @type {?Promise} */ |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 330 * @param {!Object=} params | 415 * @param {!Object=} params |
| 331 * @return {!Promise<!ReportRenderer.ReportJSON>} | 416 * @return {!Promise<!ReportRenderer.ReportJSON>} |
| 332 */ | 417 */ |
| 333 _send(method, params) { | 418 _send(method, params) { |
| 334 if (!this._backendPromise) | 419 if (!this._backendPromise) |
| 335 this._initWorker(); | 420 this._initWorker(); |
| 336 | 421 |
| 337 return this._backendPromise.then(_ => this._backend.send(method, params)); | 422 return this._backendPromise.then(_ => this._backend.send(method, params)); |
| 338 } | 423 } |
| 339 }; | 424 }; |
| 425 |
| 426 Audits2.Audits2Panel.TreeElement = class extends UI.TreeElement { |
| 427 /** |
| 428 * @param {!ReportRenderer.ReportJSON} lighthouseResult |
| 429 * @param {!Element} resultsView |
| 430 */ |
| 431 constructor(lighthouseResult, resultsView) { |
| 432 super('', false); |
| 433 this._lighthouseResult = lighthouseResult; |
| 434 this._resultsView = resultsView; |
| 435 /** @type {?Element} */ |
| 436 this._reportContainer = null; |
| 437 |
| 438 var url = new Common.ParsedURL(lighthouseResult.url); |
| 439 var timestamp = lighthouseResult.generatedTime; |
| 440 var titleElement = this.titleElement(); |
| 441 titleElement.classList.add('audits2-report-tree-item'); |
| 442 titleElement.createChild('div').textContent = url.domain(); |
| 443 titleElement.createChild('span', 'dimmed').textContent = new Date(timestamp)
.toLocaleString(); |
| 444 this.listItemElement.addEventListener('contextmenu', this._handleContextMenu
Event.bind(this), false); |
| 445 } |
| 446 |
| 447 _populate() { |
| 448 for (var category of this._lighthouseResult.reportCategories) { |
| 449 var treeElement = new Audits2.Audits2Panel.TreeSubElement(category.id, cat
egory.name, category.score); |
| 450 this.appendChild(treeElement); |
| 451 } |
| 452 } |
| 453 |
| 454 /** |
| 455 * @override |
| 456 * @param {boolean=} selectedByUser |
| 457 * @return {boolean} |
| 458 */ |
| 459 onselect(selectedByUser) { |
| 460 this._renderReport(); |
| 461 return true; |
| 462 } |
| 463 |
| 464 /** |
| 465 * @param {!Event} event |
| 466 */ |
| 467 _handleContextMenuEvent(event) { |
| 468 var contextMenu = new UI.ContextMenu(event); |
| 469 contextMenu.appendItem(Common.UIString('Save as\u2026'), () => { |
| 470 var url = new Common.ParsedURL(this._lighthouseResult.url).domain(); |
| 471 var timestamp = this._lighthouseResult.generatedTime; |
| 472 var fileName = `${url}-${new Date(timestamp).toISO8601Compact()}.json`; |
| 473 Workspace.fileManager.save(fileName, JSON.stringify(this._lighthouseResult
), true); |
| 474 }); |
| 475 contextMenu.show(); |
| 476 } |
| 477 |
| 478 /** |
| 479 * @override |
| 480 */ |
| 481 onunbind() { |
| 482 if (this._reportContainer && this._reportContainer.parentElement) |
| 483 this._reportContainer.remove(); |
| 484 } |
| 485 |
| 486 _renderReport() { |
| 487 this._resultsView.removeChildren(); |
| 488 if (this._reportContainer) { |
| 489 this._resultsView.appendChild(this._reportContainer); |
| 490 return; |
| 491 } |
| 492 |
| 493 this._reportContainer = this._resultsView.createChild('div', 'report-contain
er lh-root'); |
| 494 |
| 495 var dom = new DOM(/** @type {!Document} */(this._resultsView.ownerDocument))
; |
| 496 var detailsRenderer = new DetailsRenderer(dom); |
| 497 var categoryRenderer = new CategoryRenderer(dom, detailsRenderer); |
| 498 var renderer = new Audits2.Audits2Panel.ReportRenderer(dom, categoryRenderer
); |
| 499 |
| 500 var templatesHTML = Runtime.cachedResources['audits2/lighthouse/templates.ht
ml']; |
| 501 var templatesDOM = new DOMParser().parseFromString(templatesHTML, 'text/html
'); |
| 502 if (!templatesDOM) |
| 503 return; |
| 504 |
| 505 renderer.setTemplateContext(templatesDOM); |
| 506 renderer.renderReport(this._lighthouseResult, this._reportContainer); |
| 507 } |
| 508 }; |
| 509 |
| 510 Audits2.Audits2Panel.TreeSubElement = class extends UI.TreeElement { |
| 511 /** |
| 512 * @param {string} id |
| 513 * @param {string} name |
| 514 * @param {number} score |
| 515 */ |
| 516 constructor(id, name, score) { |
| 517 super(''); |
| 518 this._id = id; |
| 519 this.listItemElement.textContent = name; |
| 520 var label = Util.calculateRating(score); |
| 521 var subtitleElement = this.listItemElement.createChild('span', 'lh-root audi
ts2-tree-subtitle-' + label); |
| 522 subtitleElement.textContent = String(Math.round(score)); |
| 523 } |
| 524 |
| 525 /** |
| 526 * @override |
| 527 * @return {boolean} |
| 528 */ |
| 529 onselect() { |
| 530 this.parent._renderReport(); |
| 531 var node = this.parent._resultsView.querySelector('.lh-category[id=' + this.
_id + ']'); |
| 532 if (node) { |
| 533 node.scrollIntoView(true); |
| 534 return true; |
| 535 } |
| 536 return false; |
| 537 } |
| 538 }; |
| OLD | NEW |