author | Andreas Tolfsen <ato@sny.no> |
Sat, 30 Sep 2017 18:10:39 +0100 | |
changeset 385910 | 2fe618b2b66030c44ce1e69eb2b84dc36e5211fb |
parent 385909 | df3e0cc4a9bfc95f84d241eb3b2cef9da332de87 |
child 385911 | f5c5cc198dda34bac914eeb0fbe175caaf07a50a |
push id | 32672 |
push user | archaeopteryx@coole-files.de |
push date | Fri, 13 Oct 2017 09:00:05 +0000 |
treeherder | mozilla-central@3efcb26e5f37 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | whimboo |
bugs | 1403577 |
milestone | 58.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/testing/marionette/message.js +++ b/testing/marionette/message.js @@ -3,81 +3,92 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ "use strict"; const {utils: Cu} = Components; Cu.import("chrome://marionette/content/assert.js"); Cu.import("chrome://marionette/content/error.js"); +const {truncate} = Cu.import("chrome://marionette/content/format.js", {}); this.EXPORTED_SYMBOLS = [ "Command", "Message", "MessageOrigin", "Response", ]; +/** Representation of the packets transproted over the wire. */ +class Message { + /** + * @param {number} messageID + * Message ID unique identifying this message. + */ + constructor(messageID) { + this.id = assert.integer(messageID); + } + + toString() { + return truncate`${this.toPacket()}`; + } + + /** + * Converts a data packet into a {@link Command} or {@link Response}. + * + * @param {Array.<number, number, ?, ?>} data + * A four element array where the elements, in sequence, signifies + * message type, message ID, method name or error, and parameters + * or result. + * + * @return {Message} + * Based on the message type, a {@link Command} or {@link Response} + * instance. + * + * @throws {TypeError} + * If the message type is not recognised. + */ + static fromPacket(data) { + const [type] = data; + + switch (type) { + case Command.TYPE: + return Command.fromPacket(data); + + case Response.TYPE: + return Response.fromPacket(data); + + default: + throw new TypeError( + "Unrecognised message type in packet: " + JSON.stringify(data)); + } + } +} + /** * Messages may originate from either the server or the client. * Because the remote protocol is full duplex, both endpoints may be the * origin of both commands and responses. * * @enum * @see {@link Message} */ const MessageOrigin = { /** Indicates that the message originates from the client. */ Client: 0, /** Indicates that the message originates from the server. */ Server: 1, }; /** - * Representation of the packets transproted over the wire. - * - * @class - */ -this.Message = {}; - -/** - * Converts a data packet into a Command or Response type. - * - * @param {Array.<number, number, ?, ?>} data - * A four element array where the elements, in sequence, signifies - * message type, message ID, method name or error, and parameters - * or result. - * - * @return {Message} - * Based on the message type, a {@link Command} or {@link Response} - * instance. - * - * @throws {TypeError} - * If the message type is not recognised. - */ -Message.fromMsg = function(data) { - switch (data[0]) { - case Command.TYPE: - return Command.fromMsg(data); - - case Response.TYPE: - return Response.fromMsg(data); - - default: - throw new TypeError( - "Unrecognised message type in packet: " + JSON.stringify(data)); - } -}; - -/** * A command is a request from the client to run a series of remote end * steps and return a fitting response. * * The command can be synthesised from the message passed over the - * Marionette socket using the {@code fromMsg} function. The format of + * Marionette socket using the {@link fromPacket} function. The format of * a message is: * * [type, id, name, params] * * where * * type (integer) * Must be zero (integer). Zero means that this message is a command. @@ -97,26 +108,27 @@ Message.fromMsg = function(data) { * A command has an associated message {@code id} that prevents the * dispatcher from sending responses in the wrong order. * * The command may also have optional error- and result handlers that * are called when the client returns with a response. These are * {@code function onerror({Object})}, {@code function onresult({Object})}, * and {@code function onresult({Response})}. * - * @param {number} msgId + * @param {number} messageID * Message ID unique identifying this message. * @param {string} name * Command name. * @param {Object.<string, ?>} params * Command parameters. */ -class Command { - constructor(msgID, name, params = {}) { - this.id = assert.integer(msgID); +class Command extends Message { + constructor(messageID, name, params = {}) { + super(messageID); + this.name = assert.string(name); this.parameters = assert.object(params); this.onerror = null; this.onresult = null; this.origin = MessageOrigin.Client; this.sent = false; @@ -133,39 +145,56 @@ class Command { onresponse(resp) { if (this.onerror && resp.error) { this.onerror(resp.error); } else if (this.onresult && resp.body) { this.onresult(resp.body); } } - toMsg() { - return [Command.TYPE, this.id, this.name, this.parameters]; + /** + * Encodes the command to a packet. + * + * @return {Array} + * Packet. + */ + toPacket() { + return [ + Command.TYPE, + this.id, + this.name, + this.parameters, + ]; } - toString() { - return "Command {id: " + this.id + ", " + - "name: " + JSON.stringify(this.name) + ", " + - "parameters: " + JSON.stringify(this.parameters) + "}"; - } - - static fromMsg(msg) { - let [type, msgID, name, params] = msg; + /** + * Converts a data packet into {@link Command}. + * + * @param {Array.<number, number, ?, ?>} data + * A four element array where the elements, in sequence, signifies + * message type, message ID, command name, and parameters. + * + * @return {Command} + * Representation of packet. + * + * @throws {TypeError} + * If the message type is not recognised. + */ + static fromPacket(payload) { + let [type, msgID, name, params] = payload; assert.that(n => n === Command.TYPE)(type); // if parameters are given but null, treat them as undefined if (params === null) { params = undefined; } return new Command(msgID, name, params); } } - Command.TYPE = 0; const validator = { exclusionary: { "capabilities": ["error", "value"], "error": ["value", "sessionId", "capabilities"], "sessionId": ["error", "value"], "value": ["error", "sessionId", "capabilities"], @@ -215,25 +244,26 @@ const ResponseBody = () => new Proxy({}, * modification through the available setters. To send data in a response, * you modify the body property on the response. The body property can * also be replaced completely. * * The response is sent implicitly by CommandProcessor when a command * has finished executing, and any modifications made subsequent to that * will have no effect. * - * @param {number} msgID - * Message ID tied to the corresponding command request this is a - * response for. + * @param {number} messageID + * Message ID tied to the corresponding command request this is + * a response for. * @param {ResponseHandler} respHandler * Function callback called on sending the response. */ -class Response { - constructor(msgID, respHandler = () => {}) { - this.id = assert.integer(msgID); +class Response extends Message { + constructor(messageID, respHandler = () => {}) { + super(messageID); + this.respHandler_ = assert.callable(respHandler); this.error = null; this.body = ResponseBody(); this.origin = MessageOrigin.Server; this.sent = false; } @@ -284,31 +314,52 @@ class Response { this.send(); // propagate errors which are implementation problems if (!error.isWebDriverError(err)) { throw err; } } - toMsg() { - return [Response.TYPE, this.id, this.error, this.body]; + /** + * Encodes the response to a packet. + * + * @return {Array} + * Packet. + */ + toPacket() { + return [ + Response.TYPE, + this.id, + this.error, + this.body, + ]; } - toString() { - return "Response {id: " + this.id + ", " + - "error: " + JSON.stringify(this.error) + ", " + - "body: " + JSON.stringify(this.body) + "}"; - } - - static fromMsg(msg) { - let [type, msgID, err, body] = msg; + /** + * Converts a data packet into {@link Response}. + * + * @param {Array.<number, number, ?, ?>} data + * A four element array where the elements, in sequence, signifies + * message type, message ID, error, and result. + * + * @return {Response} + * Representation of packet. + * + * @throws {TypeError} + * If the message type is not recognised. + */ + static fromPacket(payload) { + let [type, msgID, err, body] = payload; assert.that(n => n === Response.TYPE)(type); let resp = new Response(msgID); resp.error = assert.string(err); resp.body = body; return resp; } } +Response.TYPE = 1; -Response.TYPE = 1; +this.Message = Message; +this.Command = Command; +this.Response = Response;
--- a/testing/marionette/server.js +++ b/testing/marionette/server.js @@ -484,17 +484,17 @@ server.TCPConnection = class { "Unable to unmarshal packet data: " + JSON.stringify(data)); error.report(e); return; } // return immediately with any error trying to unmarshal message let msg; try { - msg = Message.fromMsg(data); + msg = Message.fromPacket(data); msg.origin = MessageOrigin.Client; this.log_(msg); } catch (e) { let resp = this.createResponse(data[1]); resp.sendError(e); return; } @@ -644,17 +644,17 @@ server.TCPConnection = class { /** * Marshal message to the Marionette message format and send it. * * @param {Message} msg * The message to send. */ sendMessage(msg) { this.log_(msg); - let payload = msg.toMsg(); + let payload = msg.toPacket(); this.sendRaw(payload); } /** * Send the given payload over the debugger transport socket to the * connected client. * * @param {Object.<string, ?>} payload
--- a/testing/marionette/test_message.js +++ b/testing/marionette/test_message.js @@ -9,24 +9,24 @@ Cu.import("chrome://marionette/content/m add_test(function test_MessageOrigin() { equal(0, MessageOrigin.Client); equal(1, MessageOrigin.Server); run_next_test(); }); -add_test(function test_Message_fromMsg() { +add_test(function test_Message_fromPacket() { let cmd = new Command(4, "foo"); let resp = new Response(5, () => {}); resp.error = "foo"; - ok(Message.fromMsg(cmd.toMsg()) instanceof Command); - ok(Message.fromMsg(resp.toMsg()) instanceof Response); - Assert.throws(() => Message.fromMsg([3, 4, 5, 6]), + ok(Message.fromPacket(cmd.toPacket()) instanceof Command); + ok(Message.fromPacket(resp.toPacket()) instanceof Response); + Assert.throws(() => Message.fromPacket([3, 4, 5, 6]), /Unrecognised message type in packet/); run_next_test(); }); add_test(function test_Command() { let cmd = new Command(42, "foo", {bar: "baz"}); equal(42, cmd.id); @@ -61,53 +61,50 @@ add_test(function test_Command_onrespons cmd.onresponse(bodyResp); equal(true, onresultOk); run_next_test(); }); add_test(function test_Command_ctor() { let cmd = new Command(42, "bar", {bar: "baz"}); - let msg = cmd.toMsg(); + let msg = cmd.toPacket(); equal(Command.TYPE, msg[0]); equal(cmd.id, msg[1]); equal(cmd.name, msg[2]); equal(cmd.parameters, msg[3]); run_next_test(); }); add_test(function test_Command_toString() { let cmd = new Command(42, "foo", {bar: "baz"}); - equal(`Command {id: ${cmd.id}, ` + - `name: ${JSON.stringify(cmd.name)}, ` + - `parameters: ${JSON.stringify(cmd.parameters)}}`, - cmd.toString()); + equal(JSON.stringify(cmd.toPacket()), cmd.toString()); run_next_test(); }); -add_test(function test_Command_fromMsg() { +add_test(function test_Command_fromPacket() { let c1 = new Command(42, "foo", {bar: "baz"}); - let msg = c1.toMsg(); - let c2 = Command.fromMsg(msg); + let msg = c1.toPacket(); + let c2 = Command.fromPacket(msg); equal(c1.id, c2.id); equal(c1.name, c2.name); equal(c1.parameters, c2.parameters); - Assert.throws(() => Command.fromMsg([null, 2, "foo", {}])); - Assert.throws(() => Command.fromMsg([1, 2, "foo", {}])); - Assert.throws(() => Command.fromMsg([0, null, "foo", {}])); - Assert.throws(() => Command.fromMsg([0, 2, null, {}])); - Assert.throws(() => Command.fromMsg([0, 2, "foo", false])); + Assert.throws(() => Command.fromPacket([null, 2, "foo", {}])); + Assert.throws(() => Command.fromPacket([1, 2, "foo", {}])); + Assert.throws(() => Command.fromPacket([0, null, "foo", {}])); + Assert.throws(() => Command.fromPacket([0, 2, null, {}])); + Assert.throws(() => Command.fromPacket([0, 2, "foo", false])); - let nullParams = Command.fromMsg([0, 2, "foo", null]); + let nullParams = Command.fromPacket([0, 2, "foo", null]); equal("[object Object]", Object.prototype.toString.call(nullParams.parameters)); run_next_test(); }); add_test(function test_Command_TYPE() { equal(0, Command.TYPE); run_next_test(); @@ -194,58 +191,55 @@ add_test(function test_Response_sendErro // they should also throw after being sent Assert.throws(() => resp.sendError(err), /foo/); equal(true, resp.sent); run_next_test(); }); -add_test(function test_Response_toMsg() { +add_test(function test_Response_toPacket() { let resp = new Response(42, () => {}); - let msg = resp.toMsg(); + let msg = resp.toPacket(); equal(Response.TYPE, msg[0]); equal(resp.id, msg[1]); equal(resp.error, msg[2]); equal(resp.body, msg[3]); run_next_test(); }); add_test(function test_Response_toString() { let resp = new Response(42, () => {}); resp.error = "foo"; resp.body = "bar"; - equal(`Response {id: ${resp.id}, ` + - `error: ${JSON.stringify(resp.error)}, ` + - `body: ${JSON.stringify(resp.body)}}`, - resp.toString()); + equal(JSON.stringify(resp.toPacket()), resp.toString()); run_next_test(); }); -add_test(function test_Response_fromMsg() { +add_test(function test_Response_fromPacket() { let r1 = new Response(42, () => {}); r1.error = "foo"; r1.body = "bar"; - let msg = r1.toMsg(); - let r2 = Response.fromMsg(msg); + let msg = r1.toPacket(); + let r2 = Response.fromPacket(msg); equal(r1.id, r2.id); equal(r1.error, r2.error); equal(r1.body, r2.body); - Assert.throws(() => Response.fromMsg([null, 2, "foo", {}])); - Assert.throws(() => Response.fromMsg([0, 2, "foo", {}])); - Assert.throws(() => Response.fromMsg([1, null, "foo", {}])); - Assert.throws(() => Response.fromMsg([1, 2, null, {}])); - Response.fromMsg([1, 2, "foo", null]); + Assert.throws(() => Response.fromPacket([null, 2, "foo", {}])); + Assert.throws(() => Response.fromPacket([0, 2, "foo", {}])); + Assert.throws(() => Response.fromPacket([1, null, "foo", {}])); + Assert.throws(() => Response.fromPacket([1, 2, null, {}])); + Response.fromPacket([1, 2, "foo", null]); run_next_test(); }); add_test(function test_Response_TYPE() { equal(1, Response.TYPE); run_next_test(); });