diff --git a/src/infer/inferUserAgent.js b/src/infer/inferUserAgent.js new file mode 100644 index 0000000..ab0355d --- /dev/null +++ b/src/infer/inferUserAgent.js @@ -0,0 +1,55 @@ +import axios from 'axios'; +import _ from 'lodash'; + +const ELECTRON_VERSIONS_URL = 'https://atom.io/download/atom-shell/index.json'; +const DEFAULT_CHROME_VERSION = '47.0.2526.73'; + +function getChromeVersionForElectronVersion(electronVersion, url = ELECTRON_VERSIONS_URL) { + + return axios.get(url, {timeout: 5000}) + .then(response => { + if (response.status !== 200) { + throw `Bad request: Status code ${response.status}`; + } + + const data = response.data; + const electronVersionToChromeVersion = _.zipObject(data.map(d => d.version), data.map(d => d.chrome)); + + if (!(electronVersion in electronVersionToChromeVersion)) { + throw `Electron version '${ electronVersion }' not found in retrieved version list!`; + } + + return electronVersionToChromeVersion[electronVersion]; + }); +} + +export function getUserAgentString(chromeVersion, platform) { + let userAgent; + switch (platform) { + case 'darwin': + userAgent = `Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/${ chromeVersion } Safari/537.36`; + break; + case 'win32': + userAgent = `Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/${ chromeVersion } Safari/537.36`; + break; + case 'linux': + userAgent = `Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/${ chromeVersion } Safari/537.36`; + break; + default: + throw 'Error invalid platform specified to getUserAgentString()'; + } + return userAgent; +} + +function inferUserAgent(electronVersion, platform, url = ELECTRON_VERSIONS_URL) { + return getChromeVersionForElectronVersion(electronVersion, url) + .then(chromeVersion => { + return getUserAgentString(chromeVersion, platform); + }) + .catch(() => { + // console.warn(`Unable to infer chrome version for user agent, using ${DEFAULT_CHROME_VERSION}`); + return getUserAgentString(DEFAULT_CHROME_VERSION, platform); + }); +} + +export default inferUserAgent; diff --git a/src/options/optionsMain.js b/src/options/optionsMain.js index 351ab58..cf02279 100644 --- a/src/options/optionsMain.js +++ b/src/options/optionsMain.js @@ -1,4 +1,3 @@ -import os from 'os'; import path from 'path'; import _ from 'lodash'; import async from 'async'; @@ -7,6 +6,7 @@ import sanitizeFilenameLib from 'sanitize-filename'; import inferIcon from './../infer/inferIcon'; import inferTitle from './../infer/inferTitle'; import inferOs from './../infer/inferOs'; +import inferUserAgent from './../infer/inferUserAgent'; import normalizeUrl from './normalizeUrl'; import packageJson from './../../package.json'; @@ -14,6 +14,7 @@ const {inferPlatform, inferArch} = inferOs; const PLACEHOLDER_APP_DIR = path.join(__dirname, '../../', 'app'); const ELECTRON_VERSION = '0.36.4'; + const DEFAULT_APP_NAME = 'APP'; /** @@ -45,7 +46,7 @@ function optionsFactory(inpOptions, callback) { width: inpOptions.width || 1280, height: inpOptions.height || 800, showMenuBar: inpOptions.showMenuBar || false, - userAgent: inpOptions.userAgent || getFakeUserAgent(), + userAgent: inpOptions.userAgent, ignoreCertificate: inpOptions.ignoreCertificate || false, insecure: inpOptions.insecure || false, flashPluginDir: inpOptions.flash || null, @@ -67,6 +68,18 @@ function optionsFactory(inpOptions, callback) { } async.waterfall([ + callback => { + if (options.userAgent) { + callback(); + return; + } + inferUserAgent(options.version, options.platform) + .then(userAgent => { + options.userAgent = userAgent; + callback(); + }) + .catch(callback); + }, callback => { if (options.icon) { callback(); @@ -119,22 +132,4 @@ function sanitizeOptions(options) { return options; } -function getFakeUserAgent() { - let userAgent; - switch (os.platform()) { - case 'darwin': - userAgent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.1 Safari/537.36'; - break; - case 'win32': - userAgent = 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36'; - break; - case 'linux': - userAgent = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.0 Safari/537.36'; - break; - default: - break; - } - return userAgent; -} - export default optionsFactory; diff --git a/test/module/inferUserAgent-spec.js b/test/module/inferUserAgent-spec.js new file mode 100644 index 0000000..655c15e --- /dev/null +++ b/test/module/inferUserAgent-spec.js @@ -0,0 +1,50 @@ +import inferUserAgent from './../../lib/infer/inferUserAgent'; +import chai from 'chai'; +import _ from 'lodash'; + +const assert = chai.assert; + +const TEST_RESULT = { + darwin: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.75 Safari/537.36', + win32: 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.75 Safari/537.36', + linux: 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.75 Safari/537.36' +}; + +function testPlatform(platform) { + return inferUserAgent('0.37.1', platform) + .then(userAgent => { + assert.equal(userAgent, TEST_RESULT[platform], 'Correct user agent should be inferred'); + }); +} + +describe('Infer User Agent', function() { + this.timeout(15000); + it('Can infer userAgent for all platforms', function(done) { + const testPromises = _.keys(TEST_RESULT).map(platform => { + return testPlatform(platform); + }); + Promise + .all(testPromises) + .then(() => { + done(); + }) + .catch(error => { + done(error); + }); + }); + + it('Connection error will still get a user agent', function(done) { + const TIMEOUT_URL = 'http://www.google.com:81/'; + inferUserAgent('0.37.1', 'darwin', TIMEOUT_URL) + .then(userAgent => { + assert.equal( + userAgent, + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.73 Safari/537.36', + 'Expect default user agent on connection error' + ); + done(); + }) + .catch(done); + }); +}); +