diff --git a/browser/devtools/webide/modules/runtimes.js b/browser/devtools/webide/modules/runtimes.js index f6c3cf7ef205..d6d828cc31db 100644 --- a/browser/devtools/webide/modules/runtimes.js +++ b/browser/devtools/webide/modules/runtimes.js @@ -5,9 +5,9 @@ const {Cu, Ci} = require("chrome"); const {Devices} = Cu.import("resource://gre/modules/devtools/Devices.jsm"); const {Services} = Cu.import("resource://gre/modules/Services.jsm"); -const {Connection} = require("devtools/client/connection-manager"); +const {Simulator} = Cu.import("resource://gre/modules/devtools/Simulator.jsm"); +const {ConnectionManager, Connection} = require("devtools/client/connection-manager"); const {DebuggerServer} = require("resource://gre/modules/devtools/dbg-server.jsm"); -const {Simulators} = require("devtools/webide/simulators"); const discovery = require("devtools/toolkit/discovery/discovery"); const EventEmitter = require("devtools/toolkit/event-emitter"); const promise = require("promise"); @@ -193,12 +193,14 @@ let SimulatorScanner = { enable() { this._updateRuntimes = this._updateRuntimes.bind(this); - Simulators.on("updated", this._updateRuntimes); + Simulator.on("register", this._updateRuntimes); + Simulator.on("unregister", this._updateRuntimes); this._updateRuntimes(); }, disable() { - Simulators.off("updated", this._updateRuntimes); + Simulator.off("register", this._updateRuntimes); + Simulator.off("unregister", this._updateRuntimes); }, _emitUpdated() { @@ -206,13 +208,11 @@ let SimulatorScanner = { }, _updateRuntimes() { - Simulators.getAll().then(simulators => { - this._runtimes = []; - for (let simulator of simulators) { - this._runtimes.push(new SimulatorRuntime(simulator)); - } - this._emitUpdated(); - }); + this._runtimes = []; + for (let name of Simulator.availableNames()) { + this._runtimes.push(new SimulatorRuntime(name)); + } + this._emitUpdated(); }, scan() { @@ -542,26 +542,28 @@ WiFiRuntime.prototype = { // For testing use only exports._WiFiRuntime = WiFiRuntime; -function SimulatorRuntime(simulator) { - this.simulator = simulator; +function SimulatorRuntime(name) { + this.name = name; } SimulatorRuntime.prototype = { type: RuntimeTypes.SIMULATOR, connect: function(connection) { - return this.simulator.launch().then(port => { + let port = ConnectionManager.getFreeTCPPort(); + let simulator = Simulator.getByName(this.name); + if (!simulator || !simulator.launch) { + return promise.reject(new Error("Can't find simulator: " + this.name)); + } + return simulator.launch({port: port}).then(() => { connection.host = "localhost"; connection.port = port; connection.keepConnecting = true; - connection.once(Connection.Events.DISCONNECTED, e => this.simulator.kill()); + connection.once(Connection.Events.DISCONNECTED, simulator.close); connection.connect(); }); }, get id() { - return this.simulator.id; - }, - get name() { - return this.simulator.name; + return this.name; }, }; diff --git a/browser/devtools/webide/modules/simulator-process.js b/browser/devtools/webide/modules/simulator-process.js deleted file mode 100644 index 0ebae120b0e7..000000000000 --- a/browser/devtools/webide/modules/simulator-process.js +++ /dev/null @@ -1,273 +0,0 @@ -/* 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 } = require("chrome"); - -const Environment = require("sdk/system/environment").env; -const Subprocess = require("sdk/system/child_process/subprocess"); -const { EventEmitter } = Cu.import("resource://gre/modules/devtools/event-emitter.js", {}); -const { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {}); -const { Services } = Cu.import("resource://gre/modules/Services.jsm", {}); - -let platform = Services.appShell.hiddenDOMWindow.navigator.platform; -let OS = ""; -if (platform.indexOf("Win") != -1) { - OS = "win32"; -} else if (platform.indexOf("Mac") != -1) { - OS = "mac64"; -} else if (platform.indexOf("Linux") != -1) { - if (platform.indexOf("x86_64") != -1) { - OS = "linux64"; - } else { - OS = "linux32"; - } -} - -function SimulatorProcess() {} -SimulatorProcess.prototype = { - - // Check if B2G is running. - get isRunning() !!this.process, - - // Start the process and connect the debugger client. - run() { - - // Resolve B2G binary. - let b2g = this.b2gBinary; - if (!b2g || !b2g.exists()) { - throw Error("B2G executable not found."); - } - - this.once("stdout", function () { - if (OS == "mac64") { - console.debug("WORKAROUND run osascript to show b2g-desktop window on OS=='mac64'"); - // Escape double quotes and escape characters for use in AppleScript. - let path = b2g.path.replace(/\\/g, "\\\\").replace(/\"/g, '\\"'); - - Subprocess.call({ - command: "/usr/bin/osascript", - arguments: ["-e", 'tell application "' + path + '" to activate'], - }); - } - }); - - this.on("stdout", (e, data) => this.log(e, data.trim())); - this.on("stderr", (e, data) => this.log(e, data.trim())); - - let environment; - if (OS.indexOf("linux") > -1) { - 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: b2g, - arguments: this.args, - environment: environment, - stdout: data => this.emit("stdout", data), - stderr: data => this.emit("stderr", data), - // On B2G instance exit, reset tracked process, remote debugger port and - // shuttingDown flag, then finally emit an exit event. - done: result => { - console.log("B2G terminated with " + result.exitCode); - this.process = null; - this.emit("exit", result.exitCode); - } - }); - }, - - // Request a B2G instance kill. - kill() { - let deferred = promise.defer(); - if (this.process) { - this.once("exit", (e, exitCode) => { - this.shuttingDown = false; - deferred.resolve(exitCode); - }); - if (!this.shuttingDown) { - this.shuttingDown = true; - this.emit("kill", null); - this.process.kill(); - } - return deferred.promise; - } else { - return promise.resolve(undefined); - } - }, - - // Maybe log output messages. - log(level, message) { - if (!Services.prefs.getBoolPref("devtools.webide.logSimulatorOutput")) { - return; - } - if (level === "stderr" || level === "error") { - console.error(message); - return; - } - console.log(message); - }, - - // Compute B2G CLI arguments. - get args() { - let args = []; - - let gaia = this.gaiaProfile; - if (!gaia || !gaia.exists()) { - throw Error("Gaia profile directory not found."); - } - args.push("-profile", gaia.path); - - args.push("-start-debugger-server", "" + this.options.port); - - // Ignore eventual zombie instances of b2g that are left over. - args.push("-no-remote"); - - return args; - }, -}; - -EventEmitter.decorate(SimulatorProcess.prototype); - - -function CustomSimulatorProcess(options) { - this.options = options; -} - -let CSPp = CustomSimulatorProcess.prototype = Object.create(SimulatorProcess.prototype); - -// Compute B2G binary file handle. -Object.defineProperty(CSPp, "b2gBinary", { - get: function() { - let file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsILocalFile); - file.initWithPath(this.options.b2gBinary); - return file; - } -}); - -// Compute Gaia profile file handle. -Object.defineProperty(CSPp, "gaiaProfile", { - get: function() { - let file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsILocalFile); - file.initWithPath(this.options.gaiaProfile); - return file; - } -}); - -exports.CustomSimulatorProcess = CustomSimulatorProcess; - - -function AddonSimulatorProcess(addon, options) { - this.addon = addon; - this.options = options; -} - -let ASPp = AddonSimulatorProcess.prototype = Object.create(SimulatorProcess.prototype); - -// Compute B2G binary file handle. -Object.defineProperty(ASPp, "b2gBinary", { - get: function() { - let file; - try { - let pref = "extensions." + this.addon.id + ".customRuntime"; - file = Services.prefs.getComplexValue(pref, Ci.nsIFile); - } catch(e) {} - - if (!file) { - let binaries = { - win32: "b2g-bin.exe", - mac64: "B2G.app/Contents/MacOS/b2g-bin", - linux32: "b2g-bin", - linux64: "b2g-bin", - }; - file = this.addon.getResourceURI().QueryInterface(Ci.nsIFileURL).file; - file.append("b2g"); - file.append(binaries[OS]); - } - return file; - } -}); - -// Compute Gaia profile file handle. -Object.defineProperty(ASPp, "gaiaProfile", { - get: function() { - let file; - try { - let pref = "extensions." + this.addon.id + ".gaiaProfile"; - file = Services.prefs.getComplexValue(pref, Ci.nsIFile); - } catch(e) {} - - if (!file) { - file = this.addon.getResourceURI().QueryInterface(Ci.nsIFileURL).file; - file.append("profile"); - } - return file; - } -}); - -exports.AddonSimulatorProcess = AddonSimulatorProcess; - - -function OldAddonSimulatorProcess(addon, options) { - this.addon = addon; - this.options = options; -} - -let OASPp = OldAddonSimulatorProcess.prototype = Object.create(AddonSimulatorProcess.prototype); - -// Compute B2G binary file handle. -Object.defineProperty(OASPp, "b2gBinary", { - get: function() { - let file; - try { - let pref = "extensions." + this.addon.id + ".customRuntime"; - file = Services.prefs.getComplexValue(pref, Ci.nsIFile); - } catch(e) {} - - if (!file) { - let version = this.addon.name.match(/\d+\.\d+/)[0].replace(/\./, "_"); - file = this.addon.getResourceURI().QueryInterface(Ci.nsIFileURL).file; - file.append("resources"); - file.append("fxos_" + version + "_simulator"); - file.append("data"); - file.append(OS == "linux32" ? "linux" : OS); - if (OS == "mac64") { - file.append("B2G.app"); - file.append("Contents"); - file.append("MacOS"); - } else { - file.append("b2g"); - } - file.append("b2g-bin" + (OS == "win32" ? ".exe" : "")); - } - return file; - } -}); - -// Compute B2G CLI arguments. -Object.defineProperty(OASPp, "args", { - get: function() { - let args = []; - - let gaia = this.gaiaProfile; - if (!gaia || !gaia.exists()) { - throw Error("Gaia profile directory not found."); - } - args.push("-profile", gaia.path); - - args.push("-dbgport", "" + this.options.port); - - // Ignore eventual zombie instances of b2g that are left over. - args.push("-no-remote"); - - return args; - } -}); - -exports.OldAddonSimulatorProcess = OldAddonSimulatorProcess; diff --git a/browser/devtools/webide/modules/simulators.js b/browser/devtools/webide/modules/simulators.js deleted file mode 100644 index 2e05e91e6154..000000000000 --- a/browser/devtools/webide/modules/simulators.js +++ /dev/null @@ -1,96 +0,0 @@ -/* 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/. */ - -const { Cu } = require("chrome"); -const { AddonManager } = Cu.import("resource://gre/modules/AddonManager.jsm"); -const { EventEmitter } = Cu.import("resource://gre/modules/devtools/event-emitter.js"); -const { ConnectionManager } = require("devtools/client/connection-manager"); -const { AddonSimulatorProcess, OldAddonSimulatorProcess } = require("devtools/webide/simulator-process"); -const promise = require("promise"); - -const SimulatorRegExp = new RegExp(Services.prefs.getCharPref("devtools.webide.simulatorAddonRegExp")); - -let Simulators = { - // TODO (Bug 1090949) Don't generate this list from installed simulator - // addons, but instead implement a persistent list of user-configured - // simulators. - getAll() { - let deferred = promise.defer(); - AddonManager.getAllAddons(addons => { - let simulators = []; - for (let addon of addons) { - if (SimulatorRegExp.exec(addon.id)) { - simulators.push(new Simulator(addon)); - } - } - // Sort simulators alphabetically by name. - simulators.sort((a, b) => { - return a.name.toLowerCase().localeCompare(b.name.toLowerCase()) - }); - deferred.resolve(simulators); - }); - return deferred.promise; - }, -} -EventEmitter.decorate(Simulators); -exports.Simulators = Simulators; - -function update() { - Simulators.emit("updated"); -} -AddonManager.addAddonListener({ - onEnabled: update, - onDisabled: update, - onInstalled: update, - onUninstalled: update -}); - - -function Simulator(addon) { - this.addon = addon; -} - -Simulator.prototype = { - launch() { - // Close already opened simulation. - if (this.process) { - return this.kill().then(this.launch.bind(this)); - } - - let options = { - port: ConnectionManager.getFreeTCPPort() - }; - - if (this.version <= "1.3") { - // Support older simulator addons. - this.process = new OldAddonSimulatorProcess(this.addon, options); - } else { - this.process = new AddonSimulatorProcess(this.addon, options); - } - this.process.run(); - - return promise.resolve(options.port); - }, - - kill() { - let process = this.process; - if (!process) { - return promise.resolve(); - } - this.process = null; - return process.kill(); - }, - - get id() { - return this.addon.id; - }, - - get name() { - return this.addon.name.replace(" Simulator", ""); - }, - - get version() { - return this.name.match(/\d+\.\d+/)[0]; - }, -}; diff --git a/browser/devtools/webide/moz.build b/browser/devtools/webide/moz.build index 20a072793a96..e9804d09ca60 100644 --- a/browser/devtools/webide/moz.build +++ b/browser/devtools/webide/moz.build @@ -20,8 +20,6 @@ EXTRA_JS_MODULES.devtools.webide += [ 'modules/config-view.js', 'modules/remote-resources.js', 'modules/runtimes.js', - 'modules/simulator-process.js', - 'modules/simulators.js', 'modules/tab-store.js', 'modules/utils.js' ] diff --git a/browser/devtools/webide/webide-prefs.js b/browser/devtools/webide/webide-prefs.js index 6e21bec8b141..73a674449e90 100644 --- a/browser/devtools/webide/webide-prefs.js +++ b/browser/devtools/webide/webide-prefs.js @@ -13,7 +13,6 @@ pref("devtools.webide.enableLocalRuntime", false); pref("devtools.webide.addonsURL", "https://ftp.mozilla.org/pub/mozilla.org/labs/fxos-simulator/index.json"); pref("devtools.webide.simulatorAddonsURL", "https://ftp.mozilla.org/pub/mozilla.org/labs/fxos-simulator/#VERSION#/#OS#/fxos_#SLASHED_VERSION#_simulator-#OS#-latest.xpi"); pref("devtools.webide.simulatorAddonID", "fxos_#SLASHED_VERSION#_simulator@mozilla.org"); -pref("devtools.webide.simulatorAddonRegExp", "fxos_(.*)_simulator@mozilla\.org$"); pref("devtools.webide.adbAddonURL", "https://ftp.mozilla.org/pub/mozilla.org/labs/fxos-simulator/adb-helper/#OS#/adbhelper-#OS#-latest.xpi"); pref("devtools.webide.adbAddonID", "adbhelper@mozilla.org"); pref("devtools.webide.adaptersAddonURL", "https://ftp.mozilla.org/pub/mozilla.org/labs/fxdt-adapters/#OS#/fxdt-adapters-#OS#-latest.xpi"); @@ -21,7 +20,6 @@ pref("devtools.webide.adaptersAddonID", "fxdevtools-adapters@mozilla.org"); pref("devtools.webide.monitorWebSocketURL", "ws://localhost:9000"); pref("devtools.webide.lastConnectedRuntime", ""); pref("devtools.webide.lastSelectedProject", ""); -pref("devtools.webide.logSimulatorOutput", false); pref("devtools.webide.widget.autoinstall", true); #ifdef MOZ_DEV_EDITION pref("devtools.webide.widget.enabled", true);