mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 13:51:41 +00:00
Bug 736708 - 2/3: RIL implementation. r=gene
This commit is contained in:
parent
cb490bbcc8
commit
9b0236510d
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user