Skip to content
Closed
3 changes: 2 additions & 1 deletion lighthouse-cli/cli-flags.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ function getFlags(manualArgv) {
'skip-audits': 'Run everything except these audits',
'plugins': 'Run the specified plugins',
'print-config': 'Print the normalized config for the given config and options, then exit.',
'ignore-https-errors': 'Whether to ignore HTTPS errors during navigation. Defaults to false',
})
// set aliases
.alias({'gather-mode': 'G', 'audit-mode': 'A'})
Expand All @@ -123,7 +124,7 @@ function getFlags(manualArgv) {
// boolean values
.boolean([
'disable-storage-reset', 'save-assets', 'list-all-audits',
'list-trace-categories', 'view', 'verbose', 'quiet', 'help', 'print-config',
'list-trace-categories', 'view', 'verbose', 'quiet', 'help', 'print-config', 'ignore-https-errors',
])
.choices('output', printer.getValidOutputOptions())
.choices('emulated-form-factor', ['mobile', 'desktop', 'none'])
Expand Down
2 changes: 2 additions & 0 deletions lighthouse-cli/test/cli/__snapshots__/index-test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -1203,6 +1203,7 @@ Object {
"emulatedFormFactor": "mobile",
"extraHeaders": null,
"gatherMode": false,
"ignoreHttpsErrors": false,
"locale": "en-US",
"maxWaitForFcp": 15000,
"maxWaitForLoad": 45000,
Expand Down Expand Up @@ -1332,6 +1333,7 @@ Object {
"emulatedFormFactor": "mobile",
"extraHeaders": null,
"gatherMode": false,
"ignoreHttpsErrors": false,
"locale": "en-US",
"maxWaitForFcp": 15000,
"maxWaitForLoad": 45000,
Expand Down
1 change: 1 addition & 0 deletions lighthouse-core/config/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ const defaultSettings = {
onlyAudits: null,
onlyCategories: null,
skipAudits: null,
ignoreHttpsErrors: false,
};

/** @type {LH.Config.Pass} */
Expand Down
51 changes: 46 additions & 5 deletions lighthouse-core/gather/driver.js
Original file line number Diff line number Diff line change
Expand Up @@ -658,6 +658,22 @@ class Driver {
return {promise: Promise.resolve(), cancel() {}};
}

/**
* Returns a promise that never resolves.
* Used for placeholder conditions that we don't want race with, but still want to satisfy the same
* interface.
* @return {{promise: Promise<void>, cancel: function(): void}}
*/
_waitForever() {
let cancel = () => {};
return {
promise: new Promise(resolve => {
cancel = resolve;
}),
cancel,
};
}

/**
* Returns a promise that resolve when a frame has been navigated.
* Used for detecting that our about:blank reset has been completed.
Expand Down Expand Up @@ -977,11 +993,12 @@ class Driver {
* @param {number} cpuQuietThresholdMs
* @param {number} maxWaitForLoadedMs
* @param {number=} maxWaitForFCPMs
* @param {boolean} ignoreHttpsErrors
* @return {Promise<void>}
* @private
*/
async _waitForFullyLoaded(pauseAfterLoadMs, networkQuietThresholdMs, cpuQuietThresholdMs,
maxWaitForLoadedMs, maxWaitForFCPMs) {
maxWaitForLoadedMs, maxWaitForFCPMs, ignoreHttpsErrors) {
/** @type {NodeJS.Timer|undefined} */
let maxTimeoutHandle;

Expand All @@ -994,10 +1011,15 @@ class Driver {
// CPU listener. Resolves when the CPU has been idle for cpuQuietThresholdMs after network idle.
let waitForCPUIdle = this._waitForNothing();

const monitorForInsecureState = this._monitorForInsecureState();
/** @type {{promise: Promise<string | void>, cancel: () => void}} */
const monitorForInsecureState = ignoreHttpsErrors
? this._waitForever()
: this._monitorForInsecureState();
const securityCheckPromise = monitorForInsecureState.promise.then(securityMessages => {
return function() {
throw new LHError(LHError.errors.INSECURE_DOCUMENT_REQUEST, {securityMessages});
throw new LHError(LHError.errors.INSECURE_DOCUMENT_REQUEST, {
securityMessages: securityMessages || '',
});
};
});

Expand Down Expand Up @@ -1136,7 +1158,7 @@ class Driver {
* possible workaround.
* Resolves on the url of the loaded page, taking into account any redirects.
* @param {string} url
* @param {{waitForFCP?: boolean, waitForLoad?: boolean, waitForNavigated?: boolean, passContext?: LH.Gatherer.PassContext}} options
* @param {{waitForFCP?: boolean, waitForLoad?: boolean, waitForNavigated?: boolean, passContext?: LH.Gatherer.PassContext, ignoreHttpsErrors?: boolean}} options
* @return {Promise<string>}
*/
async gotoURL(url, options = {}) {
Expand All @@ -1145,6 +1167,7 @@ class Driver {
const waitForLoad = options.waitForLoad || false;
const passContext = /** @type {Partial<LH.Gatherer.PassContext>} */ (options.passContext || {});
const disableJS = passContext.disableJavaScript || false;
const ignoreHttpsErrors = options.ignoreHttpsErrors || false;

if (waitForNavigated && (waitForFCP || waitForLoad)) {
throw new Error('Cannot use both waitForNavigated and another event, pick just one');
Expand Down Expand Up @@ -1184,7 +1207,7 @@ class Driver {

if (!waitForFCP) maxFCPMs = undefined;
await this._waitForFullyLoaded(pauseAfterLoadMs, networkQuietThresholdMs, cpuQuietThresholdMs,
maxWaitMs, maxFCPMs);
maxWaitMs, maxFCPMs, ignoreHttpsErrors);
}

// Bring `Page.navigate` errors back into the promise chain. See https://github.com/GoogleChrome/lighthouse/pull/6739.
Expand Down Expand Up @@ -1565,6 +1588,24 @@ class Driver {

await this.sendCommand('Page.enable');
}

/**
* Set chrome security settings to ignore certificate errors.
* @return {Promise<void>}
*/
async setIgnoreHttpsErrors() {
// the devtools protocol also has an experimental Security.setIgnoreCertificateErrors
// https://chromedevtools.github.io/devtools-protocol/tot/Security#method-setIgnoreCertificateErrors
// It can be used instead of the following when it becomes stable.
this.on('Security.certificateError', event => {
this.sendCommand('Security.handleCertificateError', {
eventId: event.eventId,
action: 'continue',
}).catch(err => log.warn('Driver', err));
});
await this.sendCommand('Security.enable');
await this.sendCommand('Security.setOverrideCertificateErrors', {override: true});
}
}

module.exports = Driver;
3 changes: 3 additions & 0 deletions lighthouse-core/gather/gather-runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ class GatherRunner {
const finalUrl = await driver.gotoURL(passContext.url, {
waitForFCP: passContext.passConfig.recordTrace,
waitForLoad: true,
ignoreHttpsErrors: passContext.settings.ignoreHttpsErrors,
passContext,
});
passContext.url = finalUrl;
Expand All @@ -106,12 +107,14 @@ class GatherRunner {
const status = {msg: 'Initializing…', id: 'lh:gather:setupDriver'};
log.time(status);
const resetStorage = !options.settings.disableStorageReset;
const ignoreHttpsErrors = options.settings.ignoreHttpsErrors;
await driver.assertNoSameOriginServiceWorkerClients(options.requestedUrl);
await driver.beginEmulation(options.settings);
await driver.enableRuntimeEvents();
await driver.cacheNatives();
await driver.registerPerformanceObserver();
await driver.dismissJavaScriptDialogs();
if (ignoreHttpsErrors) await driver.setIgnoreHttpsErrors();
if (resetStorage) await driver.clearDataForOrigin(options.requestedUrl);
log.timeEnd(status);
}
Expand Down
3 changes: 2 additions & 1 deletion lighthouse-core/test/results/sample_v2.json
Original file line number Diff line number Diff line change
Expand Up @@ -2970,7 +2970,8 @@
"precomputedLanternData": null,
"onlyAudits": null,
"onlyCategories": null,
"skipAudits": null
"skipAudits": null,
"ignoreHttpsErrors": false
},
"categories": {
"performance": {
Expand Down
2 changes: 2 additions & 0 deletions types/externs.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ declare global {
channel?: string
/** Precomputed lantern estimates to use instead of observed analysis. */
precomputedLanternData?: PrecomputedLanternData | null;
/** Ignore HTTPS errors during navigation */
ignoreHttpsErrors?: boolean;
}

/**
Expand Down