1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/wappush/src/gonk/WapPushManager.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,182 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.6 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +"use strict"; 1.9 + 1.10 +const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; 1.11 + 1.12 +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); 1.13 +Cu.import("resource://gre/modules/Services.jsm"); 1.14 +Cu.import("resource://gre/modules/PhoneNumberUtils.jsm"); 1.15 +Cu.import("resource://gre/modules/WspPduHelper.jsm", this); 1.16 + 1.17 +const DEBUG = false; // set to true to see debug messages 1.18 + 1.19 +/** 1.20 + * WAP Push decoders 1.21 + */ 1.22 +XPCOMUtils.defineLazyGetter(this, "SI", function () { 1.23 + let SI = {}; 1.24 + Cu.import("resource://gre/modules/SiPduHelper.jsm", SI); 1.25 + return SI; 1.26 +}); 1.27 + 1.28 +XPCOMUtils.defineLazyGetter(this, "SL", function () { 1.29 + let SL = {}; 1.30 + Cu.import("resource://gre/modules/SlPduHelper.jsm", SL); 1.31 + return SL; 1.32 +}); 1.33 + 1.34 +XPCOMUtils.defineLazyGetter(this, "CP", function () { 1.35 + let CP = {}; 1.36 + Cu.import("resource://gre/modules/CpPduHelper.jsm", CP); 1.37 + return CP; 1.38 +}); 1.39 + 1.40 +XPCOMUtils.defineLazyServiceGetter(this, "gSystemMessenger", 1.41 + "@mozilla.org/system-message-internal;1", 1.42 + "nsISystemMessagesInternal"); 1.43 +XPCOMUtils.defineLazyServiceGetter(this, "gRIL", 1.44 + "@mozilla.org/ril;1", 1.45 + "nsIRadioInterfaceLayer"); 1.46 + 1.47 +/** 1.48 + * Helpers for WAP PDU processing. 1.49 + */ 1.50 +this.WapPushManager = { 1.51 + 1.52 + /** 1.53 + * Parse raw PDU data and deliver to a proper target. 1.54 + * 1.55 + * @param data 1.56 + * A wrapped object containing raw PDU data. 1.57 + * @param options 1.58 + * Extra context for decoding. 1.59 + */ 1.60 + processMessage: function processMessage(data, options) { 1.61 + try { 1.62 + PduHelper.parse(data, true, options); 1.63 + debug("options: " + JSON.stringify(options)); 1.64 + } catch (ex) { 1.65 + debug("Failed to parse sessionless WSP PDU: " + ex.message); 1.66 + return; 1.67 + } 1.68 + 1.69 + let appid = options.headers["x-wap-application-id"]; 1.70 + if (!appid) { 1.71 + // Assume message without applicatioin ID is WAP Push 1.72 + debug("Push message doesn't contains X-Wap-Application-Id."); 1.73 + } 1.74 + 1.75 + // MMS 1.76 + if (appid == "x-wap-application:mms.ua") { 1.77 + let mmsService = Cc["@mozilla.org/mms/rilmmsservice;1"] 1.78 + .getService(Ci.nsIMmsService); 1.79 + mmsService.QueryInterface(Ci.nsIWapPushApplication) 1.80 + .receiveWapPush(data.array, data.array.length, data.offset, options); 1.81 + return; 1.82 + } 1.83 + 1.84 + /** 1.85 + * Non-MMS, handled according to content type 1.86 + * 1.87 + * WAP Type content-type x-wap-application-id 1.88 + * MMS "application/vnd.wap.mms-message" "x-wap-application:mms.ua" 1.89 + * SI "text/vnd.wap.si" "x-wap-application:wml.ua" 1.90 + * SI(WBXML) "application/vnd.wap.sic" "x-wap-application:wml.ua" 1.91 + * SL "text/vnd.wap.sl" "x-wap-application:wml.ua" 1.92 + * SL(WBXML) "application/vnd.wap.slc" "x-wap-application:wml.ua" 1.93 + * Provisioning "text/vnd.wap.connectivity-xml" "x-wap-application:wml.ua" 1.94 + * Provisioning(WBXML) "application/vnd.wap.connectivity-wbxml" "x-wap-application:wml.ua" 1.95 + * 1.96 + * @see http://technical.openmobilealliance.org/tech/omna/omna-wsp-content-type.aspx 1.97 + */ 1.98 + let contentType = options.headers["content-type"].media; 1.99 + let msg; 1.100 + let authInfo = null; 1.101 + 1.102 + if (contentType === "text/vnd.wap.si" || 1.103 + contentType === "application/vnd.wap.sic") { 1.104 + msg = SI.PduHelper.parse(data, contentType); 1.105 + } else if (contentType === "text/vnd.wap.sl" || 1.106 + contentType === "application/vnd.wap.slc") { 1.107 + msg = SL.PduHelper.parse(data, contentType); 1.108 + } else if (contentType === "text/vnd.wap.connectivity-xml" || 1.109 + contentType === "application/vnd.wap.connectivity-wbxml") { 1.110 + // Apply HMAC authentication on WBXML encoded CP message. 1.111 + if (contentType === "application/vnd.wap.connectivity-wbxml") { 1.112 + let params = options.headers["content-type"].params; 1.113 + let sec = params && params.sec; 1.114 + let mac = params && params.mac; 1.115 + authInfo = CP.Authenticator.check(data.array.subarray(data.offset), 1.116 + sec, mac, function getNetworkPin() { 1.117 + let imsi = gRIL.getRadioInterface(options.serviceId).rilContext.imsi; 1.118 + return CP.Authenticator.formatImsi(imsi); 1.119 + }); 1.120 + } 1.121 + 1.122 + msg = CP.PduHelper.parse(data, contentType); 1.123 + } else { 1.124 + // Unsupported type, provide raw data. 1.125 + msg = { 1.126 + contentType: contentType, 1.127 + content: data.array 1.128 + }; 1.129 + msg.content.length = data.array.length; 1.130 + } 1.131 + 1.132 + let sender = PhoneNumberUtils.normalize(options.sourceAddress, false); 1.133 + let parsedSender = PhoneNumberUtils.parse(sender); 1.134 + if (parsedSender && parsedSender.internationalNumber) { 1.135 + sender = parsedSender.internationalNumber; 1.136 + } 1.137 + 1.138 + gSystemMessenger.broadcastMessage("wappush-received", { 1.139 + sender: sender, 1.140 + contentType: msg.contentType, 1.141 + content: msg.content, 1.142 + authInfo: authInfo, 1.143 + serviceId: options.serviceId 1.144 + }); 1.145 + }, 1.146 + 1.147 + /** 1.148 + * @param array 1.149 + * A Uint8Array or an octet array representing raw PDU data. 1.150 + * @param length 1.151 + * Length of the array. 1.152 + * @param offset 1.153 + * Offset of the array that a raw PDU data begins. 1.154 + * @param options 1.155 + * WDP bearer information. 1.156 + */ 1.157 + receiveWdpPDU: function receiveWdpPDU(array, length, offset, options) { 1.158 + if ((options.bearer == null) || !options.sourceAddress 1.159 + || (options.sourcePort == null) || !array) { 1.160 + debug("Incomplete WDP PDU"); 1.161 + return; 1.162 + } 1.163 + 1.164 + if (options.destinationPort != WDP_PORT_PUSH) { 1.165 + debug("Not WAP Push port: " + options.destinationPort); 1.166 + return; 1.167 + } 1.168 + 1.169 + this.processMessage({array: array, offset: offset}, options); 1.170 + }, 1.171 +}; 1.172 + 1.173 +let debug; 1.174 +if (DEBUG) { 1.175 + debug = function (s) { 1.176 + dump("-*- WapPushManager: " + s + "\n"); 1.177 + }; 1.178 +} else { 1.179 + debug = function (s) {}; 1.180 +} 1.181 + 1.182 +this.EXPORTED_SYMBOLS = ALL_CONST_SYMBOLS.concat([ 1.183 + "WapPushManager", 1.184 +]); 1.185 +