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.PanelWithSidebar { | 8 Audits2.Audits2Panel = class extends UI.PanelWithSidebar { |
9 constructor() { | 9 constructor() { |
10 super('audits2'); | 10 super('audits2'); |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
148 } | 148 } |
149 | 149 |
150 return Promise.resolve() | 150 return Promise.resolve() |
151 .then(_ => this._protocolService.attach()) | 151 .then(_ => this._protocolService.attach()) |
152 .then(_ => { | 152 .then(_ => { |
153 this._auditRunning = true; | 153 this._auditRunning = true; |
154 this._updateButton(); | 154 this._updateButton(); |
155 this._updateStatus(Common.UIString('Loading\u2026')); | 155 this._updateStatus(Common.UIString('Loading\u2026')); |
156 }) | 156 }) |
157 .then(_ => this._protocolService.startLighthouse(this._inspectedURL, cat
egoryIDs)) | 157 .then(_ => this._protocolService.startLighthouse(this._inspectedURL, cat
egoryIDs)) |
158 .then(lighthouseResult => { | 158 .then(lighthouseResult => |
159 if (lighthouseResult && lighthouseResult.fatal) { | 159 this._stopAndReattach().then(() => this._buildReportUI(lighthouseResul
t)) |
160 const error = new Error(lighthouseResult.message); | 160 ).catch(err => { |
161 error.stack = lighthouseResult.stack; | |
162 throw error; | |
163 } | |
164 | |
165 return this._stopAndReattach().then(() => this._buildReportUI(lighthou
seResult)); | |
166 }) | |
167 .catch(err => { | |
168 if (err instanceof Error) | 161 if (err instanceof Error) |
169 this._renderBugReport(err); | 162 this._renderBugReport(err); |
170 }); | 163 }); |
171 } | 164 } |
172 | 165 |
173 _hideDialog() { | 166 _hideDialog() { |
174 if (!this._dialog) | 167 if (!this._dialog) |
175 return; | 168 return; |
176 this._dialog.hide(); | 169 this._dialog.hide(); |
177 | 170 |
178 var emulationModel = self.singleton(Emulation.DeviceModeModel); | 171 var emulationModel = self.singleton(Emulation.DeviceModeModel); |
179 emulationModel.enabledSetting().set(this._emulationEnabledBefore); | 172 emulationModel.enabledSetting().set(this._emulationEnabledBefore); |
180 emulationModel.deviceOutlineSetting().set(this._emulationOutlineEnabledBefor
e); | 173 emulationModel.deviceOutlineSetting().set(this._emulationOutlineEnabledBefor
e); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
253 this._hideDialog(); | 246 this._hideDialog(); |
254 } | 247 } |
255 | 248 |
256 /** | 249 /** |
257 * @param {!Error} err | 250 * @param {!Error} err |
258 */ | 251 */ |
259 _renderBugReport(err) { | 252 _renderBugReport(err) { |
260 console.error(err); | 253 console.error(err); |
261 this._statusElement.textContent = ''; | 254 this._statusElement.textContent = ''; |
262 this._statusIcon.classList.add('error'); | 255 this._statusIcon.classList.add('error'); |
263 this._statusElement.createTextChild(Common.UIString('Ah, sorry! We ran into
an error: ')); | 256 this._statusElement.createTextChild(Common.UIString('We ran into an error. '
)); |
264 this._statusElement.createChild('em').createTextChild(err.message); | |
265 this._createBugReportLink(err, this._statusElement); | 257 this._createBugReportLink(err, this._statusElement); |
266 } | 258 } |
267 | 259 |
268 /** | 260 /** |
269 * @param {!Error} err | 261 * @param {!Error} err |
270 * @param {!Element} parentElem | 262 * @param {!Element} parentElem |
271 */ | 263 */ |
272 _createBugReportLink(err, parentElem) { | 264 _createBugReportLink(err, parentElem) { |
273 var baseURI = 'https://github.com/GoogleChrome/lighthouse/issues/new?'; | 265 var baseURI = 'https://github.com/GoogleChrome/lighthouse/issues/new?'; |
274 var title = encodeURI('title=DevTools Error: ' + err.message.substring(0, 60
)); | 266 var title = encodeURI('title=DevTools Error: ' + err.message.substring(0, 60
)); |
275 | 267 |
276 var issueBody = ` | 268 var qsBody = ''; |
277 **Initial URL**: ${this._inspectedURL} | 269 qsBody += '**Error Message**: ' + err.message + '\n'; |
278 **Chrome Version**: ${navigator.userAgent.match(/Chrome\/(\S+)/)[1]} | 270 qsBody += '**Stack Trace**:\n ```' + err.stack + '```'; |
279 **Error Message**: ${err.message} | 271 var body = '&body=' + encodeURI(qsBody); |
280 **Stack Trace**: | |
281 \`\`\` | |
282 ${err.stack} | |
283 \`\`\` | |
284 `; | |
285 var body = '&body=' + encodeURI(issueBody.trim()); | |
286 | 272 |
287 var reportErrorEl = parentElem.createChild('a', 'audits2-link audits2-report
-error'); | 273 var reportErrorEl = parentElem.createChild('a', 'audits2-link audits2-report
-error'); |
288 reportErrorEl.href = baseURI + title + body; | 274 reportErrorEl.href = baseURI + title + body; |
289 reportErrorEl.textContent = Common.UIString('Report this bug'); | 275 reportErrorEl.textContent = Common.UIString('Report this bug'); |
290 reportErrorEl.target = '_blank'; | 276 reportErrorEl.target = '_blank'; |
291 } | 277 } |
292 | 278 |
293 /** | 279 /** |
294 * @param {!DataTransfer} dataTransfer | 280 * @param {!DataTransfer} dataTransfer |
295 */ | 281 */ |
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
547 this._reportContainer.remove(); | 533 this._reportContainer.remove(); |
548 } | 534 } |
549 | 535 |
550 _renderReport() { | 536 _renderReport() { |
551 this._resultsView.removeChildren(); | 537 this._resultsView.removeChildren(); |
552 if (this._reportContainer) { | 538 if (this._reportContainer) { |
553 this._resultsView.appendChild(this._reportContainer); | 539 this._resultsView.appendChild(this._reportContainer); |
554 return; | 540 return; |
555 } | 541 } |
556 | 542 |
557 this._reportContainer = this._resultsView.createChild('div', 'report-contain
er lh-vars lh-root lh-devtools'); | 543 this._reportContainer = this._resultsView.createChild('div', 'report-contain
er lh-vars lh-root'); |
558 | 544 |
559 var dom = new DOM(/** @type {!Document} */ (this._resultsView.ownerDocument)
); | 545 var dom = new DOM(/** @type {!Document} */ (this._resultsView.ownerDocument)
); |
560 var detailsRenderer = new Audits2.DetailsRenderer(dom); | 546 var detailsRenderer = new Audits2.DetailsRenderer(dom); |
561 var categoryRenderer = new CategoryRenderer(dom, detailsRenderer); | 547 var categoryRenderer = new CategoryRenderer(dom, detailsRenderer); |
562 var renderer = new Audits2.Audits2Panel.ReportRenderer(dom, categoryRenderer
); | 548 var renderer = new Audits2.Audits2Panel.ReportRenderer(dom, categoryRenderer
); |
563 | 549 |
564 var templatesHTML = Runtime.cachedResources['audits2/lighthouse/templates.ht
ml']; | 550 var templatesHTML = Runtime.cachedResources['audits2/lighthouse/templates.ht
ml']; |
565 var templatesDOM = new DOMParser().parseFromString(templatesHTML, 'text/html
'); | 551 var templatesDOM = new DOMParser().parseFromString(templatesHTML, 'text/html
'); |
566 if (!templatesDOM) | 552 if (!templatesDOM) |
567 return; | 553 return; |
568 | 554 |
569 renderer.setTemplateContext(templatesDOM); | 555 renderer.setTemplateContext(templatesDOM); |
570 renderer.renderReport(this._lighthouseResult, this._reportContainer); | 556 renderer.renderReport(this._lighthouseResult, this._reportContainer); |
| 557 |
| 558 var performanceScoreElement = this._reportContainer.querySelector('.lh-categ
ory[id=performance] .lh-score'); |
| 559 var artifacts = this._lighthouseResult['artifacts']; |
| 560 if (!performanceScoreElement || !artifacts) |
| 561 return; |
| 562 var tracePass = artifacts['traces'] ? artifacts['traces']['defaultPass'] : n
ull; |
| 563 if (!tracePass) |
| 564 return; |
| 565 |
| 566 var fmp = this._lighthouseResult['audits']['first-meaningful-paint']; |
| 567 if (!fmp || !fmp['extendedInfo']) |
| 568 return; |
| 569 |
| 570 var tti = this._lighthouseResult['audits']['time-to-interactive']; |
| 571 if (!tti || !tti['extendedInfo']) |
| 572 return; |
| 573 |
| 574 var navStart = fmp['extendedInfo']['value']['timestamps']['navStart']; |
| 575 var markers = [ |
| 576 { |
| 577 title: Common.UIString('First contentful paint'), |
| 578 value: (fmp['extendedInfo']['value']['timestamps']['fCP'] - navStart) /
1000 |
| 579 }, |
| 580 { |
| 581 title: Common.UIString('First meaningful paint'), |
| 582 value: (fmp['extendedInfo']['value']['timestamps']['fMP'] - navStart) /
1000 |
| 583 }, |
| 584 { |
| 585 title: Common.UIString('Time to interactive'), |
| 586 value: (tti['extendedInfo']['value']['timestamps']['timeToInteractive']
- navStart) / 1000 |
| 587 }, |
| 588 { |
| 589 title: Common.UIString('Visually ready'), |
| 590 value: (tti['extendedInfo']['value']['timestamps']['visuallyReady'] - na
vStart) / 1000 |
| 591 } |
| 592 ]; |
| 593 |
| 594 var timeSpan = Math.max(...markers.map(marker => marker.value)); |
| 595 var screenshots = tracePass.traceEvents.filter(e => e.cat === 'disabled-by-d
efault-devtools.screenshot'); |
| 596 var timelineElement = createElementWithClass('div', 'audits2-timeline'); |
| 597 var filmStripElement = timelineElement.createChild('div', 'audits2-filmstrip
'); |
| 598 |
| 599 var numberOfFrames = 8; |
| 600 var roundToMs = 100; |
| 601 var timeStep = (Math.ceil(timeSpan / numberOfFrames / roundToMs)) * roundToM
s; |
| 602 |
| 603 for (var time = 0; time < timeSpan; time += timeStep) { |
| 604 var frameForTime = null; |
| 605 for (var e of screenshots) { |
| 606 if ((e.ts - navStart) / 1000 < time + timeStep) |
| 607 frameForTime = e.args.snapshot; |
| 608 } |
| 609 var frame = filmStripElement.createChild('div', 'frame'); |
| 610 frame.createChild('div', 'time').textContent = Number.millisToString(time
+ timeStep); |
| 611 |
| 612 var thumbnail = frame.createChild('div', 'thumbnail'); |
| 613 if (frameForTime) { |
| 614 var img = thumbnail.createChild('img'); |
| 615 img.src = 'data:image/jpg;base64,' + frameForTime; |
| 616 } |
| 617 } |
| 618 |
| 619 for (var marker of markers) { |
| 620 var markerElement = timelineElement.createChild('div', 'audits2-timeline-m
arker'); |
| 621 markerElement.createChild('div', 'audits2-timeline-bar').style.width = |
| 622 (100 * (marker.value / timeSpan) | 0) + '%'; |
| 623 markerElement.createChild('span').textContent = Common.UIString('%s: ', ma
rker.title); |
| 624 markerElement.createChild('span', 'audits2-timeline-subtitle').textContent
= Number.millisToString(marker.value); |
| 625 } |
| 626 |
| 627 performanceScoreElement.parentElement.insertBefore(timelineElement, performa
nceScoreElement.nextSibling); |
571 } | 628 } |
572 }; | 629 }; |
573 | 630 |
574 Audits2.Audits2Panel.TreeSubElement = class extends UI.TreeElement { | 631 Audits2.Audits2Panel.TreeSubElement = class extends UI.TreeElement { |
575 /** | 632 /** |
576 * @param {string} id | 633 * @param {string} id |
577 * @param {string} name | 634 * @param {string} name |
578 * @param {number} score | 635 * @param {number} score |
579 */ | 636 */ |
580 constructor(id, name, score) { | 637 constructor(id, name, score) { |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
647 return; | 704 return; |
648 | 705 |
649 var element = Components.DOMPresentationUtils.linkifyNodeReference(node,
undefined, detailsItem.snippet); | 706 var element = Components.DOMPresentationUtils.linkifyNodeReference(node,
undefined, detailsItem.snippet); |
650 origElement.title = ''; | 707 origElement.title = ''; |
651 origElement.textContent = ''; | 708 origElement.textContent = ''; |
652 origElement.appendChild(element); | 709 origElement.appendChild(element); |
653 }); | 710 }); |
654 }); | 711 }); |
655 } | 712 } |
656 }; | 713 }; |
OLD | NEW |