Publish Vulpes Preview 15 sources for desktop, Android and Tundra

Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
This commit is contained in:
OverSu 2026-09-30 23:13:03 +02:00
commit b38dea0597
25901 changed files with 9982925 additions and 369 deletions

View file

@ -0,0 +1,68 @@
'use strict';
/**
* This is a demo of using multiple mozilla-* projects with mozilla-runner.
*
* - downloads firefox
* - creates a profile
* - launches firefox (with a custom profile) to a given url
* - outputs the "dump'ed" content to stdout
*/
var mozdown = require('mozilla-download'),
mozprofile = require('mozilla-profile-builder'),
mozrun = require('../index'),
Static = require('node-static'),
fs = require('fs');
var PORT = 60034;
var FIREFOX_PATH = __dirname + '/firefox';
var PREFS = {
'browser.dom.window.dump.enabled': true
};
function download(callback) {
console.log('---*(-)- Downloading Firefox -----');
// download firefox if its missing
mozdown.download('firefox', FIREFOX_PATH, function(err) {
if (err) return console.error(err);
callback();
});
}
function startServer() {
// start static server
var file = new(Static.Server)(__dirname + '/public');
require('http').createServer(function(request, response) {
request.addListener('end', function() {
file.serve(request, response);
}).resume();
}).listen(PORT);
}
function profile(product, path, options, callback) {
mozprofile.firefox.profile({ userPrefs: PREFS }, function(err, path) {
callback(err, path);
});
}
function demo() {
// invoke the server
startServer();
var options = {
profile: profile,
url: 'http://localhost:' + PORT + '/index.html'
};
mozrun.run('firefox', FIREFOX_PATH, options, function(err, child) {
child.stdout.on('data', function(content) {
console.log('[firefox] %s', content.toString());
});
});
}
if (!fs.existsSync(FIREFOX_PATH)) {
download(demo);
} else {
demo();
}

View file

@ -0,0 +1,3 @@
{
"iamsocool": true
}

View file

@ -0,0 +1,19 @@
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>Demo target</title>
<script type="text/javascript" charset="utf-8">
var xhr = new XMLHttpRequest();
xhr.open('GET', './content.json', true);
xhr.onload = function() {
dump(xhr.responseText);
};
xhr.send();
</script>
</head>
<body>
DEMO YEY!
</body>
</html>

View file

@ -0,0 +1,4 @@
module.exports = {
run: require('./lib/run').run,
detectBinary: require('./lib/detectbinary').detectBinary
};

View file

@ -0,0 +1,67 @@
'use strict';
var fs = require('fs'),
fsPath = require('path');
module.exports.defaultBin = 'firefox-bin';
var platformPaths = {
darwin: 'Contents/MacOS'
};
/**
* Attempts to locate binary based on runtime/platform.
*
* detectBinary(
* '/Applications/Firefox',
* { product: 'firefox' },
* function(err, firefox) {
* // firefox === '/Applications/Firefox/Contents/MacOS/firefox-bin'
* }
* );
*
* Options:
* - bin: "firefox-bin" by default
* - platform: defaults to process.platform
*
* @param {String} source of product runtime.
* @param {Object} options for detection.
* @param {Function} callback [err, binaryPath];
*/
function detectBinary(source, options, callback) {
if (typeof options === 'function') {
callback = options;
options = {};
}
if (!options.product) throw new Error('.product must be given');
var platform = options.platform || process.platform;
var dir = platformPaths[platform] || '';
var bins = [
fsPath.join(source, dir, options.product + '-bin'),
fsPath.join(source, dir, options.product)
];
function exists(bin) {
fs.exists(bin, function(itDoes) {
if (itDoes) return callback(null, bin);
next();
});
}
function next() {
var bin = bins.shift();
if (!bin) {
return callback(
new Error('cannot find "' + options.product + '" binary in ' + source)
);
}
exists(bin);
}
next();
}
module.exports.detectBinary = detectBinary;

View file

@ -0,0 +1,132 @@
'use strict';
var detectBinary = require('./detectbinary').detectBinary,
debug = require('debug')('mozilla-runner:run'),
spawn = require('child_process').spawn,
fs = require('fs');
// private helper for building the argv
function buildArgv(options) {
var argv = [];
if (options.argv)
argv = argv.concat(options.argv);
if (options.profile) {
argv.push('-profile');
argv.push(options.profile);
}
if (options.screen &&
options.screen.width &&
options.screen.height) {
argv.push('--screen=' +
options.screen.width + 'x' +
options.screen.height + (
options.screen.dpi ?
('@' + options.screen.dpi) :
''));
}
if (options.noRemote !== false) {
argv.push('-no-remote');
}
if (options.url) {
argv.push(options.url);
}
if (options.oop) {
argv.push('-oop');
}
if (options.chrome) {
argv.push('-chrome');
argv.push(options.chrome);
}
if (options.startDebugger) {
argv.push('-start-debugger-server');
argv.push(options.startDebugger);
}
return argv;
}
/**
* Run an instance of a mozilla runtime/product.
*
* Options:
* - (Boolean) noRemote: defaults to true (-no-remote flag)
* - (String) url: url to navigate to
* - (String) profile: path to gecko profile
* - (Array) argv: additional arguments to pass to process
* - (Object) env: If present, specifies the exact environment to use.
* - (Object) envOverrides: Changes to make to the current environment; a value
* of null indicates that the key should be removed from the environment
* entirely.
*
* var options = {}
* mozrun(path, options, function(err, child, binary, argv) {
*
* });
*/
function run(path, options, callback) {
if (typeof options === 'function') {
callback = options;
options = null;
}
var spawnOpts = {
cwd: undefined,
env: process.env
};
if (options) {
if (options.env) {
spawnOpts.env = options.env;
} else if (options.envOverrides) {
spawnOpts.env = {};
var envKey, envVal;
for (envKey in process.env) {
spawnOpts.env[envKey] = process.env[envKey];
}
for (envKey in options.envOverrides) {
envVal = options.envOverrides[envKey];
// Treat undefineds like null since this makes more sense than ending up
// with the string 'undefined' in the environment.
if (envVal == null) {
delete spawnOpts.env[envKey];
}
else {
spawnOpts.env[envKey] = envVal;
}
}
}
}
// handler for creating process
function spawnProduct(binPath) {
var argv = buildArgv(options);
debug('arv:', argv);
debug('bin:', binPath);
// spawn child process
callback(null, spawn(binPath, argv, spawnOpts), binPath, argv);
}
function foundBinary(err, binPath) {
if (err) return callback(err);
debug('found bin', binPath);
spawnProduct(binPath);
}
if (options && options.runtime &&
fs.existsSync(options.runtime)) {
foundBinary(null, options.runtime);
} else {
detectBinary(path, options, foundBinary);
}
}
module.exports.run = run;

View file

@ -0,0 +1,12 @@
{
"name": "mozilla-runner",
"version": "0.5.0",
"author": "James Lal [:lightsofapollo]",
"description": "Firefox / B2G runtime manager.",
"main": "index.js",
"dependencies" : {
"debug": "*",
"mozilla-profile-builder": "file:../mozilla-profile-builder"
}
}

View file

@ -0,0 +1,65 @@
'use strict';
var assert = require('assert');
var fsPath = require('path');
var subject = require('../lib/detectbinary').detectBinary;
suite('detectbinary', function() {
var platforms = {
mac: {
path: __dirname + '/fixtures/product-mac',
suffix: '/Contents/MacOS',
platform: 'darwin',
product: 'firefox'
},
noBinMac: {
path: __dirname + '/fixtures/product-mac-no-bin',
suffix: '/Contents/MacOS',
platform: 'darwin',
product: 'firefox'
},
linux: {
path: __dirname + '/fixtures/product-linux',
suffix: '',
platform: 'linux-bs',
product: 'firefox'
},
noBinLinux: {
path: __dirname + '/fixtures/product-linux-no-bin',
suffix: '',
platform: 'linux-bs',
product: 'firefox'
}
};
function fixturePath(fixture, bin) {
fsPath.join(
fixture.path,
fixture.suffix,
bin
);
}
function verify(name, fixture, bin) {
test(name, function(done) {
subject(fixture.path, fixture, function(err, path) {
if (err) return done(err);
assert.equal(fixturePath(fixture, bin));
done();
});
});
}
verify('mac with -bin', platforms.mac, 'firefox-bin');
verify('mac without -bin', platforms.noBinMac, 'firefox');
verify('linux with -bin', platforms.linux, 'firefox-bin');
verify('linux without -bin', platforms.noBinLinux, 'firefox');
test('missing binary', function(done) {
subject(__dirname, { product: 'firefox', bin: 'nothere' }, function(err) {
assert.ok(err, 'has error');
assert.ok(err.message.indexOf(__dirname) !== 0, 'contains path');
done();
});
});
});

View file

@ -0,0 +1,3 @@
#!/bin/sh
echo FOO is $FOO and BAR is $BAR stop

View file

@ -0,0 +1,13 @@
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>Dump</title>
<script type="text/javascript" charset="utf-8">
dump('\n\n WOOT DUMP \n\n');
</script>
</head>
<body>
</body>
</html>

View file

@ -0,0 +1,189 @@
'use strict';
var Static = require('node-static');
var assert = require('assert');
var profile = require('mozilla-profile-builder');
var run = require('../lib/run').run;
var runtime = __dirname + '/../../../../../firefox';
'use strict';
suite('run', function() {
test('launch mulet', function(done) {
var options = { product: 'firefox', profile: process.env.PROFILE_FOLDER };
this.timeout(5000);
run(runtime, options, function(err, child, bin, argv) {
assert.ok(!err, err && err.message);
// verify the binary
assert.ok(bin.indexOf('firefox-bin') !== 0, 'has bin');
// verify arguments
assert.deepEqual(
argv,
['-profile', process.env.PROFILE_FOLDER, '-no-remote']
);
// verify we have a child
assert.ok(child.kill, 'is process');
child.kill();
done();
});
});
test('launch mulet with different screen', function(done) {
var options =
{ product: 'firefox', profile: process.env.PROFILE_FOLDER,
screen: {
width: 1280,
height: 800,
dpi: 160
}
};
this.timeout(5000);
run(runtime, options, function(err, child, bin, argv) {
assert.ok(!err, err && err.message);
// verify screen size
assert.deepEqual(
argv,
[
'-profile', process.env.PROFILE_FOLDER, '--screen=1280x800@160',
'-no-remote'
]
);
// verify we have a child
assert.ok(child.kill, 'is process');
child.kill();
done();
});
});
test('check env overrides', function(done) {
// this should not be seen in the child since we are deleting it
process.env.BAR = 'bar';
var options = {
product: 'echostuff',
envOverrides: {
FOO: 'foo',
BAR: null
}
};
var expected = 'FOO is foo and BAR is stop';
this.timeout(5000);
run(__dirname + '/fixtures/env-echoer', options,
function(err, child, bin, argv) {
assert.ok(!err, err && err.message);
child.stdout.on('data', function(content) {
content = content.toString();
// verify we can go to a given url
if (content.indexOf(expected) !== -1) {
child.kill();
done();
}
});
});
});
test('explicit env', function(done) {
// this should not be seen in the child since it is using an explicit env.
process.env.BAR = 'bar';
var options = {
product: 'echostuff',
env: {
FOO: 'foo',
}
};
var expected = 'FOO is foo and BAR is stop';
this.timeout(5000);
run(__dirname + '/fixtures/env-echoer', options,
function(err, child, bin, argv) {
assert.ok(!err, err && err.message);
child.stdout.on('data', function(content) {
content = content.toString();
if (content.indexOf(expected) !== -1) {
child.kill();
done();
}
});
});
});
test('env is expected default if not specified', function(done) {
process.env.FOO = 'foo';
process.env.BAR = 'bar';
var options = {
product: 'echostuff',
};
var expected = 'FOO is foo and BAR is bar stop';
this.timeout(5000);
run(__dirname + '/fixtures/env-echoer', options,
function(err, child, bin, argv) {
assert.ok(!err, err && err.message);
child.stdout.on('data', function(content) {
content = content.toString();
if (content.indexOf(expected) !== -1) {
child.kill();
done();
}
});
});
});
suite('launch mulet read dump', function() {
var server;
var port = 60033;
var config = {
// turn on dump
'browser.dom.window.dump.enabled': true
};
// create server
setup(function() {
var file = new (Static.Server)(__dirname + '/html');
server = require('http').createServer(function(req, res) {
// stolen from node-Static
req.on('end', function() {
file.serve(req, res);
}).resume();
});
server.listen(port);
});
// ensure server gets closed
teardown(function() {
server.close();
});
// create tmp profile
var profileDir;
setup(function(done) {
profile.create({ prefs: config }, function(err, result) {
if (err) return done(err);
profileDir = result.path;
done();
});
});
var url = 'http://localhost:' + port + '/dump.html';
var expected = 'WOOT DUMP';
test('go to url', function(done) {
var options = { product: 'firefox', profile: profileDir, url: url };
run(runtime, options, function(err, child) {
if (err) return done(err);
child.stdout.on('data', function(content) {
content = content.toString();
// verify we can go to a given url
if (content.indexOf(expected) !== -1) {
child.kill();
done();
}
});
});
});
});
});