2013-01-14 01:05:26 -08:00
|
|
|
/* Any copyright is dedicated to the Public Domain.
|
|
|
|
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
|
|
|
|
|
|
MARIONETTE_TIMEOUT = 10000;
|
|
|
|
|
|
|
|
const CB_MESSAGE_SIZE_ETWS = 56;
|
|
|
|
|
|
|
|
const CB_GSM_GEOGRAPHICAL_SCOPE_NAMES = [
|
|
|
|
"cell-immediate",
|
|
|
|
"plmn",
|
|
|
|
"location-area",
|
|
|
|
"cell"
|
|
|
|
];
|
|
|
|
|
|
|
|
const CB_ETWS_WARNING_TYPE_NAMES = [
|
|
|
|
"earthquake",
|
|
|
|
"tsunami",
|
|
|
|
"earthquake-tsunami",
|
|
|
|
"test",
|
|
|
|
"other"
|
|
|
|
];
|
|
|
|
|
|
|
|
SpecialPowers.addPermission("cellbroadcast", true, document);
|
|
|
|
SpecialPowers.addPermission("mobileconnection", true, document);
|
|
|
|
|
|
|
|
let cbs = window.navigator.mozCellBroadcast;
|
2013-08-26 20:38:37 -07:00
|
|
|
ok(cbs instanceof window.MozCellBroadcast,
|
2013-01-14 01:05:26 -08:00
|
|
|
"mozCellBroadcast is instanceof " + cbs.constructor);
|
|
|
|
|
|
|
|
let pendingEmulatorCmdCount = 0;
|
|
|
|
function sendCellBroadcastMessage(pdu, callback) {
|
|
|
|
pendingEmulatorCmdCount++;
|
|
|
|
|
|
|
|
let cmd = "cbs pdu " + pdu;
|
|
|
|
runEmulatorCmd(cmd, function (result) {
|
|
|
|
pendingEmulatorCmdCount--;
|
|
|
|
|
|
|
|
is(result[0], "OK", "Emulator response");
|
|
|
|
|
|
|
|
if (callback) {
|
|
|
|
window.setTimeout(callback, 0);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function buildHexStr(n, numSemiOctets) {
|
|
|
|
let str = n.toString(16);
|
|
|
|
ok(str.length <= numSemiOctets);
|
|
|
|
while (str.length < numSemiOctets) {
|
|
|
|
str = "0" + str;
|
|
|
|
}
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
function seq(end, begin) {
|
|
|
|
let result = [];
|
|
|
|
for (let i = begin || 0; i < end; i++) {
|
|
|
|
result.push(i);
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
function repeat(func, array, oncomplete) {
|
|
|
|
(function do_call(index) {
|
|
|
|
let next = index < (array.length - 1) ? do_call.bind(null, index + 1) : oncomplete;
|
|
|
|
func.apply(null, [array[index], next]);
|
|
|
|
})(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
function doTestHelper(pdu, nextTest, checkFunc) {
|
|
|
|
cbs.addEventListener("received", function onreceived(event) {
|
|
|
|
cbs.removeEventListener("received", onreceived);
|
|
|
|
|
|
|
|
checkFunc(event.message);
|
|
|
|
|
|
|
|
window.setTimeout(nextTest, 0);
|
|
|
|
});
|
|
|
|
|
|
|
|
if (Array.isArray(pdu)) {
|
|
|
|
repeat(sendCellBroadcastMessage, pdu);
|
|
|
|
} else {
|
|
|
|
sendCellBroadcastMessage(pdu);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Tests receiving Cell Broadcast messages, event instance type, all attributes
|
|
|
|
* of CellBroadcastMessage exist.
|
|
|
|
*/
|
|
|
|
function testEtwsMessageAttributes() {
|
|
|
|
log("Test ETWS Primary Notification message attributes");
|
|
|
|
|
|
|
|
cbs.addEventListener("received", function onreceived(event) {
|
|
|
|
cbs.removeEventListener("received", onreceived);
|
|
|
|
|
2013-02-07 02:43:22 -08:00
|
|
|
// Bug 838542: following check throws an exception and fails this case.
|
|
|
|
// ok(event instanceof MozCellBroadcastEvent,
|
|
|
|
// "event is instanceof " + event.constructor)
|
2013-01-14 01:05:26 -08:00
|
|
|
ok(event, "event is valid");
|
|
|
|
|
|
|
|
let message = event.message;
|
|
|
|
ok(message, "event.message is valid");
|
|
|
|
|
|
|
|
// Attributes other than `language` and `body` should always be assigned.
|
|
|
|
ok(message.geographicalScope != null, "message.geographicalScope");
|
|
|
|
ok(message.messageCode != null, "message.messageCode");
|
|
|
|
ok(message.messageId != null, "message.messageId");
|
|
|
|
ok('language' in message, "message.language");
|
|
|
|
ok(message.language == null, "message.language");
|
|
|
|
ok('body' in message, "message.body");
|
|
|
|
ok(message.body == null, "message.body");
|
|
|
|
is(message.messageClass, "normal", "message.messageClass");
|
|
|
|
ok(message.timestamp != null, "message.timestamp");
|
|
|
|
ok(message.etws != null, "message.etws");
|
|
|
|
ok(message.etws.warningType != null, "message.etws.warningType");
|
|
|
|
ok(message.etws.emergencyUserAlert != null,
|
|
|
|
"message.etws.emergencyUserAlert");
|
|
|
|
ok(message.etws.popup != null, "message.etws.popup");
|
|
|
|
|
|
|
|
window.setTimeout(testReceiving_ETWS_GeographicalScope, 0);
|
|
|
|
});
|
|
|
|
|
|
|
|
// Here we use a simple ETWS message for test.
|
|
|
|
let pdu = buildHexStr(0, CB_MESSAGE_SIZE_ETWS * 2); // 6 octets
|
|
|
|
sendCellBroadcastMessage(pdu);
|
|
|
|
}
|
|
|
|
|
|
|
|
function testReceiving_ETWS_GeographicalScope() {
|
|
|
|
log("Test receiving ETWS Primary Notification - Geographical Scope");
|
|
|
|
|
|
|
|
function do_test(gs, nextTest) {
|
|
|
|
// Here we use a simple ETWS message for test.
|
|
|
|
let pdu = buildHexStr(((gs & 0x03) << 14), 4)
|
|
|
|
+ buildHexStr(0, (CB_MESSAGE_SIZE_ETWS - 2) * 2);
|
|
|
|
|
|
|
|
doTestHelper(pdu, nextTest, function (message) {
|
|
|
|
is(message.geographicalScope, CB_GSM_GEOGRAPHICAL_SCOPE_NAMES[gs],
|
|
|
|
"message.geographicalScope");
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
repeat(do_test, seq(CB_GSM_GEOGRAPHICAL_SCOPE_NAMES.length),
|
|
|
|
testReceiving_ETWS_MessageCode);
|
|
|
|
}
|
|
|
|
|
|
|
|
function testReceiving_ETWS_MessageCode() {
|
|
|
|
log("Test receiving ETWS Primary Notification - Message Code");
|
|
|
|
|
|
|
|
// Message Code has 10 bits, and is ORed into a 16 bits 'serial' number. Here
|
|
|
|
// we test every single bit to verify the operation doesn't go wrong.
|
|
|
|
let messageCodesToTest = [
|
|
|
|
0x000, 0x001, 0x002, 0x004, 0x008, 0x010, 0x020, 0x040,
|
|
|
|
0x080, 0x100, 0x200, 0x251
|
|
|
|
];
|
|
|
|
|
|
|
|
function do_test(messageCode, nextTest) {
|
|
|
|
let pdu = buildHexStr(((messageCode & 0x3FF) << 4), 4)
|
|
|
|
+ buildHexStr(0, (CB_MESSAGE_SIZE_ETWS - 2) * 2);
|
|
|
|
|
|
|
|
doTestHelper(pdu, nextTest, function (message) {
|
|
|
|
is(message.messageCode, messageCode, "message.messageCode");
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
repeat(do_test, messageCodesToTest, testReceiving_ETWS_MessageId);
|
|
|
|
}
|
|
|
|
|
|
|
|
function testReceiving_ETWS_MessageId() {
|
|
|
|
log("Test receiving ETWS Primary Notification - Message Identifier");
|
|
|
|
|
|
|
|
// Message Identifier has 16 bits, but no bitwise operation is needed.
|
|
|
|
// Test some selected values only.
|
|
|
|
let messageIdsToTest = [
|
|
|
|
0x0000, 0x0001, 0x0010, 0x0100, 0x1000, 0x1111, 0x8888, 0x8811
|
|
|
|
];
|
|
|
|
|
|
|
|
function do_test(messageId, nextTest) {
|
|
|
|
let pdu = buildHexStr(0, 4)
|
|
|
|
+ buildHexStr((messageId & 0xFFFF), 4)
|
|
|
|
+ buildHexStr(0, (CB_MESSAGE_SIZE_ETWS - 4) * 2);
|
|
|
|
|
|
|
|
doTestHelper(pdu, nextTest, function (message) {
|
|
|
|
is(message.messageId, messageId, "message.messageId");
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
repeat(do_test, messageIdsToTest, testReceiving_ETWS_Timestamp);
|
|
|
|
}
|
|
|
|
|
|
|
|
function testReceiving_ETWS_Timestamp() {
|
|
|
|
log("Test receiving ETWS Primary Notification - Timestamp");
|
|
|
|
|
|
|
|
// Here we use a simple ETWS message for test.
|
|
|
|
let pdu = buildHexStr(0, 12); // 6 octets
|
|
|
|
doTestHelper(pdu, testReceiving_ETWS_WarningType, function (message) {
|
|
|
|
// Cell Broadcast messages do not contain a timestamp field (however, ETWS
|
|
|
|
// does). We only check the timestamp doesn't go too far (60 seconds) here.
|
|
|
|
let msMessage = message.timestamp.getTime();
|
|
|
|
let msNow = Date.now();
|
|
|
|
ok(Math.abs(msMessage - msNow) < (1000 * 60), "message.timestamp");
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function testReceiving_ETWS_WarningType() {
|
|
|
|
log("Test receiving ETWS Primary Notification - Warning Type");
|
|
|
|
|
|
|
|
// Warning Type has 7 bits, and is ORed into a 16 bits 'WarningType' field.
|
|
|
|
// Here we test every single bit to verify the operation doesn't go wrong.
|
|
|
|
let warningTypesToTest = [
|
|
|
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x08, 0x10, 0x20, 0x40, 0x41
|
|
|
|
];
|
|
|
|
|
|
|
|
function do_test(warningType, nextTest) {
|
|
|
|
let pdu = buildHexStr(0, 8)
|
|
|
|
+ buildHexStr(((warningType & 0x7F) << 9), 4)
|
|
|
|
+ buildHexStr(0, (CB_MESSAGE_SIZE_ETWS - 6) * 2);
|
|
|
|
|
|
|
|
doTestHelper(pdu, nextTest, function (message) {
|
|
|
|
ok(message.etws, "message.etws");
|
|
|
|
is(message.etws.warningType, CB_ETWS_WARNING_TYPE_NAMES[warningType],
|
|
|
|
"message.etws.warningType");
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
repeat(do_test, warningTypesToTest, testReceiving_ETWS_EmergencyUserAlert);
|
|
|
|
}
|
|
|
|
|
|
|
|
function doTestEmergencyUserAlert_or_Popup(name, mask, nextTest) {
|
|
|
|
let pdu = buildHexStr(0, 8)
|
|
|
|
+ buildHexStr(mask, 4)
|
|
|
|
+ buildHexStr(0, (CB_MESSAGE_SIZE_ETWS - 6) * 2);
|
|
|
|
doTestHelper(pdu, nextTest, function (message) {
|
|
|
|
ok(message.etws != null, "message.etws");
|
|
|
|
is(message.etws[name], mask != 0, "message.etws." + name);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function testReceiving_ETWS_EmergencyUserAlert() {
|
|
|
|
log("Test receiving ETWS Primary Notification - Emergency User Alert");
|
|
|
|
|
|
|
|
repeat(doTestEmergencyUserAlert_or_Popup.bind(null, "emergencyUserAlert"),
|
|
|
|
[0x100, 0x000], testReceiving_ETWS_Popup);
|
|
|
|
}
|
|
|
|
|
|
|
|
function testReceiving_ETWS_Popup() {
|
|
|
|
log("Test receiving ETWS Primary Notification - Popup");
|
|
|
|
|
|
|
|
repeat(doTestEmergencyUserAlert_or_Popup.bind(null, "popup"),
|
|
|
|
[0x80, 0x000], cleanUp);
|
|
|
|
}
|
|
|
|
|
|
|
|
function cleanUp() {
|
|
|
|
if (pendingEmulatorCmdCount > 0) {
|
|
|
|
window.setTimeout(cleanUp, 100);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SpecialPowers.removePermission("mobileconnection", document);
|
|
|
|
SpecialPowers.removePermission("cellbroadcast", true, document);
|
|
|
|
|
|
|
|
finish();
|
|
|
|
}
|
|
|
|
|
|
|
|
waitFor(testEtwsMessageAttributes, function () {
|
|
|
|
return navigator.mozMobileConnection.voice.connected;
|
|
|
|
});
|
|
|
|
|