├── .gitignore
├── LICENSE
├── README.md
├── lib
├── configUtil.js
└── index.js
├── package.json
└── test
└── open.js
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # Bower dependency directory (https://bower.io/)
27 | bower_components
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (http://nodejs.org/api/addons.html)
33 | build/Release
34 |
35 | # Dependency directories
36 | node_modules/
37 | jspm_packages/
38 |
39 | # Typescript v1 declaration files
40 | typings/
41 |
42 | # Optional npm cache directory
43 | .npm
44 |
45 | # Optional eslint cache
46 | .eslintcache
47 |
48 | # Optional REPL history
49 | .node_repl_history
50 |
51 | # Output of 'npm pack'
52 | *.tgz
53 |
54 | # Yarn Integrity file
55 | .yarn-integrity
56 |
57 | # dotenv environment variables file
58 | .env
59 |
60 | # system
61 | .DS_Store
62 |
63 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 张代应
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # open-browser
2 | Open browser window and set proxy
3 |
4 | # Install
5 |
6 | ```bash
7 | npm install op-browser --save
8 | ```
9 |
10 | # Usage
11 |
12 | ```js
13 | const openBrowser = require('op-browser');
14 |
15 | // Automatic proxy selection
16 | openBrowser.open('chrome', 'https://google.com', 'http://127.0.0.1:8800', '');
17 | // Proxy auto-configuration (PAC)
18 | openBrowser.open('chrome', 'https://google.com', '', 'http://127.0.0.1:8800/proxy.pac');
19 | ```
20 |
21 | # API
22 |
23 |
24 |
25 | ## op-browser : object
26 | Browser
27 |
28 | **Kind**: global namespace
29 |
30 | * [op-browser](#op-browser) : object
31 | * [.open(browser, url, proxyURL, pacFileURL)](#op-browser.open) ⇒ Promise
32 | * [.detect(name)](#op-browser.detect) ⇒ Promise
33 |
34 |
35 |
36 | ### op-browser.open(browser, url, proxyURL, pacFileURL, bypassList) ⇒ Promise
37 | open browser window, if the `pacFileURL` is not empty, will use `proxy auto-configuration`
38 |
39 | **Kind**: static method of [op-browser
](#op-browser)
40 |
41 | | Param | Type | Description |
42 | | --- | --- | --- |
43 | | browser | String
| the browser's name |
44 | | url | String
| the url that to open |
45 | | proxyURL | String
| the proxy url, format: `http://[:[port]]` |
46 | | pacFileURL | String
| the proxy url, format: `http://[:[port]]/[pac-file-name]` |
47 | | bypassList | String
| the list of hosts for whom we bypass proxy settings and use direct connections, See: "[net/proxy/proxy_bypass_rules.h](https://cs.chromium.org/chromium/src/net/proxy_resolution/proxy_bypass_rules.h?sq=package:chromium&type=cs)" for the format of these rules |
48 |
49 |
50 |
51 | ### op-browser.detect(name) ⇒ Promise
52 | detect browser, return the browser's path
53 |
54 | **Kind**: static method of [op-browser
](#op-browser)
55 |
56 | | Param | Type | Description |
57 | | --- | --- | --- |
58 | | name | String
| the browser name |
59 |
60 |
--------------------------------------------------------------------------------
/lib/configUtil.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @file
3 | * @author zdying
4 | */
5 | 'use strict';
6 |
7 | var fs = require('fs');
8 | var path = require('path');
9 | var urlParser = require('url');
10 | var childProcess = require('child_process');
11 |
12 | module.exports = {
13 | chrome: function (dataDir, url, chromePath, proxyURL, pacFileURL, bypassList) {
14 | // List of Chromium Command Line Switches
15 | // https://peter.sh/experiments/chromium-command-line-switches/
16 | var proxyOption = pacFileURL
17 | ? '--proxy-pac-url=' + pacFileURL
18 | : '--proxy-server=' + proxyURL;
19 |
20 | bypassList = bypassList === undefined ? '' : bypassList;
21 |
22 | dataDir = path.resolve(path.join(dataDir, 'chrome-cache'));
23 |
24 | return [
25 | // '--proxy-pac-url="' + proxy + '"',
26 | // '--proxy-server="' + proxy + '"',
27 | proxyOption,
28 | '--proxy-bypass-list=' + bypassList,
29 | '--user-data-dir=' + dataDir,
30 | '--lang=local',
31 | url
32 | ];
33 | },
34 |
35 | opera: function (dataDir, url, operaPath, proxyURL, pacFileURL, bypassList) {
36 | var proxyOption = pacFileURL
37 | ? '--proxy-pac-url=' + pacFileURL
38 | : '--proxy-server=' + proxyURL + '';
39 |
40 | bypassList = bypassList === undefined ? '' : bypassList;
41 |
42 | dataDir = path.resolve(path.join(dataDir, 'opera-cache'));
43 |
44 | return [
45 | proxyOption,
46 | '--proxy-bypass-list=' + bypassList,
47 | '--user-data-dir=' + dataDir,
48 | '--lang=local',
49 | url
50 | ];
51 | },
52 |
53 | safari: function (dataDir, url, safariPath, proxy) {
54 | return '';
55 | },
56 |
57 | firefox: function (dataDir, url, firefoxPath, proxyURL, pacFileURL, bypassList) {
58 | // Firefox pac set
59 | // http://www.indexdata.com/connector-platform/enginedoc/proxy-auto.html
60 | // http://kb.mozillazine.org/Network.proxy.autoconfig_url
61 | // user_pref("network.proxy.autoconfig_url", "http://us2.indexdata.com:9005/id/cf.pac");
62 | // user_pref("network.proxy.type", 2);
63 |
64 | var dir = path.join(dataDir, 'firefox-cache');
65 | var prefsPath = path.join(dir, 'prefs.js');
66 | var prefs = [];
67 |
68 | bypassList = bypassList === undefined ? 'localhost, 127.0.0.1, ::1' : bypassList;
69 |
70 | if (!fs.existsSync(dir)) {
71 | fs.mkdirSync(dir);
72 | }
73 |
74 | if (!fs.existsSync(prefsPath)) {
75 | if (pacFileURL) {
76 | // 自动代理
77 | prefs = [
78 | 'user_pref("network.proxy.autoconfig_url", "' + pacFileURL + '");',
79 | 'user_pref("network.proxy.type", 2);'
80 | ];
81 | } else {
82 | // 直接代理
83 | var urlObj = urlParser.parse(proxyURL);
84 | prefs = [
85 | 'user_pref("network.proxy.http", "' + urlObj.hostname + '");',
86 | 'user_pref("network.proxy.http_port", ' + urlObj.port + ');',
87 | 'user_pref("network.proxy.type", 1);',
88 | 'user_pref("network.proxy.no_proxies_on", "' + bypassList + '")'
89 | ];
90 | }
91 |
92 | // https://developer.mozilla.org/en-US/docs/Mozilla/Command_Line_Options
93 | childProcess.execFileSync(path.resolve(firefoxPath), [
94 | '-CreateProfile',
95 | '"firefox_op_browser_pref ' + path.resolve(dir) + '"'
96 | ]);
97 | fs.writeFileSync(prefsPath, prefs.join('\n'));
98 | }
99 |
100 | return [
101 | '-P',
102 | 'firefox_op_browser_pref',
103 | '-no-remote',
104 | '--new-instance',
105 | url
106 | ];
107 | }
108 | };
109 |
--------------------------------------------------------------------------------
/lib/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @file open browser window
3 | * @author zdying
4 | */
5 |
6 | var os = require('os');
7 | var path = require('path');
8 | var configUtil = require('./configUtil');
9 |
10 | var childProcess = require('child_process');
11 |
12 | var platform = os.platform();
13 |
14 | var browsers = {
15 | 'chrome': {
16 | darwin: 'com.google.Chrome',
17 | appName: 'Google Chrome',
18 | win32: 'chrome.exe',
19 | linux: 'google-chrome'
20 | },
21 | 'firefox': {
22 | darwin: 'org.mozilla.firefox',
23 | appName: 'firefox',
24 | win32: 'firefox.exe'
25 | },
26 | 'opera': {
27 | darwin: 'com.operasoftware.Opera',
28 | appName: 'Opera',
29 | win32: 'opera.exe'
30 | },
31 | 'safari': {
32 | darwin: 'com.apple.Safari',
33 | appName: 'Safari',
34 | win32: 'safari.exe'
35 | },
36 | };
37 |
38 | /**
39 | * Browser
40 | * @namespace op-browser
41 | */
42 | module.exports = {
43 | /**
44 | * open browser window, if the `pacFileURL` is not empty, will use `proxy auto-configuration`
45 | * @memberof op-browser
46 | * @param {String} browser the browser's name
47 | * @param {String} url the url that to open
48 | * @param {String} proxyURL the proxy url, format: `http://[:[port]]`
49 | * @param {String} pacFileURL the proxy url, format: `http://[:[port]]/[pac-file-name]`
50 | * @param {String} dataDir the user data directory
51 | * @param {String} bypassList the list of hosts for whom we bypass proxy settings and use direct connections. the list of hosts for whom we bypass proxy settings and use direct connections, See: "[net/proxy/proxy_bypass_rules.h](https://cs.chromium.org/chromium/src/net/proxy_resolution/proxy_bypass_rules.h?sq=package:chromium&type=cs)" for the format of these rules
52 | * @return {Promise}
53 | */
54 | open: function (browser, url, proxyURL, pacFileURL, dataDir, bypassList) {
55 | // Firefox pac set
56 | // http://www.indexdata.com/connector-platform/enginedoc/proxy-auto.html
57 | // http://kb.mozillazine.org/Network.proxy.autoconfig_url
58 | // user_pref("network.proxy.autoconfig_url", "http://us2.indexdata.com:9005/id/cf.pac");
59 | // user_pref("network.proxy.type", 2);
60 |
61 | return this.detect(browser).then(function (browserPath) {
62 | if (!browserPath) {
63 | throw Error('[Error] can not find browser ' + browser);
64 | } else {
65 | dataDir = dataDir || path.join(os.tmpdir(), 'op-browser');
66 |
67 | var commandOptions = configUtil[browser](dataDir, url, browserPath, proxyURL, pacFileURL, bypassList);
68 |
69 | return new Promise(function (resolve, reject) {
70 | childProcess.execFile(path.resolve(browserPath), commandOptions, {maxBuffer: 50000 * 1024}, function (err) {
71 | if (err) {
72 | reject(err);
73 | } else {
74 | resolve({
75 | path: browserPath,
76 | cmdOptions: commandOptions,
77 | proxyURL: proxyURL,
78 | pacFileURL: pacFileURL
79 | });
80 | }
81 | });
82 | });
83 | }
84 | });
85 | },
86 |
87 | /**
88 | * detect browser, return the browser's path
89 | * @memberof op-browser
90 | * @param {String} name the browser name
91 | * @return {Promise}
92 | */
93 | detect: function (name) {
94 | var result = '';
95 | var cmd = '';
96 | var info = browsers[name];
97 |
98 | return new Promise(function (resolve, reject) {
99 | if (!info) {
100 | reject(Error('Browser not supported.'));
101 | }
102 |
103 | try {
104 | switch (platform) {
105 | case 'darwin':
106 | cmd = 'mdfind "kMDItemCFBundleIdentifier==' + info.darwin + '" | head -1';
107 | result = childProcess.execSync(cmd).toString().trim();
108 | result += '/Contents/MacOS/' + info.appName;
109 | result = result.replace(/\s/g, '\\ ');
110 | break;
111 |
112 | case 'win32':
113 | // windows chrome path:
114 | // HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\chrome.exe
115 | // reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\chrome.exe" /v Path
116 |
117 | cmd = 'reg query "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\' + info.win32 + '" /ve';
118 | // result:
119 | /*
120 | HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\firefox.exe
121 | (默认) REG_SZ C:\Program Files\Mozilla Firefox\firefox.exe
122 | */
123 |
124 | result = childProcess.execSync(cmd).toString().trim();
125 | result = result.split('\n').pop().split(/\s+REG_SZ\s+/).pop();
126 | result = result.replace(/^"|"$/g, '');
127 | break;
128 |
129 | case 'linux':
130 | if(info.linux){
131 | result = path.join('/usr/bin',info.linux)
132 | }
133 | break;
134 | default:
135 | result = name;
136 | }
137 | } catch (e) {
138 | reject(Error('Can not find browser info', name));
139 | }
140 |
141 | resolve(result.trim());
142 | });
143 | }
144 | };
145 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "op-browser",
3 | "version": "1.0.9",
4 | "description": "Open browser window and set proxy",
5 | "main": "lib/index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "git+https://github.com/zdying/open-browser.git"
12 | },
13 | "keywords": [
14 | "open",
15 | "browser"
16 | ],
17 | "author": "zdying",
18 | "license": "MIT",
19 | "bugs": {
20 | "url": "https://github.com/zdying/open-browser/issues"
21 | },
22 | "homepage": "https://github.com/zdying/open-browser#readme"
23 | }
24 |
--------------------------------------------------------------------------------
/test/open.js:
--------------------------------------------------------------------------------
1 | var op = require('../lib/index');
2 |
3 | 'chrome safari firefox opera'.split(' ').forEach(function (browser) {
4 | op.detect(browser).then(function (path) {
5 | console.log(browser, '==>', path);
6 | op.open(browser, 'https://www.google.com/', 'http://127.0.0.1:5525');
7 | }).catch(function (err) {
8 | console.error(browser, 'detect fail:', err);
9 | });
10 | });
11 |
--------------------------------------------------------------------------------