From 9b0236510dfbddc133c64ea3ff0636de1167eb30 Mon Sep 17 00:00:00 2001 From: Vicamo Yang Date: Wed, 20 Nov 2013 03:46:15 +0800 Subject: [PATCH] Bug 736708 - 2/3: RIL implementation. r=gene --- .../nsIRilMobileMessageDatabaseService.idl | 1 + .../src/gonk/MobileMessageDatabaseService.js | 296 ++++++++++++------ 2 files changed, 200 insertions(+), 97 deletions(-) diff --git a/dom/mobilemessage/interfaces/nsIRilMobileMessageDatabaseService.idl b/dom/mobilemessage/interfaces/nsIRilMobileMessageDatabaseService.idl index bebca16bc0ae..b235b486a9dd 100644 --- a/dom/mobilemessage/interfaces/nsIRilMobileMessageDatabaseService.idl +++ b/dom/mobilemessage/interfaces/nsIRilMobileMessageDatabaseService.idl @@ -38,6 +38,7 @@ interface nsIRilMobileMessageDatabaseService : nsIMobileMessageDatabaseService * - If |type| == "sms", we also need: * - |messageClass| DOMString: the message class of received message * - |receiver| DOMString: the phone number of receiver + * - |pid| Number: the TP-PID field of the SMS TPDU, default 0. * * - If |type| == "mms", we also need: * - |delivery| DOMString: the delivery state of received message diff --git a/dom/mobilemessage/src/gonk/MobileMessageDatabaseService.js b/dom/mobilemessage/src/gonk/MobileMessageDatabaseService.js index c7706b498ec7..76d4ea1433a8 100644 --- a/dom/mobilemessage/src/gonk/MobileMessageDatabaseService.js +++ b/dom/mobilemessage/src/gonk/MobileMessageDatabaseService.js @@ -10,6 +10,9 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/PhoneNumberUtils.jsm"); +var RIL = {}; +Cu.import("resource://gre/modules/ril_consts.js", RIL); + const RIL_MOBILEMESSAGEDATABASESERVICE_CONTRACTID = "@mozilla.org/mobilemessage/rilmobilemessagedatabaseservice;1"; const RIL_MOBILEMESSAGEDATABASESERVICE_CID = @@ -24,7 +27,7 @@ const DISABLE_MMS_GROUPING_FOR_RECEIVING = true; const DB_NAME = "sms"; -const DB_VERSION = 18; +const DB_VERSION = 19; const MESSAGE_STORE_NAME = "sms"; const THREAD_STORE_NAME = "thread"; const PARTICIPANT_STORE_NAME = "participant"; @@ -252,6 +255,10 @@ MobileMessageDatabaseService.prototype = { self.upgradeSchema17(event.target.transaction, next); break; case 18: + if (DEBUG) debug("Upgrade to version 19. Add pid for incoming SMS."); + self.upgradeSchema18(event.target.transaction, next); + break; + case 19: // This will need to be moved for each new version if (DEBUG) debug("Upgrade finished."); break; @@ -1151,6 +1158,28 @@ MobileMessageDatabaseService.prototype = { }; }, + /** + * Add pid for incoming SMS. + */ + upgradeSchema18: function upgradeSchema18(transaction, next) { + let messageStore = transaction.objectStore(MESSAGE_STORE_NAME); + + messageStore.openCursor().onsuccess = function(event) { + let cursor = event.target.result; + if (!cursor) { + next(); + return; + } + + let messageRecord = cursor.value; + if (messageRecord.type == "sms") { + messageRecord.pid = RIL.PDU_PID_DEFAULT; + cursor.update(messageRecord); + } + cursor.continue(); + }; + }, + matchParsedPhoneNumbers: function matchParsedPhoneNumbers(addr1, parsedAddr1, addr2, parsedAddr2) { if ((parsedAddr1.internationalNumber && @@ -1485,105 +1514,174 @@ MobileMessageDatabaseService.prototype = { let messageStore = stores[0]; let participantStore = stores[1]; let threadStore = stores[2]; - - self.findThreadRecordByParticipants(threadStore, participantStore, - aAddresses, true, - function (threadRecord, - participantIds) { - if (!participantIds) { - txn.abort(); - return; - } - - let isOverriding = (aMessageRecord.id !== undefined); - if (!isOverriding) { - // |self.lastMessageId| is only updated in |txn.oncomplete|. - aMessageRecord.id = self.lastMessageId + 1; - } - - let insertMessageRecord = function (threadId) { - // Setup threadId & threadIdIndex. - aMessageRecord.threadId = threadId; - aMessageRecord.threadIdIndex = [threadId, timestamp]; - // Setup participantIdsIndex. - aMessageRecord.participantIdsIndex = []; - for each (let id in participantIds) { - aMessageRecord.participantIdsIndex.push([id, timestamp]); - } - - if (!isOverriding) { - // Really add to message store. - messageStore.put(aMessageRecord); - return; - } - - // If we're going to override an old message, we need to update the - // info of the original thread containing the overridden message. - // To get the original thread ID and read status of the overridden - // message record, we need to retrieve it before overriding it. - messageStore.get(aMessageRecord.id).onsuccess = function(event) { - let oldMessageRecord = event.target.result; - messageStore.put(aMessageRecord); - if (oldMessageRecord) { - self.updateThreadByMessageChange(messageStore, - threadStore, - oldMessageRecord.threadId, - aMessageRecord.id, - oldMessageRecord.read); - } - }; - }; - - let timestamp = aMessageRecord.timestamp; - if (threadRecord) { - let needsUpdate = false; - - if (threadRecord.lastTimestamp <= timestamp) { - let lastMessageSubject; - if (aMessageRecord.type == "mms") { - lastMessageSubject = aMessageRecord.headers.subject; - } - threadRecord.lastMessageSubject = lastMessageSubject || null; - threadRecord.lastTimestamp = timestamp; - threadRecord.body = aMessageRecord.body; - threadRecord.lastMessageId = aMessageRecord.id; - threadRecord.lastMessageType = aMessageRecord.type; - needsUpdate = true; - } - - if (!aMessageRecord.read) { - threadRecord.unreadCount++; - needsUpdate = true; - } - - if (needsUpdate) { - threadStore.put(threadRecord); - } - - insertMessageRecord(threadRecord.id); - return; - } - - let lastMessageSubject; - if (aMessageRecord.type == "mms") { - lastMessageSubject = aMessageRecord.headers.subject; - } - threadStore.add({participantIds: participantIds, - participantAddresses: aAddresses, - lastMessageId: aMessageRecord.id, - lastTimestamp: timestamp, - lastMessageSubject: lastMessageSubject || null, - body: aMessageRecord.body, - unreadCount: aMessageRecord.read ? 0 : 1, - lastMessageType: aMessageRecord.type}) - .onsuccess = function (event) { - let threadId = event.target.result; - insertMessageRecord(threadId); - }; - }); + self.replaceShortMessageOnSave(txn, messageStore, participantStore, + threadStore, aMessageRecord, aAddresses); }, [MESSAGE_STORE_NAME, PARTICIPANT_STORE_NAME, THREAD_STORE_NAME]); }, + replaceShortMessageOnSave: + function replaceShortMessageOnSave(aTransaction, aMessageStore, + aParticipantStore, aThreadStore, + aMessageRecord, aAddresses) { + if (aMessageRecord.type != "sms" || + aMessageRecord.delivery != DELIVERY_RECEIVED || + !(aMessageRecord.pid >= RIL.PDU_PID_REPLACE_SHORT_MESSAGE_TYPE_1 && + aMessageRecord.pid <= RIL.PDU_PID_REPLACE_SHORT_MESSAGE_TYPE_7)) { + this.realSaveRecord(aTransaction, aMessageStore, aParticipantStore, + aThreadStore, aMessageRecord, aAddresses); + return; + } + + // 3GPP TS 23.040 subclause 9.2.3.9 "TP-Protocol-Identifier (TP-PID)": + // + // ... the MS shall check the originating address and replace any + // existing stored message having the same Protocol Identifier code + // and originating address with the new short message and other + // parameter values. If there is no message to be replaced, the MS + // shall store the message in the normal way. ... it is recommended + // that the SC address should not be checked by the MS." + let self = this; + this.findParticipantRecordByAddress(aParticipantStore, + aMessageRecord.sender, false, + function(participantRecord) { + if (!participantRecord) { + self.realSaveRecord(aTransaction, aMessageStore, aParticipantStore, + aThreadStore, aMessageRecord, aAddresses); + return; + } + + let participantId = participantRecord.id; + let range = IDBKeyRange.bound([participantId, 0], [participantId, ""]); + let request = aMessageStore.index("participantIds").openCursor(range); + request.onsuccess = function onsuccess(event) { + let cursor = event.target.result; + if (!cursor) { + self.realSaveRecord(aTransaction, aMessageStore, aParticipantStore, + aThreadStore, aMessageRecord, aAddresses); + return; + } + + // A message record with same participantId found. + // Verify matching criteria. + let foundMessageRecord = cursor.value; + if (foundMessageRecord.type != "sms" || + foundMessageRecord.sender != aMessageRecord.sender || + foundMessageRecord.pid != aMessageRecord.pid) { + cursor.continue(); + return; + } + + // Match! Now replace that found message record with current one. + aMessageRecord.id = foundMessageRecord.id; + self.realSaveRecord(aTransaction, aMessageStore, aParticipantStore, + aThreadStore, aMessageRecord, aAddresses); + }; + }); + }, + + realSaveRecord: function realSaveRecord(aTransaction, aMessageStore, + aParticipantStore, aThreadStore, + aMessageRecord, aAddresses) { + let self = this; + this.findThreadRecordByParticipants(aThreadStore, aParticipantStore, + aAddresses, true, + function(threadRecord, participantIds) { + if (!participantIds) { + aTransaction.abort(); + return; + } + + let isOverriding = (aMessageRecord.id !== undefined); + if (!isOverriding) { + // |self.lastMessageId| is only updated in |txn.oncomplete|. + aMessageRecord.id = self.lastMessageId + 1; + } + + let timestamp = aMessageRecord.timestamp; + let insertMessageRecord = function(threadId) { + // Setup threadId & threadIdIndex. + aMessageRecord.threadId = threadId; + aMessageRecord.threadIdIndex = [threadId, timestamp]; + // Setup participantIdsIndex. + aMessageRecord.participantIdsIndex = []; + for each (let id in participantIds) { + aMessageRecord.participantIdsIndex.push([id, timestamp]); + } + + if (!isOverriding) { + // Really add to message store. + aMessageStore.put(aMessageRecord); + return; + } + + // If we're going to override an old message, we need to update the + // info of the original thread containing the overridden message. + // To get the original thread ID and read status of the overridden + // message record, we need to retrieve it before overriding it. + aMessageStore.get(aMessageRecord.id).onsuccess = function(event) { + let oldMessageRecord = event.target.result; + aMessageStore.put(aMessageRecord); + if (oldMessageRecord) { + self.updateThreadByMessageChange(aMessageStore, + aThreadStore, + oldMessageRecord.threadId, + aMessageRecord.id, + oldMessageRecord.read); + } + }; + }; + + if (threadRecord) { + let needsUpdate = false; + + if (threadRecord.lastTimestamp <= timestamp) { + let lastMessageSubject; + if (aMessageRecord.type == "mms") { + lastMessageSubject = aMessageRecord.headers.subject; + } + threadRecord.lastMessageSubject = lastMessageSubject || null; + threadRecord.lastTimestamp = timestamp; + threadRecord.body = aMessageRecord.body; + threadRecord.lastMessageId = aMessageRecord.id; + threadRecord.lastMessageType = aMessageRecord.type; + needsUpdate = true; + } + + if (!aMessageRecord.read) { + threadRecord.unreadCount++; + needsUpdate = true; + } + + if (needsUpdate) { + aThreadStore.put(threadRecord); + } + + insertMessageRecord(threadRecord.id); + return; + } + + let lastMessageSubject; + if (aMessageRecord.type == "mms") { + lastMessageSubject = aMessageRecord.headers.subject; + } + + threadRecord = { + participantIds: participantIds, + participantAddresses: aAddresses, + lastMessageId: aMessageRecord.id, + lastTimestamp: timestamp, + lastMessageSubject: lastMessageSubject || null, + body: aMessageRecord.body, + unreadCount: aMessageRecord.read ? 0 : 1, + lastMessageType: aMessageRecord.type, + }; + aThreadStore.add(threadRecord).onsuccess = function(event) { + let threadId = event.target.result; + insertMessageRecord(threadId); + }; + }); + }, + forEachMatchedMmsDeliveryInfo: function forEachMatchedMmsDeliveryInfo(aDeliveryInfo, aNeedle, aCallback) { @@ -1882,6 +1980,10 @@ MobileMessageDatabaseService.prototype = { aMessage.delivery = DELIVERY_RECEIVED; aMessage.deliveryStatus = DELIVERY_STATUS_SUCCESS; + if (aMessage.pid == undefined) { + aMessage.pid = RIL.PDU_PID_DEFAULT; + } + // If |deliveryTimestamp| is not specified, use 0 as default. if (aMessage.deliveryTimestamp == undefined) { aMessage.deliveryTimestamp = 0;