diff --git a/lighthouse-core/audits/byte-efficiency/byte-efficiency-audit.js b/lighthouse-core/audits/byte-efficiency/byte-efficiency-audit.js index 657be72fd4e3..1fd04cad389b 100644 --- a/lighthouse-core/audits/byte-efficiency/byte-efficiency-audit.js +++ b/lighthouse-core/audits/byte-efficiency/byte-efficiency-audit.js @@ -82,11 +82,11 @@ class UnusedBytes extends Audit { return Math.round(totalBytes * compressionRatio); } else if (networkRecord._resourceType && networkRecord._resourceType._name === resourceType) { // This was a regular standalone asset, just use the transfer size. - return networkRecord._transferSize || 0; + return networkRecord.transferSize || 0; } else { // This was an asset that was inlined in a different resource type (e.g. HTML document). // Use the compression ratio of the resource to estimate the total transferred bytes. - const transferSize = networkRecord._transferSize || 0; + const transferSize = networkRecord.transferSize || 0; const resourceSize = networkRecord._resourceSize; const compressionRatio = resourceSize !== undefined ? (transferSize / resourceSize) : 1; return Math.round(totalBytes * compressionRatio); @@ -151,12 +151,12 @@ class UnusedBytes extends Audit { const networkNode = /** @type {NetworkNode} */ (node); const result = resultsByUrl.get(networkNode.record.url); if (!result) return; + const original = networkNode.record.transferSize; - // cloning NetworkRequest objects is difficult, so just stash the original transfer size originalTransferSizes.set(networkNode.record.requestId, original); const wastedBytes = result.wastedBytes; - networkNode.record._transferSize = Math.max(original - wastedBytes, 0); + networkNode.record.transferSize = Math.max(original - wastedBytes, 0); }); const simulationAfterChanges = simulator.simulate(graph, {label: afterLabel}); @@ -167,7 +167,7 @@ class UnusedBytes extends Audit { const networkNode = /** @type {NetworkNode} */ (node); const originalTransferSize = originalTransferSizes.get(networkNode.record.requestId); if (originalTransferSize === undefined) return; - networkNode.record._transferSize = originalTransferSize; + networkNode.record.transferSize = originalTransferSize; }); const savingsOnOverallLoad = simulationBeforeChanges.timeInMs - simulationAfterChanges.timeInMs; diff --git a/lighthouse-core/audits/byte-efficiency/render-blocking-resources.js b/lighthouse-core/audits/byte-efficiency/render-blocking-resources.js index 5d602f606483..767200a6efa7 100644 --- a/lighthouse-core/audits/byte-efficiency/render-blocking-resources.js +++ b/lighthouse-core/audits/byte-efficiency/render-blocking-resources.js @@ -158,17 +158,17 @@ class RenderBlockingResources extends Audit { if (canDeferRequest && isStylesheet) { // We'll inline the used bytes of the stylesheet and assume the rest can be deferred const wastedBytes = wastedCssBytesByUrl.get(networkNode.record.url) || 0; - totalChildNetworkBytes += (networkNode.record._transferSize || 0) - wastedBytes; + totalChildNetworkBytes += (networkNode.record.transferSize || 0) - wastedBytes; } return !canDeferRequest; })); // Add the inlined bytes to the HTML response - const originalTransferSize = minimalFCPGraph.record._transferSize; + const originalTransferSize = minimalFCPGraph.record.transferSize; const safeTransferSize = originalTransferSize || 0; - minimalFCPGraph.record._transferSize = safeTransferSize + totalChildNetworkBytes; + minimalFCPGraph.record.transferSize = safeTransferSize + totalChildNetworkBytes; const estimateAfterInline = simulator.simulate(minimalFCPGraph).timeInMs; - minimalFCPGraph.record._transferSize = originalTransferSize; + minimalFCPGraph.record.transferSize = originalTransferSize; return Math.round(Math.max(originalEstimate - estimateAfterInline, 0)); } diff --git a/lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js b/lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js index d86ebea95b7f..309032470985 100644 --- a/lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js +++ b/lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js @@ -185,7 +185,7 @@ class CacheHeaders extends Audit { if (cacheHitProbability > IGNORE_THRESHOLD_IN_PERCENT) continue; const url = URL.elideDataURI(record._url); - const totalBytes = record._transferSize || 0; + const totalBytes = record.transferSize || 0; const wastedBytes = (1 - cacheHitProbability) * totalBytes; totalWastedBytes += wastedBytes; diff --git a/lighthouse-core/audits/mixed-content.js b/lighthouse-core/audits/mixed-content.js index f676ee7a7077..8387a7993bd0 100644 --- a/lighthouse-core/audits/mixed-content.js +++ b/lighthouse-core/audits/mixed-content.js @@ -3,7 +3,6 @@ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -// @ts-nocheck 'use strict'; const Audit = require('./audit'); @@ -32,18 +31,6 @@ class MixedContent extends Audit { }; } - /** - * Checks whether the resource was securely loaded. - * We special-case data: URLs, as they inherit the security state of their - * referring document url, and so are trivially "upgradeable" for mixed-content purposes. - * - * @param {{scheme: string, protocol: string, securityState: function}} record - * @return {boolean} - */ - static isSecureRecord(record) { - return record.securityState() === 'secure' || record.protocol === 'data'; - } - /** * Upgrades a URL to use HTTPS. * @@ -72,10 +59,10 @@ class MixedContent extends Audit { /** * Simplifies a URL string for display. * - * @param {string} url + * @param {string=} url * @return {string} */ - static displayURL(url) { + static displayURL(url = '') { const displayOptions = { numPathParts: 4, preserveQuery: false, @@ -100,15 +87,15 @@ class MixedContent extends Audit { return Promise.all(computedArtifacts).then(([defaultRecords, upgradedRecords]) => { const insecureRecords = defaultRecords.filter( - record => !MixedContent.isSecureRecord(record)); + record => !record.isSecure); const secureRecords = defaultRecords.filter( - record => MixedContent.isSecureRecord(record)); + record => record.isSecure); const upgradePassHosts = new Set(); const upgradePassSecureHosts = new Set(); upgradedRecords.forEach(record => { upgradePassHosts.add(new URL(record.url).hostname); - if (MixedContent.isSecureRecord(record) && record.finished && !record.failed) { + if (record.isSecure && record.finished && !record.failed) { upgradePassSecureHosts.add(new URL(record.url).hostname); } }); @@ -127,7 +114,7 @@ class MixedContent extends Audit { const resource = { host: new URL(record.url).hostname, fullUrl: record.url, - referrerDocUrl: this.displayURL(record._documentURL), + referrerDocUrl: this.displayURL(record.documentURL), }; // Exclude any records that aren't on an upgradeable secure host if (!upgradePassSecureHosts.has(resource.host)) continue; diff --git a/lighthouse-core/audits/time-to-first-byte.js b/lighthouse-core/audits/time-to-first-byte.js index e331319a30f5..376a1acc3eff 100644 --- a/lighthouse-core/audits/time-to-first-byte.js +++ b/lighthouse-core/audits/time-to-first-byte.js @@ -6,7 +6,6 @@ 'use strict'; const Audit = require('./audit'); -const Util = require('../report/html/renderer/util'); const TTFB_THRESHOLD = 600; @@ -29,8 +28,7 @@ class TTFBMetric extends Audit { */ static caclulateTTFB(record) { const timing = record._timing; - - return timing.receiveHeadersEnd - timing.sendEnd; + return timing ? timing.receiveHeadersEnd - timing.sendEnd : 0; } /** @@ -42,6 +40,7 @@ class TTFBMetric extends Audit { return artifacts.requestNetworkRecords(devtoolsLogs) .then((networkRecords) => { + /** @type {LH.Audit.DisplayValue} */ let displayValue = ''; const finalUrl = artifacts.URL.finalUrl; @@ -53,7 +52,7 @@ class TTFBMetric extends Audit { const passed = ttfb < TTFB_THRESHOLD; if (!passed) { - displayValue = `Root document took ${Util.formatMilliseconds(ttfb, 1)} `; + displayValue = ['Root document took %10d', ttfb]; } /** @type {LH.Result.Audit.OpportunityDetails} */ diff --git a/lighthouse-core/audits/uses-rel-preconnect.js b/lighthouse-core/audits/uses-rel-preconnect.js index 54414b027cb1..e8343d2e23df 100644 --- a/lighthouse-core/audits/uses-rel-preconnect.js +++ b/lighthouse-core/audits/uses-rel-preconnect.js @@ -38,7 +38,7 @@ class UsesRelPreconnectAudit extends Audit { * @return {boolean} */ static hasValidTiming(record) { - return record._timing && record._timing.connectEnd > 0 && record._timing.connectStart > 0; + return !!record._timing && record._timing.connectEnd > 0 && record._timing.connectStart > 0; } /** @@ -48,6 +48,7 @@ class UsesRelPreconnectAudit extends Audit { */ static hasAlreadyConnectedToOrigin(record) { return ( + !!record._timing && record._timing.dnsEnd - record._timing.dnsStart === 0 && record._timing.connectEnd - record._timing.connectStart === 0 ); @@ -90,7 +91,7 @@ class UsesRelPreconnectAudit extends Audit { // filter out all resources where timing info was invalid !UsesRelPreconnectAudit.hasValidTiming(record) || // filter out all resources that are loaded by the document - record.initiatorRequest() === mainResource || + record._initiator.url === mainResource.url || // filter out urls that do not have an origin (data, ...) !record.parsedURL || !record.parsedURL.securityOrigin() || // filter out all resources that have the same origin @@ -118,6 +119,9 @@ class UsesRelPreconnectAudit extends Audit { return (record.startTime < firstRecord.startTime) ? record: firstRecord; }); + // Skip the origin if we don't have timing information + if (!firstRecordOfOrigin._timing) return; + const securityOrigin = firstRecordOfOrigin.parsedURL.securityOrigin(); // Approximate the connection time with the duration of TCP (+potentially SSL) handshake diff --git a/lighthouse-core/config/mixed-content-config.js b/lighthouse-core/config/mixed-content-config.js index 7e21f8faa912..86341e4e50a1 100644 --- a/lighthouse-core/config/mixed-content-config.js +++ b/lighthouse-core/config/mixed-content-config.js @@ -11,7 +11,7 @@ module.exports = { // (2) Re-load page but attempt to upgrade each request to HTTPS. passes: [{ passName: 'defaultPass', - gatherers: ['url'], + gatherers: [], }, { passName: 'mixedContentPass', gatherers: ['mixed-content'], diff --git a/lighthouse-core/gather/driver.js b/lighthouse-core/gather/driver.js index 4a43dcc0127a..c9d3b98d8918 100644 --- a/lighthouse-core/gather/driver.js +++ b/lighthouse-core/gather/driver.js @@ -586,7 +586,7 @@ class Driver { * @private */ _beginNetworkStatusMonitoring(startingUrl) { - this._networkStatusMonitor = new NetworkRecorder([]); + this._networkStatusMonitor = new NetworkRecorder(); // Update startingUrl if it's ever redirected. this._monitoredUrl = startingUrl; diff --git a/lighthouse-core/gather/gatherers/dobetterweb/optimized-images.js b/lighthouse-core/gather/gatherers/dobetterweb/optimized-images.js index 8279f8ee188a..e245ca9c415d 100644 --- a/lighthouse-core/gather/gatherers/dobetterweb/optimized-images.js +++ b/lighthouse-core/gather/gatherers/dobetterweb/optimized-images.js @@ -91,7 +91,7 @@ class OptimizedImages extends Gatherer { const isSameOrigin = URL.originsMatch(pageUrl, record._url); const isBase64DataUri = /^data:.{2,40}base64\s*,/.test(record._url); - const actualResourceSize = Math.min(record._resourceSize || 0, record._transferSize || 0); + const actualResourceSize = Math.min(record._resourceSize || 0, record.transferSize || 0); if (isOptimizableImage && actualResourceSize > MINIMUM_IMAGE_SIZE) { prev.push({ isSameOrigin, diff --git a/lighthouse-core/gather/gatherers/dobetterweb/tags-blocking-first-paint.js b/lighthouse-core/gather/gatherers/dobetterweb/tags-blocking-first-paint.js index 5e841b88bc5d..bb3cb255ca47 100644 --- a/lighthouse-core/gather/gatherers/dobetterweb/tags-blocking-first-paint.js +++ b/lighthouse-core/gather/gatherers/dobetterweb/tags-blocking-first-paint.js @@ -115,10 +115,10 @@ class TagsBlockingFirstPaint extends Gatherer { // Include 404 scripts/links generated by the parser because they are likely blocking. if (isHtml || isParserScriptOrStyle || (isFailedRequest && isParserGenerated)) { prev[record._url] = { - isLinkPreload: record.isLinkPreload, - transferSize: record._transferSize, - startTime: record._startTime, - endTime: record._endTime, + isLinkPreload: !!record._isLinkPreload, + transferSize: record.transferSize, + startTime: record.startTime, + endTime: record.endTime, }; } @@ -133,7 +133,7 @@ class TagsBlockingFirstPaint extends Gatherer { static findBlockingTags(driver, networkRecords) { const scriptSrc = `(${collectTagsThatBlockFirstPaint.toString()}())`; const firstRequestEndTime = networkRecords.reduce( - (min, record) => Math.min(min, record._endTime), + (min, record) => Math.min(min, record.endTime), Infinity ); return driver.evaluateAsync(scriptSrc).then(tags => { diff --git a/lighthouse-core/lib/lantern-trace-saver.js b/lighthouse-core/lib/lantern-trace-saver.js index 1c3239e11a12..8929838621f2 100644 --- a/lighthouse-core/lib/lantern-trace-saver.js +++ b/lighthouse-core/lib/lantern-trace-saver.js @@ -147,7 +147,7 @@ function convertNodeTimingsToTrace(nodeTimings) { ...requestData, statusCode: record.statusCode, mimeType: record._mimeType, - encodedDataLength: record._transferSize, + encodedDataLength: record.transferSize, fromCache: record._fromDiskCache, fromServiceWorker: record._fetchedViaServiceWorker, }; diff --git a/lighthouse-core/lib/network-recorder.js b/lighthouse-core/lib/network-recorder.js index d37b069fe0a8..c9a09227d6ca 100644 --- a/lighthouse-core/lib/network-recorder.js +++ b/lighthouse-core/lib/network-recorder.js @@ -6,6 +6,7 @@ 'use strict'; const NetworkManager = require('./web-inspector').NetworkManager; +const NetworkRequest = require('./network-request'); const EventEmitter = require('events').EventEmitter; const log = require('lighthouse-logger'); @@ -16,22 +17,18 @@ const IGNORED_NETWORK_SCHEMES = ['data', 'ws']; class NetworkRecorder extends EventEmitter { /** * Creates an instance of NetworkRecorder. - * @param {Array} recordArray */ - constructor(recordArray) { + constructor() { super(); - this._records = recordArray; - this.networkManager = NetworkManager.createWithFakeTarget(); - - this.networkManager.addEventListener( - this.EventTypes.RequestStarted, - this.onRequestStarted.bind(this) - ); - this.networkManager.addEventListener( - this.EventTypes.RequestFinished, - this.onRequestFinished.bind(this) - ); + /** @type {NetworkRequest[]} */ + this._records = []; + /** @type {Map} */ + this._recordsById = new Map(); + } + + getRecords() { + return Array.from(this._records); } /** @@ -162,91 +159,124 @@ class NetworkRecorder extends EventEmitter { /** * Listener for the DevTools SDK NetworkManager's RequestStarted event, which includes both * web socket and normal request creation. - * @param {{data: LH.WebInspector.NetworkRequest}} request + * @param {NetworkRequest} request * @private */ onRequestStarted(request) { - this._records.push(request.data); + this._records.push(request); + this._recordsById.set(request.requestId, request); + this._emitNetworkStatus(); } /** * Listener for the DevTools SDK NetworkManager's RequestFinished event, which includes * request finish, failure, and redirect, as well as the closing of web sockets. - * @param {{data: LH.WebInspector.NetworkRequest}} request + * @param {NetworkRequest} request * @private */ onRequestFinished(request) { - this.emit('requestloaded', request.data); + this.emit('requestloaded', request); this._emitNetworkStatus(); } - // The below methods proxy network data into the DevTools SDK network layer. - // There are a few differences between the debugging protocol naming and - // the parameter naming used in NetworkManager. These are noted below. + // The below methods proxy network data into the NetworkRequest object which mimics the + // DevTools SDK network layer. /** * @param {LH.Crdp.Network.RequestWillBeSentEvent} data */ onRequestWillBeSent(data) { - // NOTE: data.timestamp -> time, data.type -> resourceType - this.networkManager._dispatcher.requestWillBeSent(data.requestId, - data.frameId, data.loaderId, data.documentURL, data.request, - data.timestamp, data.wallTime, data.initiator, data.redirectResponse, - data.type); + const originalRequest = this._findRealRequest(data.requestId); + // This is a simple new request, create the NetworkRequest object and finish. + if (!originalRequest) { + const request = new NetworkRequest(); + request.onRequestWillBeSent(data); + this.onRequestStarted(request); + return; + } + + // TODO(phulce): log these to sentry? + if (!data.redirectResponse) { + return; + } + + // On redirect, another requestWillBeSent message is fired for the same requestId. + // Update/finish the previous network request and create a new one for the redirect. + const modifiedData = { + ...data, + // Copy over the initiator as well to match DevTools behavior + // TODO(phulce): abandon this DT hack and update Lantern graph to handle it + initiator: originalRequest._initiator, + requestId: `${originalRequest.requestId}:redirect`, + }; + const redirectedRequest = new NetworkRequest(); + + redirectedRequest.onRequestWillBeSent(modifiedData); + originalRequest.onRedirectResponse(data); + + originalRequest.redirectDestination = redirectedRequest; + redirectedRequest.redirectSource = originalRequest; + + // Start the redirect request before finishing the original so we don't get erroneous quiet periods + this.onRequestStarted(redirectedRequest); + this.onRequestFinished(originalRequest); } /** * @param {LH.Crdp.Network.RequestServedFromCacheEvent} data */ onRequestServedFromCache(data) { - this.networkManager._dispatcher.requestServedFromCache(data.requestId); + const request = this._findRealRequest(data.requestId); + if (!request) return; + request.onRequestServedFromCache(); } /** * @param {LH.Crdp.Network.ResponseReceivedEvent} data */ onResponseReceived(data) { - // NOTE: data.timestamp -> time, data.type -> resourceType - this.networkManager._dispatcher.responseReceived(data.requestId, - data.frameId, data.loaderId, data.timestamp, data.type, data.response); + const request = this._findRealRequest(data.requestId); + if (!request) return; + request.onResponseReceived(data); } /** * @param {LH.Crdp.Network.DataReceivedEvent} data */ onDataReceived(data) { - // NOTE: data.timestamp -> time - this.networkManager._dispatcher.dataReceived(data.requestId, data.timestamp, - data.dataLength, data.encodedDataLength); + const request = this._findRealRequest(data.requestId); + if (!request) return; + request.onDataReceived(data); } /** * @param {LH.Crdp.Network.LoadingFinishedEvent} data */ onLoadingFinished(data) { - // NOTE: data.timestamp -> finishTime - this.networkManager._dispatcher.loadingFinished(data.requestId, - data.timestamp, data.encodedDataLength); + const request = this._findRealRequest(data.requestId); + if (!request) return; + request.onLoadingFinished(data); + this.onRequestFinished(request); } /** * @param {LH.Crdp.Network.LoadingFailedEvent} data */ onLoadingFailed(data) { - // NOTE: data.timestamp -> time, data.type -> resourceType, - // data.errorText -> localizedDescription - this.networkManager._dispatcher.loadingFailed(data.requestId, - data.timestamp, data.type, data.errorText, data.canceled, - data.blockedReason); + const request = this._findRealRequest(data.requestId); + if (!request) return; + request.onLoadingFailed(data); + this.onRequestFinished(request); } /** * @param {LH.Crdp.Network.ResourceChangedPriorityEvent} data */ onResourceChangedPriority(data) { - this.networkManager._dispatcher.resourceChangedPriority(data.requestId, - data.newPriority, data.timestamp); + const request = this._findRealRequest(data.requestId); + if (!request) return; + request.onResourceChangedPriority(data); } /** @@ -270,18 +300,71 @@ class NetworkRecorder extends EventEmitter { } } + /** + * Redirected requests all have identical requestIds over the protocol. Once a request has been + * redirected all future messages referrencing that requestId are about the new destination, not + * the original. This method is a helper for finding the real request object to which the current + * message is referring. + * + * @param {string} requestId + * @return {NetworkRequest|undefined} + */ + _findRealRequest(requestId) { + let request = this._recordsById.get(requestId); + if (!request) return undefined; + + while (request.redirectDestination) { + request = request.redirectDestination; + } + + return request; + } + /** * Construct network records from a log of devtools protocol messages. * @param {LH.DevtoolsLog} devtoolsLog * @return {Array} */ static recordsFromLogs(devtoolsLog) { - /** @type {Array} */ - const records = []; - const nr = new NetworkRecorder(records); - devtoolsLog.forEach(message => { - nr.dispatch(message); - }); + const networkRecorder = new NetworkRecorder(); + // playback all the devtools messages to recreate network records + devtoolsLog.forEach(message => networkRecorder.dispatch(message)); + + // get out the list of records + const records = networkRecorder.getRecords(); + + // create a map of all the records by URL to link up initiator + const recordsByURL = new Map(); + for (const record of records) { + if (recordsByURL.has(record.url)) continue; + recordsByURL.set(record.url, record); + } + + // set the initiator and redirects array + for (const record of records) { + const stackFrames = (record._initiator.stack && record._initiator.stack.callFrames) || []; + const initiatorURL = record._initiator.url || (stackFrames[0] && stackFrames[0].url); + const initiator = recordsByURL.get(initiatorURL) || record.redirectSource; + if (initiator) { + record.setInitiatorRequest(initiator); + } + + let finalRecord = record; + while (finalRecord.redirectDestination) finalRecord = finalRecord.redirectDestination; + if (finalRecord === record || finalRecord.redirects) continue; + + const redirects = []; + for ( + let redirect = finalRecord.redirectSource; + redirect; + redirect = redirect.redirectSource + ) { + redirects.unshift(redirect); + } + + finalRecord.redirects = redirects; + } + return records; } } diff --git a/lighthouse-core/lib/network-request.js b/lighthouse-core/lib/network-request.js new file mode 100644 index 000000000000..2116101902c6 --- /dev/null +++ b/lighthouse-core/lib/network-request.js @@ -0,0 +1,267 @@ +/** + * @license Copyright 2018 Google Inc. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + */ +'use strict'; + +/** + * @fileoverview Fills most of the role of NetworkManager and NetworkRequest classes from DevTools. + * @see https://cs.chromium.org/chromium/src/third_party/blink/renderer/devtools/front_end/sdk/NetworkRequest.js + * @see https://cs.chromium.org/chromium/src/third_party/blink/renderer/devtools/front_end/sdk/NetworkManager.js + */ + +const URL = require('./url-shim'); +const ResourceType = require('../../third-party/devtools/ResourceType'); + +const SECURE_SCHEMES = ['data', 'https', 'wss', 'blob', 'chrome', 'chrome-extension', 'about']; + +module.exports = class NetworkRequest { + constructor() { + this.requestId = ''; + this._requestId = ''; + // TODO(phulce): remove default DevTools connectionId + this.connectionId = '0'; + this.connectionReused = false; + + this.url = ''; + this._url = ''; + this.protocol = ''; + this.isSecure = false; + this.parsedURL = /** @type {LH.WebInspector.ParsedURL} */ ({scheme: ''}); + this.documentURL = ''; + + this.startTime = -1; + /** @type {number} */ + this.endTime = -1; + /** @type {number} */ + this._responseReceivedTime = -1; + + this.transferSize = 0; + this._resourceSize = 0; + this._fromDiskCache = false; + this._fromMemoryCache = false; + + this.finished = false; + this.requestMethod = ''; + this.statusCode = -1; + /** @type {NetworkRequest|undefined} The network request that redirected to this one */ + this.redirectSource = undefined; + /** @type {NetworkRequest|undefined} The network request that this one redirected to */ + this.redirectDestination = undefined; + /** @type {NetworkRequest[]|undefined} The chain of network requests that redirected to this one */ + this.redirects = undefined; + this.failed = false; + this.localizedFailDescription = ''; + + this._initiator = /** @type {LH.Crdp.Network.Initiator} */ ({type: 'other'}); + /** @type {LH.Crdp.Network.ResourceTiming|undefined} */ + this._timing = undefined; + /** @type {ResourceType|undefined} */ + this._resourceType = undefined; + this._mimeType = ''; + this.priority = () => /** @type {LH.Crdp.Network.ResourcePriority} */ ('Low'); + /** @type {() => NetworkRequest|undefined} */ + this.initiatorRequest = () => undefined; + /** @type {LH.WebInspector.HeaderValue[]} */ + this._responseHeaders = []; + + this._fetchedViaServiceWorker = false; + /** @type {string|undefined} */ + this._frameId = ''; + this._isLinkPreload = false; + + // Make sure we're compatible with old WebInspector.NetworkRequest + // eslint-disable-next-line no-unused-vars + const record = /** @type {LH.WebInspector.NetworkRequest} */ (this); + } + + /** + * @param {NetworkRequest} initiator + */ + setInitiatorRequest(initiator) { + this.initiatorRequest = () => initiator; + } + + /** + * @param {LH.Crdp.Network.RequestWillBeSentEvent} data + */ + onRequestWillBeSent(data) { + this.requestId = data.requestId; + this._requestId = data.requestId; + + const url = new URL(data.request.url); + this.url = data.request.url; + this._url = data.request.url; + this.documentURL = data.documentURL; + this.parsedURL = { + scheme: url.protocol.split(':')[0], + // Intentional, DevTools uses different terminology + host: url.hostname, + securityOrigin: () => url.origin, + }; + this.isSecure = SECURE_SCHEMES.includes(this.parsedURL.scheme); + + this.startTime = data.timestamp; + + this.requestMethod = data.request.method; + + this._initiator = data.initiator; + this._resourceType = data.type && ResourceType.TYPES[data.type]; + this.priority = () => data.request.initialPriority; + + this._frameId = data.frameId; + this._isLinkPreload = data.initiator.type === 'preload' || !!data.request.isLinkPreload; + } + + onRequestServedFromCache() { + this._fromMemoryCache = true; + } + + /** + * @param {LH.Crdp.Network.ResponseReceivedEvent} data + */ + onResponseReceived(data) { + this._onResponse(data.response, data.timestamp, data.type); + this._frameId = data.frameId; + } + + /** + * @param {LH.Crdp.Network.DataReceivedEvent} data + */ + onDataReceived(data) { + this._resourceSize += data.dataLength; + if (data.encodedDataLength !== -1) { + this.transferSize += data.encodedDataLength; + } + } + + /** + * @param {LH.Crdp.Network.LoadingFinishedEvent} data + */ + onLoadingFinished(data) { + // On some requests DevTools can send duplicate events, prefer the first one for best timing data + if (this.finished) return; + + this.finished = true; + this.endTime = data.timestamp; + if (data.encodedDataLength >= 0) { + this.transferSize = data.encodedDataLength; + } + + this._updateResponseReceivedTimeIfNecessary(); + } + + /** + * @param {LH.Crdp.Network.LoadingFailedEvent} data + */ + onLoadingFailed(data) { + // On some requests DevTools can send duplicate events, prefer the first one for best timing data + if (this.finished) return; + + this.finished = true; + this.endTime = data.timestamp; + + this.failed = true; + this._resourceType = data.type && ResourceType.TYPES[data.type]; + this.localizedFailDescription = data.errorText; + + this._updateResponseReceivedTimeIfNecessary(); + } + + /** + * @param {LH.Crdp.Network.ResourceChangedPriorityEvent} data + */ + onResourceChangedPriority(data) { + this.priority = () => data.newPriority; + } + + /** + * @param {LH.Crdp.Network.RequestWillBeSentEvent} data + */ + onRedirectResponse(data) { + if (!data.redirectResponse) throw new Error('Missing redirectResponse data'); + this._onResponse(data.redirectResponse, data.timestamp, data.type); + this._resourceType = undefined; + this.finished = true; + this.endTime = data.timestamp; + + this._updateResponseReceivedTimeIfNecessary(); + } + + /** + * @param {LH.Crdp.Network.Response} response + * @param {number} timestamp + * @param {LH.Crdp.Network.ResponseReceivedEvent['type']=} resourceType + */ + _onResponse(response, timestamp, resourceType) { + this.url = response.url; + this._url = response.url; + + this.connectionId = String(response.connectionId); + this.connectionReused = response.connectionReused; + + if (response.protocol) this.protocol = response.protocol; + + this._responseReceivedTime = timestamp; + + this.transferSize = response.encodedDataLength; + if (typeof response.fromDiskCache === 'boolean') this._fromDiskCache = response.fromDiskCache; + + this.statusCode = response.status; + + this._timing = response.timing; + if (resourceType) this._resourceType = ResourceType.TYPES[resourceType]; + this._mimeType = response.mimeType; + this._responseHeaders = NetworkRequest._headersDictToHeadersArray(response.headers); + + this._fetchedViaServiceWorker = !!response.fromServiceWorker; + + if (this._fromMemoryCache) this._timing = undefined; + if (this._timing) this._recomputeTimesWithResourceTiming(this._timing); + } + + /** + * Resolve differences between conflicting timing signals. Based on the property setters in DevTools. + * @see https://github.com/ChromeDevTools/devtools-frontend/blob/56a99365197b85c24b732ac92b0ac70feed80179/front_end/sdk/NetworkRequest.js#L485-L502 + * @param {LH.Crdp.Network.ResourceTiming} timing + */ + _recomputeTimesWithResourceTiming(timing) { + // Take startTime and responseReceivedTime from timing data for better accuracy. + // Timing's requestTime is a baseline in seconds, rest of the numbers there are ticks in millis. + this.startTime = timing.requestTime; + const headersReceivedTime = timing.requestTime + timing.receiveHeadersEnd / 1000; + if (!this._responseReceivedTime || this._responseReceivedTime < 0) { + this._responseReceivedTime = headersReceivedTime; + } + + this._responseReceivedTime = Math.min(this._responseReceivedTime, headersReceivedTime); + this._responseReceivedTime = Math.max(this._responseReceivedTime, this.startTime); + this.endTime = Math.max(this.endTime, this._responseReceivedTime); + } + + /** + * Update responseReceivedTime to the endTime if endTime is earlier. + * A response can't be received after the entire request finished. + */ + _updateResponseReceivedTimeIfNecessary() { + this._responseReceivedTime = Math.min(this.endTime, this._responseReceivedTime); + } + + /** + * Based on DevTools NetworkManager. + * @see https://github.com/ChromeDevTools/devtools-frontend/blob/3415ee28e86a3f4bcc2e15b652d22069938df3a6/front_end/sdk/NetworkManager.js#L285-L297 + * @param {LH.Crdp.Network.Headers} headersDict + * @return {Array} + */ + static _headersDictToHeadersArray(headersDict) { + const result = []; + for (const name of Object.keys(headersDict)) { + const values = headersDict[name].split('\n'); + for (let i = 0; i < values.length; ++i) { + result.push({name: name, value: values[i]}); + } + } + return result; + } +}; diff --git a/lighthouse-core/lib/web-inspector.js b/lighthouse-core/lib/web-inspector.js index fc0a86af0292..8375a4647206 100644 --- a/lighthouse-core/lib/web-inspector.js +++ b/lighthouse-core/lib/web-inspector.js @@ -100,67 +100,13 @@ module.exports = (function() { return this._moduleSettings[settingName]; }; - // Enum from chromium//src/third_party/WebKit/Source/core/loader/MixedContentChecker.h - global.NetworkAgent = { - RequestMixedContentType: { - Blockable: 'blockable', - OptionallyBlockable: 'optionally-blockable', - None: 'none', - }, - BlockedReason: { - CSP: 'csp', - MixedContent: 'mixed-content', - Origin: 'origin', - Inspector: 'inspector', - Other: 'other', - }, - InitiatorType: { - Other: 'other', - Parser: 'parser', - Redirect: 'redirect', - Script: 'script', - }, - }; - - // Enum from SecurityState enum in protocol's Security domain - global.SecurityAgent = { - SecurityState: { - Unknown: 'unknown', - Neutral: 'neutral', - Insecure: 'insecure', - Warning: 'warning', - Secure: 'secure', - Info: 'info', - }, - }; - // From https://chromium.googlesource.com/chromium/src/third_party/WebKit/Source/devtools/+/master/protocol.json#93 - global.PageAgent = { - ResourceType: { - Document: 'document', - Stylesheet: 'stylesheet', - Image: 'image', - Media: 'media', - Font: 'font', - Script: 'script', - TextTrack: 'texttrack', - XHR: 'xhr', - Fetch: 'fetch', - EventSource: 'eventsource', - WebSocket: 'websocket', - Manifest: 'manifest', - Other: 'other', - }, - }; - // Dependencies for network-recorder + // Shared Dependencies require('chrome-devtools-frontend/front_end/common/Object.js'); require('chrome-devtools-frontend/front_end/common/ParsedURL.js'); - require('chrome-devtools-frontend/front_end/common/ResourceType.js'); require('chrome-devtools-frontend/front_end/common/UIString.js'); require('chrome-devtools-frontend/front_end/platform/utilities.js'); require('chrome-devtools-frontend/front_end/sdk/Target.js'); require('chrome-devtools-frontend/front_end/sdk/TargetManager.js'); - require('chrome-devtools-frontend/front_end/sdk/NetworkManager.js'); - require('chrome-devtools-frontend/front_end/sdk/NetworkRequest.js'); // Dependencies for timeline-model WebInspector.targetManager = { @@ -226,78 +172,9 @@ module.exports = (function() { Log: 'log', }; - // Mock NetworkLog - WebInspector.NetworkLog = function(target) { - this._requests = new Map(); - target.networkManager.addEventListener( - WebInspector.NetworkManager.Events.RequestStarted, this._onRequestStarted, this); - }; - - WebInspector.NetworkLog.prototype = { - requestForURL: function(url) { - return this._requests.get(url) || null; - }, - - _onRequestStarted: function(event) { - const request = event.data; - if (this._requests.has(request.url)) { - return; - } - this._requests.set(request.url, request); - }, - }; - // Dependencies for color parsing. require('chrome-devtools-frontend/front_end/common/Color.js'); - // Monkey patch update so we don't lose request information - // TODO: Remove when we update to a devtools version that has isLinkPreload - const Dispatcher = WebInspector.NetworkDispatcher; - const origUpdateRequest = Dispatcher.prototype._updateNetworkRequestWithRequest; - Dispatcher.prototype._updateNetworkRequestWithRequest = function(netRecord, request) { - origUpdateRequest.apply(this, arguments); // eslint-disable-line - netRecord.isLinkPreload = Boolean(request.isLinkPreload); - netRecord._isLinkPreload = Boolean(request.isLinkPreload); - }; - - /** - * Creates a new WebInspector NetworkManager using a mocked Target. - * @return {!WebInspector.NetworkManager} - */ - WebInspector.NetworkManager.createWithFakeTarget = function() { - // Mocked-up WebInspector Target for NetworkManager - const fakeNetworkAgent = { - enable() {}, - getResponseBody() { - throw new Error('Use driver.getRequestContent() for network request content'); - }, - }; - const fakeConsoleModel = { - addMessage() {}, - target() {}, - }; - const fakeTarget = { - _modelByConstructor: new Map(), - get consoleModel() { - return fakeConsoleModel; - }, - networkAgent() { - return fakeNetworkAgent; - }, - registerNetworkDispatcher() { }, - model() { }, - }; - - fakeTarget.networkManager = new WebInspector.NetworkManager(fakeTarget); - fakeTarget.networkLog = new WebInspector.NetworkLog(fakeTarget); - - WebInspector.NetworkLog.fromTarget = () => { - return fakeTarget.networkLog; - }; - - return fakeTarget.networkManager; - }; - // Dependencies for effective CSS rule calculation. require('chrome-devtools-frontend/front_end/common/TextRange.js'); require('chrome-devtools-frontend/front_end/sdk/CSSMatchedStyles.js'); @@ -317,5 +194,7 @@ module.exports = (function() { // Restore setImmediate, see comment at top. global.setImmediate = _setImmediate; + // TODO(phulce): replace client requires to not need this + WebInspector.resourceTypes = require('../../third-party/devtools/ResourceType').TYPES; return WebInspector; })(); diff --git a/lighthouse-core/test/audits/byte-efficiency/byte-efficiency-audit-test.js b/lighthouse-core/test/audits/byte-efficiency/byte-efficiency-audit-test.js index ba12ac47cdf3..b1db444c1a0d 100644 --- a/lighthouse-core/test/audits/byte-efficiency/byte-efficiency-audit-test.js +++ b/lighthouse-core/test/audits/byte-efficiency/byte-efficiency-audit-test.js @@ -32,16 +32,10 @@ describe('Byte efficiency base audit', () => { requestId: 1, url: 'http://example.com/', parsedURL: {scheme: 'http', securityOrigin: () => 'http://example.com'}, - _transferSize: 400000, + transferSize: 400000, _timing: {receiveHeadersEnd: 0}, }; - Object.defineProperty(networkRecord, 'transferSize', { - get() { - return this._transferSize; - }, - }); - graph = new NetworkNode(networkRecord); // add a CPU node to force improvement to TTI graph.addDependent(new CPUNode({tid: 1, ts: 0, dur: 100 * 1000})); @@ -64,19 +58,19 @@ describe('Byte efficiency base audit', () => { it('should return transferSize when asset matches', () => { const _resourceType = {_name: 'stylesheet'}; - const result = estimate({_transferSize: 1234, _resourceType}, 10000, 'stylesheet'); + const result = estimate({transferSize: 1234, _resourceType}, 10000, 'stylesheet'); assert.equal(result, 1234); }); it('should estimate by network compression ratio when asset does not match', () => { const _resourceType = {_name: 'other'}; - const result = estimate({_resourceSize: 2000, _transferSize: 1000, _resourceType}, 100); + const result = estimate({_resourceSize: 2000, transferSize: 1000, _resourceType}, 100); assert.equal(result, 50); }); it('should not error when missing resource size', () => { const _resourceType = {_name: 'other'}; - const result = estimate({_transferSize: 1000, _resourceType}, 100); + const result = estimate({transferSize: 1000, _resourceType}, 100); assert.equal(result, 100); }); }); diff --git a/lighthouse-core/test/audits/byte-efficiency/render-blocking-resources-test.js b/lighthouse-core/test/audits/byte-efficiency/render-blocking-resources-test.js index 09c1e6ee49b5..c3b529947f15 100644 --- a/lighthouse-core/test/audits/byte-efficiency/render-blocking-resources-test.js +++ b/lighthouse-core/test/audits/byte-efficiency/render-blocking-resources-test.js @@ -52,22 +52,16 @@ describe('Render blocking resources audit', () => { requestId = 1; record = props => { const parsedURL = {securityOrigin: () => 'http://example.com'}; - const ret = Object.assign({parsedURL, requestId: requestId++}, props); - Object.defineProperty(ret, 'transferSize', { - get() { - return ret._transferSize; - }, - }); - return ret; + return Object.assign({parsedURL, requestId: requestId++}, props); }; }); it('computes savings from deferring', () => { const serverResponseTimeByOrigin = new Map([['http://example.com', 100]]); const simulator = new Simulator({rtt: 1000, serverResponseTimeByOrigin}); - const documentNode = new NetworkNode(record({_transferSize: 4000})); - const styleNode = new NetworkNode(record({_transferSize: 3000})); - const scriptNode = new NetworkNode(record({_transferSize: 1000})); + const documentNode = new NetworkNode(record({transferSize: 4000})); + const styleNode = new NetworkNode(record({transferSize: 3000})); + const scriptNode = new NetworkNode(record({transferSize: 1000})); const scriptExecution = new CPUNode({tid: 1, ts: 1, dur: 50 * 1000}, []); const deferredIds = new Set([2, 3]); const wastedBytesMap = new Map(); @@ -84,9 +78,9 @@ describe('Render blocking resources audit', () => { it('computes savings from inlining', () => { const serverResponseTimeByOrigin = new Map([['http://example.com', 100]]); const simulator = new Simulator({rtt: 1000, serverResponseTimeByOrigin}); - const documentNode = new NetworkNode(record({_transferSize: 10 * 1000})); + const documentNode = new NetworkNode(record({transferSize: 10 * 1000})); const styleNode = new NetworkNode( - record({_transferSize: 23 * 1000, _resourceType: WebInspector.resourceTypes.Stylesheet}) + record({transferSize: 23 * 1000, _resourceType: WebInspector.resourceTypes.Stylesheet}) ); // pushes document over 14KB const deferredIds = new Set([2]); const wastedBytesMap = new Map([[undefined, 18 * 1000]]); diff --git a/lighthouse-core/test/audits/byte-efficiency/unminified-css-test.js b/lighthouse-core/test/audits/byte-efficiency/unminified-css-test.js index 83c7a867d302..8c5ec38ddff6 100644 --- a/lighthouse-core/test/audits/byte-efficiency/unminified-css-test.js +++ b/lighthouse-core/test/audits/byte-efficiency/unminified-css-test.js @@ -148,8 +148,8 @@ describe('Page uses optimized css', () => { ]}, }, [ - {url: 'foo.css', _transferSize: 20 * KB, _resourceType}, - {url: 'other.css', _transferSize: 50 * KB, _resourceType}, + {url: 'foo.css', transferSize: 20 * KB, _resourceType}, + {url: 'other.css', transferSize: 50 * KB, _resourceType}, ] ); @@ -184,9 +184,9 @@ describe('Page uses optimized css', () => { ]}, }, [ - {url: 'foo.css', _transferSize: 20 * KB, _resourceType}, - {url: 'other.css', _transferSize: 512, _resourceType}, - {url: 'invalid.css', _transferSize: 20 * KB, _resourceType}, + {url: 'foo.css', transferSize: 20 * KB, _resourceType}, + {url: 'other.css', transferSize: 512, _resourceType}, + {url: 'invalid.css', transferSize: 20 * KB, _resourceType}, ] ); diff --git a/lighthouse-core/test/audits/byte-efficiency/unminified-javascript-test.js b/lighthouse-core/test/audits/byte-efficiency/unminified-javascript-test.js index 9905c3b49b57..a27db629b6e5 100644 --- a/lighthouse-core/test/audits/byte-efficiency/unminified-javascript-test.js +++ b/lighthouse-core/test/audits/byte-efficiency/unminified-javascript-test.js @@ -46,10 +46,10 @@ describe('Page uses optimized responses', () => { '123.4': '#$*% non sense', }, }, [ - {requestId: '123.1', url: 'foo.js', _transferSize: 20 * KB, _resourceType}, - {requestId: '123.2', url: 'other.js', _transferSize: 50 * KB, _resourceType}, - {requestId: '123.3', url: 'valid-ish.js', _transferSize: 100 * KB, _resourceType}, - {requestId: '123.4', url: 'invalid.js', _transferSize: 100 * KB, _resourceType}, + {requestId: '123.1', url: 'foo.js', transferSize: 20 * KB, _resourceType}, + {requestId: '123.2', url: 'other.js', transferSize: 50 * KB, _resourceType}, + {requestId: '123.3', url: 'valid-ish.js', transferSize: 100 * KB, _resourceType}, + {requestId: '123.4', url: 'invalid.js', transferSize: 100 * KB, _resourceType}, ]); assert.ok(auditResult.warnings.length); @@ -84,9 +84,9 @@ describe('Page uses optimized responses', () => { 'for{(wtf', }, }, [ - {requestId: '123.1', url: 'foo.js', _transferSize: 20 * KB, _resourceType}, - {requestId: '123.2', url: 'other.js', _transferSize: 3 * KB, _resourceType}, - {requestId: '123.3', url: 'invalid.js', _transferSize: 20 * KB, _resourceType}, + {requestId: '123.1', url: 'foo.js', transferSize: 20 * KB, _resourceType}, + {requestId: '123.2', url: 'other.js', transferSize: 3 * KB, _resourceType}, + {requestId: '123.3', url: 'invalid.js', transferSize: 20 * KB, _resourceType}, ]); assert.equal(auditResult.items.length, 0); diff --git a/lighthouse-core/test/audits/byte-efficiency/unused-css-rules-test.js b/lighthouse-core/test/audits/byte-efficiency/unused-css-rules-test.js index 4dc357859333..7633576c7b9a 100644 --- a/lighthouse-core/test/audits/byte-efficiency/unused-css-rules-test.js +++ b/lighthouse-core/test/audits/byte-efficiency/unused-css-rules-test.js @@ -122,7 +122,7 @@ describe('Best Practices: unused css rules audit', () => { return Promise.resolve([ { url: 'file://a.css', - _transferSize: 10 * 1024, + transferSize: 10 * 1024, _resourceType: {_name: 'stylesheet'}, }, ]); diff --git a/lighthouse-core/test/audits/byte-efficiency/unused-javascript-test.js b/lighthouse-core/test/audits/byte-efficiency/unused-javascript-test.js index 68c6064e9340..5f20dc47fde7 100644 --- a/lighthouse-core/test/audits/byte-efficiency/unused-javascript-test.js +++ b/lighthouse-core/test/audits/byte-efficiency/unused-javascript-test.js @@ -10,9 +10,9 @@ const assert = require('assert'); /* eslint-env mocha */ -function generateRecord(url, _transferSize, _resourceType) { +function generateRecord(url, transferSize, _resourceType) { url = `https://google.com/${url}`; - return {url, _transferSize, _resourceType}; + return {url, transferSize, _resourceType}; } function generateScript(url, ranges, transferSize = 1000) { diff --git a/lighthouse-core/test/audits/byte-efficiency/uses-long-cache-ttl-test.js b/lighthouse-core/test/audits/byte-efficiency/uses-long-cache-ttl-test.js index 8b401e3db7de..431341858a31 100644 --- a/lighthouse-core/test/audits/byte-efficiency/uses-long-cache-ttl-test.js +++ b/lighthouse-core/test/audits/byte-efficiency/uses-long-cache-ttl-test.js @@ -22,7 +22,7 @@ function networkRecord(options = {}) { _url: options.url || 'https://example.com/asset', statusCode: options.statusCode || 200, _resourceType: options.resourceType || WebInspector.resourceTypes.Script, - _transferSize: options.transferSize || 10000, + transferSize: options.transferSize || 10000, _responseHeaders: headers, }; } diff --git a/lighthouse-core/test/audits/mixed-content-test.js b/lighthouse-core/test/audits/mixed-content-test.js index 7f1fc9cc5781..436763212fe9 100644 --- a/lighthouse-core/test/audits/mixed-content-test.js +++ b/lighthouse-core/test/audits/mixed-content-test.js @@ -27,14 +27,14 @@ describe('Mixed Content audit', () => { it('passes when there are no insecure resources by default', () => { const defaultRecords = [ - {url: 'https://example.org/', securityState: () => 'secure', finished: true, _documentURL: 'https://example.org/'}, - {url: 'https://example.org/resource1.js', securityState: () => 'secure', finished: true, _documentURL: 'https://example.org'}, - {url: 'https://third-party.example.com/resource2.js', securityState: () => 'secure', finished: true, _documentURL: 'https://example.org'}, + {url: 'https://example.org/', isSecure: true, finished: true, documentURL: 'https://example.org/'}, + {url: 'https://example.org/resource1.js', isSecure: true, finished: true, documentURL: 'https://example.org'}, + {url: 'https://third-party.example.com/resource2.js', isSecure: true, finished: true, documentURL: 'https://example.org'}, ]; const upgradeRecords = [ - {url: 'https://example.org/', securityState: () => 'secure', finished: true, _documentURL: 'http://example.org/'}, - {url: 'https://example.org/resource1.js', securityState: () => 'secure', finished: true, _documentURL: 'https://example.org'}, - {url: 'https://third-party.example.com/resource2.js', securityState: () => 'secure', finished: true, _documentURL: 'https://example.org'}, + {url: 'https://example.org/', isSecure: true, finished: true, documentURL: 'http://example.org/'}, + {url: 'https://example.org/resource1.js', isSecure: true, finished: true, documentURL: 'https://example.org'}, + {url: 'https://third-party.example.com/resource2.js', isSecure: true, finished: true, documentURL: 'https://example.org'}, ]; return Audit.audit( getArtifacts('https://example.org', defaultRecords, upgradeRecords) @@ -46,16 +46,16 @@ describe('Mixed Content audit', () => { it('finds resources that could be upgraded to https', () => { const defaultRecords = [ - {url: 'http://example.org/', securityState: () => 'none', finished: true, _documentURL: 'http://example.org/'}, - {url: 'http://example.org/resource1.js', securityState: () => 'none', finished: true, _documentURL: 'https://example.org'}, - {url: 'http://third-party.example.com/resource2.js', securityState: () => 'none', finished: true, _documentURL: 'https://example.org'}, - {url: 'http://fourth-party.example.com/resource3.js', securityState: () => 'none', finished: true, _documentURL: 'https://third-party.example.com'}, + {url: 'http://example.org/', isSecure: false, finished: true, documentURL: 'http://example.org/'}, + {url: 'http://example.org/resource1.js', isSecure: false, finished: true, documentURL: 'https://example.org'}, + {url: 'http://third-party.example.com/resource2.js', isSecure: false, finished: true, documentURL: 'https://example.org'}, + {url: 'http://fourth-party.example.com/resource3.js', isSecure: false, finished: true, documentURL: 'https://third-party.example.com'}, ]; const upgradeRecords = [ - {url: 'https://example.org/', securityState: () => 'secure', finished: true, _documentURL: 'http://example.org/'}, - {url: 'https://example.org/resource1.js', securityState: () => 'secure', finished: true, _documentURL: 'https://example.org'}, - {url: 'https://third-party.example.com/resource2.js', securityState: () => 'secure', finished: true, _documentURL: 'https://example.org'}, - {url: 'https://fourth-party.example.com/resource3.js', securityState: () => 'none', finished: true, _documentURL: 'https://third-party.example.com'}, + {url: 'https://example.org/', isSecure: true, finished: true, documentURL: 'http://example.org/'}, + {url: 'https://example.org/resource1.js', isSecure: true, finished: true, documentURL: 'https://example.org'}, + {url: 'https://third-party.example.com/resource2.js', isSecure: true, finished: true, documentURL: 'https://example.org'}, + {url: 'https://fourth-party.example.com/resource3.js', isSecure: false, finished: true, documentURL: 'https://third-party.example.com'}, ]; return Audit.audit( getArtifacts('http://example.org', defaultRecords, upgradeRecords) diff --git a/lighthouse-core/test/audits/uses-rel-preconnect-test.js b/lighthouse-core/test/audits/uses-rel-preconnect-test.js index 5c5ceedfa791..8f44d4723678 100644 --- a/lighthouse-core/test/audits/uses-rel-preconnect-test.js +++ b/lighthouse-core/test/audits/uses-rel-preconnect-test.js @@ -59,7 +59,7 @@ describe('Performance: uses-rel-preconnect audit', () => { mainResource, { url: 'https://cdn.example.com/request', - initiatorRequest: () => mainResource, + _initiator: mainResource, }, ]; const artifacts = { @@ -80,7 +80,7 @@ describe('Performance: uses-rel-preconnect audit', () => { mainResource, { url: 'data:text/plain;base64,hello', - initiatorRequest: () => null, + _initiator: {}, }, ]; const artifacts = { @@ -101,7 +101,7 @@ describe('Performance: uses-rel-preconnect audit', () => { mainResource, { url: 'https://cdn.example.com/request', - initiatorRequest: () => null, + _initiator: {}, _timing: { dnsStart: -1, dnsEnd: -1, @@ -128,7 +128,7 @@ describe('Performance: uses-rel-preconnect audit', () => { mainResource, { url: 'https://cdn.example.com/request', - initiatorRequest: () => null, + _initiator: {}, _startTime: 16, }, ]; @@ -150,7 +150,7 @@ describe('Performance: uses-rel-preconnect audit', () => { mainResource, { url: 'https://cdn.example.com/first', - initiatorRequest: () => null, + _initiator: {}, parsedURL: { scheme: 'https', securityOrigin: () => 'https://cdn.example.com', @@ -164,7 +164,7 @@ describe('Performance: uses-rel-preconnect audit', () => { }, { url: 'https://cdn.example.com/second', - initiatorRequest: () => null, + _initiator: {}, parsedURL: { scheme: 'https', securityOrigin: () => 'https://cdn.example.com', @@ -197,7 +197,7 @@ describe('Performance: uses-rel-preconnect audit', () => { mainResource, { url: 'https://cdn.example.com/first', - initiatorRequest: () => null, + _initiator: {}, parsedURL: { scheme: 'http', securityOrigin: () => 'http://cdn.example.com', @@ -211,7 +211,7 @@ describe('Performance: uses-rel-preconnect audit', () => { }, { url: 'https://othercdn.example.com/second', - initiatorRequest: () => null, + _initiator: {}, parsedURL: { scheme: 'https', securityOrigin: () => 'https://othercdn.example.com', diff --git a/lighthouse-core/test/fixtures/lantern-master-computed-values.json b/lighthouse-core/test/fixtures/lantern-master-computed-values.json index be568ed1ca2b..c128d855c651 100644 --- a/lighthouse-core/test/fixtures/lantern-master-computed-values.json +++ b/lighthouse-core/test/fixtures/lantern-master-computed-values.json @@ -2,7 +2,7 @@ "sites": [ {"url": "https://flipkart.com", "roughEstimateOfFCP": 2819, "optimisticFCP": 2017, "pessimisticFCP": 2017, "roughEstimateOfFMP": 6108, "optimisticFMP": 4960, "pessimisticFMP": 4960, "roughEstimateOfTTI": 12534, "optimisticTTI": 9513, "pessimisticTTI": 11613, "roughEstimateOfTTFCPUI": 12534, "optimisticTTFCPUI": 9513, "pessimisticTTFCPUI": 11613, "roughEstimateOfSI": 6223, "optimisticSI": 3687, "pessimisticSI": 2017, "roughEstimateOfEIL": 766, "optimisticEIL": 957, "pessimisticEIL": 957}, {"url": "https://vine.co/", "roughEstimateOfFCP": 1977, "optimisticFCP": 1251, "pessimisticFCP": 1251, "roughEstimateOfFMP": 3204, "optimisticFMP": 1251, "pessimisticFMP": 2901, "roughEstimateOfTTI": 8901, "optimisticTTI": 6372, "pessimisticTTI": 7727, "roughEstimateOfTTFCPUI": 8901, "optimisticTTFCPUI": 6372, "pessimisticTTFCPUI": 7727, "roughEstimateOfSI": 3707, "optimisticSI": 2246, "pessimisticSI": 1251, "roughEstimateOfEIL": 961, "optimisticEIL": 1202, "pessimisticEIL": 1202}, - {"url": "https://weather.com/", "roughEstimateOfFCP": 5617, "optimisticFCP": 4561, "pessimisticFCP": 4561, "roughEstimateOfFMP": 5689, "optimisticFMP": 4561, "pessimisticFMP": 4561, "roughEstimateOfTTI": 25715, "optimisticTTI": 20554, "pessimisticTTI": 26182, "roughEstimateOfTTFCPUI": 25715, "optimisticTTFCPUI": 20554, "pessimisticTTFCPUI": 26182, "roughEstimateOfSI": 6301, "optimisticSI": 2561, "pessimisticSI": 4561, "roughEstimateOfEIL": 1648, "optimisticEIL": 2060, "pessimisticEIL": 2060}, + {"url": "https://weather.com/", "roughEstimateOfFCP": 5617, "optimisticFCP": 4561, "pessimisticFCP": 4561, "roughEstimateOfFMP": 5689, "optimisticFMP": 4561, "pessimisticFMP": 4561, "roughEstimateOfTTI": 25785, "optimisticTTI": 20854, "pessimisticTTI": 25939, "roughEstimateOfTTFCPUI": 25785, "optimisticTTFCPUI": 20854, "pessimisticTTFCPUI": 25939, "roughEstimateOfSI": 6301, "optimisticSI": 2561, "pessimisticSI": 4561, "roughEstimateOfEIL": 1648, "optimisticEIL": 2060, "pessimisticEIL": 2060}, {"url": "http://www.4399.com/", "roughEstimateOfFCP": 3554, "optimisticFCP": 2685, "pessimisticFCP": 2685, "roughEstimateOfFMP": 3719, "optimisticFMP": 2685, "pessimisticFMP": 2685, "roughEstimateOfTTI": 5551, "optimisticTTI": 2696, "pessimisticTTI": 5185, "roughEstimateOfTTFCPUI": 5551, "optimisticTTFCPUI": 2696, "pessimisticTTFCPUI": 5185, "roughEstimateOfSI": 3554, "optimisticSI": 350, "pessimisticSI": 2685, "roughEstimateOfEIL": 13, "optimisticEIL": 16, "pessimisticEIL": 16}, {"url": "http://www.4shared.com/", "roughEstimateOfFCP": 4380, "optimisticFCP": 3437, "pessimisticFCP": 3437, "roughEstimateOfFMP": 4509, "optimisticFMP": 3437, "pessimisticFMP": 3437, "roughEstimateOfTTI": 6302, "optimisticTTI": 4192, "pessimisticTTI": 4860, "roughEstimateOfTTFCPUI": 6302, "optimisticTTFCPUI": 4192, "pessimisticTTFCPUI": 4860, "roughEstimateOfSI": 4380, "optimisticSI": 1467, "pessimisticSI": 3437, "roughEstimateOfEIL": 51, "optimisticEIL": 63, "pessimisticEIL": 63}, {"url": "http://www.56.com/", "roughEstimateOfFCP": 3727, "optimisticFCP": 2843, "pessimisticFCP": 2843, "roughEstimateOfFMP": 3885, "optimisticFMP": 2843, "pessimisticFMP": 2843, "roughEstimateOfTTI": 10645, "optimisticTTI": 3348, "pessimisticTTI": 15637, "roughEstimateOfTTFCPUI": 4476, "optimisticTTFCPUI": 3348, "pessimisticTTFCPUI": 1926, "roughEstimateOfSI": 9882, "optimisticSI": 5917, "pessimisticSI": 2843, "roughEstimateOfEIL": 13, "optimisticEIL": 16, "pessimisticEIL": 16}, @@ -16,14 +16,14 @@ {"url": "http://www.blogspot.com/", "roughEstimateOfFCP": 2815, "optimisticFCP": 2013, "pessimisticFCP": 2013, "roughEstimateOfFMP": 3014, "optimisticFMP": 2013, "pessimisticFMP": 2013, "roughEstimateOfTTI": 4407, "optimisticTTI": 2594, "pessimisticTTI": 2780, "roughEstimateOfTTFCPUI": 4407, "optimisticTTFCPUI": 2594, "pessimisticTTFCPUI": 2780, "roughEstimateOfSI": 11239, "optimisticSI": 7272, "pessimisticSI": 2013, "roughEstimateOfEIL": 13, "optimisticEIL": 16, "pessimisticEIL": 16}, {"url": "http://www.brothersoft.com/", "roughEstimateOfFCP": 2481, "optimisticFCP": 1710, "pessimisticFCP": 1710, "roughEstimateOfFMP": 3365, "optimisticFMP": 2208, "pessimisticFMP": 2452, "roughEstimateOfTTI": 16936, "optimisticTTI": 12900, "pessimisticTTI": 16881, "roughEstimateOfTTFCPUI": 16936, "optimisticTTFCPUI": 12900, "pessimisticTTFCPUI": 16881, "roughEstimateOfSI": 4084, "optimisticSI": 2302, "pessimisticSI": 1710, "roughEstimateOfEIL": 636, "optimisticEIL": 795, "pessimisticEIL": 795}, {"url": "http://www.china.com.cn/", "roughEstimateOfFCP": 5034, "optimisticFCP": 3589, "pessimisticFCP": 4562, "roughEstimateOfFMP": 5252, "optimisticFMP": 3589, "pessimisticFMP": 4562, "roughEstimateOfTTI": 7914, "optimisticTTI": 4173, "pessimisticTTI": 8466, "roughEstimateOfTTFCPUI": 5252, "optimisticTTFCPUI": 4173, "pessimisticTTFCPUI": 2407, "roughEstimateOfSI": 8102, "optimisticSI": 3848, "pessimisticSI": 4562, "roughEstimateOfEIL": 20, "optimisticEIL": 25, "pessimisticEIL": 25}, - {"url": "http://www.cnet.com/", "roughEstimateOfFCP": 2393, "optimisticFCP": 1451, "pessimisticFCP": 1845, "roughEstimateOfFMP": 2929, "optimisticFMP": 1451, "pessimisticFMP": 2294, "roughEstimateOfTTI": 25155, "optimisticTTI": 18878, "pessimisticTTI": 27174, "roughEstimateOfTTFCPUI": 25155, "optimisticTTFCPUI": 18878, "pessimisticTTFCPUI": 27174, "roughEstimateOfSI": 4292, "optimisticSI": 2388, "pessimisticSI": 1845, "roughEstimateOfEIL": 1061, "optimisticEIL": 1326, "pessimisticEIL": 1326}, + {"url": "http://www.cnet.com/", "roughEstimateOfFCP": 2393, "optimisticFCP": 1451, "pessimisticFCP": 1845, "roughEstimateOfFMP": 2929, "optimisticFMP": 1451, "pessimisticFMP": 2294, "roughEstimateOfTTI": 24938, "optimisticTTI": 18538, "pessimisticTTI": 27145, "roughEstimateOfTTFCPUI": 24938, "optimisticTTFCPUI": 18538, "pessimisticTTFCPUI": 27145, "roughEstimateOfSI": 4292, "optimisticSI": 2388, "pessimisticSI": 1845, "roughEstimateOfEIL": 1061, "optimisticEIL": 1326, "pessimisticEIL": 1326}, {"url": "http://www.cntv.cn/", "roughEstimateOfFCP": 3567, "optimisticFCP": 2697, "pessimisticFCP": 2697, "roughEstimateOfFMP": 3732, "optimisticFMP": 2697, "pessimisticFMP": 2697, "roughEstimateOfTTI": 4567, "optimisticTTI": 2697, "pessimisticTTI": 2997, "roughEstimateOfTTFCPUI": 4567, "optimisticTTFCPUI": 2697, "pessimisticTTFCPUI": 2997, "roughEstimateOfSI": 3890, "optimisticSI": 1705, "pessimisticSI": 2697, "roughEstimateOfEIL": 13, "optimisticEIL": 16, "pessimisticEIL": 16}, {"url": "http://www.conduit.com/", "roughEstimateOfFCP": 2258, "optimisticFCP": 1507, "pessimisticFCP": 1507, "roughEstimateOfFMP": 2483, "optimisticFMP": 1507, "pessimisticFMP": 1507, "roughEstimateOfTTI": 3884, "optimisticTTI": 1960, "pessimisticTTI": 2463, "roughEstimateOfTTFCPUI": 3884, "optimisticTTFCPUI": 1960, "pessimisticTTFCPUI": 2463, "roughEstimateOfSI": 2539, "optimisticSI": 1292, "pessimisticSI": 1507, "roughEstimateOfEIL": 20, "optimisticEIL": 25, "pessimisticEIL": 25}, {"url": "http://www.craigslist.org/", "roughEstimateOfFCP": 3615, "optimisticFCP": 2634, "pessimisticFCP": 2869, "roughEstimateOfFMP": 5456, "optimisticFMP": 4201, "pessimisticFMP": 4443, "roughEstimateOfTTI": 6120, "optimisticTTI": 4201, "pessimisticTTI": 4443, "roughEstimateOfTTFCPUI": 6120, "optimisticTTFCPUI": 4201, "pessimisticTTFCPUI": 4443, "roughEstimateOfSI": 3615, "optimisticSI": 1334, "pessimisticSI": 2869, "roughEstimateOfEIL": 182, "optimisticEIL": 227, "pessimisticEIL": 227}, - {"url": "http://www.dawn.com/", "roughEstimateOfFCP": 3859, "optimisticFCP": 2695, "pessimisticFCP": 3283, "roughEstimateOfFMP": 4083, "optimisticFMP": 2695, "pessimisticFMP": 3283, "roughEstimateOfTTI": 16102, "optimisticTTI": 12156, "pessimisticTTI": 16019, "roughEstimateOfTTFCPUI": 16102, "optimisticTTFCPUI": 12156, "pessimisticTTFCPUI": 16019, "roughEstimateOfSI": 5025, "optimisticSI": 2243, "pessimisticSI": 3283, "roughEstimateOfEIL": 298, "optimisticEIL": 373, "pessimisticEIL": 373}, + {"url": "http://www.dawn.com/", "roughEstimateOfFCP": 3859, "optimisticFCP": 2695, "pessimisticFCP": 3283, "roughEstimateOfFMP": 4083, "optimisticFMP": 2695, "pessimisticFMP": 3283, "roughEstimateOfTTI": 16165, "optimisticTTI": 12156, "pessimisticTTI": 16158, "roughEstimateOfTTFCPUI": 16165, "optimisticTTFCPUI": 12156, "pessimisticTTFCPUI": 16158, "roughEstimateOfSI": 5025, "optimisticSI": 2243, "pessimisticSI": 3283, "roughEstimateOfEIL": 298, "optimisticEIL": 373, "pessimisticEIL": 373}, {"url": "http://www.depositfiles.com/", "roughEstimateOfFCP": 8891, "optimisticFCP": 7537, "pessimisticFCP": 7537, "roughEstimateOfFMP": 8891, "optimisticFMP": 7537, "pessimisticFMP": 7537, "roughEstimateOfTTI": 10999, "optimisticTTI": 8951, "pessimisticTTI": 8951, "roughEstimateOfTTFCPUI": 8891, "optimisticTTFCPUI": 775, "pessimisticTTFCPUI": 8951, "roughEstimateOfSI": 12654, "optimisticSI": 5718, "pessimisticSI": 7537, "roughEstimateOfEIL": 273, "optimisticEIL": 341, "pessimisticEIL": 341}, {"url": "http://www.deviantart.com/", "roughEstimateOfFCP": 4693, "optimisticFCP": 3721, "pessimisticFCP": 3721, "roughEstimateOfFMP": 6268, "optimisticFMP": 5112, "pessimisticFMP": 5112, "roughEstimateOfTTI": 32184, "optimisticTTI": 18527, "pessimisticTTI": 43261, "roughEstimateOfTTFCPUI": 17915, "optimisticTTFCPUI": 18527, "pessimisticTTFCPUI": 11553, "roughEstimateOfSI": 5681, "optimisticSI": 2509, "pessimisticSI": 3721, "roughEstimateOfEIL": 624, "optimisticEIL": 780, "pessimisticEIL": 780}, - {"url": "http://www.dion.ne.jp/", "roughEstimateOfFCP": 8474, "optimisticFCP": 4680, "pessimisticFCP": 10133, "roughEstimateOfFMP": 9086, "optimisticFMP": 4680, "pessimisticFMP": 10133, "roughEstimateOfTTI": 34706, "optimisticTTI": 14284, "pessimisticTTI": 54524, "roughEstimateOfTTFCPUI": 20617, "optimisticTTFCPUI": 14284, "pessimisticTTFCPUI": 23214, "roughEstimateOfSI": 17627, "optimisticSI": 8065, "pessimisticSI": 10133, "roughEstimateOfEIL": 1028, "optimisticEIL": 1285, "pessimisticEIL": 1285}, + {"url": "http://www.dion.ne.jp/", "roughEstimateOfFCP": 8474, "optimisticFCP": 4680, "pessimisticFCP": 10133, "roughEstimateOfFMP": 9086, "optimisticFMP": 4680, "pessimisticFMP": 10133, "roughEstimateOfTTI": 34618, "optimisticTTI": 14284, "pessimisticTTI": 54327, "roughEstimateOfTTFCPUI": 20669, "optimisticTTFCPUI": 14284, "pessimisticTTFCPUI": 23330, "roughEstimateOfSI": 17627, "optimisticSI": 8065, "pessimisticSI": 10133, "roughEstimateOfEIL": 1028, "optimisticEIL": 1285, "pessimisticEIL": 1285}, {"url": "http://www.domaintools.com/", "roughEstimateOfFCP": 1837, "optimisticFCP": 1125, "pessimisticFCP": 1125, "roughEstimateOfFMP": 3227, "optimisticFMP": 1995, "pessimisticFMP": 2383, "roughEstimateOfTTI": 9578, "optimisticTTI": 7177, "pessimisticTTI": 8159, "roughEstimateOfTTFCPUI": 9578, "optimisticTTFCPUI": 7177, "pessimisticTTFCPUI": 8159, "roughEstimateOfSI": 9196, "optimisticSI": 6225, "pessimisticSI": 1125, "roughEstimateOfEIL": 1346, "optimisticEIL": 1682, "pessimisticEIL": 1682}, {"url": "http://www.douban.com/", "roughEstimateOfFCP": 7125, "optimisticFCP": 5932, "pessimisticFCP": 5932, "roughEstimateOfFMP": 7129, "optimisticFMP": 5932, "pessimisticFMP": 5932, "roughEstimateOfTTI": 9324, "optimisticTTI": 7076, "pessimisticTTI": 7729, "roughEstimateOfTTFCPUI": 9324, "optimisticTTFCPUI": 7076, "pessimisticTTFCPUI": 7729, "roughEstimateOfSI": 9975, "optimisticSI": 4549, "pessimisticSI": 5932, "roughEstimateOfEIL": 558, "optimisticEIL": 697, "pessimisticEIL": 697}, {"url": "http://www.ebay.com/", "roughEstimateOfFCP": 2893, "optimisticFCP": 2085, "pessimisticFCP": 2085, "roughEstimateOfFMP": 3089, "optimisticFMP": 2085, "pessimisticFMP": 2085, "roughEstimateOfTTI": 8923, "optimisticTTI": 6143, "pessimisticTTI": 8083, "roughEstimateOfTTFCPUI": 8923, "optimisticTTFCPUI": 6143, "pessimisticTTFCPUI": 8083, "roughEstimateOfSI": 3728, "optimisticSI": 1873, "pessimisticSI": 2085, "roughEstimateOfEIL": 187, "optimisticEIL": 233, "pessimisticEIL": 233}, @@ -32,12 +32,12 @@ {"url": "http://www.facebook.com/", "roughEstimateOfFCP": 3443, "optimisticFCP": 2585, "pessimisticFCP": 2585, "roughEstimateOfFMP": 3614, "optimisticFMP": 2585, "pessimisticFMP": 2585, "roughEstimateOfTTI": 5666, "optimisticTTI": 3421, "pessimisticTTI": 4474, "roughEstimateOfTTFCPUI": 5666, "optimisticTTFCPUI": 3421, "pessimisticTTFCPUI": 4474, "roughEstimateOfSI": 3669, "optimisticSI": 1599, "pessimisticSI": 2585, "roughEstimateOfEIL": 65, "optimisticEIL": 82, "pessimisticEIL": 82}, {"url": "http://www.fc2.com/", "roughEstimateOfFCP": 3066, "optimisticFCP": 2242, "pessimisticFCP": 2242, "roughEstimateOfFMP": 3254, "optimisticFMP": 2242, "pessimisticFMP": 2242, "roughEstimateOfTTI": 4251, "optimisticTTI": 2440, "pessimisticTTI": 2638, "roughEstimateOfTTFCPUI": 4251, "optimisticTTFCPUI": 2440, "pessimisticTTFCPUI": 2638, "roughEstimateOfSI": 3231, "optimisticSI": 1446, "pessimisticSI": 2242, "roughEstimateOfEIL": 13, "optimisticEIL": 16, "pessimisticEIL": 16}, {"url": "http://www.filestube.com/", "roughEstimateOfFCP": 9184, "optimisticFCP": 7803, "pessimisticFCP": 7803, "roughEstimateOfFMP": 11107, "optimisticFMP": 9264, "pessimisticFMP": 10063, "roughEstimateOfTTI": 25406, "optimisticTTI": 16639, "pessimisticTTI": 30716, "roughEstimateOfTTFCPUI": 18010, "optimisticTTFCPUI": 16639, "pessimisticTTFCPUI": 14282, "roughEstimateOfSI": 11939, "optimisticSI": 5083, "pessimisticSI": 7803, "roughEstimateOfEIL": 1198, "optimisticEIL": 1497, "pessimisticEIL": 1497}, - {"url": "http://www.foxnews.com/", "roughEstimateOfFCP": 3447, "optimisticFCP": 2588, "pessimisticFCP": 2588, "roughEstimateOfFMP": 3617, "optimisticFMP": 2588, "pessimisticFMP": 2588, "roughEstimateOfTTI": 30132, "optimisticTTI": 20217, "pessimisticTTI": 36447, "roughEstimateOfTTFCPUI": 28467, "optimisticTTFCPUI": 20217, "pessimisticTTFCPUI": 32749, "roughEstimateOfSI": 11115, "optimisticSI": 6916, "pessimisticSI": 2588, "roughEstimateOfEIL": 1306, "optimisticEIL": 1632, "pessimisticEIL": 1632}, + {"url": "http://www.foxnews.com/", "roughEstimateOfFCP": 3447, "optimisticFCP": 2588, "pessimisticFCP": 2588, "roughEstimateOfFMP": 3617, "optimisticFMP": 2588, "pessimisticFMP": 2588, "roughEstimateOfTTI": 30430, "optimisticTTI": 20477, "pessimisticTTI": 36765, "roughEstimateOfTTFCPUI": 28544, "optimisticTTFCPUI": 20477, "pessimisticTTFCPUI": 32572, "roughEstimateOfSI": 11115, "optimisticSI": 6916, "pessimisticSI": 2588, "roughEstimateOfEIL": 1306, "optimisticEIL": 1632, "pessimisticEIL": 1632}, {"url": "http://www.getpersonas.com/", "roughEstimateOfFCP": 4265, "optimisticFCP": 3321, "pessimisticFCP": 3344, "roughEstimateOfFMP": 6777, "optimisticFMP": 5597, "pessimisticFMP": 5597, "roughEstimateOfTTI": 12397, "optimisticTTI": 9001, "pessimisticTTI": 11991, "roughEstimateOfTTFCPUI": 12397, "optimisticTTFCPUI": 9001, "pessimisticTTFCPUI": 11991, "roughEstimateOfSI": 4265, "optimisticSI": 1509, "pessimisticSI": 3344, "roughEstimateOfEIL": 1510, "optimisticEIL": 1888, "pessimisticEIL": 1888}, {"url": "http://www.globo.com/", "roughEstimateOfFCP": 3558, "optimisticFCP": 2689, "pessimisticFCP": 2689, "roughEstimateOfFMP": 4217, "optimisticFMP": 2957, "pessimisticFMP": 3310, "roughEstimateOfTTI": 20958, "optimisticTTI": 15884, "pessimisticTTI": 21839, "roughEstimateOfTTFCPUI": 20958, "optimisticTTFCPUI": 15884, "pessimisticTTFCPUI": 21839, "roughEstimateOfSI": 4469, "optimisticSI": 2122, "pessimisticSI": 2689, "roughEstimateOfEIL": 2070, "optimisticEIL": 2588, "pessimisticEIL": 2588}, {"url": "http://www.gmx.net/", "roughEstimateOfFCP": 2291, "optimisticFCP": 1537, "pessimisticFCP": 1537, "roughEstimateOfFMP": 2514, "optimisticFMP": 1537, "pessimisticFMP": 1537, "roughEstimateOfTTI": 9616, "optimisticTTI": 6627, "pessimisticTTI": 8978, "roughEstimateOfTTFCPUI": 9616, "optimisticTTFCPUI": 6627, "pessimisticTTFCPUI": 8978, "roughEstimateOfSI": 4970, "optimisticSI": 3015, "pessimisticSI": 1537, "roughEstimateOfEIL": 453, "optimisticEIL": 566, "pessimisticEIL": 566}, {"url": "http://www.hatena.ne.jp/", "roughEstimateOfFCP": 1853, "optimisticFCP": 1025, "pessimisticFCP": 1276, "roughEstimateOfFMP": 2200, "optimisticFMP": 1188, "pessimisticFMP": 1276, "roughEstimateOfTTI": 22065, "optimisticTTI": 10950, "pessimisticTTI": 30878, "roughEstimateOfTTFCPUI": 14902, "optimisticTTFCPUI": 10950, "pessimisticTTFCPUI": 14960, "roughEstimateOfSI": 4530, "optimisticSI": 2821, "pessimisticSI": 1276, "roughEstimateOfEIL": 194, "optimisticEIL": 242, "pessimisticEIL": 242}, - {"url": "http://www.hexun.com/", "roughEstimateOfFCP": 4206, "optimisticFCP": 3278, "pessimisticFCP": 3278, "roughEstimateOfFMP": 5261, "optimisticFMP": 3278, "pessimisticFMP": 4809, "roughEstimateOfTTI": 8895, "optimisticTTI": 5514, "pessimisticTTI": 8858, "roughEstimateOfTTFCPUI": 8895, "optimisticTTFCPUI": 5514, "pessimisticTTFCPUI": 8858, "roughEstimateOfSI": 12760, "optimisticSI": 7771, "pessimisticSI": 3278, "roughEstimateOfEIL": 64, "optimisticEIL": 71, "pessimisticEIL": 88}, + {"url": "http://www.hexun.com/", "roughEstimateOfFCP": 4206, "optimisticFCP": 3278, "pessimisticFCP": 3278, "roughEstimateOfFMP": 5261, "optimisticFMP": 3278, "pessimisticFMP": 4809, "roughEstimateOfTTI": 8877, "optimisticTTI": 5514, "pessimisticTTI": 8820, "roughEstimateOfTTFCPUI": 8877, "optimisticTTFCPUI": 5514, "pessimisticTTFCPUI": 8820, "roughEstimateOfSI": 12760, "optimisticSI": 7771, "pessimisticSI": 3278, "roughEstimateOfEIL": 64, "optimisticEIL": 71, "pessimisticEIL": 88}, {"url": "http://www.hotfile.com/", "roughEstimateOfFCP": 4943, "optimisticFCP": 3376, "pessimisticFCP": 4634, "roughEstimateOfFMP": 5200, "optimisticFMP": 3376, "pessimisticFMP": 4634, "roughEstimateOfTTI": 9928, "optimisticTTI": 5310, "pessimisticTTI": 11426, "roughEstimateOfTTFCPUI": 9928, "optimisticTTFCPUI": 5310, "pessimisticTTFCPUI": 11426, "roughEstimateOfSI": 9493, "optimisticSI": 4807, "pessimisticSI": 4634, "roughEstimateOfEIL": 100, "optimisticEIL": 126, "pessimisticEIL": 125}, {"url": "http://www.hp.com/", "roughEstimateOfFCP": 8474, "optimisticFCP": 5962, "pessimisticFCP": 8594, "roughEstimateOfFMP": 9882, "optimisticFMP": 7293, "pessimisticFMP": 9499, "roughEstimateOfTTI": 17501, "optimisticTTI": 13912, "pessimisticTTI": 16785, "roughEstimateOfTTFCPUI": 17501, "optimisticTTFCPUI": 13912, "pessimisticTTFCPUI": 16785, "roughEstimateOfSI": 8693, "optimisticSI": 2398, "pessimisticSI": 8594, "roughEstimateOfEIL": 414, "optimisticEIL": 517, "pessimisticEIL": 517}, {"url": "http://www.huffingtonpost.com/", "roughEstimateOfFCP": 3291, "optimisticFCP": 2446, "pessimisticFCP": 2446, "roughEstimateOfFMP": 3468, "optimisticFMP": 2446, "pessimisticFMP": 2446, "roughEstimateOfTTI": 20378, "optimisticTTI": 15398, "pessimisticTTI": 21198, "roughEstimateOfTTFCPUI": 20378, "optimisticTTFCPUI": 15398, "pessimisticTTFCPUI": 21198, "roughEstimateOfSI": 4104, "optimisticSI": 1974, "pessimisticSI": 2446, "roughEstimateOfEIL": 373, "optimisticEIL": 466, "pessimisticEIL": 466}, @@ -54,7 +54,7 @@ {"url": "http://www.maktoob.com/", "roughEstimateOfFCP": 3986, "optimisticFCP": 3078, "pessimisticFCP": 3078, "roughEstimateOfFMP": 4132, "optimisticFMP": 3078, "pessimisticFMP": 3078, "roughEstimateOfTTI": 12242, "optimisticTTI": 9682, "pessimisticTTI": 10739, "roughEstimateOfTTFCPUI": 12242, "optimisticTTFCPUI": 9682, "pessimisticTTFCPUI": 10739, "roughEstimateOfSI": 4716, "optimisticSI": 2118, "pessimisticSI": 3078, "roughEstimateOfEIL": 265, "optimisticEIL": 332, "pessimisticEIL": 332}, {"url": "http://www.marketgid.com/", "roughEstimateOfFCP": 3848, "optimisticFCP": 2952, "pessimisticFCP": 2952, "roughEstimateOfFMP": 6657, "optimisticFMP": 5483, "pessimisticFMP": 5483, "roughEstimateOfTTI": 9770, "optimisticTTI": 7073, "pessimisticTTI": 8723, "roughEstimateOfTTFCPUI": 9770, "optimisticTTFCPUI": 7073, "pessimisticTTFCPUI": 8723, "roughEstimateOfSI": 4795, "optimisticSI": 2233, "pessimisticSI": 2952, "roughEstimateOfEIL": 226, "optimisticEIL": 283, "pessimisticEIL": 283}, {"url": "http://www.metacafe.com/", "roughEstimateOfFCP": 1973, "optimisticFCP": 1248, "pessimisticFCP": 1248, "roughEstimateOfFMP": 2213, "optimisticFMP": 1250, "pessimisticFMP": 1250, "roughEstimateOfTTI": 16192, "optimisticTTI": 12260, "pessimisticTTI": 16080, "roughEstimateOfTTFCPUI": 16192, "optimisticTTFCPUI": 12260, "pessimisticTTFCPUI": 16080, "roughEstimateOfSI": 2512, "optimisticSI": 1393, "pessimisticSI": 1248, "roughEstimateOfEIL": 361, "optimisticEIL": 451, "pessimisticEIL": 451}, - {"url": "http://www.metrolyrics.com/", "roughEstimateOfFCP": 3401, "optimisticFCP": 2456, "pessimisticFCP": 2654, "roughEstimateOfFMP": 3598, "optimisticFMP": 2456, "pessimisticFMP": 2654, "roughEstimateOfTTI": 54608, "optimisticTTI": 38080, "pessimisticTTI": 67023, "roughEstimateOfTTFCPUI": 28570, "optimisticTTFCPUI": 38080, "pessimisticTTFCPUI": 9160, "roughEstimateOfSI": 14965, "optimisticSI": 9636, "pessimisticSI": 2654, "roughEstimateOfEIL": 1134, "optimisticEIL": 1417, "pessimisticEIL": 1417}, + {"url": "http://www.metrolyrics.com/", "roughEstimateOfFCP": 3401, "optimisticFCP": 2456, "pessimisticFCP": 2654, "roughEstimateOfFMP": 3598, "optimisticFMP": 2456, "pessimisticFMP": 2654, "roughEstimateOfTTI": 54705, "optimisticTTI": 37954, "pessimisticTTI": 67406, "roughEstimateOfTTFCPUI": 28494, "optimisticTTFCPUI": 37954, "pessimisticTTFCPUI": 9160, "roughEstimateOfSI": 14965, "optimisticSI": 9636, "pessimisticSI": 2654, "roughEstimateOfEIL": 1134, "optimisticEIL": 1417, "pessimisticEIL": 1417}, {"url": "http://www.mlb.com/", "roughEstimateOfFCP": 3235, "optimisticFCP": 2124, "pessimisticFCP": 2722, "roughEstimateOfFMP": 3489, "optimisticFMP": 2124, "pessimisticFMP": 2722, "roughEstimateOfTTI": 31734, "optimisticTTI": 25537, "pessimisticTTI": 32914, "roughEstimateOfTTFCPUI": 20685, "optimisticTTFCPUI": 25537, "pessimisticTTFCPUI": 8361, "roughEstimateOfSI": 7242, "optimisticSI": 4088, "pessimisticSI": 2722, "roughEstimateOfEIL": 761, "optimisticEIL": 951, "pessimisticEIL": 951}, {"url": "http://www.mop.com/", "roughEstimateOfFCP": 7496, "optimisticFCP": 5780, "pessimisticFCP": 6856, "roughEstimateOfFMP": 7614, "optimisticFMP": 5780, "pessimisticFMP": 6856, "roughEstimateOfTTI": 20885, "optimisticTTI": 9659, "pessimisticTTI": 29977, "roughEstimateOfTTFCPUI": 8565, "optimisticTTFCPUI": 9659, "pessimisticTTFCPUI": 2599, "roughEstimateOfSI": 9814, "optimisticSI": 4006, "pessimisticSI": 6856, "roughEstimateOfEIL": 828, "optimisticEIL": 1035, "pessimisticEIL": 1035}, {"url": "http://www.mozilla.org/", "roughEstimateOfFCP": 2556, "optimisticFCP": 1455, "pessimisticFCP": 2166, "roughEstimateOfFMP": 3307, "optimisticFMP": 1455, "pessimisticFMP": 2919, "roughEstimateOfTTI": 6322, "optimisticTTI": 3850, "pessimisticTTI": 5361, "roughEstimateOfTTFCPUI": 6322, "optimisticTTFCPUI": 3850, "pessimisticTTFCPUI": 5361, "roughEstimateOfSI": 2798, "optimisticSI": 1172, "pessimisticSI": 2166, "roughEstimateOfEIL": 842, "optimisticEIL": 1053, "pessimisticEIL": 1053}, @@ -94,7 +94,7 @@ {"url": "http://www.typepad.com/", "roughEstimateOfFCP": 3665, "optimisticFCP": 1826, "pessimisticFCP": 3938, "roughEstimateOfFMP": 4229, "optimisticFMP": 2147, "pessimisticFMP": 3938, "roughEstimateOfTTI": 5732, "optimisticTTI": 3275, "pessimisticTTI": 4817, "roughEstimateOfTTFCPUI": 5732, "optimisticTTFCPUI": 3275, "pessimisticTTFCPUI": 4817, "roughEstimateOfSI": 3665, "optimisticSI": 962, "pessimisticSI": 3938, "roughEstimateOfEIL": 108, "optimisticEIL": 16, "pessimisticEIL": 253}, {"url": "http://www.verizonwireless.com/", "roughEstimateOfFCP": 3131, "optimisticFCP": 2301, "pessimisticFCP": 2301, "roughEstimateOfFMP": 4107, "optimisticFMP": 3054, "pessimisticFMP": 3054, "roughEstimateOfTTI": 16796, "optimisticTTI": 12895, "pessimisticTTI": 16577, "roughEstimateOfTTFCPUI": 16796, "optimisticTTFCPUI": 12895, "pessimisticTTFCPUI": 16577, "roughEstimateOfSI": 3437, "optimisticSI": 1565, "pessimisticSI": 2301, "roughEstimateOfEIL": 931, "optimisticEIL": 1164, "pessimisticEIL": 1164}, {"url": "http://www.vevo.com/", "roughEstimateOfFCP": 2592, "optimisticFCP": 1811, "pessimisticFCP": 1811, "roughEstimateOfFMP": 3701, "optimisticFMP": 2668, "pessimisticFMP": 2668, "roughEstimateOfTTI": 24162, "optimisticTTI": 18073, "pessimisticTTI": 26039, "roughEstimateOfTTFCPUI": 14355, "optimisticTTFCPUI": 18073, "pessimisticTTFCPUI": 4248, "roughEstimateOfSI": 4172, "optimisticSI": 2318, "pessimisticSI": 1811, "roughEstimateOfEIL": 2218, "optimisticEIL": 2772, "pessimisticEIL": 2772}, - {"url": "http://www.weather.com/", "roughEstimateOfFCP": 6844, "optimisticFCP": 5676, "pessimisticFCP": 5676, "roughEstimateOfFMP": 6860, "optimisticFMP": 5676, "pessimisticFMP": 5676, "roughEstimateOfTTI": 28641, "optimisticTTI": 22898, "pessimisticTTI": 29561, "roughEstimateOfTTFCPUI": 22576, "optimisticTTFCPUI": 22898, "pessimisticTTFCPUI": 16083, "roughEstimateOfSI": 7932, "optimisticSI": 3209, "pessimisticSI": 5676, "roughEstimateOfEIL": 1338, "optimisticEIL": 1672, "pessimisticEIL": 1672}, + {"url": "http://www.weather.com/", "roughEstimateOfFCP": 6844, "optimisticFCP": 5676, "pessimisticFCP": 5676, "roughEstimateOfFMP": 6860, "optimisticFMP": 5676, "pessimisticFMP": 5676, "roughEstimateOfTTI": 28799, "optimisticTTI": 23048, "pessimisticTTI": 29711, "roughEstimateOfTTFCPUI": 22772, "optimisticTTFCPUI": 23048, "pessimisticTTFCPUI": 16319, "roughEstimateOfSI": 7932, "optimisticSI": 3209, "pessimisticSI": 5676, "roughEstimateOfEIL": 1338, "optimisticEIL": 1672, "pessimisticEIL": 1672}, {"url": "http://www.wikipedia.org/", "roughEstimateOfFCP": 1587, "optimisticFCP": 934, "pessimisticFCP": 934, "roughEstimateOfFMP": 1821, "optimisticFMP": 934, "pessimisticFMP": 934, "roughEstimateOfTTI": 5915, "optimisticTTI": 4070, "pessimisticTTI": 4161, "roughEstimateOfTTFCPUI": 5915, "optimisticTTFCPUI": 4070, "pessimisticTTFCPUI": 4161, "roughEstimateOfSI": 2299, "optimisticSI": 1387, "pessimisticSI": 934, "roughEstimateOfEIL": 1682, "optimisticEIL": 2102, "pessimisticEIL": 2102}, {"url": "http://www.ynet.com/", "roughEstimateOfFCP": 2518, "optimisticFCP": 1744, "pessimisticFCP": 1744, "roughEstimateOfFMP": 2731, "optimisticFMP": 1744, "pessimisticFMP": 1744, "roughEstimateOfTTI": 9865, "optimisticTTI": 3663, "pessimisticTTI": 13483, "roughEstimateOfTTFCPUI": 5439, "optimisticTTFCPUI": 3663, "pessimisticTTFCPUI": 3649, "roughEstimateOfSI": 4689, "optimisticSI": 2718, "pessimisticSI": 1744, "roughEstimateOfEIL": 152, "optimisticEIL": 190, "pessimisticEIL": 190}, {"url": "http://www.youdao.com/", "roughEstimateOfFCP": 3309, "optimisticFCP": 2463, "pessimisticFCP": 2463, "roughEstimateOfFMP": 3486, "optimisticFMP": 2463, "pessimisticFMP": 2463, "roughEstimateOfTTI": 4186, "optimisticTTI": 2463, "pessimisticTTI": 2463, "roughEstimateOfTTFCPUI": 3486, "optimisticTTFCPUI": 1231, "pessimisticTTFCPUI": 1277, "roughEstimateOfSI": 6077, "optimisticSI": 3376, "pessimisticSI": 2463, "roughEstimateOfEIL": 13, "optimisticEIL": 16, "pessimisticEIL": 16}, diff --git a/lighthouse-core/test/fixtures/wikipedia-redirect.critical-request-chains.json b/lighthouse-core/test/fixtures/wikipedia-redirect.critical-request-chains.json index bd5ccf1c3d22..c38d64cbaf49 100644 --- a/lighthouse-core/test/fixtures/wikipedia-redirect.critical-request-chains.json +++ b/lighthouse-core/test/fixtures/wikipedia-redirect.critical-request-chains.json @@ -1,11 +1,11 @@ { - "33097.1:redirected.0": { + "33097.1": { "children": { - "33097.1:redirected.1": { + "33097.1:redirect": { "children": { - "33097.1:redirected.2": { + "33097.1:redirect:redirect": { "children": { - "33097.1": { + "33097.1:redirect:redirect:redirect": { "children": { "33097.3": { "children": {} diff --git a/lighthouse-core/test/gather/computed/critical-request-chains-test.js b/lighthouse-core/test/gather/computed/critical-request-chains-test.js index 349a684b91e3..3da32f1d4c63 100644 --- a/lighthouse-core/test/gather/computed/critical-request-chains-test.js +++ b/lighthouse-core/test/gather/computed/critical-request-chains-test.js @@ -57,7 +57,7 @@ describe('CriticalRequestChain gatherer: extractChain function', () => { const networkPromise = computedArtifacts.requestNetworkRecords(wikiDevtoolsLog); const CRCPromise = computedArtifacts.requestCriticalRequestChains({devtoolsLog: wikiDevtoolsLog, URL}); - Promise.all([CRCPromise, networkPromise]).then(([chains, networkRecords]) => { + return Promise.all([CRCPromise, networkPromise]).then(([chains, networkRecords]) => { // set all network requests based on requestid replaceChain(wikiChains, networkRecords); assert.deepEqual(chains, wikiChains); diff --git a/lighthouse-core/test/gather/gatherers/dobetterweb/optimized-images-test.js b/lighthouse-core/test/gather/gatherers/dobetterweb/optimized-images-test.js index 009eb2d7c79f..c71e2f81bfba 100644 --- a/lighthouse-core/test/gather/gatherers/dobetterweb/optimized-images-test.js +++ b/lighthouse-core/test/gather/gatherers/dobetterweb/optimized-images-test.js @@ -23,7 +23,7 @@ const traceData = { _url: 'http://google.com/image.jpg', _mimeType: 'image/jpeg', _resourceSize: 10000, - _transferSize: 20000, + transferSize: 20000, _resourceType: {_name: 'image'}, finished: true, }, @@ -31,7 +31,7 @@ const traceData = { _url: 'http://google.com/transparent.png', _mimeType: 'image/png', _resourceSize: 11000, - _transferSize: 20000, + transferSize: 20000, _resourceType: {_name: 'image'}, finished: true, }, @@ -39,7 +39,7 @@ const traceData = { _url: 'http://google.com/image.bmp', _mimeType: 'image/bmp', _resourceSize: 12000, - _transferSize: 9000, // bitmap was compressed another way + transferSize: 9000, // bitmap was compressed another way _resourceType: {_name: 'image'}, finished: true, }, @@ -47,7 +47,7 @@ const traceData = { _url: 'http://google.com/image.bmp', _mimeType: 'image/bmp', _resourceSize: 12000, - _transferSize: 20000, + transferSize: 20000, _resourceType: {_name: 'image'}, finished: true, }, @@ -55,7 +55,7 @@ const traceData = { _url: 'http://google.com/vector.svg', _mimeType: 'image/svg+xml', _resourceSize: 13000, - _transferSize: 20000, + transferSize: 20000, _resourceType: {_name: 'image'}, finished: true, }, @@ -63,7 +63,7 @@ const traceData = { _url: 'http://gmail.com/image.jpg', _mimeType: 'image/jpeg', _resourceSize: 15000, - _transferSize: 20000, + transferSize: 20000, _resourceType: {_name: 'image'}, finished: true, }, @@ -72,7 +72,7 @@ const traceData = { _mimeType: 'image/jpeg', _resourceType: {_name: 'image'}, _resourceSize: 14000, - _transferSize: 20000, + transferSize: 20000, finished: true, }, { @@ -80,7 +80,7 @@ const traceData = { _mimeType: 'image/bmp', _resourceType: {_name: 'image'}, _resourceSize: 12000, - _transferSize: 20000, + transferSize: 20000, finished: false, // ignore for not finishing }, { @@ -88,7 +88,7 @@ const traceData = { _mimeType: 'image/bmp', _resourceType: {_name: 'document'}, // ignore for not really being an image _resourceSize: 12000, - _transferSize: 20000, + transferSize: 20000, finished: true, }, ], diff --git a/lighthouse-core/test/gather/gatherers/dobetterweb/response-compression-test.js b/lighthouse-core/test/gather/gatherers/dobetterweb/response-compression-test.js index b8177cc81864..06473b13ddc0 100644 --- a/lighthouse-core/test/gather/gatherers/dobetterweb/response-compression-test.js +++ b/lighthouse-core/test/gather/gatherers/dobetterweb/response-compression-test.js @@ -22,7 +22,7 @@ const traceData = { _mimeType: 'text/javascript', _requestId: 0, _resourceSize: 9, - _transferSize: 10, + transferSize: 10, _resourceType: { _isTextType: true, }, @@ -39,7 +39,7 @@ const traceData = { _mimeType: 'text/css', _requestId: 1, _resourceSize: 6, - _transferSize: 7, + transferSize: 7, _resourceType: { _isTextType: true, }, @@ -53,7 +53,7 @@ const traceData = { _mimeType: 'application/json', _requestId: 2, _resourceSize: 7, - _transferSize: 8, + transferSize: 8, _resourceType: { _isTextType: true, }, @@ -67,7 +67,7 @@ const traceData = { _mimeType: 'application/json', _requestId: 22, _resourceSize: 7, - _transferSize: 7, + transferSize: 7, _resourceType: { _isTextType: true, }, @@ -81,7 +81,7 @@ const traceData = { _mimeType: 'application/json', _requestId: 23, _resourceSize: 7, - _transferSize: 8, + transferSize: 8, _resourceType: { _isTextType: true, }, @@ -95,7 +95,7 @@ const traceData = { _mimeType: 'image/jpg', _requestId: 3, _resourceSize: 10, - _transferSize: 10, + transferSize: 10, _resourceType: { _isTextType: false, }, @@ -109,7 +109,7 @@ const traceData = { _mimeType: 'video/mp4', _requestId: 4, _resourceSize: 100, - _transferSize: 100, + transferSize: 100, _resourceType: { _isTextType: false, }, @@ -162,7 +162,7 @@ describe('Optimized responses', () => { _mimeType: 'text/css', _requestId: 1, _resourceSize: 10, - _transferSize: 10, + transferSize: 10, _resourceType: { _isTextType: true, }, @@ -175,7 +175,7 @@ describe('Optimized responses', () => { _mimeType: 'text/css', _requestId: 1, _resourceSize: 123, - _transferSize: 123, + transferSize: 123, _resourceType: { _isTextType: true, }, @@ -200,7 +200,7 @@ describe('Optimized responses', () => { record.statusCode = record._statusCode; record.mimeType = record._mimeType; record.resourceSize = record._resourceSize; - record.transferSize = record._transferSize; + record.transferSize = record.transferSize; record.responseHeaders = record._responseHeaders; record.requestId = record._requestId; record._resourceType = Object.assign( diff --git a/lighthouse-core/test/gather/gatherers/dobetterweb/tags-blocking-first-paint-test.js b/lighthouse-core/test/gather/gatherers/dobetterweb/tags-blocking-first-paint-test.js index 6987b261492c..f787644bb535 100644 --- a/lighthouse-core/test/gather/gatherers/dobetterweb/tags-blocking-first-paint-test.js +++ b/lighthouse-core/test/gather/gatherers/dobetterweb/tags-blocking-first-paint-test.js @@ -16,81 +16,81 @@ const traceData = { { _url: 'http://google.com/css/style.css', _mimeType: 'text/css', - _transferSize: 10, - _startTime: 10, - _endTime: 10, + transferSize: 10, + startTime: 10, + endTime: 10, finished: true, - isLinkPreload: false, + _isLinkPreload: false, _initiator: {type: 'parser'}, }, { _url: 'http://google.com/wc/select.html', _mimeType: 'text/html', - _transferSize: 11, - _startTime: 11, - _endTime: 11, + transferSize: 11, + startTime: 11, + endTime: 11, finished: true, - isLinkPreload: false, + _isLinkPreload: false, _initiator: {type: 'other'}, }, { _url: 'http://google.com/js/app.json', _mimeType: 'application/json', - _transferSize: 24, - _startTime: 24, - _endTime: 24, + transferSize: 24, + startTime: 24, + endTime: 24, finished: true, - isLinkPreload: false, + _isLinkPreload: false, _initiator: {type: 'script'}, }, { _url: 'http://google.com/js/app.js', _mimeType: 'text/javascript', - _transferSize: 12, - _startTime: 12, - _endTime: 22, + transferSize: 12, + startTime: 12, + endTime: 22, finished: true, - isLinkPreload: false, + _isLinkPreload: false, _initiator: {type: 'parser'}, }, { _url: 'http://google.com/wc/import.html', _mimeType: 'text/html', - _transferSize: 13, - _startTime: 13, - _endTime: 13, + transferSize: 13, + startTime: 13, + endTime: 13, finished: true, - isLinkPreload: false, + _isLinkPreload: false, _initiator: {type: 'script'}, }, { _url: 'http://google.com/css/ignored.css', _mimeType: 'text/css', - _transferSize: 16, - _startTime: 16, - _endTime: 16, + transferSize: 16, + startTime: 16, + endTime: 16, finished: true, - isLinkPreload: true, + _isLinkPreload: true, _initiator: {type: 'script'}, }, { _url: 'http://google.com/js/ignored.js', _mimeType: 'text/javascript', - _transferSize: 16, - _startTime: 16, - _endTime: 16, + transferSize: 16, + startTime: 16, + endTime: 16, finished: true, - isLinkPreload: false, + _isLinkPreload: false, _initiator: {type: 'script'}, }, { _url: 'http://google.com/js/also-ignored.js', _mimeType: 'text/javascript', - _transferSize: 12, - _startTime: 12, - _endTime: 22, + transferSize: 12, + startTime: 12, + endTime: 22, finished: false, - isLinkPreload: false, + _isLinkPreload: false, _initiator: {type: 'parser'}, }, ], diff --git a/lighthouse-core/test/gather/network-recorder-test.js b/lighthouse-core/test/lib/network-recorder-test.js similarity index 73% rename from lighthouse-core/test/gather/network-recorder-test.js rename to lighthouse-core/test/lib/network-recorder-test.js index 2aadd9bb6376..7119b3a1d036 100644 --- a/lighthouse-core/test/gather/network-recorder-test.js +++ b/lighthouse-core/test/lib/network-recorder-test.js @@ -8,6 +8,7 @@ const NetworkRecorder = require('../../lib/network-recorder'); const assert = require('assert'); const devtoolsLogItems = require('../fixtures/artifacts/perflog/defaultPass.devtoolslog.json'); +const redirectsDevtoolsLog = require('../fixtures/wikipedia-redirect.devtoolslog.json'); /* eslint-env mocha */ describe('network recorder', function() { @@ -17,6 +18,33 @@ describe('network recorder', function() { assert.equal(records.length, 76); }); + it('handles redirects properly', () => { + const records = NetworkRecorder.recordsFromLogs(redirectsDevtoolsLog); + assert.equal(records.length, 25); + + const [redirectA, redirectB, redirectC, mainDocument] = records.slice(0, 4); + assert.equal(redirectA.initiatorRequest(), undefined); + assert.equal(redirectA.redirectSource, undefined); + assert.equal(redirectA.redirectDestination, redirectB); + assert.equal(redirectB.initiatorRequest(), redirectA); + assert.equal(redirectB.redirectSource, redirectA); + assert.equal(redirectB.redirectDestination, redirectC); + assert.equal(redirectC.initiatorRequest(), redirectB); + assert.equal(redirectC.redirectSource, redirectB); + assert.equal(redirectC.redirectDestination, mainDocument); + assert.equal(mainDocument.initiatorRequest(), redirectC); + assert.equal(mainDocument.redirectSource, redirectC); + assert.equal(mainDocument.redirectDestination, undefined); + + const redirectURLs = mainDocument.redirects.map(request => request.url); + assert.deepStrictEqual(redirectURLs, [redirectA.url, redirectB.url, redirectC.url]); + + assert.equal(redirectA._resourceType, undefined); + assert.equal(redirectB._resourceType, undefined); + assert.equal(redirectC._resourceType, undefined); + assert.equal(mainDocument._resourceType._name, 'document'); + }); + describe('#findNetworkQuietPeriods', () => { function record(data) { const url = data.url || 'https://example.com'; diff --git a/lighthouse-core/test/lib/web-inspector-test.js b/lighthouse-core/test/lib/web-inspector-test.js index d84fbe9f58fa..36cba612d77e 100644 --- a/lighthouse-core/test/lib/web-inspector-test.js +++ b/lighthouse-core/test/lib/web-inspector-test.js @@ -17,7 +17,6 @@ describe('Web Inspector lib', function() { assert.ok(WebInspector.FilmStripModel); assert.ok(WebInspector.TimelineProfileTree); assert.ok(WebInspector.TimelineAggregator); - assert.ok(WebInspector.NetworkManager); assert.ok(WebInspector.Color); assert.ok(WebInspector.CSSMetadata); }); diff --git a/package.json b/package.json index a1c278b93047..bbcc284a5252 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "update:sample-json": "node ./lighthouse-cli -A=./lighthouse-core/test/results/artifacts --throttling-method=devtools --output=json --output-path=./lighthouse-core/test/results/sample_v2.json && node lighthouse-core/scripts/cleanup-LHR-for-diff.js ./lighthouse-core/test/results/sample_v2.json --only-remove-timing", "diff:sample-json": "bash lighthouse-core/scripts/assert-golden-lhr-unchanged.sh", "update:crdp-typings": "node lighthouse-core/scripts/extract-crdp-mapping.js", - "mixed-content": "./lighthouse-cli/index.js --chrome-flags='--headless' --config-path=./lighthouse-core/config/mixed-content.js", + "mixed-content": "./lighthouse-cli/index.js --chrome-flags='--headless' --preset=mixed-content", "minify-latest-run": "./lighthouse-core/scripts/lantern/minify-trace.js ./latest-run/defaultPass.trace.json ./latest-run/defaultPass.trace.min.json && ./lighthouse-core/scripts/lantern/minify-devtoolslog.js ./latest-run/defaultPass.devtoolslog.json ./latest-run/defaultPass.devtoolslog.min.json" }, "devDependencies": { diff --git a/third-party/devtools/LICENSE b/third-party/devtools/LICENSE new file mode 100644 index 000000000000..972bb2edb099 --- /dev/null +++ b/third-party/devtools/LICENSE @@ -0,0 +1,27 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/third-party/devtools/ResourceType.js b/third-party/devtools/ResourceType.js new file mode 100644 index 000000000000..4952fae31955 --- /dev/null +++ b/third-party/devtools/ResourceType.js @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2012 Google Inc. All rights reserved. + * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// ADAPTED FROM https://cs.chromium.org/chromium/src/third_party/blink/renderer/devtools/front_end/common/ResourceType.js + +/* eslint-disable */ + +class ResourceType { + /** + * @param {string} name + * @param {string} title + * @param {string} category + * @param {boolean} isTextType + */ + constructor(name, title, category, isTextType) { + this._name = name; + this._title = title; + this._category = category; + this._isTextType = isTextType; + } + + /** + * @return {boolean} + */ + isTextType() { + return this._isTextType; + } +}; + +/** @type {Record} */ +ResourceType.TYPES = { + XHR: new ResourceType('xhr', 'XHR', 'XHR', true), + Fetch: new ResourceType('fetch', 'Fetch', 'XHR', true), + EventSource: new ResourceType('eventsource', 'EventSource', 'XHR', true), + Script: new ResourceType('script', 'Script', 'Script', true), + Stylesheet: new ResourceType('stylesheet', 'Stylesheet', 'Stylesheet', true), + Image: new ResourceType('image', 'Image', 'Image', false), + Media: new ResourceType('media', 'Media', 'Media', false), + Font: new ResourceType('font', 'Font', 'Font', false), + Document: new ResourceType('document', 'Document', 'Document', true), + TextTrack: new ResourceType('texttrack', 'TextTrack', 'Other', true), + WebSocket: new ResourceType('websocket', 'WebSocket', 'WebSocket', false), + Other: new ResourceType('other', 'Other', 'Other', false), + Manifest: new ResourceType('manifest', 'Manifest', 'Manifest', true), +}; + +module.exports = ResourceType; diff --git a/tsconfig.json b/tsconfig.json index 1a9dfd707c90..1542dedfd2df 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -17,6 +17,7 @@ "include": [ // TODO(bckenny): unnecessary workaround until https://github.com/Microsoft/TypeScript/issues/24062 "node_modules/@types/node/index.d.ts", + "third-party/devtools/*.js", "lighthouse-cli/**/*.js", "lighthouse-core/**/*.js", diff --git a/typings/artifacts.d.ts b/typings/artifacts.d.ts index 1d6aa61868b8..b3d0beaf47bb 100644 --- a/typings/artifacts.d.ts +++ b/typings/artifacts.d.ts @@ -79,6 +79,8 @@ declare global { MetaDescription: string|null; /** The value of the 's content attribute, or null. */ MetaRobots: string|null; + /** The URL loaded with interception */ + MixedContent: {url: string}; /** The status code of the attempted load of the page while network access is disabled. */ Offline: number; /** Size and compression opportunity information for all the images in the page. */ diff --git a/typings/web-inspector.d.ts b/typings/web-inspector.d.ts index ce845066a879..9f194b6c4bd4 100644 --- a/typings/web-inspector.d.ts +++ b/typings/web-inspector.d.ts @@ -4,10 +4,12 @@ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ +import ResourceType = require("../third-party/devtools/ResourceType"); + declare global { module LH.WebInspector { - // TODO(bckenny): standardize on underscored internal API - // externs for chrome-devtools-frontend/front_end/sdk/NetworkRequest.js + // TODO(phulce): migrate to use network-request.js + // externs for old chrome-devtools-frontend/front_end/sdk/NetworkRequest.js export interface NetworkRequest { requestId: string; _requestId: string; @@ -18,8 +20,8 @@ declare global { _url: string; protocol: string; parsedURL: ParsedURL; - // Use parsedURL.securityOrigin() instead - origin: never; + isSecure: boolean; + documentURL: string; startTime: number; endTime: number; @@ -27,32 +29,35 @@ declare global { transferSize: number; /** Should use a default of 0 if not defined */ - _transferSize?: number; - /** Should use a default of 0 if not defined */ _resourceSize?: number; _fromDiskCache?: boolean; + _fromMemoryCache?: boolean; finished: boolean; requestMethod: string; statusCode: number; - redirectSource?: { - url: string; - } + redirectSource?: {url: string;}; + redirectDestination?: {url: string;}; + redirects?: NetworkRequest[]; failed?: boolean; localizedFailDescription?: string; _initiator: Crdp.Network.Initiator; - _timing: Crdp.Network.ResourceTiming; - _resourceType: ResourceType; + _timing?: Crdp.Network.ResourceTiming; + _resourceType?: ResourceType; _mimeType: string; - priority(): 'VeryHigh' | 'High' | 'Medium' | 'Low'; - _responseHeaders?: {name: string, value: string}[]; + priority(): Crdp.Network.ResourcePriority; + initiatorRequest(): NetworkRequest | undefined; + _responseHeaders?: HeaderValue[]; _fetchedViaServiceWorker?: boolean; - _frameId: Crdp.Page.FrameId; + _frameId?: Crdp.Page.FrameId; _isLinkPreload?: boolean; - initiatorRequest(): NetworkRequest | null; - redirects?: NetworkRequest[]; + } + + export interface HeaderValue { + name: string; + value: string; } export interface ParsedURL { @@ -60,18 +65,6 @@ declare global { host: string; securityOrigin(): string; } - - export interface ResourceType { - _category: ResourceCategory; - name(): string; - _name: string; - title(): string; - isTextType(): boolean; - } - - export interface ResourceCategory { - title: string; - } } }