From 4b6716efefbede10c3816613d9d32d84c2a07844 Mon Sep 17 00:00:00 2001 From: sa Date: Sat, 19 Mar 2016 21:14:41 -0400 Subject: [PATCH 1/6] Infer user agent from Electron's online version list --- src/infer/inferUserAgent.js | 52 +++++++++++++++++++++++++++++++++++++ src/options/optionsMain.js | 40 ++++++++++++++-------------- 2 files changed, 72 insertions(+), 20 deletions(-) create mode 100644 src/infer/inferUserAgent.js diff --git a/src/infer/inferUserAgent.js b/src/infer/inferUserAgent.js new file mode 100644 index 0000000..161b728 --- /dev/null +++ b/src/infer/inferUserAgent.js @@ -0,0 +1,52 @@ +import request from 'request'; +import _ from 'lodash'; + +const ELECTRON_VERSIONS_URL = 'https://atom.io/download/atom-shell/index.json'; + +function getChromeVersionForElectronVersion(electronVersion, url = ELECTRON_VERSIONS_URL) { + return new Promise((resolve, reject) => { + request(url, (error, response, body) => { + if (error) { + reject(error); + return; + } + if (response.statusCode === 200) { + const data = JSON.parse(body); + const electronVersionToChromeVersion = _.zipObject(data.map(d => d.version), data.map(d => d.chrome)); + if (!(electronVersion in electronVersionToChromeVersion)) { + reject(`Electron version '${ electronVersion }' not found in retrieved version list!`); + return; + } + resolve(electronVersionToChromeVersion[electronVersion]); + return; + } + reject('Bad request: ' + response.statusCode); + return; + }); + }); +} + +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: + break; + } + return userAgent; +} + +export function inferUserAgent(electronVersion, platform) { + return getChromeVersionForElectronVersion(electronVersion) + .then(chromeVersion => { + return getUserAgentString(chromeVersion, platform); + }); +} diff --git a/src/options/optionsMain.js b/src/options/optionsMain.js index 554fe73..dc126bb 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, getUserAgentString} from './../infer/inferUserAgent'; import normalizeUrl from './normalizeUrl'; import packageJson from './../../package.json'; @@ -14,6 +14,8 @@ const {inferPlatform, inferArch} = inferOs; const PLACEHOLDER_APP_DIR = path.join(__dirname, '../../', 'app'); const ELECTRON_VERSION = '0.36.4'; +const CHROME_VERSION = '47.0.2526.73'; + const DEFAULT_APP_NAME = 'APP'; /** @@ -45,7 +47,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, @@ -66,6 +68,22 @@ function optionsFactory(inpOptions, callback) { } async.waterfall([ + callback => { + if (options.userAgent) { + callback(); + return; + } + inferUserAgent(options.version, options.platform) + .then(userAgent => { + options.userAgent = userAgent; + callback(); + }) + .catch(error => { + console.warn('Cannot get user agent:', error); + options.userAgent = getUserAgentString(CHROME_VERSION, options.platform); + callback(); + }); + }, callback => { if (options.icon) { callback(); @@ -118,22 +136,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; From d890078e6e251aebdecb43bebed71a25df5bf3e8 Mon Sep 17 00:00:00 2001 From: Jia Hao Date: Fri, 25 Mar 2016 19:29:13 +0800 Subject: [PATCH 2/6] Should throw error on invalid platform --- src/infer/inferUserAgent.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/infer/inferUserAgent.js b/src/infer/inferUserAgent.js index 161b728..b5caf79 100644 --- a/src/infer/inferUserAgent.js +++ b/src/infer/inferUserAgent.js @@ -39,7 +39,7 @@ export function getUserAgentString(chromeVersion, platform) { userAgent = `Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/${ chromeVersion } Safari/537.36`; break; default: - break; + throw 'Error invalid platform specified to getUserAgentString()'; } return userAgent; } From d2ed86e62c5d4dbb1c4cd20d73de75ce95a16eb6 Mon Sep 17 00:00:00 2001 From: Jia Hao Date: Fri, 25 Mar 2016 19:29:33 +0800 Subject: [PATCH 3/6] Add test for infer user agent --- test/module/inferUserAgent-spec.js | 36 ++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 test/module/inferUserAgent-spec.js diff --git a/test/module/inferUserAgent-spec.js b/test/module/inferUserAgent-spec.js new file mode 100644 index 0000000..0d0d906 --- /dev/null +++ b/test/module/inferUserAgent-spec.js @@ -0,0 +1,36 @@ +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(10000); + 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); + }); + }); +}); + From 9a9a63c15a393cdc43c80fe1a905a739ae5a4904 Mon Sep 17 00:00:00 2001 From: Jia Hao Date: Fri, 25 Mar 2016 19:58:03 +0800 Subject: [PATCH 4/6] Use axios instead of request --- src/infer/inferUserAgent.js | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/src/infer/inferUserAgent.js b/src/infer/inferUserAgent.js index b5caf79..3a3db0f 100644 --- a/src/infer/inferUserAgent.js +++ b/src/infer/inferUserAgent.js @@ -1,29 +1,25 @@ -import request from 'request'; +import axios from 'axios'; import _ from 'lodash'; const ELECTRON_VERSIONS_URL = 'https://atom.io/download/atom-shell/index.json'; function getChromeVersionForElectronVersion(electronVersion, url = ELECTRON_VERSIONS_URL) { - return new Promise((resolve, reject) => { - request(url, (error, response, body) => { - if (error) { - reject(error); - return; + + return axios.get(url) + .then(response => { + if (response.status !== 200) { + throw `Bad request: Status code ${response.status}`; } - if (response.statusCode === 200) { - const data = JSON.parse(body); - const electronVersionToChromeVersion = _.zipObject(data.map(d => d.version), data.map(d => d.chrome)); - if (!(electronVersion in electronVersionToChromeVersion)) { - reject(`Electron version '${ electronVersion }' not found in retrieved version list!`); - return; - } - resolve(electronVersionToChromeVersion[electronVersion]); - return; + + 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!`; } - reject('Bad request: ' + response.statusCode); - return; + + return electronVersionToChromeVersion[electronVersion]; }); - }); } export function getUserAgentString(chromeVersion, platform) { From 94c9fdb4243fceb088697cdf7ef90ca81df3bc62 Mon Sep 17 00:00:00 2001 From: Jia Hao Date: Fri, 25 Mar 2016 20:10:45 +0800 Subject: [PATCH 5/6] Contain fallback user agent within inferUserAgent --- src/infer/inferUserAgent.js | 13 ++++++++++--- src/options/optionsMain.js | 9 ++------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/infer/inferUserAgent.js b/src/infer/inferUserAgent.js index 3a3db0f..ab0355d 100644 --- a/src/infer/inferUserAgent.js +++ b/src/infer/inferUserAgent.js @@ -2,10 +2,11 @@ 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) + return axios.get(url, {timeout: 5000}) .then(response => { if (response.status !== 200) { throw `Bad request: Status code ${response.status}`; @@ -40,9 +41,15 @@ export function getUserAgentString(chromeVersion, platform) { return userAgent; } -export function inferUserAgent(electronVersion, platform) { - return getChromeVersionForElectronVersion(electronVersion) +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 dc126bb..3fdf14b 100644 --- a/src/options/optionsMain.js +++ b/src/options/optionsMain.js @@ -6,7 +6,7 @@ import sanitizeFilenameLib from 'sanitize-filename'; import inferIcon from './../infer/inferIcon'; import inferTitle from './../infer/inferTitle'; import inferOs from './../infer/inferOs'; -import {inferUserAgent, getUserAgentString} from './../infer/inferUserAgent'; +import inferUserAgent from './../infer/inferUserAgent'; import normalizeUrl from './normalizeUrl'; import packageJson from './../../package.json'; @@ -14,7 +14,6 @@ const {inferPlatform, inferArch} = inferOs; const PLACEHOLDER_APP_DIR = path.join(__dirname, '../../', 'app'); const ELECTRON_VERSION = '0.36.4'; -const CHROME_VERSION = '47.0.2526.73'; const DEFAULT_APP_NAME = 'APP'; @@ -78,11 +77,7 @@ function optionsFactory(inpOptions, callback) { options.userAgent = userAgent; callback(); }) - .catch(error => { - console.warn('Cannot get user agent:', error); - options.userAgent = getUserAgentString(CHROME_VERSION, options.platform); - callback(); - }); + .catch(callback); }, callback => { if (options.icon) { From 26cfb1a86f00a639cb9df7f18f737289c79c4012 Mon Sep 17 00:00:00 2001 From: Jia Hao Date: Fri, 25 Mar 2016 20:10:56 +0800 Subject: [PATCH 6/6] Add test for connection error --- test/module/inferUserAgent-spec.js | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/test/module/inferUserAgent-spec.js b/test/module/inferUserAgent-spec.js index 0d0d906..655c15e 100644 --- a/test/module/inferUserAgent-spec.js +++ b/test/module/inferUserAgent-spec.js @@ -1,4 +1,4 @@ -import {inferUserAgent} from './../../lib/infer/inferUserAgent'; +import inferUserAgent from './../../lib/infer/inferUserAgent'; import chai from 'chai'; import _ from 'lodash'; @@ -18,7 +18,7 @@ function testPlatform(platform) { } describe('Infer User Agent', function() { - this.timeout(10000); + this.timeout(15000); it('Can infer userAgent for all platforms', function(done) { const testPromises = _.keys(TEST_RESULT).map(platform => { return testPlatform(platform); @@ -32,5 +32,19 @@ describe('Infer User Agent', function() { 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); + }); });