diff options
Diffstat (limited to 'testing/marionette/server.js')
-rw-r--r-- | testing/marionette/server.js | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/testing/marionette/server.js b/testing/marionette/server.js new file mode 100644 index 000000000..0d8a7bf23 --- /dev/null +++ b/testing/marionette/server.js @@ -0,0 +1,144 @@ +/* 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"; + +var {Constructor: CC, classes: Cc, interfaces: Ci, utils: Cu} = Components; + +var loader = Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader); +const ServerSocket = CC("@mozilla.org/network/server-socket;1", "nsIServerSocket", "initSpecialConnection"); + +Cu.import("resource://gre/modules/Log.jsm"); +Cu.import("resource://gre/modules/Preferences.jsm"); +Cu.import("resource://gre/modules/Services.jsm"); + +Cu.import("chrome://marionette/content/dispatcher.js"); +Cu.import("chrome://marionette/content/driver.js"); +Cu.import("chrome://marionette/content/element.js"); +Cu.import("chrome://marionette/content/simpletest.js"); + +// Bug 1083711: Load transport.js as an SDK module instead of subscript +loader.loadSubScript("resource://devtools/shared/transport/transport.js"); + +const logger = Log.repository.getLogger("Marionette"); + +this.EXPORTED_SYMBOLS = ["MarionetteServer"]; + +const CONTENT_LISTENER_PREF = "marionette.contentListener"; +const MANAGE_OFFLINE_STATUS_PREF = "network.gonk.manage-offline-status"; + +/** + * Bootstraps Marionette and handles incoming client connections. + * + * Once started, it opens a TCP socket sporting the debugger transport + * protocol on the provided port. For every new client a Dispatcher is + * created. + * + * @param {number} port + * Port for server to listen to. + * @param {boolean} forceLocal + * Listen only to connections from loopback if true. If false, + * accept all connections. + */ +this.MarionetteServer = function (port, forceLocal) { + this.port = port; + this.forceLocal = forceLocal; + this.conns = {}; + this.nextConnId = 0; + this.alive = false; + this._acceptConnections = false; +}; + +/** + * Function produces a GeckoDriver. + * + * Determines application nameto initialise the driver with. + * + * @return {GeckoDriver} + * A driver instance. + */ +MarionetteServer.prototype.driverFactory = function() { + let appName = isMulet() ? "B2G" : Services.appinfo.name; + let bypassOffline = false; + + Preferences.set(CONTENT_LISTENER_PREF, false); + + if (bypassOffline) { + logger.debug("Bypassing offline status"); + Preferences.set(MANAGE_OFFLINE_STATUS_PREF, false); + Services.io.manageOfflineStatus = false; + Services.io.offline = false; + } + + return new GeckoDriver(appName, this); +}; + +MarionetteServer.prototype.__defineSetter__("acceptConnections", function (value) { + if (!value) { + logger.info("New connections will no longer be accepted"); + } else { + logger.info("New connections are accepted again"); + } + + this._acceptConnections = value; +}); + +MarionetteServer.prototype.start = function() { + if (this.alive) { + return; + } + let flags = Ci.nsIServerSocket.KeepWhenOffline; + if (this.forceLocal) { + flags |= Ci.nsIServerSocket.LoopbackOnly; + } + this.listener = new ServerSocket(this.port, flags, 1); + this.listener.asyncListen(this); + this.alive = true; + this._acceptConnections = true; +}; + +MarionetteServer.prototype.stop = function() { + if (!this.alive) { + return; + } + this.closeListener(); + this.alive = false; + this._acceptConnections = false; +}; + +MarionetteServer.prototype.closeListener = function() { + this.listener.close(); + this.listener = null; +}; + +MarionetteServer.prototype.onSocketAccepted = function ( + serverSocket, clientSocket) { + if (!this._acceptConnections) { + logger.warn("New connections are currently not accepted"); + return; + } + + let input = clientSocket.openInputStream(0, 0, 0); + let output = clientSocket.openOutputStream(0, 0, 0); + let transport = new DebuggerTransport(input, output); + let connId = "conn" + this.nextConnId++; + + let dispatcher = new Dispatcher(connId, transport, this.driverFactory.bind(this)); + dispatcher.onclose = this.onConnectionClosed.bind(this); + this.conns[connId] = dispatcher; + + logger.debug(`Accepted connection ${connId} from ${clientSocket.host}:${clientSocket.port}`); + dispatcher.sayHello(); + transport.ready(); +}; + +MarionetteServer.prototype.onConnectionClosed = function (conn) { + let id = conn.connId; + delete this.conns[id]; + logger.debug(`Closed connection ${id}`); +}; + +function isMulet() { + return Preferences.get("b2g.is_mulet", false); +} |