From 9a5086847c3a9e489da30c9fcd80ca86938440a4 Mon Sep 17 00:00:00 2001 From: Andrey Lushnikov Date: Fri, 8 Dec 2017 13:39:13 -0800 Subject: [PATCH] refactor: move ChromiumDownloader under lib/ (#1554) This patch: - renames ChromiumDownloader into just Downloader (this is in preparation for different products download) - moves Downloader from utils/ to lib/. This unifies all of the production-critical code in the lib/. Drive-by: make Downloader a regular class. --- install.js | 20 ++-- .../Downloader.js | 110 +++++++++++------- lib/Launcher.js | 11 +- test/test.js | 7 +- utils/check_availability.js | 12 +- utils/doclint/check_public_api/index.js | 1 + 6 files changed, 98 insertions(+), 63 deletions(-) rename utils/ChromiumDownloader.js => lib/Downloader.js (76%) diff --git a/install.js b/install.js index f129887d363..2704cca60f8 100644 --- a/install.js +++ b/install.js @@ -23,12 +23,14 @@ if (process.env.NPM_CONFIG_PUPPETEER_SKIP_CHROMIUM_DOWNLOAD || process.env.npm_c return; } -const Downloader = require('./utils/ChromiumDownloader'); -const platform = Downloader.currentPlatform(); -const revision = require('./package').puppeteer.chromium_revision; +const Downloader = require('./lib/Downloader'); +const downloader = Downloader.createDefault(); + +const platform = downloader.currentPlatform(); +const revision = Downloader.defaultRevision(); const ProgressBar = require('progress'); -const revisionInfo = Downloader.revisionInfo(platform, revision); +const revisionInfo = downloader.revisionInfo(platform, revision); // Do nothing if the revision is already downloaded. if (revisionInfo.downloaded) return; @@ -45,9 +47,11 @@ if (NPM_HTTP_PROXY) if (NPM_NO_PROXY) process.env.NO_PROXY = NPM_NO_PROXY; -const allRevisions = Downloader.downloadedRevisions(); -const DOWNLOAD_HOST = process.env.PUPPETEER_DOWNLOAD_HOST || process.env.npm_config_puppeteer_download_host; -Downloader.downloadRevision(platform, revision, DOWNLOAD_HOST, onProgress) +const allRevisions = downloader.downloadedRevisions(); +const downloadHost = process.env.PUPPETEER_DOWNLOAD_HOST || process.env.npm_config_puppeteer_download_host; +if (downloadHost) + downloader.setDownloadHost(downloadHost); +downloader.downloadRevision(platform, revision, onProgress) .then(onSuccess) .catch(onError); @@ -57,7 +61,7 @@ Downloader.downloadRevision(platform, revision, DOWNLOAD_HOST, onProgress) function onSuccess() { console.log('Chromium downloaded to ' + revisionInfo.folderPath); // Remove previous chromium revisions. - const cleanupOldVersions = allRevisions.map(({platform, revision}) => Downloader.removeRevision(platform, revision)); + const cleanupOldVersions = allRevisions.map(({platform, revision}) => downloader.removeRevision(platform, revision)); return Promise.all(cleanupOldVersions); } diff --git a/utils/ChromiumDownloader.js b/lib/Downloader.js similarity index 76% rename from utils/ChromiumDownloader.js rename to lib/Downloader.js index b565113b359..1c927adf6ac 100644 --- a/utils/ChromiumDownloader.js +++ b/lib/Downloader.js @@ -26,9 +26,7 @@ const ProxyAgent = require('https-proxy-agent'); // @ts-ignore const getProxyForUrl = require('proxy-from-env').getProxyForUrl; -const DOWNLOADS_FOLDER = path.join(__dirname, '..', '.local-chromium'); const DEFAULT_DOWNLOAD_HOST = 'https://storage.googleapis.com'; - const downloadURLs = { linux: '%s/chromium-browser-snapshots/Linux_x64/%d/chrome-linux.zip', mac: '%s/chromium-browser-snapshots/Mac/%d/chrome-mac.zip', @@ -36,18 +34,50 @@ const downloadURLs = { win64: '%s/chromium-browser-snapshots/Win_x64/%d/chrome-win32.zip', }; -module.exports = { +const PROJECT_ROOT = path.join(__dirname, '..'); + +class Downloader { /** - * @return {!Array} + * @param {string} downloadsFolder */ - supportedPlatforms: function() { - return Object.keys(downloadURLs); - }, + constructor(downloadsFolder) { + this._downloadsFolder = downloadsFolder; + this._downloadHost = DEFAULT_DOWNLOAD_HOST; + } /** * @return {string} */ - currentPlatform: function() { + static defaultRevision() { + return require(path.join(PROJECT_ROOT, 'package.json')).puppeteer.chromium_revision; + } + + /** + * @return {!Downloader} + */ + static createDefault() { + const downloadsFolder = path.join(PROJECT_ROOT, '.local-chromium'); + return new Downloader(downloadsFolder); + } + + /** + * @param {string} downloadHost + */ + setDownloadHost(downloadHost) { + this._downloadHost = downloadHost; + } + + /** + * @return {!Array} + */ + supportedPlatforms() { + return Object.keys(downloadURLs); + } + + /** + * @return {string} + */ + currentPlatform() { const platform = os.platform(); if (platform === 'darwin') return 'mac'; @@ -56,17 +86,17 @@ module.exports = { if (platform === 'win32') return os.arch() === 'x64' ? 'win64' : 'win32'; return ''; - }, + } /** * @param {string} platform * @param {string} revision * @return {!Promise} */ - canDownloadRevision: function(platform, revision) { + canDownloadRevision(platform, revision) { console.assert(downloadURLs[platform], 'Unknown platform: ' + platform); - const url = util.format(downloadURLs[platform], DEFAULT_DOWNLOAD_HOST, revision); + const url = util.format(downloadURLs[platform], this._downloadHost, revision); let resolve; const promise = new Promise(x => resolve = x); @@ -78,25 +108,24 @@ module.exports = { resolve(false); }); return promise; - }, + } /** * @param {string} platform * @param {string} revision - * @param {string} [downloadHost=DEFAULT_DOWNLOAD_HOST] * @param {?function(number, number)} progressCallback * @return {!Promise} */ - downloadRevision: function(platform, revision, downloadHost = DEFAULT_DOWNLOAD_HOST, progressCallback) { + downloadRevision(platform, revision, progressCallback) { let url = downloadURLs[platform]; console.assert(url, `Unsupported platform: ${platform}`); - url = util.format(url, downloadHost, revision); - const zipPath = path.join(DOWNLOADS_FOLDER, `download-${platform}-${revision}.zip`); - const folderPath = getFolderPath(platform, revision); + url = util.format(url, this._downloadHost, revision); + const zipPath = path.join(this._downloadsFolder, `download-${platform}-${revision}.zip`); + const folderPath = this._getFolderPath(platform, revision); if (fs.existsSync(folderPath)) return; - if (!fs.existsSync(DOWNLOADS_FOLDER)) - fs.mkdirSync(DOWNLOADS_FOLDER); + if (!fs.existsSync(this._downloadsFolder)) + fs.mkdirSync(this._downloadsFolder); return downloadFile(url, zipPath, progressCallback) .then(() => extractZip(zipPath, folderPath)) .catch(err => err) @@ -106,38 +135,38 @@ module.exports = { if (err) throw err; }); - }, + } /** * @return {!Array} */ - downloadedRevisions: function() { - if (!fs.existsSync(DOWNLOADS_FOLDER)) + downloadedRevisions() { + if (!fs.existsSync(this._downloadsFolder)) return []; - const fileNames = fs.readdirSync(DOWNLOADS_FOLDER); + const fileNames = fs.readdirSync(this._downloadsFolder); return fileNames.map(fileName => parseFolderPath(fileName)).filter(revision => !!revision); - }, + } /** * @param {string} platform * @param {string} revision * @return {!Promise} */ - removeRevision: function(platform, revision) { + removeRevision(platform, revision) { console.assert(downloadURLs[platform], `Unsupported platform: ${platform}`); - const folderPath = getFolderPath(platform, revision); + const folderPath = this._getFolderPath(platform, revision); console.assert(fs.existsSync(folderPath)); return new Promise(fulfill => removeRecursive(folderPath, fulfill)); - }, + } /** * @param {string} platform * @param {string} revision - * @return {!{folderPath: string, executablePath: string, downloaded: boolean}} + * @return {!{revision: string, folderPath: string, executablePath: string, downloaded: boolean}} */ - revisionInfo: function(platform, revision) { + revisionInfo(platform, revision) { console.assert(downloadURLs[platform], `Unsupported platform: ${platform}`); - const folderPath = getFolderPath(platform, revision); + const folderPath = this._getFolderPath(platform, revision); let executablePath = ''; if (platform === 'mac') executablePath = path.join(folderPath, 'chrome-mac', 'Chromium.app', 'Contents', 'MacOS', 'Chromium'); @@ -148,22 +177,25 @@ module.exports = { else throw 'Unsupported platform: ' + platform; return { + revision, executablePath, folderPath, downloaded: fs.existsSync(folderPath) }; - }, -}; + } -/** - * @param {string} platform - * @param {string} revision - * @return {string} - */ -function getFolderPath(platform, revision) { - return path.join(DOWNLOADS_FOLDER, platform + '-' + revision); + /** + * @param {string} platform + * @param {string} revision + * @return {string} + */ + _getFolderPath(platform, revision) { + return path.join(this._downloadsFolder, platform + '-' + revision); + } } +module.exports = Downloader; + /** * @param {string} folderPath * @return {?{platform: string, revision: string}} diff --git a/lib/Launcher.js b/lib/Launcher.js index 9565bc63b09..3b6b6962010 100644 --- a/lib/Launcher.js +++ b/lib/Launcher.js @@ -17,14 +17,13 @@ const os = require('os'); const path = require('path'); const removeFolder = require('rimraf'); const childProcess = require('child_process'); -const Downloader = require('../utils/ChromiumDownloader'); +const Downloader = require('./Downloader'); const {Connection} = require('./Connection'); const {Browser} = require('./Browser'); const readline = require('readline'); const fs = require('fs'); const {helper} = require('./helper'); -// @ts-ignore -const ChromiumRevision = require('../package.json').puppeteer.chromium_revision; +const ChromiumRevision = Downloader.defaultRevision(); const mkdtempAsync = helper.promisify(fs.mkdtemp); const removeFolderAsync = helper.promisify(removeFolder); @@ -88,7 +87,8 @@ class Launcher { } let chromeExecutable = options.executablePath; if (typeof chromeExecutable !== 'string') { - const revisionInfo = Downloader.revisionInfo(Downloader.currentPlatform(), ChromiumRevision); + const downloader = Downloader.createDefault(); + const revisionInfo = downloader.revisionInfo(downloader.currentPlatform(), ChromiumRevision); console.assert(revisionInfo.downloaded, `Chromium revision is not downloaded. Run "npm install"`); chromeExecutable = revisionInfo.executablePath; } @@ -176,7 +176,8 @@ class Launcher { * @return {string} */ static executablePath() { - const revisionInfo = Downloader.revisionInfo(Downloader.currentPlatform(), ChromiumRevision); + const downloader = Downloader.createDefault(); + const revisionInfo = downloader.revisionInfo(downloader.currentPlatform(), ChromiumRevision); return revisionInfo.executablePath; } diff --git a/test/test.js b/test/test.js index 58ca9a8ce30..7b687106faa 100644 --- a/test/test.js +++ b/test/test.js @@ -51,12 +51,7 @@ const defaultBrowserOptions = { }; // Make sure the `npm install` was run after the chromium roll. -{ - const Downloader = require('../utils/ChromiumDownloader'); - const chromiumRevision = require('../package.json').puppeteer.chromium_revision; - const revisionInfo = Downloader.revisionInfo(Downloader.currentPlatform(), chromiumRevision); - console.assert(revisionInfo.downloaded, `Chromium r${chromiumRevision} is not downloaded. Run 'npm install' and try to re-run tests.`); -} +console.assert(fs.existsSync(puppeteer.executablePath()), `Chromium is not Downloaded. Run 'npm install' and try to re-run tests`); const timeout = process.env.DEBUG_TEST || slowMo ? 0 : 10 * 1000; diff --git a/utils/check_availability.js b/utils/check_availability.js index 62350760ae6..4aad014208f 100755 --- a/utils/check_availability.js +++ b/utils/check_availability.js @@ -15,10 +15,12 @@ * limitations under the License. */ -const Downloader = require('./ChromiumDownloader'); +const Downloader = require('../lib/Downloader'); const https = require('https'); const OMAHA_PROXY = 'https://omahaproxy.appspot.com/all.json'; +const downloader = Downloader.createDefault(); + const colors = { reset: '\x1b[0m', red: '\x1b[31m', @@ -71,7 +73,7 @@ async function checkOmahaProxyAvailability() { return; } const table = new Table([27, 7, 7, 7, 7]); - table.drawRow([''].concat(Downloader.supportedPlatforms())); + table.drawRow([''].concat(downloader.supportedPlatforms())); for (const platform of platforms) { // Trust only to the main platforms. if (platform.os !== 'mac' && platform.os !== 'win' && platform.os !== 'win64' && platform.os !== 'linux') @@ -93,7 +95,7 @@ async function checkOmahaProxyAvailability() { */ async function checkRangeAvailability(fromRevision, toRevision) { const table = new Table([10, 7, 7, 7, 7]); - table.drawRow([''].concat(Downloader.supportedPlatforms())); + table.drawRow([''].concat(downloader.supportedPlatforms())); const inc = fromRevision < toRevision ? 1 : -1; for (let revision = fromRevision; revision !== toRevision; revision += inc) await checkAndDrawRevisionAvailability(table, '', revision); @@ -106,8 +108,8 @@ async function checkRangeAvailability(fromRevision, toRevision) { */ async function checkAndDrawRevisionAvailability(table, name, revision) { const promises = []; - for (const platform of Downloader.supportedPlatforms()) - promises.push(Downloader.canDownloadRevision(platform, revision)); + for (const platform of downloader.supportedPlatforms()) + promises.push(downloader.canDownloadRevision(platform, revision)); const availability = await Promise.all(promises); const allAvailable = availability.every(e => !!e); const values = [name + ' ' + (allAvailable ? colors.green + revision + colors.reset : revision)]; diff --git a/utils/doclint/check_public_api/index.js b/utils/doclint/check_public_api/index.js index 40d7b1d48f0..82018c13f5a 100644 --- a/utils/doclint/check_public_api/index.js +++ b/utils/doclint/check_public_api/index.js @@ -21,6 +21,7 @@ const Message = require('../Message'); const EXCLUDE_CLASSES = new Set([ 'Connection', + 'Downloader', 'EmulationManager', 'FrameManager', 'Helper',