Last active
August 29, 2015 14:26
-
-
Save begeeben/358e87242fabe1112b16 to your computer and use it in GitHub Desktop.
A handly script to make and run Firefox OS Gaia. Watch for file changes and make on the fly.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Usage: node make_onsave.js b2g tv browser | |
// node make_onsave.js nightly phone settings | |
// node make_onsave.js simulator tv tv-deck | |
// node make_onsave.js b2g tv | |
'use strict'; | |
var fs = require('fs'); | |
var path = require('path'); | |
var exec = require('child_process').exec; | |
// Firefox runtimes | |
// Change these to your local runtime paths | |
var firefoxRuntimes = { | |
firefox: '/Applications/FirefoxNightly.app/Contents/MacOS/firefox-bin', | |
developer: '/Applications/FirefoxDeveloperEdition.app/Contents/MacOS/firefox-bin', | |
nightly: '/Applications/FirefoxNightly.app/Contents/MacOS/firefox-bin', | |
mulet: '/Applications/mulet/FirefoxNightly.app/Contents/MacOS/firefox-bin', | |
b2g: '/Applications/B2G.app/Contents/MacOS/b2g-bin', | |
simulator: '/Users/asail/mozilla/b2g-tv/B2G.app/Contents/MacOS/b2g-bin' | |
}; | |
var runtimeTypes = ['firefox', 'developer', 'b2g', 'mulet', 'nightly', 'simulator']; | |
var deviceTypes = ['phone', 'tv']; | |
var apps = fs.readdirSync(path.join(__dirname, 'apps')).filter(function(file) { | |
return fs.statSync(path.join(path.join(__dirname, 'apps'), file)).isDirectory(); | |
}); | |
var tvApps = fs.readdirSync(path.join(__dirname, 'tv_apps')).filter(function(file) { | |
return fs.statSync(path.join(path.join(__dirname, 'tv_apps'), file)).isDirectory(); | |
}); | |
// Default runtime and device type | |
var runtime = 'b2g'; | |
var deviceType = 'tv'; | |
var app; | |
process.argv.forEach(function(val, index, array) { | |
if (runtimeTypes.indexOf(val) > -1) { | |
runtime = val; | |
} else if (deviceTypes.indexOf(val) > -1) { | |
deviceType = val; | |
} else if (apps.indexOf(val) > -1 || tvApps.indexOf(val) > -1) { | |
app = val; | |
} | |
}); | |
var makeScript = ''; | |
if (app) { | |
makeScript = 'APP=' + app + ' '; | |
} | |
if (deviceType === 'tv') { | |
makeScript += 'GAIA_DEVICE_TYPE=' + deviceType + ' DEVICE_DEBUG=1 '; | |
} else { | |
makeScript += 'DEVICE_DEBUG=1 '; | |
} | |
if (runtime === 'nightly') { | |
makeScript += 'DESKTOP=0 '; | |
} | |
makeScript += 'make'; | |
var runScript = firefoxRuntimes[runtime] + ' -profile '; | |
if (deviceType === 'tv') { | |
runScript += '${PWD}/profile -start-debugger-server 6000 -screen 1920x1080'; | |
// runScript += ' -screen 1920x1080 app://browser.gaiamobile.org'; | |
} else { | |
runScript += path.join(__dirname, 'profile'); | |
// runScript += path.join(__dirname, 'profile-debug') + ' --no-remote app://sms.gaiamobile.org'; | |
} | |
function makeGaia (callback) { | |
console.log('makeGaia: ' + makeScript); | |
var make = exec(makeScript); | |
make.stdout.on('data', function (data) { | |
console.log(data); | |
}); | |
make.stderr.on('data', function (data) { | |
console.log(data); | |
}); | |
make.on('close', function (code) { | |
console.log(code); | |
if (typeof callback === 'function') { | |
callback(); | |
} | |
}); | |
} | |
function startRuntime (callback) { | |
console.log('startRuntime: ' + runScript); | |
var run = exec(runScript); | |
run.stdout.on('data', function (data) { | |
console.log(data); | |
if (data.trim() === 'Opening debugger server on 6000' && typeof callback === 'function') { | |
// XXX: Run the callback later in case the debugger server hasn't been ready yet. | |
setTimeout(callback, 6000); | |
} | |
}); | |
run.stderr.on('data', function (data) { | |
console.log(data); | |
}); | |
run.on('close', function (code) { | |
console.log(code); | |
}); | |
} | |
function watch () { | |
function onfilechange (event, filename) { | |
console.log('file changed in source directory'); | |
if (filename && filename.indexOf('.') !== 0) { | |
console.log('filename provided: ' + filename); | |
makeGaia(connectToRuntime); | |
} else { | |
console.log('filename not provided'); | |
} | |
} | |
if (deviceType === 'phone') { | |
fs.watch(path.join(__dirname, 'apps'), { persistent: true, recursive: true }, onfilechange); | |
} else { | |
fs.watch(path.join(__dirname, 'tv_apps'), { persistent: true, recursive: true }, onfilechange); | |
} | |
fs.watch(path.join(__dirname, 'shared'), { persistent: true, recursive: true }, onfilechange); | |
} | |
makeGaia(function () { | |
startRuntime(function() { | |
watch(); | |
// connectToRuntime(); | |
}); | |
}); | |
// Connect to runtime with remote debugging protocol | |
var net = require('net'); | |
var client; | |
var webappsActor; | |
var appActor; | |
// borrowed from https://github.com/harthur/firefox-client/blob/master/lib/client.js#L117 | |
function sendMessage(message) { | |
if (!message.to) { | |
throw new Error("No actor specified in request"); | |
} | |
if (!client) { | |
throw new Error("Not connected, connect() before sending requests"); | |
} | |
var str = JSON.stringify(message); | |
// message is preceded by byteLength(message): | |
str = (new Buffer(str).length) + ":" + str; | |
console.log('sendMessage: ' + str); | |
client.write(str); | |
} | |
function connectToRuntime() { | |
console.log('connectToRuntime'); | |
// borrowed from https://github.com/harthur/firefox-client/blob/a9caacdf8f138d07195402fe1b7183c7aeb964ec/lib/client.js#L194 | |
function readMessage() { | |
var sep = str.toString().indexOf(':'); | |
if (sep < 0) { | |
return false; | |
} | |
// beginning of a message is preceded by byteLength(message) + ":" | |
var count = parseInt(str.slice(0, sep)); | |
if (str.length - (sep + 1) < count) { | |
console.log('no complete response yet'.grey); | |
return false; | |
} | |
str = str.slice(sep + 1); | |
var packet = str.slice(0, count); | |
str = str.slice(count); | |
var message; | |
try { | |
message = JSON.parse(packet.toString()); | |
} catch(e) { | |
throw new Error('Couldn\'t parse packet from server as JSON ' + e + | |
', message:\n' + packet); | |
} | |
handleMessage(message); | |
return true; | |
} | |
function handleMessage(message) { | |
console.log('handleMessage: ', message); | |
if (message.webappsActor) { | |
webappsActor = message.webappsActor; | |
sendMessage({ | |
to: webappsActor, | |
type: 'getAppActor', | |
manifestURL: 'app://' + app + '.gaiamobile.org/manifest.webapp' | |
}); | |
} | |
if (message.actor) { | |
if (message.actor.url.indexOf(app) > -1) { | |
appActor = message.actor.actor; | |
reload(); | |
} | |
} | |
} | |
var str = new Buffer(''); | |
client = net.connect({port: 6000}, | |
function() { //'connect' listener | |
console.log('connected to server!'); | |
sendMessage({to: 'root', type: 'listTabs'}); | |
}); | |
client.on('data', function(data) { | |
// console.log(data.toString()); | |
// console.log('\n'); | |
str = Buffer.concat([str, data]); | |
while(readMessage()) {} | |
}); | |
client.on('error', function(error) { | |
console.log(error.toString()); | |
}); | |
client.on('end', function() { | |
console.log('disconnected from server'); | |
}); | |
} | |
function reload() { | |
console.log('reload'); | |
sendMessage({ | |
to: appActor, | |
type: 'reload', | |
options: { | |
'force': true | |
}, | |
manifestURL: 'app://' + app + '.gaiamobile.org/manifest.webapp' | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment