diff --git a/dom/mobilemessage/interfaces/nsIRilMobileMessageDatabaseService.idl b/dom/mobilemessage/interfaces/nsIRilMobileMessageDatabaseService.idl index 87169c328bf0..609447ddcc4a 100644 --- a/dom/mobilemessage/interfaces/nsIRilMobileMessageDatabaseService.idl +++ b/dom/mobilemessage/interfaces/nsIRilMobileMessageDatabaseService.idl @@ -2,30 +2,42 @@ * 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" #include "nsIMobileMessageDatabaseService.idl" -interface nsIDOMMozSmsMessage; - -[scriptable, function, uuid(9cd80750-6a08-11e2-ac93-bf895e53f40e)] +[scriptable, function, uuid(0bffae74-71db-11e2-962a-73cf64d6393e)] interface nsIRilMobileMessageDatabaseCallback : nsISupports { - void notify(in nsresult aRv, in nsIDOMMozSmsMessage aSms); + /** + * |aRecord| Object: the mobile-message database record + */ + void notify(in nsresult aRv, in jsval aRecord); }; -[scriptable, uuid(89528354-6a08-11e2-8243-af4cf90404a9)] +[scriptable, uuid(3592525a-71d6-11e2-82ca-f75ae6e08ee2)] interface nsIRilMobileMessageDatabaseService : nsIMobileMessageDatabaseService { - long saveReceivedMessage(in DOMString aSender, - in DOMString aBody, - in DOMString aMessageClass, - in unsigned long long aDate, + /** + * |aMessage| Object: should contain the following properties for internal use: + * - |type| DOMString: "sms" or "mms" + * - |sender| DOMString: the phone number of sender + * - |timestamp| Number: the timestamp of received message + * - |messageClass| DOMString: the message class of received message + */ + long saveReceivedMessage(in jsval aMessage, [optional] in nsIRilMobileMessageDatabaseCallback aCallback); - long saveSendingMessage(in DOMString aReceiver, - in DOMString aBody, - in DOMString aDeliveryStatus, - in unsigned long long aDate, + + /** + * |aMessage| Object: should contain the following properties for internal use: + * - |type| DOMString: "sms" or "mms" + * - |receiver| DOMString: the phone number of receiver + * - |timestamp| Number: the timestamp of sending message + * - |deliveryStatus| DOMString: the delivery status of sending message + */ + long saveSendingMessage(in jsval aMessage, [optional] in nsIRilMobileMessageDatabaseCallback aCallback); + void setMessageDelivery(in long aMessageId, in DOMString aDelivery, in DOMString aDeliveryStatus, diff --git a/dom/mobilemessage/src/ril/MobileMessageDatabaseService.js b/dom/mobilemessage/src/ril/MobileMessageDatabaseService.js index 4d8f02d1f430..a53765504c2e 100644 --- a/dom/mobilemessage/src/ril/MobileMessageDatabaseService.js +++ b/dom/mobilemessage/src/ril/MobileMessageDatabaseService.js @@ -413,8 +413,8 @@ MobileMessageDatabaseService.prototype = { }; }, - createMessageFromRecord: function createMessageFromRecord(aRecord) { - if (DEBUG) debug("createMessageFromRecord: " + JSON.stringify(aRecord)); + createSmsMessageFromRecord: function createSmsMessageFromRecord(aRecord) { + if (DEBUG) debug("createSmsMessageFromRecord: " + JSON.stringify(aRecord)); return gSmsService.createSmsMessage(aRecord.id, aRecord.delivery, aRecord.deliveryStatus, @@ -482,7 +482,7 @@ MobileMessageDatabaseService.prototype = { let getRequest = aObjectStore.get(firstMessageId); let self = this; getRequest.onsuccess = function onsuccess(event) { - let sms = self.createMessageFromRecord(event.target.result); + let sms = self.createSmsMessageFromRecord(event.target.result); if (aMessageList.listId >= 0) { if (DEBUG) { debug("notifyNextMessageInListGot - listId: " @@ -657,8 +657,7 @@ MobileMessageDatabaseService.prototype = { if (!aCallback) { return; } - let sms = self.createMessageFromRecord(aRecord); - aCallback.notify(rv, sms); + aCallback.notify(rv, aRecord); } this.newTxn(READ_WRITE, function(error, txn, stores) { @@ -678,9 +677,8 @@ MobileMessageDatabaseService.prototype = { // First add to main objectStore. stores[0].put(aRecord); - let number = getNumberFromRecord(aRecord); - // Next update the other objectStore. + let number = getNumberFromRecord(aRecord); stores[1].get(number).onsuccess = function onsuccess(event) { let mostRecentEntry = event.target.result; if (mostRecentEntry) { @@ -713,100 +711,96 @@ MobileMessageDatabaseService.prototype = { return aRecord.id; }, + getRilIccInfoMsisdn: function getRilIccInfoMsisdn() { + let iccInfo = this.mRIL.rilContext.iccInfo; + let number = iccInfo ? iccInfo.msisdn : null; + + // Workaround an xpconnect issue with undefined string objects. + // See bug 808220 + if (number === undefined || number === "undefined") { + return null; + } + return number; + }, + + makePhoneNumberInternational: function makePhoneNumberInternational(aNumber) { + if (!aNumber) { + return aNumber; + } + let parsedNumber = PhoneNumberUtils.parse(aNumber.toString()); + if (!parsedNumber || !parsedNumber.internationalNumber) { + return aNumber; + } + return parsedNumber.internationalNumber; + }, /** * nsIRilMobileMessageDatabaseService API */ - saveReceivedMessage: function saveReceivedMessage( - aSender, aBody, aMessageClass, aDate, aCallback) { - let iccInfo = this.mRIL.rilContext.iccInfo; - let receiver = iccInfo ? iccInfo.msisdn : null; - - // Workaround an xpconnect issue with undefined string objects. - // See bug 808220 - if (receiver === undefined || receiver === "undefined") { - receiver = null; + saveReceivedMessage: function saveReceivedMessage(aMessage, aCallback) { + if (aMessage.type === undefined || + aMessage.sender === undefined || + aMessage.messageClass === undefined || + aMessage.timestamp === undefined) { + if (aCallback) { + aCallback.notify(Cr.NS_ERROR_FAILURE, null); + } + return; } - if (receiver) { - let parsedNumber = PhoneNumberUtils.parse(receiver); - receiver = (parsedNumber && parsedNumber.internationalNumber) - ? parsedNumber.internationalNumber - : receiver; - } + let receiver = this.getRilIccInfoMsisdn(); + receiver = this.makePhoneNumberInternational(receiver); - let sender = aSender; - if (sender) { - let parsedNumber = PhoneNumberUtils.parse(sender); - sender = (parsedNumber && parsedNumber.internationalNumber) - ? parsedNumber.internationalNumber - : sender; - } + let sender = aMessage.sender = + this.makePhoneNumberInternational(aMessage.sender); - let record = { - deliveryIndex: [DELIVERY_RECEIVED, aDate], - numberIndex: [[sender, aDate], [receiver, aDate]], - readIndex: [FILTER_READ_UNREAD, aDate], + let timestamp = aMessage.timestamp; - delivery: DELIVERY_RECEIVED, - deliveryStatus: DELIVERY_STATUS_SUCCESS, - sender: sender, - receiver: receiver, - body: aBody, - messageClass: aMessageClass, - timestamp: aDate, - read: FILTER_READ_UNREAD - }; - return this.saveRecord(record, aCallback); + // Adding needed indexes and extra attributes for internal use. + aMessage.deliveryIndex = [DELIVERY_RECEIVED, timestamp]; + aMessage.numberIndex = [[sender, timestamp], [receiver, timestamp]]; + aMessage.readIndex = [FILTER_READ_UNREAD, timestamp]; + aMessage.delivery = DELIVERY_RECEIVED; + aMessage.deliveryStatus = DELIVERY_STATUS_SUCCESS; + aMessage.receiver = receiver; + aMessage.read = FILTER_READ_UNREAD; + + return this.saveRecord(aMessage, aCallback); }, - saveSendingMessage: function saveSendingMessage( - aReceiver, aBody, aDeliveryStatus, aDate, aCallback) { + saveSendingMessage: function saveSendingMessage(aMessage, aCallback) { + if (aMessage.type === undefined || + aMessage.receiver === undefined || + aMessage.deliveryStatus === undefined || + aMessage.timestamp === undefined) { + if (aCallback) { + aCallback.notify(Cr.NS_ERROR_FAILURE, null); + } + return; + } + + let sender = this.getRilIccInfoMsisdn(); + let receiver = aMessage.receiver; + let rilContext = this.mRIL.rilContext; - let sender = rilContext.iccInfo - ? rilContext.iccInfo.msisdn - : null; - - // Workaround an xpconnect issue with undefined string objects. - // See bug 808220 - if (sender === undefined || sender === "undefined") { - sender = null; - } - - let receiver = aReceiver; - if (rilContext.voice.network.mcc === rilContext.iccInfo.mcc) { - if (receiver) { - let parsedNumber = PhoneNumberUtils.parse(receiver.toString()); - receiver = (parsedNumber && parsedNumber.internationalNumber) - ? parsedNumber.internationalNumber - : receiver; - } - - if (sender) { - let parsedNumber = PhoneNumberUtils.parse(sender.toString()); - sender = (parsedNumber && parsedNumber.internationalNumber) - ? parsedNumber.internationalNumber - : sender; - } + receiver = aMessage.receiver = this.makePhoneNumberInternational(receiver); + sender = this.makePhoneNumberInternational(sender); } - let record = { - deliveryIndex: [DELIVERY_SENDING, aDate], - numberIndex: [[sender, aDate], [receiver, aDate]], - readIndex: [FILTER_READ_READ, aDate], + let timestamp = aMessage.timestamp; - delivery: DELIVERY_SENDING, - deliveryStatus: aDeliveryStatus, - sender: sender, - receiver: receiver, - body: aBody, - messageClass: MESSAGE_CLASS_NORMAL, - timestamp: aDate, - read: FILTER_READ_READ - }; - return this.saveRecord(record, aCallback); + // Adding needed indexes and extra attributes for internal use. + aMessage.deliveryIndex = [DELIVERY_SENDING, timestamp]; + aMessage.numberIndex = [[sender, timestamp], [receiver, timestamp]]; + aMessage.readIndex = [FILTER_READ_READ, timestamp]; + aMessage.delivery = DELIVERY_SENDING; + aMessage.sender = sender; + aMessage.messageClass = MESSAGE_CLASS_NORMAL; + aMessage.read = FILTER_READ_READ; + + return this.saveRecord(aMessage, aCallback); }, setMessageDelivery: function setMessageDelivery( @@ -822,11 +816,7 @@ MobileMessageDatabaseService.prototype = { if (!callback) { return; } - let sms = null; - if (record) { - sms = self.createMessageFromRecord(record); - } - callback.notify(rv, sms); + callback.notify(rv, record); } this.newTxn(READ_WRITE, function (error, txn, store) { @@ -914,7 +904,7 @@ MobileMessageDatabaseService.prototype = { aRequest.notifyGetMessageFailed(Ci.nsISmsRequest.UNKNOWN_ERROR); return; } - let sms = self.createMessageFromRecord(record); + let sms = self.createSmsMessageFromRecord(record); aRequest.notifyMessageGot(sms); }; @@ -1220,7 +1210,7 @@ MobileMessageDatabaseService.prototype = { // For all numbers. processing: filter.numbers.length, results: [] - }]; + }]; let timeRange = null; if (filter.startDate != null && filter.endDate != null) { @@ -1327,7 +1317,7 @@ MobileMessageDatabaseService.prototype = { if (DEBUG) debug("Could not get message id " + messageId); aRequest.notifyReadMessageListFailed(Ci.nsISmsRequest.NOT_FOUND_ERROR); } - let sms = self.createMessageFromRecord(record); + let sms = self.createSmsMessageFromRecord(record); aRequest.notifyNextMessageInListGot(sms); }; diff --git a/dom/sms/tests/test_smsdatabaseservice.xul b/dom/sms/tests/test_smsdatabaseservice.xul index 9f3f621f1e79..3bd3e523617f 100644 --- a/dom/sms/tests/test_smsdatabaseservice.xul +++ b/dom/sms/tests/test_smsdatabaseservice.xul @@ -177,21 +177,27 @@ function newRandomId() { let sms = [ { + type: "sms", sender: "+34666000000", receiver: "+34666111000", body: "message 0", + messageClass: "normal", timestamp: 1329999861762 }, { + type: "sms", sender: "+34666000111", receiver: "+34666111111", body: "message 1", + messageClass: "normal", timestamp: 1329999861763 }, { + type: "sms", sender: "+34666000222", receiver: "+34666111222", body: "message 2", + messageClass: "normal", timestamp: 1329999861764 }, ]; @@ -201,9 +207,7 @@ let sms = [ */ add_test(function test_saveReceivedMessage() { info("test_saveReceivedMessage"); - let messageId = gMobileMessageDatabaseService.saveReceivedMessage(sms[0].sender, - sms[0].body, - sms[0].timestamp); + let messageId = gMobileMessageDatabaseService.saveReceivedMessage(sms[0]); checkDB(function (store) { let request = store.get(messageId); request.onsuccess = function onsuccess() { @@ -262,9 +266,7 @@ add_test(function test_getMessage_success() { run_next_test(); } }); - let messageId = gMobileMessageDatabaseService.saveReceivedMessage(sms[2].sender, - sms[2].body, - sms[2].timestamp); + let messageId = gMobileMessageDatabaseService.saveReceivedMessage(sms[2]); SimpleTest.executeSoon(function () { gMobileMessageDatabaseService.getMessage(messageId, fakeRequestId); }); @@ -821,9 +823,7 @@ add_test(function test_deleteMessage_success() { run_next_test(); } }); - let messageId = gMobileMessageDatabaseService.saveReceivedMessage(sms[0].sender, - sms[0].body, - sms[0].timestamp); + let messageId = gMobileMessageDatabaseService.saveReceivedMessage(sms[0]); SimpleTest.executeSoon(function () { gMobileMessageDatabaseService.deleteMessage(messageId, fakeRequestId); }); @@ -852,9 +852,7 @@ add_test(function test_markMessageRead_success() { run_next_test(); } }); - let messageId = gMobileMessageDatabaseService.saveReceivedMessage(sms[2].sender, - sms[2].body, - sms[2].timestamp); + let messageId = gMobileMessageDatabaseService.saveReceivedMessage(sms[2]); SimpleTest.executeSoon(function () { gMobileMessageDatabaseService.markMessageRead(messageId, true, fakeRequestId); }); diff --git a/dom/system/gonk/RadioInterfaceLayer.js b/dom/system/gonk/RadioInterfaceLayer.js index 28e0cb51fe27..e2214d583404 100644 --- a/dom/system/gonk/RadioInterfaceLayer.js +++ b/dom/system/gonk/RadioInterfaceLayer.js @@ -1476,6 +1476,18 @@ RadioInterfaceLayer.prototype = { 0, options); }, + createSmsMessageFromRecord: function createSmsMessageFromRecord(aRecord) { + return gSmsService.createSmsMessage(aRecord.id, + aRecord.delivery, + aRecord.deliveryStatus, + aRecord.sender, + aRecord.receiver, + aRecord.body, + aRecord.messageClass, + aRecord.timestamp, + aRecord.read); + }, + portAddressedSmsApps: null, handleSmsReceived: function handleSmsReceived(message) { debug("handleSmsReceived: " + JSON.stringify(message)); @@ -1501,6 +1513,11 @@ RadioInterfaceLayer.prototype = { return true; } + message.type = "sms"; + message.sender = message.sender || null; + message.receiver = message.receiver || null; + message.body = message.fullBody = message.fullBody || null; + // TODO: Bug #768441 // For now we don't store indicators persistently. When the mwi.discard // flag is false, we'll need to persist the indicator to EFmwis. @@ -1508,13 +1525,14 @@ RadioInterfaceLayer.prototype = { let mwi = message.mwi; if (mwi) { - mwi.returnNumber = message.sender || null; - mwi.returnMessage = message.fullBody || null; + mwi.returnNumber = message.sender; + mwi.returnMessage = message.fullBody; this._sendTargetMessage("voicemail", "RIL:VoicemailNotification", mwi); return true; } - let notifyReceived = function notifyReceived(rv, sms) { + let notifyReceived = function notifyReceived(rv, record) { + let sms = this.createSmsMessageFromRecord(record); let success = Components.isSuccessCode(rv); // Acknowledge the reception of the SMS. @@ -1532,38 +1550,30 @@ RadioInterfaceLayer.prototype = { } gSystemMessenger.broadcastMessage("sms-received", { - id: message.id, - delivery: DOM_SMS_DELIVERY_RECEIVED, - deliveryStatus: RIL.GECKO_SMS_DELIVERY_STATUS_SUCCESS, - sender: message.sender || null, - receiver: message.receiver || null, - body: message.fullBody || null, - messageClass: message.messageClass, - timestamp: message.timestamp, - read: false + id: message.id, + delivery: DOM_SMS_DELIVERY_RECEIVED, + deliveryStatus: RIL.GECKO_SMS_DELIVERY_STATUS_SUCCESS, + sender: message.sender, + receiver: message.receiver, + body: message.fullBody, + messageClass: message.messageClass, + timestamp: message.timestamp, + read: false }); + Services.obs.notifyObservers(sms, kSmsReceivedObserverTopic, null); }.bind(this); if (message.messageClass != RIL.GECKO_SMS_MESSAGE_CLASSES[RIL.PDU_DCS_MSG_CLASS_0]) { - message.id = gMobileMessageDatabaseService.saveReceivedMessage( - message.sender || null, - message.fullBody || null, - message.messageClass, - message.timestamp, - notifyReceived); + message.id = gMobileMessageDatabaseService.saveReceivedMessage(message, + notifyReceived); } else { message.id = -1; - let sms = gSmsService.createSmsMessage(message.id, - DOM_SMS_DELIVERY_RECEIVED, - RIL.GECKO_SMS_DELIVERY_STATUS_SUCCESS, - message.sender || null, - message.receiver || null, - message.fullBody || null, - message.messageClass, - message.timestamp, - false); - notifyReceived(Cr.NS_OK, sms); + message.delivery = DOM_SMS_DELIVERY_RECEIVED; + message.deliveryStatus = RIL.GECKO_SMS_DELIVERY_STATUS_SUCCESS; + message.read = false; + + notifyReceived(Cr.NS_OK, message); } // SMS ACK will be sent in notifyReceived. Return false here. @@ -1596,7 +1606,8 @@ RadioInterfaceLayer.prototype = { gMobileMessageDatabaseService.setMessageDelivery(options.sms.id, DOM_SMS_DELIVERY_SENT, options.sms.deliveryStatus, - function notifyResult(rv, sms) { + function notifyResult(rv, record) { + let sms = this.createSmsMessageFromRecord(record); //TODO bug 832140 handle !Components.isSuccessCode(rv) gSystemMessenger.broadcastMessage("sms-sent", {id: options.sms.id, @@ -1634,13 +1645,14 @@ RadioInterfaceLayer.prototype = { gMobileMessageDatabaseService.setMessageDelivery(options.sms.id, options.sms.delivery, message.deliveryStatus, - function notifyResult(rv, sms) { + function notifyResult(rv, record) { + let sms = this.createSmsMessageFromRecord(record); //TODO bug 832140 handle !Components.isSuccessCode(rv) let topic = (message.deliveryStatus == RIL.GECKO_SMS_DELIVERY_STATUS_SUCCESS) ? kSmsDeliverySuccessObserverTopic : kSmsDeliveryErrorObserverTopic; Services.obs.notifyObservers(sms, topic, null); - }); + }.bind(this)); }, handleSmsSendFailed: function handleSmsSendFailed(message) { @@ -1662,11 +1674,12 @@ RadioInterfaceLayer.prototype = { gMobileMessageDatabaseService.setMessageDelivery(options.sms.id, DOM_SMS_DELIVERY_ERROR, RIL.GECKO_SMS_DELIVERY_STATUS_ERROR, - function notifyResult(rv, sms) { + function notifyResult(rv, record) { + let sms = this.createSmsMessageFromRecord(record); //TODO bug 832140 handle !Components.isSuccessCode(rv) options.request.notifySendMessageFailed(error); Services.obs.notifyObservers(sms, kSmsFailedObserverTopic, null); - }); + }.bind(this)); }, /** @@ -2645,8 +2658,17 @@ RadioInterfaceLayer.prototype = { let deliveryStatus = options.requestStatusReport ? RIL.GECKO_SMS_DELIVERY_STATUS_PENDING : RIL.GECKO_SMS_DELIVERY_STATUS_NOT_APPLICABLE; - let id = gMobileMessageDatabaseService.saveSendingMessage(number, message, deliveryStatus, timestamp, - function notifyResult(rv, sms) { + let sendingMessage = { + type: "sms", + receiver: number, + body: message, + deliveryStatus: deliveryStatus, + timestamp: timestamp + }; + + let id = gMobileMessageDatabaseService.saveSendingMessage(sendingMessage, + function notifyResult(rv, record) { + let sms = this.createSmsMessageFromRecord(record); //TODO bug 832140 handle !Components.isSuccessCode(rv) Services.obs.notifyObservers(sms, kSmsSendingObserverTopic, null);