b2g/simulator/lib/simulator-process.js

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
michael@0 4 */
michael@0 5
michael@0 6 'use strict';
michael@0 7
michael@0 8 const { Cc, Ci, Cu, ChromeWorker } = require("chrome");
michael@0 9
michael@0 10 Cu.import("resource://gre/modules/Services.jsm");
michael@0 11
michael@0 12 const { EventTarget } = require("sdk/event/target");
michael@0 13 const { emit, off } = require("sdk/event/core");
michael@0 14 const { Class } = require("sdk/core/heritage");
michael@0 15 const Environment = require("sdk/system/environment").env;
michael@0 16 const Runtime = require("sdk/system/runtime");
michael@0 17 const Self = require("sdk/self");
michael@0 18 const URL = require("sdk/url");
michael@0 19 const Subprocess = require("subprocess");
michael@0 20 const { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
michael@0 21 const Prefs = require("sdk/simple-prefs").prefs;
michael@0 22
michael@0 23 const { rootURI: ROOT_URI } = require('@loader/options');
michael@0 24 const PROFILE_URL = ROOT_URI + "profile/";
michael@0 25 const BIN_URL = ROOT_URI + "b2g/";
michael@0 26
michael@0 27 // Log subprocess error and debug messages to the console. This logs messages
michael@0 28 // for all consumers of the API. We trim the messages because they sometimes
michael@0 29 // have trailing newlines. And note that registerLogHandler actually registers
michael@0 30 // an error handler, despite its name.
michael@0 31 Subprocess.registerLogHandler(
michael@0 32 function(s) console.error("subprocess: " + s.trim())
michael@0 33 );
michael@0 34 Subprocess.registerDebugHandler(
michael@0 35 function(s) console.debug("subprocess: " + s.trim())
michael@0 36 );
michael@0 37
michael@0 38 exports.SimulatorProcess = Class({
michael@0 39 extends: EventTarget,
michael@0 40 initialize: function initialize(options) {
michael@0 41 EventTarget.prototype.initialize.call(this, options);
michael@0 42
michael@0 43 this.on("stdout", function onStdout(data) console.log(data.trim()));
michael@0 44 this.on("stderr", function onStderr(data) console.error(data.trim()));
michael@0 45 },
michael@0 46
michael@0 47 // check if b2g is running
michael@0 48 get isRunning() !!this.process,
michael@0 49
michael@0 50 /**
michael@0 51 * Start the process and connect the debugger client.
michael@0 52 */
michael@0 53 run: function() {
michael@0 54 // kill before start if already running
michael@0 55 if (this.process != null) {
michael@0 56 this.process
michael@0 57 .kill()
michael@0 58 .then(this.run.bind(this));
michael@0 59 return;
michael@0 60 }
michael@0 61
michael@0 62 // resolve b2g binaries path (raise exception if not found)
michael@0 63 let b2gExecutable = this.b2gExecutable;
michael@0 64
michael@0 65 this.once("stdout", function () {
michael@0 66 if (Runtime.OS == "Darwin") {
michael@0 67 console.debug("WORKAROUND run osascript to show b2g-desktop window"+
michael@0 68 " on Runtime.OS=='Darwin'");
michael@0 69 // Escape double quotes and escape characters for use in AppleScript.
michael@0 70 let path = b2gExecutable.path
michael@0 71 .replace(/\\/g, "\\\\").replace(/\"/g, '\\"');
michael@0 72
michael@0 73 Subprocess.call({
michael@0 74 command: "/usr/bin/osascript",
michael@0 75 arguments: ["-e", 'tell application "' + path + '" to activate'],
michael@0 76 });
michael@0 77 }
michael@0 78 });
michael@0 79
michael@0 80 let environment;
michael@0 81 if (Runtime.OS == "Linux") {
michael@0 82 environment = ["TMPDIR=" + Services.dirsvc.get("TmpD",Ci.nsIFile).path];
michael@0 83 if ("DISPLAY" in Environment) {
michael@0 84 environment.push("DISPLAY=" + Environment.DISPLAY);
michael@0 85 }
michael@0 86 }
michael@0 87
michael@0 88 // spawn a b2g instance
michael@0 89 this.process = Subprocess.call({
michael@0 90 command: b2gExecutable,
michael@0 91 arguments: this.b2gArguments,
michael@0 92 environment: environment,
michael@0 93
michael@0 94 // emit stdout event
michael@0 95 stdout: (function(data) {
michael@0 96 emit(this, "stdout", data);
michael@0 97 }).bind(this),
michael@0 98
michael@0 99 // emit stderr event
michael@0 100 stderr: (function(data) {
michael@0 101 emit(this, "stderr", data);
michael@0 102 }).bind(this),
michael@0 103
michael@0 104 // on b2g instance exit, reset tracked process, remoteDebuggerPort and
michael@0 105 // shuttingDown flag, then finally emit an exit event
michael@0 106 done: (function(result) {
michael@0 107 console.log(this.b2gFilename + " terminated with " + result.exitCode);
michael@0 108 this.process = null;
michael@0 109 emit(this, "exit", result.exitCode);
michael@0 110 }).bind(this)
michael@0 111 });
michael@0 112 },
michael@0 113
michael@0 114 // request a b2g instance kill
michael@0 115 kill: function() {
michael@0 116 let deferred = promise.defer();
michael@0 117 if (this.process) {
michael@0 118 this.once("exit", (exitCode) => {
michael@0 119 this.shuttingDown = false;
michael@0 120 deferred.resolve(exitCode);
michael@0 121 });
michael@0 122 if (!this.shuttingDown) {
michael@0 123 this.shuttingDown = true;
michael@0 124 emit(this, "kill", null);
michael@0 125 this.process.kill();
michael@0 126 }
michael@0 127 return deferred.promise;
michael@0 128 } else {
michael@0 129 return promise.resolve(undefined);
michael@0 130 }
michael@0 131 },
michael@0 132
michael@0 133 // compute current b2g filename
michael@0 134 get b2gFilename() {
michael@0 135 return this._executable ? this._executableFilename : "B2G";
michael@0 136 },
michael@0 137
michael@0 138 // compute current b2g file handle
michael@0 139 get b2gExecutable() {
michael@0 140 if (this._executable) {
michael@0 141 return this._executable;
michael@0 142 }
michael@0 143
michael@0 144 if (Prefs.customRuntime) {
michael@0 145 this._executable = Prefs.customRuntime;
michael@0 146 this._executableFilename = "Custom runtime";
michael@0 147 return this._executable;
michael@0 148 }
michael@0 149
michael@0 150 let bin = URL.toFilename(BIN_URL);
michael@0 151 let executables = {
michael@0 152 WINNT: "b2g-bin.exe",
michael@0 153 Darwin: "B2G.app/Contents/MacOS/b2g-bin",
michael@0 154 Linux: "b2g-bin",
michael@0 155 };
michael@0 156
michael@0 157 let path = bin;
michael@0 158 path += Runtime.OS == "WINNT" ? "\\" : "/";
michael@0 159 path += executables[Runtime.OS];
michael@0 160 console.log("simulator path: " + path);
michael@0 161
michael@0 162 let executable = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
michael@0 163 executable.initWithPath(path);
michael@0 164
michael@0 165 if (!executable.exists()) {
michael@0 166 // B2G binaries not found
michael@0 167 throw Error("b2g-desktop Executable not found.");
michael@0 168 }
michael@0 169
michael@0 170 this._executable = executable;
michael@0 171 this._executableFilename = "b2g-bin";
michael@0 172
michael@0 173 return executable;
michael@0 174 },
michael@0 175
michael@0 176 // compute b2g CLI arguments
michael@0 177 get b2gArguments() {
michael@0 178 let args = [];
michael@0 179
michael@0 180 let profile = Prefs.gaiaProfile || URL.toFilename(PROFILE_URL);
michael@0 181 args.push("-profile", profile);
michael@0 182 console.log("profile", profile);
michael@0 183
michael@0 184 // NOTE: push dbgport option on the b2g-desktop commandline
michael@0 185 args.push("-start-debugger-server", "" + this.remoteDebuggerPort);
michael@0 186
michael@0 187 // Ignore eventual zombie instances of b2g that are left over
michael@0 188 args.push("-no-remote");
michael@0 189
michael@0 190 return args;
michael@0 191 },
michael@0 192 });
michael@0 193

mercurial