зеркало из https://github.com/mozilla/gecko-dev.git
203 строки
5.9 KiB
JavaScript
203 строки
5.9 KiB
JavaScript
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
const { Cc, Ci, Cu, ChromeWorker } = require("chrome");
|
|
|
|
Cu.import("resource://gre/modules/Services.jsm");
|
|
|
|
const { EventTarget } = require("sdk/event/target");
|
|
const { emit, off } = require("sdk/event/core");
|
|
const { Class } = require("sdk/core/heritage");
|
|
const Environment = require("sdk/system/environment").env;
|
|
const Runtime = require("sdk/system/runtime");
|
|
const URL = require("sdk/url");
|
|
const Subprocess = require("sdk/system/child_process/subprocess");
|
|
const { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
|
|
|
|
const ROOT_URI = require("addon").uri;
|
|
const PROFILE_URL = ROOT_URI + "profile/";
|
|
const BIN_URL = ROOT_URI + "b2g/";
|
|
|
|
// Log subprocess error and debug messages to the console. This logs messages
|
|
// for all consumers of the API. We trim the messages because they sometimes
|
|
// have trailing newlines. And note that registerLogHandler actually registers
|
|
// an error handler, despite its name.
|
|
Subprocess.registerLogHandler(
|
|
function(s) console.error("subprocess: " + s.trim())
|
|
);
|
|
Subprocess.registerDebugHandler(
|
|
function(s) console.debug("subprocess: " + s.trim())
|
|
);
|
|
|
|
exports.SimulatorProcess = Class({
|
|
extends: EventTarget,
|
|
initialize: function initialize(options) {
|
|
EventTarget.prototype.initialize.call(this, options);
|
|
|
|
this.on("stdout", function onStdout(data) console.log(data.trim()));
|
|
this.on("stderr", function onStderr(data) console.error(data.trim()));
|
|
},
|
|
|
|
// check if b2g is running
|
|
get isRunning() !!this.process,
|
|
|
|
/**
|
|
* Start the process and connect the debugger client.
|
|
*/
|
|
run: function() {
|
|
// kill before start if already running
|
|
if (this.process != null) {
|
|
this.process
|
|
.kill()
|
|
.then(this.run.bind(this));
|
|
return;
|
|
}
|
|
|
|
// resolve b2g binaries path (raise exception if not found)
|
|
let b2gExecutable = this.b2gExecutable;
|
|
|
|
this.once("stdout", function () {
|
|
if (Runtime.OS == "Darwin") {
|
|
console.debug("WORKAROUND run osascript to show b2g-desktop window"+
|
|
" on Runtime.OS=='Darwin'");
|
|
// Escape double quotes and escape characters for use in AppleScript.
|
|
let path = b2gExecutable.path
|
|
.replace(/\\/g, "\\\\").replace(/\"/g, '\\"');
|
|
|
|
Subprocess.call({
|
|
command: "/usr/bin/osascript",
|
|
arguments: ["-e", 'tell application "' + path + '" to activate'],
|
|
});
|
|
}
|
|
});
|
|
|
|
let environment;
|
|
if (Runtime.OS == "Linux") {
|
|
environment = ["TMPDIR=" + Services.dirsvc.get("TmpD",Ci.nsIFile).path];
|
|
if ("DISPLAY" in Environment) {
|
|
environment.push("DISPLAY=" + Environment.DISPLAY);
|
|
}
|
|
}
|
|
|
|
// spawn a b2g instance
|
|
this.process = Subprocess.call({
|
|
command: b2gExecutable,
|
|
arguments: this.b2gArguments,
|
|
environment: environment,
|
|
|
|
// emit stdout event
|
|
stdout: (function(data) {
|
|
emit(this, "stdout", data);
|
|
}).bind(this),
|
|
|
|
// emit stderr event
|
|
stderr: (function(data) {
|
|
emit(this, "stderr", data);
|
|
}).bind(this),
|
|
|
|
// on b2g instance exit, reset tracked process, remoteDebuggerPort and
|
|
// shuttingDown flag, then finally emit an exit event
|
|
done: (function(result) {
|
|
console.log(this.b2gFilename + " terminated with " + result.exitCode);
|
|
this.process = null;
|
|
emit(this, "exit", result.exitCode);
|
|
}).bind(this)
|
|
});
|
|
},
|
|
|
|
// request a b2g instance kill
|
|
kill: function() {
|
|
let deferred = promise.defer();
|
|
if (this.process) {
|
|
this.once("exit", (exitCode) => {
|
|
this.shuttingDown = false;
|
|
deferred.resolve(exitCode);
|
|
});
|
|
if (!this.shuttingDown) {
|
|
this.shuttingDown = true;
|
|
emit(this, "kill", null);
|
|
this.process.kill();
|
|
}
|
|
return deferred.promise;
|
|
} else {
|
|
return promise.resolve(undefined);
|
|
}
|
|
},
|
|
|
|
// compute current b2g filename
|
|
get b2gFilename() {
|
|
return this._executable ? this._executableFilename : "B2G";
|
|
},
|
|
|
|
// compute current b2g file handle
|
|
get b2gExecutable() {
|
|
if (this._executable) {
|
|
return this._executable;
|
|
}
|
|
let customRuntime;
|
|
try {
|
|
let pref = "extensions." + require("addon").id + ".customRuntime";
|
|
customRuntime = Services.prefs.getComplexValue(pref, Ci.nsIFile);
|
|
} catch(e) {}
|
|
|
|
if (customRuntime) {
|
|
this._executable = customRuntime;
|
|
this._executableFilename = "Custom runtime";
|
|
return this._executable;
|
|
}
|
|
|
|
let bin = URL.toFilename(BIN_URL);
|
|
let executables = {
|
|
WINNT: "b2g-bin.exe",
|
|
Darwin: "B2G.app/Contents/MacOS/b2g-bin",
|
|
Linux: "b2g-bin",
|
|
};
|
|
|
|
let path = bin;
|
|
path += Runtime.OS == "WINNT" ? "\\" : "/";
|
|
path += executables[Runtime.OS];
|
|
console.log("simulator path: " + path);
|
|
|
|
let executable = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
|
|
executable.initWithPath(path);
|
|
|
|
if (!executable.exists()) {
|
|
// B2G binaries not found
|
|
throw Error("b2g-desktop Executable not found.");
|
|
}
|
|
|
|
this._executable = executable;
|
|
this._executableFilename = "b2g-bin";
|
|
|
|
return executable;
|
|
},
|
|
|
|
// compute b2g CLI arguments
|
|
get b2gArguments() {
|
|
let args = [];
|
|
|
|
let gaiaProfile;
|
|
try {
|
|
let pref = "extensions." + require("addon").id + ".gaiaProfile";
|
|
gaiaProfile = Services.prefs.getComplexValue(pref, Ci.nsIFile).path;
|
|
} catch(e) {}
|
|
|
|
let profile = gaiaProfile || URL.toFilename(PROFILE_URL);
|
|
args.push("-profile", profile);
|
|
console.log("profile", profile);
|
|
|
|
// NOTE: push dbgport option on the b2g-desktop commandline
|
|
args.push("-start-debugger-server", "" + this.remoteDebuggerPort);
|
|
|
|
// Ignore eventual zombie instances of b2g that are left over
|
|
args.push("-no-remote");
|
|
|
|
return args;
|
|
},
|
|
});
|
|
|