|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file, |
|
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 "use strict"; |
|
6 |
|
7 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; |
|
8 |
|
9 Cu.import("resource://gre/modules/XPCOMUtils.jsm"); |
|
10 Cu.import("resource://gre/modules/Services.jsm"); |
|
11 Cu.import("resource://gre/modules/PhoneNumberUtils.jsm"); |
|
12 Cu.import("resource://gre/modules/WspPduHelper.jsm", this); |
|
13 |
|
14 const DEBUG = false; // set to true to see debug messages |
|
15 |
|
16 /** |
|
17 * WAP Push decoders |
|
18 */ |
|
19 XPCOMUtils.defineLazyGetter(this, "SI", function () { |
|
20 let SI = {}; |
|
21 Cu.import("resource://gre/modules/SiPduHelper.jsm", SI); |
|
22 return SI; |
|
23 }); |
|
24 |
|
25 XPCOMUtils.defineLazyGetter(this, "SL", function () { |
|
26 let SL = {}; |
|
27 Cu.import("resource://gre/modules/SlPduHelper.jsm", SL); |
|
28 return SL; |
|
29 }); |
|
30 |
|
31 XPCOMUtils.defineLazyGetter(this, "CP", function () { |
|
32 let CP = {}; |
|
33 Cu.import("resource://gre/modules/CpPduHelper.jsm", CP); |
|
34 return CP; |
|
35 }); |
|
36 |
|
37 XPCOMUtils.defineLazyServiceGetter(this, "gSystemMessenger", |
|
38 "@mozilla.org/system-message-internal;1", |
|
39 "nsISystemMessagesInternal"); |
|
40 XPCOMUtils.defineLazyServiceGetter(this, "gRIL", |
|
41 "@mozilla.org/ril;1", |
|
42 "nsIRadioInterfaceLayer"); |
|
43 |
|
44 /** |
|
45 * Helpers for WAP PDU processing. |
|
46 */ |
|
47 this.WapPushManager = { |
|
48 |
|
49 /** |
|
50 * Parse raw PDU data and deliver to a proper target. |
|
51 * |
|
52 * @param data |
|
53 * A wrapped object containing raw PDU data. |
|
54 * @param options |
|
55 * Extra context for decoding. |
|
56 */ |
|
57 processMessage: function processMessage(data, options) { |
|
58 try { |
|
59 PduHelper.parse(data, true, options); |
|
60 debug("options: " + JSON.stringify(options)); |
|
61 } catch (ex) { |
|
62 debug("Failed to parse sessionless WSP PDU: " + ex.message); |
|
63 return; |
|
64 } |
|
65 |
|
66 let appid = options.headers["x-wap-application-id"]; |
|
67 if (!appid) { |
|
68 // Assume message without applicatioin ID is WAP Push |
|
69 debug("Push message doesn't contains X-Wap-Application-Id."); |
|
70 } |
|
71 |
|
72 // MMS |
|
73 if (appid == "x-wap-application:mms.ua") { |
|
74 let mmsService = Cc["@mozilla.org/mms/rilmmsservice;1"] |
|
75 .getService(Ci.nsIMmsService); |
|
76 mmsService.QueryInterface(Ci.nsIWapPushApplication) |
|
77 .receiveWapPush(data.array, data.array.length, data.offset, options); |
|
78 return; |
|
79 } |
|
80 |
|
81 /** |
|
82 * Non-MMS, handled according to content type |
|
83 * |
|
84 * WAP Type content-type x-wap-application-id |
|
85 * MMS "application/vnd.wap.mms-message" "x-wap-application:mms.ua" |
|
86 * SI "text/vnd.wap.si" "x-wap-application:wml.ua" |
|
87 * SI(WBXML) "application/vnd.wap.sic" "x-wap-application:wml.ua" |
|
88 * SL "text/vnd.wap.sl" "x-wap-application:wml.ua" |
|
89 * SL(WBXML) "application/vnd.wap.slc" "x-wap-application:wml.ua" |
|
90 * Provisioning "text/vnd.wap.connectivity-xml" "x-wap-application:wml.ua" |
|
91 * Provisioning(WBXML) "application/vnd.wap.connectivity-wbxml" "x-wap-application:wml.ua" |
|
92 * |
|
93 * @see http://technical.openmobilealliance.org/tech/omna/omna-wsp-content-type.aspx |
|
94 */ |
|
95 let contentType = options.headers["content-type"].media; |
|
96 let msg; |
|
97 let authInfo = null; |
|
98 |
|
99 if (contentType === "text/vnd.wap.si" || |
|
100 contentType === "application/vnd.wap.sic") { |
|
101 msg = SI.PduHelper.parse(data, contentType); |
|
102 } else if (contentType === "text/vnd.wap.sl" || |
|
103 contentType === "application/vnd.wap.slc") { |
|
104 msg = SL.PduHelper.parse(data, contentType); |
|
105 } else if (contentType === "text/vnd.wap.connectivity-xml" || |
|
106 contentType === "application/vnd.wap.connectivity-wbxml") { |
|
107 // Apply HMAC authentication on WBXML encoded CP message. |
|
108 if (contentType === "application/vnd.wap.connectivity-wbxml") { |
|
109 let params = options.headers["content-type"].params; |
|
110 let sec = params && params.sec; |
|
111 let mac = params && params.mac; |
|
112 authInfo = CP.Authenticator.check(data.array.subarray(data.offset), |
|
113 sec, mac, function getNetworkPin() { |
|
114 let imsi = gRIL.getRadioInterface(options.serviceId).rilContext.imsi; |
|
115 return CP.Authenticator.formatImsi(imsi); |
|
116 }); |
|
117 } |
|
118 |
|
119 msg = CP.PduHelper.parse(data, contentType); |
|
120 } else { |
|
121 // Unsupported type, provide raw data. |
|
122 msg = { |
|
123 contentType: contentType, |
|
124 content: data.array |
|
125 }; |
|
126 msg.content.length = data.array.length; |
|
127 } |
|
128 |
|
129 let sender = PhoneNumberUtils.normalize(options.sourceAddress, false); |
|
130 let parsedSender = PhoneNumberUtils.parse(sender); |
|
131 if (parsedSender && parsedSender.internationalNumber) { |
|
132 sender = parsedSender.internationalNumber; |
|
133 } |
|
134 |
|
135 gSystemMessenger.broadcastMessage("wappush-received", { |
|
136 sender: sender, |
|
137 contentType: msg.contentType, |
|
138 content: msg.content, |
|
139 authInfo: authInfo, |
|
140 serviceId: options.serviceId |
|
141 }); |
|
142 }, |
|
143 |
|
144 /** |
|
145 * @param array |
|
146 * A Uint8Array or an octet array representing raw PDU data. |
|
147 * @param length |
|
148 * Length of the array. |
|
149 * @param offset |
|
150 * Offset of the array that a raw PDU data begins. |
|
151 * @param options |
|
152 * WDP bearer information. |
|
153 */ |
|
154 receiveWdpPDU: function receiveWdpPDU(array, length, offset, options) { |
|
155 if ((options.bearer == null) || !options.sourceAddress |
|
156 || (options.sourcePort == null) || !array) { |
|
157 debug("Incomplete WDP PDU"); |
|
158 return; |
|
159 } |
|
160 |
|
161 if (options.destinationPort != WDP_PORT_PUSH) { |
|
162 debug("Not WAP Push port: " + options.destinationPort); |
|
163 return; |
|
164 } |
|
165 |
|
166 this.processMessage({array: array, offset: offset}, options); |
|
167 }, |
|
168 }; |
|
169 |
|
170 let debug; |
|
171 if (DEBUG) { |
|
172 debug = function (s) { |
|
173 dump("-*- WapPushManager: " + s + "\n"); |
|
174 }; |
|
175 } else { |
|
176 debug = function (s) {}; |
|
177 } |
|
178 |
|
179 this.EXPORTED_SYMBOLS = ALL_CONST_SYMBOLS.concat([ |
|
180 "WapPushManager", |
|
181 ]); |
|
182 |