From a237cd8ce1fe5b8ac815a5d419155561ea84f21a Mon Sep 17 00:00:00 2001 From: Vicamo Yang Date: Mon, 23 Jul 2012 10:20:34 +0800 Subject: [PATCH] Bug 775038 - Part 1: fix various minor defects, r=philikon * Document Address.decode() * Merge CharsetEncodedString into EncodedStringValue * Merge ClassIdentifier into MessageClassValue * Export missed coder objects and fix test scripts as well * ReplyChargingValue is defined in MmsPduHelper, not WspPduHelper * Fix multiple decode test cases data * Char-set value in EncodedStringValue should be decoded as IntegerValue * Don't insert per PDU typeinfo into decoded MMS message object * "Date" is also a mandatory field for M-Retrieve.req PDU. --- dom/mms/src/ril/MmsPduHelper.jsm | 130 +++++++++++++---------- dom/mms/src/ril/WspPduHelper.jsm | 4 +- dom/mms/tests/header_helpers.js | 2 +- dom/mms/tests/test_mms_pdu_helper.js | 66 +++++------- dom/mms/tests/test_wsp_pdu_helper.js | 151 +++++++++------------------ 5 files changed, 154 insertions(+), 199 deletions(-) diff --git a/dom/mms/src/ril/MmsPduHelper.jsm b/dom/mms/src/ril/MmsPduHelper.jsm index 6f173431146f..ccd80fd9272d 100644 --- a/dom/mms/src/ril/MmsPduHelper.jsm +++ b/dom/mms/src/ril/MmsPduHelper.jsm @@ -70,7 +70,13 @@ let BooleanValue = { * @see OMA-TS-MMS_ENC-V1_3-20110913-A section 8 */ let Address = { - decode: function (data) { + /** + * @param data + * A wrapped object to store encoded raw data. + * + * @return An object of two string-typed attributes: address and type. + */ + decode: function decode(data) { let str = EncodedStringValue.decode(data); let result; @@ -398,30 +404,15 @@ let Parameter = { }; /** - * Encoded-string-value = Text-string | Value-length Char-set Text-string - * The Char-set values are registered by IANA as MIBEnum value. + * The Char-set values are registered by IANA as MIBEnum value and SHALL be + * encoded as Integer-value. + * + * Encoded-string-value = Text-string | Value-length Char-set Text-string * * @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.19 + * @see OMA-TS-MMS_CONF-V1_3-20110913-A clause 10.2.1 */ let EncodedStringValue = { - /** - * @param data - * A wrapped object containing raw PDU data. - * - * @return Decoded string. - */ - decode: function decode(data) { - return WSP.decodeAlternatives(data, null, - WSP.TextString, CharsetEncodedString); - }, -}; - -/** - * Charset-encoded-string = Value-length Char-set Text-string - * - * @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.19 - */ -let CharsetEncodedString = { /** * @param data * A wrapped object containing raw PDU data. @@ -432,11 +423,11 @@ let CharsetEncodedString = { * @throws NotWellKnownEncodingError if decoded well-known charset number is * not registered or supported. */ - decode: function decode(data) { + decodeCharsetEncodedString: function decodeCharsetEncodedString(data) { let length = WSP.ValueLength.decode(data); let end = data.offset + length; - let charset = WSP.ShortInteger.decode(data); + let charset = WSP.IntegerValue.decode(data); let entry = WSP.WSP_WELL_KNOWN_CHARSETS[charset]; if (!entry) { throw new WSP.NotWellKnownEncodingError( @@ -477,11 +468,27 @@ let CharsetEncodedString = { return str; }, + + /** + * @param data + * A wrapped object containing raw PDU data. + * + * @return Decoded string. + */ + decode: function decode(data) { + let begin = data.offset; + try { + return WSP.TextString.decode(data); + } catch (e) { + data.offset = begin; + return this.decodeCharsetEncodedString(data); + } + }, }; /** * Expiry-value = Value-length (Absolute-token Date-value | Relative-token Delta-seconds-value) - * Address-token = + * Absolute-token = * Relative-token = * * @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.20 @@ -531,7 +538,8 @@ let FromValue = { * @param data * A wrapped object containing raw PDU data. * - * @return Decoded string or null for MMS Proxy-Relay Insert-Address mode. + * @return A decoded Address-value or null for MMS Proxy-Relay Insert-Address + * mode. * * @throws CodeError if decoded token equals to neither 128 nor 129. */ @@ -619,32 +627,15 @@ let PreviouslySentDateValue = { /** * Message-class-value = Class-identifier | Token-text + * Class-identifier = Personal | Advertisement | Informational | Auto + * Personal = + * Advertisement = + * Informational = + * Auto = * * @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.27 */ let MessageClassValue = { - /** - * @param data - * A wrapped object containing raw PDU data. - * - * @return A decoded string. - */ - decode: function decode(data) { - return WSP.decodeAlternatives(data, null, - ClassIdentifier, WSP.TokenText); - }, -}; - -/** - * Class-identifier = Personal | Advertisement | Informational | Auto - * Personal = - * Advertisement = - * Informational = - * Auto = - * - * @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.27 - */ -let ClassIdentifier = { /** * @param data * A wrapped object containing raw PDU data. @@ -653,7 +644,7 @@ let ClassIdentifier = { * * @throws CodeError if decoded value is not in the range 128..131. */ - decode: function decode(data) { + decodeClassIdentifier: function decodeClassIdentifier(data) { let value = WSP.Octet.decode(data); switch (value) { case 128: return "personal"; @@ -664,6 +655,22 @@ let ClassIdentifier = { throw new WSP.CodeError("Class-identifier: invalid id " + value); }, + + /** + * @param data + * A wrapped object containing raw PDU data. + * + * @return A decoded string. + */ + decode: function decode(data) { + let begin = data.offset; + try { + return this.decodeClassIdentifier(data); + } catch (e) { + data.offset = begin; + return WSP.TokenText.decode(data); + } + }, }; /** @@ -720,7 +727,7 @@ let MmFlagsValue = { * A wrapped object containing raw PDU data. * * @return Decoded object containing an integer `type` and an string-typed - * `address` attributes. + * `text` attributes. * * @throws CodeError if decoded value is not in the range 128..130. */ @@ -1020,11 +1027,13 @@ let PduHelper = { /** * Check existences of all mandatory fields of a MMS message. Also sets `type` - * and `typeinfo` for convient access. + * for convenient access. * * @param msg * A MMS message object. * + * @return The corresponding entry in MMS_PDU_TYPES; + * * @throws FatalCodeError if the PDU type is not supported yet. */ checkMandatoryFields: function checkMandatoryFields(msg) { @@ -1039,9 +1048,10 @@ let PduHelper = { WSP.ensureHeader(msg.headers, name); }); - // Setup convient alias that referenced frequently. + // Setup convenient alias that referenced frequently. msg.type = type; - msg.typeinfo = entry; + + return entry; }, /** @@ -1061,9 +1071,8 @@ let PduHelper = { msg.headers = this.parseHeaders(data, msg.headers); // Validity checks - this.checkMandatoryFields(msg); - - if (msg.typeinfo.hasContent) { + let typeinfo = this.checkMandatoryFields(msg); + if (typeinfo.hasContent) { this.parseContent(data, msg); } } catch (e) { @@ -1161,7 +1170,7 @@ let PduHelper = { try { // Validity checks - this.checkMandatoryFields(msg); + let typeinfo = this.checkMandatoryFields(msg); let data = this.encodeHeaders(null, msg.headers); debug("Composed PDU Header: " + JSON.stringify(data.array)); @@ -1195,6 +1204,7 @@ const MMS_PDU_TYPES = (function () { "x-mms-content-location"]); add(MMS_PDU_TYPE_RETRIEVE_CONF, true, ["x-mms-message-type", "x-mms-mms-version", + "date", "content-type"]); add(MMS_PDU_TYPE_NOTIFYRESP_IND, false, ["x-mms-message-type", "x-mms-transaction-id", @@ -1247,7 +1257,7 @@ const MMS_HEADER_FIELDS = (function () { add("x-mms-retrieve-status", 0x19, RetrieveStatusValue); add("x-mms-retrieve-text", 0x1A, EncodedStringValue); //add("x-mms-read-status", 0x1B); - add("x-mms-reply-charging", 0x1C, WSP.ReplyChargingValue); + add("x-mms-reply-charging", 0x1C, ReplyChargingValue); add("x-mms-reply-charging-deadline", 0x1D, ExpiryValue); add("x-mms-reply-charging-id", 0x1E, WSP.TextString); add("x-mms-reply-charging-size", 0x1F, WSP.LongInteger); @@ -1330,12 +1340,16 @@ const EXPORTED_SYMBOLS = ALL_CONST_SYMBOLS.concat([ "EncodedStringValue", "ExpiryValue", "FromValue", + "PreviouslySentByValue", + "PreviouslySentDateValue", "MessageClassValue", - "ClassIdentifier", "MessageTypeValue", + "MmFlagsValue", + "MmStateValue", "PriorityValue", "RecommendedRetrievalModeValue", "ReplyChargingValue", + "RetrieveStatusValue", "StatusValue", // Parser diff --git a/dom/mms/src/ril/WspPduHelper.jsm b/dom/mms/src/ril/WspPduHelper.jsm index e0662fe23ee2..9cc7824ca5d8 100644 --- a/dom/mms/src/ril/WspPduHelper.jsm +++ b/dom/mms/src/ril/WspPduHelper.jsm @@ -487,7 +487,7 @@ let Token = { // Fallback to throw CodeError } else { Octet.encode(data, token.charCodeAt(0)); - return; + return; } } @@ -697,7 +697,7 @@ let ShortInteger = { * @throws CodeError if the octet read is larger-equal than 0x80. */ encode: function encode(data, value) { - if (value & 0x80) { + if (value >= 0x80) { throw new CodeError("Short-integer: invalid value " + value); } diff --git a/dom/mms/tests/header_helpers.js b/dom/mms/tests/header_helpers.js index f579cd3e19c4..6554e2f11c36 100644 --- a/dom/mms/tests/header_helpers.js +++ b/dom/mms/tests/header_helpers.js @@ -54,7 +54,7 @@ function wsp_test_func(func, data, expect) { let result_str = JSON.stringify(func(data)); let expect_str = JSON.stringify(expect); if (result_str !== expect_str) { - do_throw("expect decoded value: '" + expect_str + "', got '" + result_str + "'"); + do_throw("expect value: '" + expect_str + "', got '" + result_str + "'"); } } diff --git a/dom/mms/tests/test_mms_pdu_helper.js b/dom/mms/tests/test_mms_pdu_helper.js index fac746cce96f..f666c121f811 100644 --- a/dom/mms/tests/test_mms_pdu_helper.js +++ b/dom/mms/tests/test_mms_pdu_helper.js @@ -263,19 +263,9 @@ add_test(function test_EncodedStringValue_decode() { .createInstance(Ci.nsIScriptableUnicodeConverter); conv.charset = entry.converter; - let raw; - try { - let raw = conv.convertToByteArray(str).concat([0]); - if (raw[0] >= 128) { - wsp_decode_test(MMS.EncodedStringValue, - [raw.length + 2, 0x80 | entry.number, 127].concat(raw), str); - } else { - wsp_decode_test(MMS.EncodedStringValue, - [raw.length + 1, 0x80 | entry.number].concat(raw), str); - } - } catch (e) { - do_print("Can't convert test string to byte array with " + entry.converter); - } + let raw = conv.convertToByteArray(str).concat([0]); + wsp_decode_test(MMS.EncodedStringValue, + [raw.length + 2, 0x80 | entry.number, 127].concat(raw), str); } run_next_test(); @@ -291,7 +281,7 @@ add_test(function test_ExpiryValue_decode() { // Test for Absolute-token Date-value wsp_decode_test(MMS.ExpiryValue, [3, 128, 1, 0x80], new Date(0x80 * 1000)); // Test for Relative-token Delta-seconds-value - wsp_decode_test(MMS.ExpiryValue, [3, 129, 0x80], 0); + wsp_decode_test(MMS.ExpiryValue, [2, 129, 0x80], 0); run_next_test(); }); @@ -334,7 +324,7 @@ add_test(function test_FromValue_decode() { wsp_decode_test(MMS.FromValue, [1, 129], null); // Test for Address-present-token: let (addr = strToCharCodeArray("+123/TYPE=PLMN")) { - wsp_decode_test(MMS.FromValue, [addr.length + 2, 128].concat(addr), + wsp_decode_test(MMS.FromValue, [addr.length + 1, 128].concat(addr), {address: "+123", type: "PLMN"}); } @@ -345,6 +335,28 @@ add_test(function test_FromValue_decode() { // Test target: MessageClassValue // +//// MessageClassValue.decodeClassIdentifier //// + +add_test(function test_MessageClassValue_decodeClassIdentifier() { + let (IDs = ["personal", "advertisement", "informational", "auto"]) { + for (let i = 0; i < 256; i++) { + if ((i >= 128) && (i <= 131)) { + wsp_decode_test_ex(function (data) { + return MMS.MessageClassValue.decodeClassIdentifier(data); + }, [i], IDs[i - 128] + ); + } else { + wsp_decode_test_ex(function (data) { + return MMS.MessageClassValue.decodeClassIdentifier(data); + }, [i], null, "CodeError" + ); + } + } + } + + run_next_test(); +}); + //// MessageClassValue.decode //// add_test(function test_MessageClassValue_decode() { @@ -354,26 +366,6 @@ add_test(function test_MessageClassValue_decode() { run_next_test(); }); -// -// Test target: ClassIdentifier -// - -//// ClassIdentifier.decode //// - -add_test(function test_ClassIdentifier_decode() { - let (IDs = ["personal", "advertisement", "informational", "auto"]) { - for (let i = 0; i < 256; i++) { - if ((i >= 128) && (i <= 131)) { - wsp_decode_test(MMS.ClassIdentifier, [i], IDs[i - 128]); - } else { - wsp_decode_test(MMS.ClassIdentifier, [i], null, "CodeError"); - } - } - } - - run_next_test(); -}); - // // Test target: MessageTypeValue // @@ -433,9 +425,9 @@ add_test(function test_MmFlagsValue_decode() { add_test(function test_MmStateValue_decode() { for (let i = 0; i < 256; i++) { if ((i >= 128) && (i <= 132)) { - wsp_decode_test(MMS.MmStateValue, [i, 0], i); + wsp_decode_test(MMS.MmStateValue, [i], i); } else { - wsp_decode_test(MMS.MmStateValue, [i, 0], null, "CodeError"); + wsp_decode_test(MMS.MmStateValue, [i], null, "CodeError"); } } diff --git a/dom/mms/tests/test_wsp_pdu_helper.js b/dom/mms/tests/test_wsp_pdu_helper.js index fbc705375a2c..653f06f7936b 100644 --- a/dom/mms/tests/test_wsp_pdu_helper.js +++ b/dom/mms/tests/test_wsp_pdu_helper.js @@ -27,35 +27,21 @@ add_test(function test_ensureHeader() { // add_test(function test_skipValue() { + function func(data) { + return WSP.skipValue(data); + } + // Test for zero-valued first octet: - wsp_decode_test_ex(function (data) { - return WSP.skipValue(data); - }, [0], null - ); + wsp_decode_test_ex(func, [0], null); // Test first octet < 31 - wsp_decode_test_ex(function (data) { - return WSP.skipValue(data); - }, [1, 2], [2] - ); + wsp_decode_test_ex(func, [1, 2], [2]); // Test first octet = 31 - wsp_decode_test_ex(function (data) { - return WSP.skipValue(data); - }, [31, 0], null - ); - wsp_decode_test_ex(function (data) { - return WSP.skipValue(data); - }, [31, 1, 2], [2] - ); + wsp_decode_test_ex(func, [31, 0], null); + wsp_decode_test_ex(func, [31, 1, 2], [2]); // Test first octet <= 127 - wsp_decode_test_ex(function (data) { - return WSP.skipValue(data); - }, strToCharCodeArray("Hello world!"), "Hello world!" - ); + wsp_decode_test_ex(func, strToCharCodeArray("Hello world!"), "Hello world!"); // Test first octet >= 128 - wsp_decode_test_ex(function (data) { - return WSP.skipValue(data); - }, [0x80 | 0x01], 0x01 - ); + wsp_decode_test_ex(func, [0x80 | 0x01], 0x01); run_next_test(); }); @@ -495,7 +481,7 @@ add_test(function test_DateValue_decode() { // // Test target: DeltaSecondsValue // - // DeltaSecondsValue is only an alias of IntegerValue. +// DeltaSecondsValue is only an alias of IntegerValue. // // Test target: QValue @@ -561,41 +547,26 @@ add_test(function test_UriValue_decode() { //// Parameter.decodeTypedParameter //// add_test(function test_Parameter_decodeTypedParameter() { + function func(data) { + return WSP.Parameter.decodeTypedParameter(data); + } + // Test for array-typed return value from IntegerValue - wsp_decode_test_ex(function (data) { - return WSP.Parameter.decodeTypedParameter(data); - }, [7, 0, 0, 0, 0, 0, 0, 0], null, "CodeError" - ); + wsp_decode_test_ex(func, [7, 0, 0, 0, 0, 0, 0, 0], null, "CodeError"); // Test for number-typed return value from IntegerValue - wsp_decode_test_ex(function (data) { - return WSP.Parameter.decodeTypedParameter(data); - }, [1, 0, 0], {name: "q", value: null} - ); + wsp_decode_test_ex(func, [1, 0, 0], {name: "q", value: null}); // Test for NotWellKnownEncodingError - wsp_decode_test_ex(function (data) { - return WSP.Parameter.decodeTypedParameter(data); - }, [1, 0xFF], null, "NotWellKnownEncodingError" - ); + wsp_decode_test_ex(func, [1, 0xFF], null, "NotWellKnownEncodingError"); // Test for parameter specific decoder - wsp_decode_test_ex(function (data) { - return WSP.Parameter.decodeTypedParameter(data); - }, [1, 0, 100], {name: "q", value: 0.99} - ); + wsp_decode_test_ex(func, [1, 0, 100], {name: "q", value: 0.99}); // Test for TextValue - wsp_decode_test_ex(function (data) { - return WSP.Parameter.decodeTypedParameter(data); - }, [1, 0x10, 48, 46, 57, 57, 0], {name: "secure", value: "0.99"} - ); + wsp_decode_test_ex(func, [1, 0x10, 48, 46, 57, 57, 0], + {name: "secure", value: "0.99"}); // Test for TextString - wsp_decode_test_ex(function (data) { - return WSP.Parameter.decodeTypedParameter(data); - }, [1, 0x19, 60, 115, 109, 105, 108, 62, 0], {name: "start", value: ""} - ); + wsp_decode_test_ex(func, [1, 0x19, 60, 115, 109, 105, 108, 62, 0], + {name: "start", value: ""}); // Test for skipValue - wsp_decode_test_ex(function (data) { - return WSP.Parameter.decodeTypedParameter(data); - }, [1, 0x19, 128], null - ); + wsp_decode_test_ex(func, [1, 0x19, 128], null); run_next_test(); }); @@ -603,24 +574,16 @@ add_test(function test_Parameter_decodeTypedParameter() { //// Parameter.decodeUntypedParameter //// add_test(function test_Parameter_decodeUntypedParameter() { - wsp_decode_test_ex(function (data) { - return WSP.Parameter.decodeUntypedParameter(data); - }, [1], null, "CodeError" - ); - wsp_decode_test_ex(function (data) { - return WSP.Parameter.decodeUntypedParameter(data); - }, [65, 0, 0], {name: "a", value: null} - ); + function func (data) { + return WSP.Parameter.decodeUntypedParameter(data); + } + + wsp_decode_test_ex(func, [1], null, "CodeError"); + wsp_decode_test_ex(func, [65, 0, 0], {name: "a", value: null}); // Test for IntegerValue - wsp_decode_test_ex(function (data) { - return WSP.Parameter.decodeUntypedParameter(data); - }, [65, 0, 1, 0], {name: "a", value: 0} - ); + wsp_decode_test_ex(func, [65, 0, 1, 0], {name: "a", value: 0}); // Test for TextValue - wsp_decode_test_ex(function (data) { - return WSP.Parameter.decodeUntypedParameter(data); - }, [65, 0, 66, 0], {name: "a", value: "B"} - ); + wsp_decode_test_ex(func, [65, 0, 66, 0], {name: "a", value: "B"}); run_next_test(); }); @@ -628,14 +591,9 @@ add_test(function test_Parameter_decodeUntypedParameter() { //// Parameter.decode //// add_test(function test_Parameter_decode() { - wsp_decode_test_ex(function (data) { - return WSP.Parameter.decode(data); - }, [1, 0x19, 60, 115, 109, 105, 108, 62, 0], {name: "start", value: ""} - ); - wsp_decode_test_ex(function (data) { - return WSP.Parameter.decode(data); - }, [65, 0, 66, 0], {name: "a", value: "B"} - ); + wsp_decode_test(WSP.Parameter, [1, 0x19, 60, 115, 109, 105, 108, 62, 0], + {name: "start", value: ""}); + wsp_decode_test(WSP.Parameter, [65, 0, 66, 0], {name: "a", value: "B"}); run_next_test(); }); @@ -797,21 +755,17 @@ add_test(function test_WellKnownCharset_decode() { //// ContentTypeValue.decodeConstrainedMedia //// add_test(function test_ContentTypeValue_decodeConstrainedMedia() { + function func(data) { + return WSP.ContentTypeValue.decodeConstrainedMedia(data); + } + // Test for string-typed return value from ConstrainedEncoding - wsp_decode_test_ex(function (data) { - return WSP.ContentTypeValue.decodeConstrainedMedia(data); - }, [65, 0], {media: "a", params: null} - ); + wsp_decode_test_ex(func, [65, 0], {media: "a", params: null}); // Test for number-typed return value from ConstrainedEncoding - wsp_decode_test_ex(function (data) { - return WSP.ContentTypeValue.decodeConstrainedMedia(data); - }, [0x33 | 0x80], {media: "application/vnd.wap.multipart.related", params: null} - ); + wsp_decode_test_ex(func, [0x33 | 0x80], + {media: "application/vnd.wap.multipart.related", params: null}); // Test for NotWellKnownEncodingError - wsp_decode_test_ex(function (data) { - return WSP.ContentTypeValue.decodeConstrainedMedia(data); - }, [0x80], null, "NotWellKnownEncodingError" - ); + wsp_decode_test_ex(func, [0x80], null, "NotWellKnownEncodingError"); run_next_test(); }); @@ -819,20 +773,15 @@ add_test(function test_ContentTypeValue_decodeConstrainedMedia() { //// ContentTypeValue.decodeMedia //// add_test(function test_ContentTypeValue_decodeMedia() { + function func(data) { + return WSP.ContentTypeValue.decodeMedia(data); + } + // Test for NullTerminatedTexts - wsp_decode_test_ex(function (data) { - return WSP.ContentTypeValue.decodeMedia(data); - }, [65, 0], "a" - ); + wsp_decode_test_ex(func, [65, 0], "a"); // Test for IntegerValue - wsp_decode_test_ex(function (data) { - return WSP.ContentTypeValue.decodeMedia(data); - }, [0x3E | 0x80], "application/vnd.wap.mms-message" - ); - wsp_decode_test_ex(function (data) { - return WSP.ContentTypeValue.decodeMedia(data); - }, [0x80], null, "NotWellKnownEncodingError" - ); + wsp_decode_test_ex(func, [0x3E | 0x80], "application/vnd.wap.mms-message"); + wsp_decode_test_ex(func, [0x80], null, "NotWellKnownEncodingError"); run_next_test(); });