Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
michael@0 | 1 | /* Any copyright is dedicated to the Public Domain. |
michael@0 | 2 | * http://creativecommons.org/publicdomain/zero/1.0/ */ |
michael@0 | 3 | |
michael@0 | 4 | MARIONETTE_TIMEOUT = 30000; |
michael@0 | 5 | |
michael@0 | 6 | const PDU_DCS_CODING_GROUP_BITS = 0xF0; |
michael@0 | 7 | const PDU_DCS_MSG_CODING_7BITS_ALPHABET = 0x00; |
michael@0 | 8 | const PDU_DCS_MSG_CODING_8BITS_ALPHABET = 0x04; |
michael@0 | 9 | const PDU_DCS_MSG_CODING_16BITS_ALPHABET = 0x08; |
michael@0 | 10 | |
michael@0 | 11 | const PDU_DCS_MSG_CLASS_BITS = 0x03; |
michael@0 | 12 | const PDU_DCS_MSG_CLASS_NORMAL = 0xFF; |
michael@0 | 13 | const PDU_DCS_MSG_CLASS_0 = 0x00; |
michael@0 | 14 | const PDU_DCS_MSG_CLASS_ME_SPECIFIC = 0x01; |
michael@0 | 15 | const PDU_DCS_MSG_CLASS_SIM_SPECIFIC = 0x02; |
michael@0 | 16 | const PDU_DCS_MSG_CLASS_TE_SPECIFIC = 0x03; |
michael@0 | 17 | const PDU_DCS_MSG_CLASS_USER_1 = 0x04; |
michael@0 | 18 | const PDU_DCS_MSG_CLASS_USER_2 = 0x05; |
michael@0 | 19 | |
michael@0 | 20 | const GECKO_SMS_MESSAGE_CLASSES = {}; |
michael@0 | 21 | GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL] = "normal"; |
michael@0 | 22 | GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_0] = "class-0"; |
michael@0 | 23 | GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_ME_SPECIFIC] = "class-1"; |
michael@0 | 24 | GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_SIM_SPECIFIC] = "class-2"; |
michael@0 | 25 | GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_TE_SPECIFIC] = "class-3"; |
michael@0 | 26 | GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_USER_1] = "user-1"; |
michael@0 | 27 | GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_USER_2] = "user-2"; |
michael@0 | 28 | |
michael@0 | 29 | const CB_MESSAGE_SIZE_GSM = 88; |
michael@0 | 30 | |
michael@0 | 31 | const CB_GSM_MESSAGEID_ETWS_BEGIN = 0x1100; |
michael@0 | 32 | const CB_GSM_MESSAGEID_ETWS_END = 0x1107; |
michael@0 | 33 | |
michael@0 | 34 | const CB_GSM_GEOGRAPHICAL_SCOPE_NAMES = [ |
michael@0 | 35 | "cell-immediate", |
michael@0 | 36 | "plmn", |
michael@0 | 37 | "location-area", |
michael@0 | 38 | "cell" |
michael@0 | 39 | ]; |
michael@0 | 40 | |
michael@0 | 41 | const CB_ETWS_WARNING_TYPE_NAMES = [ |
michael@0 | 42 | "earthquake", |
michael@0 | 43 | "tsunami", |
michael@0 | 44 | "earthquake-tsunami", |
michael@0 | 45 | "test", |
michael@0 | 46 | "other" |
michael@0 | 47 | ]; |
michael@0 | 48 | |
michael@0 | 49 | const CB_DCS_LANG_GROUP_1 = [ |
michael@0 | 50 | "de", "en", "it", "fr", "es", "nl", "sv", "da", "pt", "fi", |
michael@0 | 51 | "no", "el", "tr", "hu", "pl", null |
michael@0 | 52 | ]; |
michael@0 | 53 | const CB_DCS_LANG_GROUP_2 = [ |
michael@0 | 54 | "cs", "he", "ar", "ru", "is", null, null, null, null, null, |
michael@0 | 55 | null, null, null, null, null, null |
michael@0 | 56 | ]; |
michael@0 | 57 | |
michael@0 | 58 | const CB_MAX_CONTENT_7BIT = Math.floor((CB_MESSAGE_SIZE_GSM - 6) * 8 / 7); |
michael@0 | 59 | const CB_MAX_CONTENT_UCS2 = Math.floor((CB_MESSAGE_SIZE_GSM - 6) / 2); |
michael@0 | 60 | |
michael@0 | 61 | const BODY_7BITS = "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" |
michael@0 | 62 | + "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" |
michael@0 | 63 | + "@@@@@@@@@@@@@"; // 93 ascii chars. |
michael@0 | 64 | const BODY_7BITS_IND = BODY_7BITS.substr(3); |
michael@0 | 65 | const BODY_UCS2 = "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" |
michael@0 | 66 | + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" |
michael@0 | 67 | + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" |
michael@0 | 68 | + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" |
michael@0 | 69 | + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" |
michael@0 | 70 | + "\u0000"; // 41 unicode chars. |
michael@0 | 71 | const BODY_UCS2_IND = BODY_UCS2.substr(1); |
michael@0 | 72 | |
michael@0 | 73 | SpecialPowers.addPermission("cellbroadcast", true, document); |
michael@0 | 74 | SpecialPowers.addPermission("mobileconnection", true, document); |
michael@0 | 75 | |
michael@0 | 76 | is(BODY_7BITS.length, CB_MAX_CONTENT_7BIT, "BODY_7BITS.length"); |
michael@0 | 77 | is(BODY_7BITS_IND.length, CB_MAX_CONTENT_7BIT - 3, "BODY_7BITS_IND.length"); |
michael@0 | 78 | is(BODY_UCS2.length, CB_MAX_CONTENT_UCS2, "BODY_UCS2.length"); |
michael@0 | 79 | is(BODY_UCS2_IND.length, CB_MAX_CONTENT_UCS2 - 1, "BODY_UCS2_IND.length") |
michael@0 | 80 | |
michael@0 | 81 | let cbs = window.navigator.mozCellBroadcast; |
michael@0 | 82 | ok(cbs instanceof window.MozCellBroadcast, |
michael@0 | 83 | "mozCellBroadcast is instanceof " + cbs.constructor); |
michael@0 | 84 | |
michael@0 | 85 | let pendingEmulatorCmdCount = 0; |
michael@0 | 86 | function sendCellBroadcastMessage(pdu, callback) { |
michael@0 | 87 | pendingEmulatorCmdCount++; |
michael@0 | 88 | |
michael@0 | 89 | let cmd = "cbs pdu " + pdu; |
michael@0 | 90 | runEmulatorCmd(cmd, function(result) { |
michael@0 | 91 | pendingEmulatorCmdCount--; |
michael@0 | 92 | |
michael@0 | 93 | is(result[0], "OK", "Emulator response"); |
michael@0 | 94 | |
michael@0 | 95 | if (callback) { |
michael@0 | 96 | window.setTimeout(callback, 0); |
michael@0 | 97 | } |
michael@0 | 98 | }); |
michael@0 | 99 | } |
michael@0 | 100 | |
michael@0 | 101 | function buildHexStr(n, numSemiOctets) { |
michael@0 | 102 | let str = n.toString(16); |
michael@0 | 103 | ok(str.length <= numSemiOctets); |
michael@0 | 104 | while (str.length < numSemiOctets) { |
michael@0 | 105 | str = "0" + str; |
michael@0 | 106 | } |
michael@0 | 107 | return str; |
michael@0 | 108 | } |
michael@0 | 109 | |
michael@0 | 110 | function seq(end, begin) { |
michael@0 | 111 | let result = []; |
michael@0 | 112 | for (let i = begin || 0; i < end; i++) { |
michael@0 | 113 | result.push(i); |
michael@0 | 114 | } |
michael@0 | 115 | return result; |
michael@0 | 116 | } |
michael@0 | 117 | |
michael@0 | 118 | function repeat(func, array, oncomplete) { |
michael@0 | 119 | (function do_call(index) { |
michael@0 | 120 | let next = index < (array.length - 1) ? do_call.bind(null, index + 1) : oncomplete; |
michael@0 | 121 | func.apply(null, [array[index], next]); |
michael@0 | 122 | })(0); |
michael@0 | 123 | } |
michael@0 | 124 | |
michael@0 | 125 | function doTestHelper(pdu, nextTest, checkFunc) { |
michael@0 | 126 | cbs.addEventListener("received", function onreceived(event) { |
michael@0 | 127 | cbs.removeEventListener("received", onreceived); |
michael@0 | 128 | |
michael@0 | 129 | checkFunc(event.message); |
michael@0 | 130 | |
michael@0 | 131 | window.setTimeout(nextTest, 0); |
michael@0 | 132 | }); |
michael@0 | 133 | |
michael@0 | 134 | if (Array.isArray(pdu)) { |
michael@0 | 135 | repeat(sendCellBroadcastMessage, pdu); |
michael@0 | 136 | } else { |
michael@0 | 137 | sendCellBroadcastMessage(pdu); |
michael@0 | 138 | } |
michael@0 | 139 | } |
michael@0 | 140 | |
michael@0 | 141 | /** |
michael@0 | 142 | * Tests receiving Cell Broadcast messages, event instance type, all attributes |
michael@0 | 143 | * of CellBroadcastMessage exist. |
michael@0 | 144 | */ |
michael@0 | 145 | function testGsmMessageAttributes() { |
michael@0 | 146 | log("Test GSM Cell Broadcast message attributes"); |
michael@0 | 147 | |
michael@0 | 148 | cbs.addEventListener("received", function onreceived(event) { |
michael@0 | 149 | cbs.removeEventListener("received", onreceived); |
michael@0 | 150 | |
michael@0 | 151 | // Bug 838542: following check throws an exception and fails this case. |
michael@0 | 152 | // ok(event instanceof MozCellBroadcastEvent, |
michael@0 | 153 | // "event is instanceof " + event.constructor) |
michael@0 | 154 | ok(event, "event is valid"); |
michael@0 | 155 | |
michael@0 | 156 | let message = event.message; |
michael@0 | 157 | ok(message, "event.message is valid"); |
michael@0 | 158 | |
michael@0 | 159 | // Attributes other than `language` and `body` should always be assigned. |
michael@0 | 160 | ok(message.gsmGeographicalScope != null, "message.gsmGeographicalScope"); |
michael@0 | 161 | ok(message.messageCode != null, "message.messageCode"); |
michael@0 | 162 | ok(message.messageId != null, "message.messageId"); |
michael@0 | 163 | ok(message.language != null, "message.language"); |
michael@0 | 164 | ok(message.body != null, "message.body"); |
michael@0 | 165 | ok(message.messageClass != null, "message.messageClass"); |
michael@0 | 166 | ok(message.timestamp != null, "message.timestamp"); |
michael@0 | 167 | ok('etws' in message, "message.etws"); |
michael@0 | 168 | if (message.etws) { |
michael@0 | 169 | ok('warningType' in message.etws, "message.etws.warningType"); |
michael@0 | 170 | ok(message.etws.emergencyUserAlert != null, "message.etws.emergencyUserAlert"); |
michael@0 | 171 | ok(message.etws.popup != null, "message.etws.popup"); |
michael@0 | 172 | } |
michael@0 | 173 | ok(message.cdmaServiceCategory != null, "message.cdmaServiceCategory"); |
michael@0 | 174 | |
michael@0 | 175 | window.setTimeout(testReceiving_GSM_GeographicalScope, 0); |
michael@0 | 176 | }); |
michael@0 | 177 | |
michael@0 | 178 | // Here we use a simple GSM message for test. |
michael@0 | 179 | let pdu = buildHexStr(0, CB_MESSAGE_SIZE_GSM * 2); |
michael@0 | 180 | sendCellBroadcastMessage(pdu); |
michael@0 | 181 | } |
michael@0 | 182 | |
michael@0 | 183 | function testReceiving_GSM_GeographicalScope() { |
michael@0 | 184 | log("Test receiving GSM Cell Broadcast - Geographical Scope"); |
michael@0 | 185 | |
michael@0 | 186 | function do_test(gs, nextTest) { |
michael@0 | 187 | let pdu = buildHexStr(((gs & 0x03) << 14), 4) |
michael@0 | 188 | + buildHexStr(0, (CB_MESSAGE_SIZE_GSM - 2) * 2); |
michael@0 | 189 | |
michael@0 | 190 | doTestHelper(pdu, nextTest, function(message) { |
michael@0 | 191 | is(message.gsmGeographicalScope, CB_GSM_GEOGRAPHICAL_SCOPE_NAMES[gs], |
michael@0 | 192 | "message.gsmGeographicalScope"); |
michael@0 | 193 | }); |
michael@0 | 194 | } |
michael@0 | 195 | |
michael@0 | 196 | repeat(do_test, seq(CB_GSM_GEOGRAPHICAL_SCOPE_NAMES.length), |
michael@0 | 197 | testReceiving_GSM_MessageCode); |
michael@0 | 198 | } |
michael@0 | 199 | |
michael@0 | 200 | function testReceiving_GSM_MessageCode() { |
michael@0 | 201 | log("Test receiving GSM Cell Broadcast - Message Code"); |
michael@0 | 202 | |
michael@0 | 203 | // Message Code has 10 bits, and is ORed into a 16 bits 'serial' number. Here |
michael@0 | 204 | // we test every single bit to verify the operation doesn't go wrong. |
michael@0 | 205 | let messageCodesToTest = [ |
michael@0 | 206 | 0x000, 0x001, 0x002, 0x004, 0x008, 0x010, 0x020, 0x040, |
michael@0 | 207 | 0x080, 0x100, 0x200, 0x251 |
michael@0 | 208 | ]; |
michael@0 | 209 | |
michael@0 | 210 | function do_test(messageCode, nextTest) { |
michael@0 | 211 | let pdu = buildHexStr(((messageCode & 0x3FF) << 4), 4) |
michael@0 | 212 | + buildHexStr(0, (CB_MESSAGE_SIZE_GSM - 2) * 2); |
michael@0 | 213 | |
michael@0 | 214 | doTestHelper(pdu, nextTest, function(message) { |
michael@0 | 215 | is(message.messageCode, messageCode, "message.messageCode"); |
michael@0 | 216 | }); |
michael@0 | 217 | } |
michael@0 | 218 | |
michael@0 | 219 | repeat(do_test, messageCodesToTest, testReceiving_GSM_MessageId); |
michael@0 | 220 | } |
michael@0 | 221 | |
michael@0 | 222 | function testReceiving_GSM_MessageId() { |
michael@0 | 223 | log("Test receiving GSM Cell Broadcast - Message Identifier"); |
michael@0 | 224 | |
michael@0 | 225 | // Message Identifier has 16 bits, but no bitwise operation is needed. |
michael@0 | 226 | // Test some selected values only. |
michael@0 | 227 | let messageIdsToTest = [ |
michael@0 | 228 | 0x0000, 0x0001, 0x0010, 0x0100, 0x1000, 0x1111, 0x8888, 0x8811, |
michael@0 | 229 | ]; |
michael@0 | 230 | |
michael@0 | 231 | function do_test(messageId, nextTest) { |
michael@0 | 232 | let pdu = buildHexStr(0, 4) |
michael@0 | 233 | + buildHexStr((messageId & 0xFFFF), 4) |
michael@0 | 234 | + buildHexStr(0, (CB_MESSAGE_SIZE_GSM - 4) * 2); |
michael@0 | 235 | |
michael@0 | 236 | doTestHelper(pdu, nextTest, function(message) { |
michael@0 | 237 | is(message.messageId, messageId, "message.messageId"); |
michael@0 | 238 | ok(message.etws == null, "message.etws"); |
michael@0 | 239 | }); |
michael@0 | 240 | } |
michael@0 | 241 | |
michael@0 | 242 | repeat(do_test, messageIdsToTest, testReceiving_GSM_Language_and_Body); |
michael@0 | 243 | } |
michael@0 | 244 | |
michael@0 | 245 | // Copied from GsmPDUHelper.readCbDataCodingScheme |
michael@0 | 246 | function decodeDataCodingScheme(dcs) { |
michael@0 | 247 | let language = null; |
michael@0 | 248 | let hasLanguageIndicator = false; |
michael@0 | 249 | let encoding = PDU_DCS_MSG_CODING_7BITS_ALPHABET; |
michael@0 | 250 | let messageClass = PDU_DCS_MSG_CLASS_NORMAL; |
michael@0 | 251 | |
michael@0 | 252 | switch (dcs & PDU_DCS_CODING_GROUP_BITS) { |
michael@0 | 253 | case 0x00: // 0000 |
michael@0 | 254 | language = CB_DCS_LANG_GROUP_1[dcs & 0x0F]; |
michael@0 | 255 | break; |
michael@0 | 256 | |
michael@0 | 257 | case 0x10: // 0001 |
michael@0 | 258 | switch (dcs & 0x0F) { |
michael@0 | 259 | case 0x00: |
michael@0 | 260 | hasLanguageIndicator = true; |
michael@0 | 261 | break; |
michael@0 | 262 | case 0x01: |
michael@0 | 263 | encoding = PDU_DCS_MSG_CODING_16BITS_ALPHABET; |
michael@0 | 264 | hasLanguageIndicator = true; |
michael@0 | 265 | break; |
michael@0 | 266 | } |
michael@0 | 267 | break; |
michael@0 | 268 | |
michael@0 | 269 | case 0x20: // 0010 |
michael@0 | 270 | language = CB_DCS_LANG_GROUP_2[dcs & 0x0F]; |
michael@0 | 271 | break; |
michael@0 | 272 | |
michael@0 | 273 | case 0x40: // 01xx |
michael@0 | 274 | case 0x50: |
michael@0 | 275 | //case 0x60: |
michael@0 | 276 | //case 0x70: |
michael@0 | 277 | case 0x90: // 1001 |
michael@0 | 278 | encoding = (dcs & 0x0C); |
michael@0 | 279 | if (encoding == 0x0C) { |
michael@0 | 280 | encoding = PDU_DCS_MSG_CODING_7BITS_ALPHABET; |
michael@0 | 281 | } |
michael@0 | 282 | messageClass = (dcs & PDU_DCS_MSG_CLASS_BITS); |
michael@0 | 283 | break; |
michael@0 | 284 | |
michael@0 | 285 | case 0xF0: |
michael@0 | 286 | encoding = (dcs & 0x04) ? PDU_DCS_MSG_CODING_8BITS_ALPHABET |
michael@0 | 287 | : PDU_DCS_MSG_CODING_7BITS_ALPHABET; |
michael@0 | 288 | switch(dcs & PDU_DCS_MSG_CLASS_BITS) { |
michael@0 | 289 | case 0x01: messageClass = PDU_DCS_MSG_CLASS_USER_1; break; |
michael@0 | 290 | case 0x02: messageClass = PDU_DCS_MSG_CLASS_USER_2; break; |
michael@0 | 291 | case 0x03: messageClass = PDU_DCS_MSG_CLASS_TE_SPECIFIC; break; |
michael@0 | 292 | } |
michael@0 | 293 | break; |
michael@0 | 294 | |
michael@0 | 295 | case 0x30: // 0011 (Reserved) |
michael@0 | 296 | case 0x80: // 1000 (Reserved) |
michael@0 | 297 | case 0xA0: // 1010..1100 (Reserved) |
michael@0 | 298 | case 0xB0: |
michael@0 | 299 | case 0xC0: |
michael@0 | 300 | break; |
michael@0 | 301 | default: |
michael@0 | 302 | throw new Error("Unsupported CBS data coding scheme: " + dcs); |
michael@0 | 303 | } |
michael@0 | 304 | |
michael@0 | 305 | return [encoding, language, hasLanguageIndicator, |
michael@0 | 306 | GECKO_SMS_MESSAGE_CLASSES[messageClass]]; |
michael@0 | 307 | } |
michael@0 | 308 | |
michael@0 | 309 | function testReceiving_GSM_Language_and_Body() { |
michael@0 | 310 | log("Test receiving GSM Cell Broadcast - Language & Body"); |
michael@0 | 311 | |
michael@0 | 312 | function do_test(dcs) { |
michael@0 | 313 | let encoding, language, indicator, messageClass; |
michael@0 | 314 | try { |
michael@0 | 315 | [encoding, language, indicator, messageClass] = decodeDataCodingScheme(dcs); |
michael@0 | 316 | } catch (e) { |
michael@0 | 317 | // Unsupported coding group, skip. |
michael@0 | 318 | let nextGroup = (dcs & PDU_DCS_CODING_GROUP_BITS) + 0x10; |
michael@0 | 319 | window.setTimeout(do_test.bind(null, nextGroup), 0); |
michael@0 | 320 | return; |
michael@0 | 321 | } |
michael@0 | 322 | |
michael@0 | 323 | let pdu = buildHexStr(0, 8) |
michael@0 | 324 | + buildHexStr(dcs, 2) |
michael@0 | 325 | + buildHexStr(0, (CB_MESSAGE_SIZE_GSM - 5) * 2); |
michael@0 | 326 | |
michael@0 | 327 | let nextTest = (dcs < 0xFF) ? do_test.bind(null, dcs + 1) |
michael@0 | 328 | : testReceiving_GSM_Timestamp; |
michael@0 | 329 | doTestHelper(pdu, nextTest, function(message) { |
michael@0 | 330 | if (language) { |
michael@0 | 331 | is(message.language, language, "message.language"); |
michael@0 | 332 | } else if (indicator) { |
michael@0 | 333 | is(message.language, "@@", "message.language"); |
michael@0 | 334 | } else { |
michael@0 | 335 | ok(message.language == null, "message.language"); |
michael@0 | 336 | } |
michael@0 | 337 | |
michael@0 | 338 | switch (encoding) { |
michael@0 | 339 | case PDU_DCS_MSG_CODING_7BITS_ALPHABET: |
michael@0 | 340 | is(message.body, indicator ? BODY_7BITS_IND : BODY_7BITS, "message.body"); |
michael@0 | 341 | break; |
michael@0 | 342 | case PDU_DCS_MSG_CODING_8BITS_ALPHABET: |
michael@0 | 343 | ok(message.body == null, "message.body"); |
michael@0 | 344 | break; |
michael@0 | 345 | case PDU_DCS_MSG_CODING_16BITS_ALPHABET: |
michael@0 | 346 | is(message.body, indicator ? BODY_UCS2_IND : BODY_UCS2, "message.body"); |
michael@0 | 347 | break; |
michael@0 | 348 | } |
michael@0 | 349 | |
michael@0 | 350 | is(message.messageClass, messageClass, "message.messageClass"); |
michael@0 | 351 | }); |
michael@0 | 352 | } |
michael@0 | 353 | |
michael@0 | 354 | do_test(0); |
michael@0 | 355 | } |
michael@0 | 356 | |
michael@0 | 357 | function testReceiving_GSM_Timestamp() { |
michael@0 | 358 | log("Test receiving GSM Cell Broadcast - Timestamp"); |
michael@0 | 359 | |
michael@0 | 360 | let pdu = buildHexStr(0, CB_MESSAGE_SIZE_GSM * 2); |
michael@0 | 361 | doTestHelper(pdu, testReceiving_GSM_WarningType, function(message) { |
michael@0 | 362 | // Cell Broadcast messages do not contain a timestamp field (however, ETWS |
michael@0 | 363 | // does). We only check the timestamp doesn't go too far (60 seconds) here. |
michael@0 | 364 | let msMessage = message.timestamp.getTime(); |
michael@0 | 365 | let msNow = Date.now(); |
michael@0 | 366 | ok(Math.abs(msMessage - msNow) < (1000 * 60), "message.timestamp"); |
michael@0 | 367 | }); |
michael@0 | 368 | } |
michael@0 | 369 | |
michael@0 | 370 | function testReceiving_GSM_WarningType() { |
michael@0 | 371 | log("Test receiving GSM Cell Broadcast - Warning Type"); |
michael@0 | 372 | |
michael@0 | 373 | let messageIdsToTest = []; |
michael@0 | 374 | for (let i = CB_GSM_MESSAGEID_ETWS_BEGIN; i <= CB_GSM_MESSAGEID_ETWS_END; i++) { |
michael@0 | 375 | messageIdsToTest.push(i); |
michael@0 | 376 | } |
michael@0 | 377 | |
michael@0 | 378 | function do_test(messageId, nextTest) { |
michael@0 | 379 | let pdu = buildHexStr(0, 4) |
michael@0 | 380 | + buildHexStr((messageId & 0xFFFF), 4) |
michael@0 | 381 | + buildHexStr(0, (CB_MESSAGE_SIZE_GSM - 4) * 2); |
michael@0 | 382 | |
michael@0 | 383 | doTestHelper(pdu, nextTest, function(message) { |
michael@0 | 384 | is(message.messageId, messageId, "message.messageId"); |
michael@0 | 385 | ok(message.etws != null, "message.etws"); |
michael@0 | 386 | |
michael@0 | 387 | let offset = messageId - CB_GSM_MESSAGEID_ETWS_BEGIN; |
michael@0 | 388 | if (offset < CB_ETWS_WARNING_TYPE_NAMES.length) { |
michael@0 | 389 | is(message.etws.warningType, CB_ETWS_WARNING_TYPE_NAMES[offset], |
michael@0 | 390 | "message.etws.warningType"); |
michael@0 | 391 | } else { |
michael@0 | 392 | ok(message.etws.warningType == null, "message.etws.warningType"); |
michael@0 | 393 | } |
michael@0 | 394 | }); |
michael@0 | 395 | } |
michael@0 | 396 | |
michael@0 | 397 | repeat(do_test, messageIdsToTest, testReceiving_GSM_EmergencyUserAlert); |
michael@0 | 398 | } |
michael@0 | 399 | |
michael@0 | 400 | function doTestEmergencyUserAlert_or_Popup(name, mask, nextTest) { |
michael@0 | 401 | let pdu = buildHexStr(mask, 4) |
michael@0 | 402 | + buildHexStr(CB_GSM_MESSAGEID_ETWS_BEGIN, 4) |
michael@0 | 403 | + buildHexStr(0, (CB_MESSAGE_SIZE_GSM - 4) * 2); |
michael@0 | 404 | |
michael@0 | 405 | doTestHelper(pdu, nextTest, function(message) { |
michael@0 | 406 | is(message.messageId, CB_GSM_MESSAGEID_ETWS_BEGIN, "message.messageId"); |
michael@0 | 407 | ok(message.etws != null, "message.etws"); |
michael@0 | 408 | is(message.etws[name], mask != 0, "message.etws." + name); |
michael@0 | 409 | }); |
michael@0 | 410 | } |
michael@0 | 411 | |
michael@0 | 412 | function testReceiving_GSM_EmergencyUserAlert() { |
michael@0 | 413 | log("Test receiving GSM Cell Broadcast - Emergency User Alert"); |
michael@0 | 414 | |
michael@0 | 415 | repeat(doTestEmergencyUserAlert_or_Popup.bind(null, "emergencyUserAlert"), |
michael@0 | 416 | [0x2000, 0x0000], testReceiving_GSM_Popup); |
michael@0 | 417 | } |
michael@0 | 418 | |
michael@0 | 419 | function testReceiving_GSM_Popup() { |
michael@0 | 420 | log("Test receiving GSM Cell Broadcast - Popup"); |
michael@0 | 421 | |
michael@0 | 422 | repeat(doTestEmergencyUserAlert_or_Popup.bind(null, "popup"), |
michael@0 | 423 | [0x1000, 0x0000], testReceiving_GSM_Multipart); |
michael@0 | 424 | } |
michael@0 | 425 | |
michael@0 | 426 | function testReceiving_GSM_Multipart() { |
michael@0 | 427 | log("Test receiving GSM Cell Broadcast - Multipart Messages"); |
michael@0 | 428 | |
michael@0 | 429 | function do_test(numParts, nextTest) { |
michael@0 | 430 | let pdus = []; |
michael@0 | 431 | for (let i = 1; i <= numParts; i++) { |
michael@0 | 432 | let pdu = buildHexStr(0, 10) |
michael@0 | 433 | + buildHexStr((i << 4) + numParts, 2) |
michael@0 | 434 | + buildHexStr(0, (CB_MESSAGE_SIZE_GSM - 6) * 2); |
michael@0 | 435 | pdus.push(pdu); |
michael@0 | 436 | } |
michael@0 | 437 | |
michael@0 | 438 | doTestHelper(pdus, nextTest, function(message) { |
michael@0 | 439 | is(message.body.length, (numParts * CB_MAX_CONTENT_7BIT), |
michael@0 | 440 | "message.body"); |
michael@0 | 441 | }); |
michael@0 | 442 | } |
michael@0 | 443 | |
michael@0 | 444 | repeat(do_test, seq(16, 1), testReceiving_GSM_ServiceCategory); |
michael@0 | 445 | } |
michael@0 | 446 | |
michael@0 | 447 | function testReceiving_GSM_ServiceCategory() { |
michael@0 | 448 | log("Test receiving GSM Cell Broadcast - Service Category"); |
michael@0 | 449 | |
michael@0 | 450 | cbs.addEventListener("received", function onreceived(event) { |
michael@0 | 451 | cbs.removeEventListener("received", onreceived); |
michael@0 | 452 | |
michael@0 | 453 | let message = event.message; |
michael@0 | 454 | |
michael@0 | 455 | // Bug 910091 |
michael@0 | 456 | // "Service Category" is not defined in GSM. We should always get '0' here. |
michael@0 | 457 | is(message.cdmaServiceCategory, 0, "message.cdmaServiceCategory"); |
michael@0 | 458 | |
michael@0 | 459 | window.setTimeout(cleanUp, 0); |
michael@0 | 460 | }); |
michael@0 | 461 | |
michael@0 | 462 | let pdu = buildHexStr(0, CB_MESSAGE_SIZE_GSM * 2); |
michael@0 | 463 | sendCellBroadcastMessage(pdu); |
michael@0 | 464 | } |
michael@0 | 465 | |
michael@0 | 466 | function cleanUp() { |
michael@0 | 467 | if (pendingEmulatorCmdCount > 0) { |
michael@0 | 468 | window.setTimeout(cleanUp, 100); |
michael@0 | 469 | return; |
michael@0 | 470 | } |
michael@0 | 471 | |
michael@0 | 472 | SpecialPowers.removePermission("mobileconnection", document); |
michael@0 | 473 | SpecialPowers.removePermission("cellbroadcast", true, document); |
michael@0 | 474 | |
michael@0 | 475 | finish(); |
michael@0 | 476 | } |
michael@0 | 477 | |
michael@0 | 478 | waitFor(testGsmMessageAttributes, function() { |
michael@0 | 479 | return navigator.mozMobileConnections[0].voice.connected; |
michael@0 | 480 | }); |
michael@0 | 481 |