Bug 1072808 - Part 2: Add SmsMessenger as a Wrapper for Sms-Related System Messages. r=echen

This commit is contained in:
Bevis Tseng 2014-10-24 11:33:01 +08:00
Родитель 17c1f46219
Коммит 24d942773e
7 изменённых файлов: 373 добавлений и 23 удалений

Просмотреть файл

@ -21,6 +21,7 @@ XPIDL_SOURCES += [
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['MOZ_B2G_RIL']:
XPIDL_SOURCES += [
'nsIRilMobileMessageDatabaseService.idl',
'nsISmsMessenger.idl',
]
XPIDL_MODULE = 'dom_mobilemessage'

Просмотреть файл

@ -0,0 +1,69 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "domstubs.idl"
#include "nsISupports.idl"
[scriptable, uuid(f77ad4d4-68a9-11e4-920f-0b26b7a5e713)]
interface nsISmsMessenger : nsISupports
{
/* 'sms-received' system message */
const unsigned short NOTIFICATION_TYPE_RECEIVED = 0;
/* 'sms-sent' system message */
const unsigned short NOTIFICATION_TYPE_SENT = 1;
/* 'sms-delivery-success' system message */
const unsigned short NOTIFICATION_TYPE_DELIVERY_SUCCESS = 2;
/**
* To broadcast 'sms-received', 'sms-delivery-success', 'sms-sent' system message
*
* Note: Except aNotificationType, all parameters are the attributes of the
* nsIDOMMozSmsMessage generated by nsIMobileMessageService.createSmsMessage().
*
* @param aNotificationType
* A predefined constant of nsISmsMessenger.NOTIFICATION_TYPE_*.
* @param aId
* The unique identity of this message.
* @param aThreadId
* The unique identity of the thread this message belongs to.
* @param aIccId
* Integrated Circuit Card Identifier. null if ICC is not available.
* @param aDelivery
* A predefined constant of nsISmsService.DELIVERY_TYPE_*.
* @param aDeliveryStatus
* A predefined constant of nsISmsService.DELIVERY_STATUS_TYPE_*.
* @param aSender
* Sender address. null if not available.
* @param aReceiver
* Receiver address. null if not available.
* @param aBody
* Text message body. null if not available.
* @param aMessageClass
* A predefined constant of nsISmsService.MESSAGE_CLASS_TYPE_*.
* @param aTimestamp
* The device system time when creating or saving this message.
* @param aSentTimestamp
* The SMSC timestamp of the incoming message.
* 0 if not available.
* @param aDeliveryTimestamp
* The delivery timestamp to the remote party of the sent message.
* 0 if not available.
* @param aRead
* True if the message was read.
*/
void notifySms(in unsigned short aNotificationType,
in long aId,
in unsigned long long aThreadId,
in DOMString aIccId,
in unsigned long aDelivery,
in unsigned long aDeliveryStatus,
in DOMString aSender,
in DOMString aReceiver,
in DOMString aBody,
in unsigned long aMessageClass,
in DOMTimeStamp aTimestamp,
in DOMTimeStamp aSentTimestamp,
in DOMTimeStamp aDeliveryTimestamp,
in boolean aRead);
};

Просмотреть файл

@ -12,9 +12,35 @@ interface nsIMobileMessageCallback;
#define SMS_SERVICE_CONTRACTID "@mozilla.org/sms/smsservice;1"
%}
[scriptable, builtinclass, uuid(cb7d7b60-01f1-4241-a0ae-2ff035c3fbe5)]
[scriptable, builtinclass, uuid(8f86d068-698e-11e4-9470-8f75a088b84a)]
interface nsISmsService : nsISupports
{
/**
* Constant definitions of predefined GSM Message Class
* See 3GPP TS 23.038 clause 4 SMS Data Coding Scheme
*/
const unsigned short MESSAGE_CLASS_TYPE_CLASS_0 = 0;
const unsigned short MESSAGE_CLASS_TYPE_CLASS_1 = 1;
const unsigned short MESSAGE_CLASS_TYPE_CLASS_2 = 2;
const unsigned short MESSAGE_CLASS_TYPE_CLASS_3 = 3;
const unsigned short MESSAGE_CLASS_TYPE_NORMAL = 6;
/**
* Constant definitions of SMS Delivery
*/
const unsigned short DELIVERY_TYPE_RECEIVED = 0;
const unsigned short DELIVERY_TYPE_SENDING = 1;
const unsigned short DELIVERY_TYPE_SENT = 2;
const unsigned short DELIVERY_TYPE_ERROR = 3;
/**
* Constant definitions of SMS Delivery Status
*/
const unsigned short DELIVERY_STATUS_TYPE_NOT_APPLICABLE = 0;
const unsigned short DELIVERY_STATUS_TYPE_SUCCESS = 1;
const unsigned short DELIVERY_STATUS_TYPE_PENDING = 2;
const unsigned short DELIVERY_STATUS_TYPE_ERROR = 3;
readonly attribute unsigned long smsDefaultServiceId;
void getSegmentInfoForText(in DOMString text,

Просмотреть файл

@ -4,6 +4,16 @@
"use strict";
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyGetter(this, "RIL", function () {
let obj = {};
Cu.import("resource://gre/modules/ril_consts.js", obj);
return obj;
});
/**
* RILSystemMessenger
*/
@ -48,6 +58,54 @@ RILSystemMessenger.prototype = {
}
this.broadcastMessage("telephony-call-ended", data);
},
_convertSmsMessageClass: function(aMessageClass) {
return RIL.GECKO_SMS_MESSAGE_CLASSES[aMessageClass] || null;
},
_convertSmsDelivery: function(aDelivery) {
return ["received", "sending", "sent", "error"][aDelivery] || null;
},
_convertSmsDeliveryStatus: function(aDeliveryStatus) {
return [
RIL.GECKO_SMS_DELIVERY_STATUS_NOT_APPLICABLE,
RIL.GECKO_SMS_DELIVERY_STATUS_SUCCESS,
RIL.GECKO_SMS_DELIVERY_STATUS_PENDING,
RIL.GECKO_SMS_DELIVERY_STATUS_ERROR
][aDeliveryStatus] || null;
},
/**
* Wrapper to send 'sms-received', 'sms-delivery-success', 'sms-sent' system message.
*/
notifySms: function(aNotificationType, aId, aThreadId, aIccId, aDelivery,
aDeliveryStatus, aSender, aReceiver, aBody, aMessageClass,
aTimestamp, aSentTimestamp, aDeliveryTimestamp, aRead) {
let msgType =
["sms-received", "sms-sent", "sms-delivery-success"][aNotificationType];
if (!msgType) {
throw new Error("Invalid Notification Type: " + aNotificationType);
}
this.broadcastMessage(msgType, {
iccId: aIccId,
type: "sms",
id: aId,
threadId: aThreadId,
delivery: this._convertSmsDelivery(aDelivery),
deliveryStatus: this._convertSmsDeliveryStatus(aDeliveryStatus),
sender: aSender,
receiver: aReceiver,
body: aBody,
messageClass: this._convertSmsMessageClass(aMessageClass),
timestamp: aTimestamp,
sentTimestamp: aSentTimestamp,
deliveryTimestamp: aDeliveryTimestamp,
read: aRead
});
}
};

Просмотреть файл

@ -49,7 +49,8 @@ function RILSystemMessengerHelper() {
RILSystemMessengerHelper.prototype = {
classID: RILSYSTEMMESSENGERHELPER_CID,
QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephonyMessenger]),
QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephonyMessenger,
Ci.nsISmsMessenger]),
/**
* RILSystemMessenger instance.
@ -67,6 +68,17 @@ RILSystemMessengerHelper.prototype = {
aDuration, aOutgoing, aHangUpLocal) {
this.messenger.notifyCallEnded(aServiceId, aNumber, aCdmaWaitingNumber, aEmergency,
aDuration, aOutgoing, aHangUpLocal);
},
/**
* nsISmsMessenger API
*/
notifySms: function(aNotificationType, aId, aThreadId, aIccId, aDelivery,
aDeliveryStatus, aSender, aReceiver, aBody, aMessageClass,
aTimestamp, aSentTimestamp, aDeliveryTimestamp, aRead) {
this.messenger.notifySms(aNotificationType, aId, aThreadId, aIccId, aDelivery,
aDeliveryStatus, aSender, aReceiver, aBody, aMessageClass,
aTimestamp, aSentTimestamp, aDeliveryTimestamp, aRead);
}
};

Просмотреть файл

@ -187,6 +187,10 @@ XPCOMUtils.defineLazyServiceGetter(this, "gCellBroadcastService",
"@mozilla.org/cellbroadcast/gonkservice;1",
"nsIGonkCellBroadcastService");
XPCOMUtils.defineLazyServiceGetter(this, "gSmsMessenger",
"@mozilla.org/ril/system-messenger-helper;1",
"nsISmsMessenger");
XPCOMUtils.defineLazyGetter(this, "WAP", function() {
let wap = {};
Cu.import("resource://gre/modules/WapPushManager.js", wap);
@ -2171,6 +2175,42 @@ RadioInterface.prototype = {
0, options);
},
_convertSmsMessageClass: function(aMessageClass) {
let index = RIL.GECKO_SMS_MESSAGE_CLASSES.indexOf(aMessageClass);
if (index < 0) {
throw new Error("Invalid MessageClass: " + aMessageClass);
}
return index;
},
_convertSmsDelivery: function(aDelivery) {
let index = [DOM_MOBILE_MESSAGE_DELIVERY_RECEIVED,
DOM_MOBILE_MESSAGE_DELIVERY_SENDING,
DOM_MOBILE_MESSAGE_DELIVERY_SENT,
DOM_MOBILE_MESSAGE_DELIVERY_ERROR].indexOf(aDelivery);
if (index < 0) {
throw new Error("Invalid Delivery: " + aDelivery);
}
return index;
},
_convertSmsDeliveryStatus: function(aDeliveryStatus) {
let index = [RIL.GECKO_SMS_DELIVERY_STATUS_NOT_APPLICABLE,
RIL.GECKO_SMS_DELIVERY_STATUS_SUCCESS,
RIL.GECKO_SMS_DELIVERY_STATUS_PENDING,
RIL.GECKO_SMS_DELIVERY_STATUS_ERROR].indexOf(aDeliveryStatus);
if (index < 0) {
throw new Error("Invalid DeliveryStatus: " + aDeliveryStatus);
}
return index;
},
/**
* A helper to broadcast the system message to launch registered apps
* like Costcontrol, Notification and Message app... etc.
@ -2180,28 +2220,35 @@ RadioInterface.prototype = {
* @param aDomMessage
* The nsIDOMMozSmsMessage object.
*/
broadcastSmsSystemMessage: function(aName, aDomMessage) {
if (DEBUG) this.debug("Broadcasting the SMS system message: " + aName);
broadcastSmsSystemMessage: function(aNotificationType, aDomMessage) {
if (DEBUG) this.debug("Broadcasting the SMS system message: " + aNotificationType);
// Sadly we cannot directly broadcast the aDomMessage object
// because the system message mechamism will rewrap the object
// based on the content window, which needs to know the properties.
gSystemMessenger.broadcastMessage(aName, {
iccId: aDomMessage.iccId,
type: aDomMessage.type,
id: aDomMessage.id,
threadId: aDomMessage.threadId,
delivery: aDomMessage.delivery,
deliveryStatus: aDomMessage.deliveryStatus,
sender: aDomMessage.sender,
receiver: aDomMessage.receiver,
body: aDomMessage.body,
messageClass: aDomMessage.messageClass,
timestamp: aDomMessage.timestamp,
sentTimestamp: aDomMessage.sentTimestamp,
deliveryTimestamp: aDomMessage.deliveryTimestamp,
read: aDomMessage.read
});
try {
gSmsMessenger.notifySms(aNotificationType,
aDomMessage.id,
aDomMessage.threadId,
aDomMessage.iccId,
this._convertSmsDelivery(
aDomMessage.delivery),
this._convertSmsDeliveryStatus(
aDomMessage.deliveryStatus),
aDomMessage.sender,
aDomMessage.receiver,
aDomMessage.body,
this._convertSmsMessageClass(
aDomMessage.messageClass),
aDomMessage.timestamp,
aDomMessage.sentTimestamp,
aDomMessage.deliveryTimestamp,
aDomMessage.read);
} catch (e) {
if (DEBUG) {
this.debug("Failed to broadcastSmsSystemMessage: " + e);
}
}
},
// The following attributes/functions are used for acquiring/releasing the
@ -2546,7 +2593,8 @@ RadioInterface.prototype = {
return;
}
this.broadcastSmsSystemMessage(kSmsReceivedObserverTopic, domMessage);
this.broadcastSmsSystemMessage(
Ci.nsISmsMessenger.NOTIFICATION_TYPE_RECEIVED, domMessage);
Services.obs.notifyObservers(domMessage, kSmsReceivedObserverTopic, null);
}.bind(this);
@ -3663,7 +3711,8 @@ RadioInterface.prototype = {
// Broadcasting a "sms-delivery-success" system message to open apps.
if (topic == kSmsDeliverySuccessObserverTopic) {
this.broadcastSmsSystemMessage(topic, domMessage);
this.broadcastSmsSystemMessage(
Ci.nsISmsMessenger.NOTIFICATION_TYPE_DELIVERY_SUCCESS, domMessage);
}
// Notifying observers the delivery status is updated.
@ -3711,7 +3760,8 @@ RadioInterface.prototype = {
context.sms = domMessage;
}
this.broadcastSmsSystemMessage(kSmsSentObserverTopic, domMessage);
this.broadcastSmsSystemMessage(
Ci.nsISmsMessenger.NOTIFICATION_TYPE_SENT, domMessage);
context.request.notifyMessageSent(domMessage);
Services.obs.notifyObservers(domMessage, kSmsSentObserverTopic, null);
}).bind(this));

Просмотреть файл

@ -48,7 +48,11 @@ function run_test() {
let telephonyMessenger = Cc["@mozilla.org/ril/system-messenger-helper;1"]
.getService(Ci.nsITelephonyMessenger);
let smsMessenger = Cc["@mozilla.org/ril/system-messenger-helper;1"]
.getService(Ci.nsISmsMessenger);
ok(telephonyMessenger !== null, "Get TelephonyMessenger.");
ok(smsMessenger != null, "Get SmsMessenger.");
run_next_test();
}
@ -109,3 +113,133 @@ add_test(function test_telephony_messenger_notify_call_ended() {
run_next_test();
});
/**
* Verify RILSystemMessenger.notifySms()
*/
add_test(function test_sms_messenger_notify_sms() {
let messenger = newRILSystemMessenger();
let timestamp = Date.now();
let sentTimestamp = timestamp + 100;
let deliveryTimestamp = sentTimestamp + 100;
// Verify 'sms-received' system message.
messenger.notifySms(Ci.nsISmsMessenger.NOTIFICATION_TYPE_RECEIVED,
1,
2,
"99887766554433221100",
Ci.nsISmsService.DELIVERY_TYPE_RECEIVED,
Ci.nsISmsService.DELIVERY_STATUS_TYPE_SUCCESS,
"+0987654321",
null,
"Incoming message",
Ci.nsISmsService.MESSAGE_CLASS_TYPE_CLASS_2,
timestamp,
sentTimestamp,
0,
false);
equal_received_system_message("sms-received", {
iccId: "99887766554433221100",
type: "sms",
id: 1,
threadId: 2,
delivery: "received",
deliveryStatus: "success",
sender: "+0987654321",
receiver: null,
body: "Incoming message",
messageClass: "class-2",
timestamp: timestamp,
sentTimestamp: sentTimestamp,
deliveryTimestamp: 0,
read: false
});
// Verify 'sms-sent' system message.
messenger.notifySms(Ci.nsISmsMessenger.NOTIFICATION_TYPE_SENT,
3,
4,
"99887766554433221100",
Ci.nsISmsService.DELIVERY_TYPE_SENT,
Ci.nsISmsService.DELIVERY_STATUS_TYPE_PENDING,
null,
"+0987654321",
"Outgoing message",
Ci.nsISmsService.MESSAGE_CLASS_TYPE_NORMAL,
timestamp,
0,
0,
true);
equal_received_system_message("sms-sent", {
iccId: "99887766554433221100",
type: "sms",
id: 3,
threadId: 4,
delivery: "sent",
deliveryStatus: "pending",
sender: null,
receiver: "+0987654321",
body: "Outgoing message",
messageClass: "normal",
timestamp: timestamp,
sentTimestamp: 0,
deliveryTimestamp: 0,
read: true
});
// Verify 'sms-delivery-success' system message.
messenger.notifySms(Ci.nsISmsMessenger.NOTIFICATION_TYPE_DELIVERY_SUCCESS,
5,
6,
"99887766554433221100",
Ci.nsISmsService.DELIVERY_TYPE_SENT,
Ci.nsISmsService.DELIVERY_STATUS_TYPE_SUCCESS,
null,
"+0987654321",
"Outgoing message",
Ci.nsISmsService.MESSAGE_CLASS_TYPE_NORMAL,
timestamp,
0,
deliveryTimestamp,
true);
equal_received_system_message("sms-delivery-success", {
iccId: "99887766554433221100",
type: "sms",
id: 5,
threadId: 6,
delivery: "sent",
deliveryStatus: "success",
sender: null,
receiver: "+0987654321",
body: "Outgoing message",
messageClass: "normal",
timestamp: timestamp,
sentTimestamp: 0,
deliveryTimestamp: deliveryTimestamp,
read: true
});
// Verify the protection of invalid nsISmsMessenger.NOTIFICATION_TYPEs.
try {
messenger.notifySms(3,
1,
2,
"99887766554433221100",
Ci.nsISmsService.DELIVERY_TYPE_RECEIVED,
Ci.nsISmsService.DELIVERY_STATUS_TYPE_SUCCESS,
"+0987654321",
null,
"Incoming message",
Ci.nsISmsService.MESSAGE_CLASS_TYPE_NORMAL,
timestamp,
sentTimestamp,
0,
false);
ok(false, "Failed to verify the protection of invalid nsISmsMessenger.NOTIFICATION_TYPE!");
} catch (e) {}
run_next_test();
});