diff --git a/lighthouse-extension/app/manifest.json b/lighthouse-extension/app/manifest.json index 3d0a0e680a1a..83c213c4b8e6 100644 --- a/lighthouse-extension/app/manifest.json +++ b/lighthouse-extension/app/manifest.json @@ -19,6 +19,7 @@ "permissions": [ "activeTab", "debugger", + "management", "storage" ], "browser_action": { diff --git a/lighthouse-extension/app/src/lighthouse-background.js b/lighthouse-extension/app/src/lighthouse-background.js index d747d23cb44a..7f2ad4c29711 100644 --- a/lighthouse-extension/app/src/lighthouse-background.js +++ b/lighthouse-extension/app/src/lighthouse-background.js @@ -26,11 +26,36 @@ const log = require('../../../lighthouse-core/lib/log'); const ReportGenerator = require('../../../lighthouse-core/report/report-generator'); const STORAGE_KEY = 'lighthouse_audits'; -const _flatten = arr => [].concat(...arr); +let installedExtensions = []; let lighthouseIsRunning = false; let latestStatusLog = []; +const _flatten = arr => [].concat(...arr); + +/** + * Enables or disables all other installed chrome extensions. The initial list + * of the user's extension is created when the background page is started. + * @param {!boolean} enable If true, enables all other installed extensions. + * False disables them. + * @param {!Promise} + */ +function enableOtherChromeExtensions(enable) { + const str = enable ? 'enabling' : 'disabling'; + log.log('Chrome', `${str} ${installedExtensions.length} extensions.`); + + return Promise.all(installedExtensions.map(info => { + return new Promise((resolve, reject) => { + chrome.management.setEnabled(info.id, enable, _ => { + if (chrome.runtime.lastError) { + reject(chrome.runtime.lastError); + } + resolve(); + }); + }); + })); +} + /** * Filter out any unrequested aggregations from the config. If any audits are * no longer needed by any remaining aggregations, filter out those as well. @@ -124,8 +149,7 @@ window.runLighthouseForConnection = function(connection, url, options, requested lighthouseIsRunning = true; updateBadgeUI(url); - // Run Lighthouse. - return Runner.run(connection, runOptions) + return Runner.run(connection, runOptions) // Run Lighthouse. .then(result => { lighthouseIsRunning = false; updateBadgeUI(); @@ -148,11 +172,18 @@ window.runLighthouseInExtension = function(options, requestedAggregations) { // Default to 'info' logging level. log.setLevel('info'); const connection = new ExtensionProtocol(); - return connection.getCurrentTabURL() + return enableOtherChromeExtensions(false) + .then(_ => connection.getCurrentTabURL()) .then(url => window.runLighthouseForConnection(connection, url, options, requestedAggregations)) .then(results => { - const blobURL = window.createReportPageAsBlob(results, 'extension'); - chrome.tabs.create({url: blobURL}); + return enableOtherChromeExtensions(true).then(_ => { + const blobURL = window.createReportPageAsBlob(results, 'extension'); + chrome.tabs.create({url: blobURL}); + }); + }).catch(err => { + return enableOtherChromeExtensions(true).then(_ => { + throw err; + }); }); }; @@ -277,7 +308,19 @@ window.isRunning = function() { return lighthouseIsRunning; }; +// Run when in extension context, but not in devtools. if (window.chrome && chrome.runtime) { + // Get list of installed extensions that are enabled and can be disabled. + // Extensions are not allowed to be disabled if they are under an admin policy. + chrome.management.getAll(installs => { + chrome.management.getSelf(lighthouseCrxInfo => { + installedExtensions = installs.filter(info => { + return info.id !== lighthouseCrxInfo.id && info.type === 'extension' && + info.enabled && info.mayDisable; + }); + }); + }); + chrome.runtime.onInstalled.addListener(details => { if (details.previousVersion) { // eslint-disable-next-line no-console