Bug 897368 - 0001. Handle code page switch token. r=vicamo
authorChuck Lee <chulee@mozilla.com>
Mon, 29 Jul 2013 15:08:37 +0800
changeset 152802 ead27e7569fe559182e2620cf24f75a234e596ad
parent 152801 9262cbb74ed5b12b521b286f222cf42a699efdad
child 152803 f63c9bd75e3f626bb0617904d5fc64fd0d35a531
push id2859
push userakeybl@mozilla.com
push dateMon, 16 Sep 2013 19:14:59 +0000
treeherdermozilla-beta@87d3c51cd2bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersvicamo
bugs897368
milestone25.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
Bug 897368 - 0001. Handle code page switch token. r=vicamo
dom/wappush/src/gonk/WapPushManager.js
dom/wappush/src/gonk/WbxmlPduHelper.jsm
--- a/dom/wappush/src/gonk/WapPushManager.js
+++ b/dom/wappush/src/gonk/WapPushManager.js
@@ -57,18 +57,18 @@ this.WapPushManager = {
       debug("options: " + JSON.stringify(options));
     } catch (ex) {
       debug("Failed to parse sessionless WSP PDU: " + ex.message);
       return;
     }
 
     let appid = options.headers["x-wap-application-id"];
     if (!appid) {
+      // Assume message without applicatioin ID is WAP Push
       debug("Push message doesn't contains X-Wap-Application-Id.");
-      return;
     }
 
     // MMS
     if (appid == "x-wap-application:mms.ua") {
       let mmsService = Cc["@mozilla.org/mms/rilmmsservice;1"]
                        .getService(Ci.nsIMmsService);
       mmsService.QueryInterface(Ci.nsIWapPushApplication)
                 .receiveWapPush(data.array, data.array.length, data.offset, options);
--- a/dom/wappush/src/gonk/WbxmlPduHelper.jsm
+++ b/dom/wappush/src/gonk/WbxmlPduHelper.jsm
@@ -18,32 +18,75 @@ const TAG_TOKEN_ATTR_MASK     = 0x80;
 const TAG_TOKEN_CONTENT_MASK  = 0x40;
 const TAG_TOKEN_VALUE_MASK    = 0x3F;
 
 /**
  * Global tokens
  *
  * @see WAP-192-WBXML-20010725-A, clause 7.1
  */
+const CODE_PAGE_SWITCH_TOKEN  = 0x00;
 const TAG_END_TOKEN           = 0x01;
 const INLINE_STRING_TOKEN     = 0x03;
 const STRING_TABLE_TOKEN      = 0x83;
 const OPAQUE_TOKEN            = 0xC3;
 
 // Set to true to enable debug message on all WBXML decoders.
 this.DEBUG_ALL = false;
 
 // Enable debug message for WBXML decoder core.
 this.DEBUG = DEBUG_ALL | false;
 
 /**
+ * Handle WBXML code page switch.
+ *
+ * @param data
+ *        A wrapped object containing raw PDU data.
+ * @param decodeInfo
+ *        Internal information for decode process.
+ *
+ * @see WAP-192-WBXML-20010725-A, clause 5.8.4.7.2 and 5.8.1
+ */
+this.WbxmlCodePageSwitch = {
+  decode: function decode_wbxml_code_page_switch(data, decodeInfo) {
+    let codePage = WSP.Octet.decode(data);
+
+    if (decodeInfo.currentState === "tag") {
+      decodeInfo.currentTokenList.tag = decodeInfo.tokenList.tag[codePage];
+
+      if (!decodeInfo.currentTokenList.tag) {
+        throw new Error("Invalid tag code page: " + codePage + ".");
+      }
+
+      return "";
+    }
+
+    if (decodeInfo.currentState === "attr") {
+      decodeInfo.currentTokenList.attr = decodeInfo.tokenList.attr[codePage];
+      decodeInfo.currentTokenList.value = decodeInfo.tokenList.value[codePage];
+
+      if (!decodeInfo.currentTokenList.attr ||
+          !decodeInfo.currentTokenList.value) {
+        throw new Error("Invalid attr code page: " + codePage + ".");
+      }
+
+      return "";
+    }
+
+    throw new Error("Invalid decoder state: " + decodeInfo.currentState + ".");
+  },
+};
+
+/**
  * Parse end WBXML encoded message.
  *
  * @param data
  *        A wrapped object containing raw PDU data.
+ * @param decodeInfo
+ *        Internal information for decode process.
  *
  * @see WAP-192-WBXML-20010725-A, clause 5.8.4.7.1
  *
  */
 this.WbxmlEnd = {
   decode: function decode_wbxml_end(data, decodeInfo) {
     let tagInfo = decodeInfo.tagStack.pop();
     return "</" + tagInfo.name + ">";
@@ -79,16 +122,18 @@ this.WbxmlStringTable = {
   }
 };
 
 /**
  * Parse inline string in WBXML encoded message.
  *
  * @param data
  *        A wrapped object containing raw PDU data.
+ * @param decodeInfo
+ *        Internal information for decode process.
  *
  * @see WAP-192-WBXML-20010725-A, clause 5.8.4.1
  *
  */
 this.WbxmlInlineString = {
   decode: function decode_wbxml_inline_string(data, decodeInfo) {
     let charCode = WSP.Octet.decode(data);
     let stringData = [];
@@ -101,16 +146,18 @@ this.WbxmlInlineString = {
   },
 };
 
 /**
  * Parse inline Opaque data in WBXML encoded message.
  *
  * @param data
  *        A wrapped object containing raw PDU data.
+ * @param decodeInfo
+ *        Internal information for decode process.
  *
  * @see WAP-192-WBXML-20010725-A, clause 5.8.4.6
  *
  */
 this.WbxmlOpaque = {
   decode: function decode_wbxml_inline_opaque(data) {
     // Inline OPAQUE must be decoded based on application definition,
     // so it's illegal to run into OPAQUE type in general decoder.
@@ -130,84 +177,99 @@ this.PduHelper = {
    * @param appToken
    *        Application-specific token difinition.
    *
    * @return Decoded WBXML message string.
    */
   parseWbxml: function parseWbxml_wbxml(data, decodeInfo, appToken) {
 
     // Parse token definition to my structure.
-    let tagTokenList = appToken.tagTokenList;
-    let attrTokenList = appToken.attrTokenList;
-    let valueTokenList = appToken.valueTokenList;
-
-    decodeInfo.tagStack = [];    // tag decode stack
+    decodeInfo.tokenList = {
+      tag: appToken.tagTokenList,
+      attr: appToken.attrTokenList,
+      value: appToken.valueTokenList
+    };
+    decodeInfo.tagStack = [];   // tag decode stack
+    decodeInfo.currentTokenList = {
+      tag: decodeInfo.tokenList.tag[0],
+      attr: decodeInfo.tokenList.attr[0],
+      value: decodeInfo.tokenList.value[0]
+    };
+    decodeInfo.currentState = "tag";  // Current decoding state, "tag" or "attr"
+                                      // Used to read corresponding code page
+                                      // initial state : "tag"
 
     // Merge global tag tokens into single list, so we don't have
     // to search two lists every time.
     let globalTagTokenList = Object.create(WBXML_GLOBAL_TOKENS);
     if (appToken.globalTokenOverride) {
       let globalTokenOverrideList = appToken.globalTokenOverride;
       for (let token in globalTokenOverrideList) {
         globalTagTokenList[token] = globalTokenOverrideList[token];
       }
     }
 
     let content = "";
     while (data.offset < data.array.length) {
       // Decode content, might be a new tag token, an end of tag token, or an
       // inline string.
 
+      // Switch to tag domain
+      decodeInfo.currentState = "tag";
+
       let tagToken = WSP.Octet.decode(data);
       let tagTokenValue = tagToken & TAG_TOKEN_VALUE_MASK;
 
       // Try global tag first, tagToken of string table is 0x83, and will be 0x03
       // in tagTokenValue, which is collision with inline string.
       // So tagToken need to be searched before tagTokenValue.
       let tagInfo = globalTagTokenList[tagToken] ||
                     globalTagTokenList[tagTokenValue];
       if (tagInfo) {
         content += tagInfo.coder.decode(data, decodeInfo);
         continue;
       }
 
       // Check if application tag token is valid
-      tagInfo = tagTokenList[tagTokenValue];
+      tagInfo = decodeInfo.currentTokenList.tag[tagTokenValue];
       if (!tagInfo) {
         throw new Error("Unsupported WBXML token: " + tagTokenValue + ".");
       }
 
       content += "<" + tagInfo.name;
 
       if (tagToken & TAG_TOKEN_ATTR_MASK) {
         // Decode attributes, might be a new attribute token, a value token,
         // or an inline string
 
+        // Switch to attr/value domain
+        decodeInfo.currentState = "attr";
+
         let attrSeperator = "";
         while (data.offset < data.array.length) {
           let attrToken = WSP.Octet.decode(data);
           if (attrToken === TAG_END_TOKEN) {
             break;
           }
 
           let attrInfo = globalTagTokenList[attrToken];
           if (attrInfo) {
             content += attrInfo.coder.decode(data, decodeInfo);
             continue;
           }
 
           // Check if attribute token is valid
-          attrInfo = attrTokenList[attrToken];
+          attrInfo = decodeInfo.currentTokenList.attr[attrToken];
           if (attrInfo) {
             content += attrSeperator + " " + attrInfo.name + "=\"" + attrInfo.value;
             attrSeperator = "\"";
             continue;
           }
 
-          attrInfo = valueTokenList[attrToken];
+          attrInfo = decodeInfo.currentTokenList.value[attrToken];
           if (attrInfo) {
             content += attrInfo.value;
             continue;
           }
 
           throw new Error("Unsupported WBXML token: " + attrToken + ".");
         }
 
@@ -320,20 +382,21 @@ const WBXML_GLOBAL_TOKENS = (function ()
   function add(number, coder) {
     let entry = {
       number: number,
       coder: coder,
     };
     names[number] = entry;
   }
 
-  add(TAG_END_TOKEN,        WbxmlEnd);
-  add(INLINE_STRING_TOKEN,  WbxmlInlineString);
-  add(STRING_TABLE_TOKEN,   WbxmlStringTable);
-  add(OPAQUE_TOKEN,         WbxmlOpaque);
+  add(CODE_PAGE_SWITCH_TOKEN, WbxmlCodePageSwitch);
+  add(TAG_END_TOKEN,          WbxmlEnd);
+  add(INLINE_STRING_TOKEN,    WbxmlInlineString);
+  add(STRING_TABLE_TOKEN,     WbxmlStringTable);
+  add(OPAQUE_TOKEN,           WbxmlOpaque);
 
   return names;
 })();
 
 /**
  *  Pre-defined public IDs
  *
  * @see http://technical.openmobilealliance.org/tech/omna/omna-wbxml-public-docid.aspx