UNPKG

6.12 kBJavaScriptView Raw
1var headless = require('headless');
2var fs = require('fs');
3var path = require('path');
4var spawn = require('child_process').spawn;
5
6var argue = {};
7argue.firefox = function (br, uri, opts, cb) {
8 var prefs = '';
9 opts.options = opts.options || [];
10 if (opts.proxy) {
11 var m = /^(?:http:\/\/)?([^:\/]+)(?::(\d+))?/.exec(opts.proxy);
12 var host = JSON.stringify(m[1]);
13 var port = m[2] || 80;
14 prefs += [
15 '"network.proxy.http", ' + host,
16 '"network.proxy.http_port", ' + port,
17 '"network.proxy.type", 1',
18 '"browser.cache.disk.capacity", 0',
19 '"browser.cache.disk.smart_size.enabled", false',
20 '"browser.cache.disk.smart_size.first_run", false',
21 '"browser.sessionstore.resume_from_crash", false',
22 '"browser.startup.page", 0',
23 '"network.proxy.no_proxies_on", '
24 + JSON.stringify(opts.noProxy || '')
25 ,
26 ].map(function (x) { return 'user_pref(' + x + ');\n' }).join('');
27 }
28
29 prefs += 'user_pref("browser.shell.checkDefaultBrowser", false);\n';
30
31 var file = path.join(path.dirname(br.profile.file), 'user.js');
32 fs.writeFile(file, prefs, function (err) {
33 if (err) cb(err)
34 else cb(null, opts.options.concat([
35 '--no-remote',
36 '-P', br.profile.name,
37 uri,
38 ]))
39 });
40};
41
42argue.ie = function(br, uri, opts, cb) {
43 cb(null, [uri]);
44};
45
46argue.safari = function(br, uri, opts, cb) {
47 cb(null, [uri]);
48};
49
50argue.chrome = function (br, uri, opts, cb) {
51 opts.options = opts.options || [];
52 cb(null, opts.options.concat([
53 opts.proxy ? '--proxy-server=' + opts.proxy : null,
54 br.profile ? '--user-data-dir=' + br.profile : null,
55 '--disable-restore-session-state',
56 '--no-default-browser-check',
57 '--start-maximized',
58 '--disable-default-apps',
59 '--disable-sync',
60 '--enable-fixed-layout',
61 '--no-first-run',
62 '--noerrdialogs ',
63 uri,
64 ]).filter(Boolean));
65};
66
67argue.phantom = function (br, uri, opts, cb) {
68 // `phantomjs uri` would be TOO EASY I guess?
69 opts.options = opts.options || [];
70 var file = path.join(br.profile, 'phantom.js');
71 var src = '(new WebPage).open('
72 + JSON.stringify(uri)
73 + ',function(){})'
74 ;
75 fs.writeFile(file, src, function (err) {
76 if (err) cb(err)
77 else cb(null, opts.options.concat([
78 opts.proxy ?
79 '--proxy=' + opts.proxy.replace(/^http:\/\//, '')
80 : null
81 ,
82 file
83 ]).filter(Boolean))
84 });
85};
86
87module.exports = function (config, name, version) {
88 var m = selectMatch(config, name, version);
89 if (!m) return;
90 return function (uri, opts, cb) {
91 if (opts.headless && !m.headless) {
92 headless(function (err, proc, display) {
93 run({ DISPLAY : ':' + display });
94 });
95 }
96 else run({})
97
98 function run (env_) {
99 var env = {},
100 cwd = process.cwd();
101
102 Object.keys(process.env).forEach(function (key) {
103 env[key] = process.env[key];
104 });
105 Object.keys(env_).forEach(function (key) {
106 env[key] = env_[key];
107 });
108
109 argue[m.type](m, uri, opts, function (err, args) {
110 if (err) return cb(err);
111 if (opts.noProxy && env.no_proxy === undefined) {
112 env.no_proxy = opts.noProxy;
113 }
114 if (opts.proxy && env.http_proxy === undefined) {
115 env.http_proxy = opts.proxy;
116 }
117 if (opts.proxy && env.HTTP_PROXY === undefined) {
118 env.HTTP_PROXY = opts.proxy;
119 }
120 switch (process.platform) {
121 case 'win32':
122 m.command = m.command.replace(/"/g, ''); //Ensure all the quotes are removed
123 cwd = require('path').dirname(m.command); //Change directory to the app's base (Chrome)
124 break;
125 case 'darwin':
126 if (m.name !== 'firefox' && m.name !== 'phantom') { //Use the bin path under the hood
127 /*
128 This creates a command line structure like this:
129 open --wait-apps --new --fresh -a /Path/To/Executable <url> --args <rest of app args>
130 */
131 args.unshift('--args');
132 args.unshift(args.pop());
133 args.unshift(m.command);
134 args.unshift('-a');
135 args.unshift('--fresh');
136 args.unshift('--new');
137 args.unshift('--wait-apps');
138 m.command = 'open';
139 }
140 break;
141 }
142 cb(null, spawn(m.command, args, { env : env, cwd: cwd }));
143
144 });
145 }
146 };
147};
148
149function selectMatch (config, name, version) {
150 var order = (config.preference || []).concat(Object.keys(config.browsers));
151 for (var i = 0; i < order.length; i++) {
152 var bs = config.browsers[order[i]];
153 var matching = bs
154 .filter(function (b) {
155 return b.name === name
156 && matches(b.version, version)
157 ;
158 })
159 .sort(function (a, b) {
160 return b.version - a.version;
161 })
162 ;
163 if (matching.length) return matching[0];
164 }
165}
166
167function matches (version, pattern) {
168 if (pattern === undefined || pattern === '*') return true;
169
170 // todo: real semvers
171 var vs = version.split('.');
172 var ps = pattern.split('.');
173 for (var i = 0; i < ps.length; i++) {
174 if (ps[i] === 'x' || ps[i] === '*') continue;
175 if (ps[i] !== vs[i]) return false;
176 }
177 return true;
178}