--- a/testing/marionette/transport.js
+++ b/testing/marionette/transport.js
@@ -1,35 +1,25 @@
/* 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";
-/* global Pipe, ScriptableInputStream, uneval */
+/* global Pipe, ScriptableInputStream */
const CC = Components.Constructor;
ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.import("resource://gre/modules/EventEmitter.jsm");
const {StreamUtils} =
ChromeUtils.import("chrome://marionette/content/stream-utils.js", {});
const {Packet, JSONPacket, BulkPacket} =
ChromeUtils.import("chrome://marionette/content/packets.js", {});
-const defer = function() {
- let deferred = {
- promise: new Promise((resolve, reject) => {
- deferred.resolve = resolve;
- deferred.reject = reject;
- }),
- };
- return deferred;
-};
-
const executeSoon = function(func) {
Services.tm.dispatchToMainThread(func);
};
const flags = {wantVerbose: false, wantLogging: false};
const dumpv =
flags.wantVerbose ?
@@ -526,401 +516,8 @@ DebuggerTransport.prototype = {
_destroyIncoming() {
if (this._incoming) {
this._incoming.destroy();
}
this._incomingHeader = "";
this._incoming = null;
},
};
-
-/**
- * An adapter that handles data transfers between the debugger client
- * and server when they both run in the same process. It presents the
- * same API as DebuggerTransport, but instead of transmitting serialized
- * messages across a connection it merely calls the packet dispatcher of
- * the other side.
- *
- * @param {LocalDebuggerTransport} other
- * The other endpoint for this debugger connection.
- *
- * @see {DebuggerTransport}
- */
-function LocalDebuggerTransport(other) {
- EventEmitter.decorate(this);
-
- this.other = other;
- this.hooks = null;
-
- // A packet number, shared between this and this.other. This isn't
- // used by the protocol at all, but it makes the packet traces a lot
- // easier to follow.
- this._serial = this.other ? this.other._serial : {count: 0};
- this.close = this.close.bind(this);
-}
-
-LocalDebuggerTransport.prototype = {
- /**
- * Transmit a message by directly calling the onPacket handler of the other
- * endpoint.
- */
- send(packet) {
- this.emit("send", packet);
-
- let serial = this._serial.count++;
- if (flags.wantLogging) {
- // Check 'from' first, as 'echo' packets have both.
- if (packet.from) {
- dumpv("Packet " + serial + " sent from " + uneval(packet.from));
- } else if (packet.to) {
- dumpv("Packet " + serial + " sent to " + uneval(packet.to));
- }
- }
- this._deepFreeze(packet);
- let other = this.other;
- if (other) {
- executeSoon(() => {
- // Avoid the cost of JSON.stringify() when logging is disabled.
- if (flags.wantLogging) {
- dumpv(`Received packet ${serial}: ` +
- JSON.stringify(packet, null, 2));
- }
- if (other.hooks) {
- other.emit("packet", packet);
- other.hooks.onPacket(packet);
- }
- });
- }
- },
-
- /**
- * Send a streaming bulk packet directly to the onBulkPacket handler
- * of the other endpoint.
- *
- * This case is much simpler than the full DebuggerTransport, since
- * there is no primary stream we have to worry about managing while
- * we hand it off to others temporarily. Instead, we can just make a
- * single use pipe and be done with it.
- */
- startBulkSend({actor, type, length}) {
- this.emit("startbulksend", {actor, type, length});
-
- let serial = this._serial.count++;
-
- dumpv("Sent bulk packet " + serial + " for actor " + actor);
- if (!this.other) {
- let error = new Error("startBulkSend: other side of transport missing");
- return Promise.reject(error);
- }
-
- let pipe = new Pipe(true, true, 0, 0, null);
-
- executeSoon(() => {
- dumpv("Received bulk packet " + serial);
- if (!this.other.hooks) {
- return;
- }
-
- // Receiver
- let deferred = defer();
- let packet = {
- actor,
- type,
- length,
- copyTo: (output) => {
- let copying =
- StreamUtils.copyStream(pipe.inputStream, output, length);
- deferred.resolve(copying);
- return copying;
- },
- stream: pipe.inputStream,
- done: deferred,
- };
-
- this.other.emit("bulkpacket", packet);
- this.other.hooks.onBulkPacket(packet);
-
- // Await the result of reading from the stream
- deferred.promise.then(() => pipe.inputStream.close(), this.close);
- });
-
- // Sender
- let sendDeferred = defer();
-
- // The remote transport is not capable of resolving immediately here,
- // so we shouldn't be able to either.
- executeSoon(() => {
- let copyDeferred = defer();
-
- sendDeferred.resolve({
- copyFrom: (input) => {
- let copying =
- StreamUtils.copyStream(input, pipe.outputStream, length);
- copyDeferred.resolve(copying);
- return copying;
- },
- stream: pipe.outputStream,
- done: copyDeferred,
- });
-
- // Await the result of writing to the stream
- copyDeferred.promise.then(() => pipe.outputStream.close(), this.close);
- });
-
- return sendDeferred.promise;
- },
-
- /**
- * Close the transport.
- */
- close() {
- this.emit("close");
-
- if (this.other) {
- // Remove the reference to the other endpoint before calling close(), to
- // avoid infinite recursion.
- let other = this.other;
- this.other = null;
- other.close();
- }
- if (this.hooks) {
- try {
- this.hooks.onClosed();
- } catch (ex) {
- console.error(ex);
- }
- this.hooks = null;
- }
- },
-
- /**
- * An empty method for emulating the DebuggerTransport API.
- */
- ready() {},
-
- /**
- * Helper function that makes an object fully immutable.
- */
- _deepFreeze(object) {
- Object.freeze(object);
- for (let prop in object) {
- // Freeze the properties that are objects, not on the prototype,
- // and not already frozen. Note that this might leave an unfrozen
- // reference somewhere in the object if there is an already frozen
- // object containing an unfrozen object.
- if (object.hasOwnProperty(prop) && typeof object === "object" &&
- !Object.isFrozen(object)) {
- this._deepFreeze(object[prop]);
- }
- }
- },
-};
-
-/**
- * A transport for the debugging protocol that uses nsIMessageManagers to
- * exchange packets with servers running in child processes.
- *
- * In the parent process, <var>mm</var> should be the nsIMessageSender
- * for the child process. In a child process, |mm| should be the child
- * process message manager, which sends packets to the parent.
- *
- * <var>prefix</var> is a string included in the message names, to
- * distinguish multiple servers running in the same child process.
- *
- * This transport exchanges messages named <tt>debug:PREFIX:packet</tt>,
- * where <tt>PREFIX</tt> is <var>prefix</var>, whose data is the protocol
- * packet.
- */
-function ChildDebuggerTransport(mm, prefix) {
- EventEmitter.decorate(this);
-
- this._mm = mm;
- this._messageName = "debug:" + prefix + ":packet";
-}
-
-/*
- * To avoid confusion, we use 'message' to mean something that
- * nsIMessageSender conveys, and 'packet' to mean a remote debugging
- * protocol packet.
- */
-ChildDebuggerTransport.prototype = {
- constructor: ChildDebuggerTransport,
-
- hooks: null,
-
- _addListener() {
- this._mm.addMessageListener(this._messageName, this);
- },
-
- _removeListener() {
- try {
- this._mm.removeMessageListener(this._messageName, this);
- } catch (e) {
- if (e.result != Cr.NS_ERROR_NULL_POINTER) {
- throw e;
- }
- // In some cases, especially when using messageManagers in non-e10s
- // mode, we reach this point with a dead messageManager which only
- // throws errors but does not seem to indicate in any other way that
- // it is dead.
- }
- },
-
- ready() {
- this._addListener();
- },
-
- close() {
- this._removeListener();
- this.emit("close");
- this.hooks.onClosed();
- },
-
- receiveMessage({data}) {
- this.emit("packet", data);
- this.hooks.onPacket(data);
- },
-
- send(packet) {
- this.emit("send", packet);
- try {
- this._mm.sendAsyncMessage(this._messageName, packet);
- } catch (e) {
- if (e.result != Cr.NS_ERROR_NULL_POINTER) {
- throw e;
- }
- // In some cases, especially when using messageManagers in non-e10s
- // mode, we reach this point with a dead messageManager which only
- // throws errors but does not seem to indicate in any other way that
- // it is dead.
- }
- },
-
- startBulkSend() {
- throw new Error("Can't send bulk data to child processes.");
- },
-
- swapBrowser(mm) {
- this._removeListener();
- this._mm = mm;
- this._addListener();
- },
-};
-
-// WorkerDebuggerTransport is defined differently depending on whether we are
-// on the main thread or a worker thread. In the former case, we are required
-// by the devtools loader, and isWorker will be false. Otherwise, we are
-// required by the worker loader, and isWorker will be true.
-//
-// Each worker debugger supports only a single connection to the main thread.
-// However, its theoretically possible for multiple servers to connect to the
-// same worker. Consequently, each transport has a connection id, to allow
-// messages from multiple connections to be multiplexed on a single channel.
-
-if (!this.isWorker) {
- // Main thread
- (function() {
- /**
- * A transport that uses a WorkerDebugger to send packets from the main
- * thread to a worker thread.
- *
- * @class WorkerDebuggerTransport
- */
- function WorkerDebuggerTransport(dbg, id) {
- this._dbg = dbg;
- this._id = id;
- this.onMessage = this._onMessage.bind(this);
- }
-
- WorkerDebuggerTransport.prototype = {
- constructor: WorkerDebuggerTransport,
-
- ready() {
- this._dbg.addListener(this);
- },
-
- close() {
- this._dbg.removeListener(this);
- if (this.hooks) {
- this.hooks.onClosed();
- }
- },
-
- send(packet) {
- this._dbg.postMessage(JSON.stringify({
- type: "message",
- id: this._id,
- message: packet,
- }));
- },
-
- startBulkSend() {
- throw new Error("Can't send bulk data from worker threads!");
- },
-
- _onMessage(message) {
- let packet = JSON.parse(message);
- if (packet.type !== "message" || packet.id !== this._id) {
- return;
- }
-
- if (this.hooks) {
- this.hooks.onPacket(packet.message);
- }
- },
- };
-
- }).call(this);
-} else {
- // Worker thread
- (function() {
- /**
- * A transport that uses a WorkerDebuggerGlobalScope to send packets
- * from a worker thread to the main thread.
- *
- * @class WorkerDebuggerTransportThread
- */
- function WorkerDebuggerTransport(scope, id) {
- this._scope = scope;
- this._id = id;
- this._onMessage = this._onMessage.bind(this);
- }
-
- WorkerDebuggerTransport.prototype = {
- constructor: WorkerDebuggerTransport,
-
- ready() {
- this._scope.addEventListener("message", this._onMessage);
- },
-
- close() {
- this._scope.removeEventListener("message", this._onMessage);
- if (this.hooks) {
- this.hooks.onClosed();
- }
- },
-
- send(packet) {
- this._scope.postMessage(JSON.stringify({
- type: "message",
- id: this._id,
- message: packet,
- }));
- },
-
- startBulkSend() {
- throw new Error("Can't send bulk data from worker threads!");
- },
-
- _onMessage(event) {
- let packet = JSON.parse(event.data);
- if (packet.type !== "message" || packet.id !== this._id) {
- return;
- }
-
- if (this.hooks) {
- this.hooks.onPacket(packet.message);
- }
- },
- };
-
- }).call(this);
-}