Bug 921919 - B2G MMS: Notify Gaia SMS AP the MMS read report request and return the read result to the requester. r=vyang

This commit is contained in:
Chia-hung Tai 2013-11-04 11:36:00 +08:00
Родитель b6149335c3
Коммит 2a6d7cd489
18 изменённых файлов: 200 добавлений и 25 удалений

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

@ -11,7 +11,7 @@ interface nsIDOMDOMCursor;
interface nsIDOMDOMRequest;
interface nsIDOMBlob;
[scriptable, builtinclass, uuid(d1e35354-3d21-11e3-86da-77253f4c5683)]
[scriptable, builtinclass, uuid(0e4ff35e-ab84-434a-96b4-46807798cc7e)]
interface nsIDOMMozMobileMessageManager : nsIDOMEventTarget
{
nsIDOMDOMRequest getSegmentInfoForText(in DOMString text);
@ -57,7 +57,8 @@ interface nsIDOMMozMobileMessageManager : nsIDOMEventTarget
// Iterates through nsIDOMMoz{Mms,Sms}Message.
nsIDOMDOMCursor getMessages(in nsIDOMMozSmsFilter filter, in boolean reverse);
nsIDOMDOMRequest markMessageRead(in long id, in boolean value);
nsIDOMDOMRequest markMessageRead(in long id, in boolean value,
[optional] in boolean aSendReadReport);
// Iterates through nsIDOMMozMobileMessageThread.
nsIDOMDOMCursor getThreads();

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

@ -21,7 +21,7 @@ dictionary MmsDeliveryInfo
DOMString? deliveryStatus;
};
[scriptable, builtinclass, uuid(35d88c5e-2746-11e3-9d7b-83ca2203a291)]
[scriptable, builtinclass, uuid(85bfc639-0d8f-43fa-8c12-6bd2958bf219)]
interface nsIDOMMozMmsMessage : nsISupports
{
/**
@ -67,4 +67,7 @@ interface nsIDOMMozMmsMessage : nsISupports
readonly attribute jsval expiryDate; // Date object
// Expiry date for an MMS to be
// manually downloaded.
// Request read report from sender or not.
readonly attribute boolean isReadReportRequested;
};

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

@ -12,7 +12,7 @@ interface nsIDOMBlob;
#define MMS_SERVICE_CONTRACTID "@mozilla.org/mms/mmsservice;1"
%}
[scriptable, uuid(544bfa56-3d60-11e3-8b69-2383ccac8c81)]
[scriptable, uuid(543278b3-d926-4c65-84b8-b49ad7a17d21)]
interface nsIMmsService : nsISupports
{
readonly attribute unsigned long mmsDefaultServiceId;
@ -23,4 +23,8 @@ interface nsIMmsService : nsISupports
void retrieve(in long id,
in nsIMobileMessageCallback request);
void sendReadReport(in DOMString messageID,
in DOMString toAddress,
in DOMString iccId);
};

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

@ -16,7 +16,7 @@ interface nsIDOMMozSmsFilter;
interface nsIMobileMessageCallback;
interface nsIMobileMessageCursorCallback;
[scriptable, uuid(ea6f49ae-3a4c-47eb-a489-15578e634100)]
[scriptable, uuid(8439916f-abc1-4c67-aa45-8a276a0a7855)]
interface nsIMobileMessageDatabaseService : nsISupports
{
[binaryname(GetMessageMoz)]
@ -33,6 +33,7 @@ interface nsIMobileMessageDatabaseService : nsISupports
void markMessageRead(in long messageId,
in boolean value,
in boolean sendReadReport,
in nsIMobileMessageCallback request);
nsICursorContinueCallback createThreadCursor(in nsIMobileMessageCursorCallback callback);

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

@ -14,7 +14,7 @@ interface nsIDOMMozSmsSegmentInfo;
#define MOBILE_MESSAGE_SERVICE_CONTRACTID "@mozilla.org/mobilemessage/mobilemessageservice;1"
%}
[scriptable, builtinclass, uuid(729b616e-2766-11e3-9c6a-47e6110e44c6)]
[scriptable, builtinclass, uuid(7a39eeb4-827e-4c70-9804-288f94174ebe)]
interface nsIMobileMessageService : nsISupports
{
[implicit_jscontext]
@ -44,7 +44,8 @@ interface nsIMobileMessageService : nsISupports
in DOMString subject,
in DOMString smil,
in jsval attachments,
in jsval expiryDate);
in jsval expiryDate,
in boolean isReadReportRequested);
nsIDOMMozSmsSegmentInfo createSmsSegmentInfo(in long segments,
in long charsPerSegment,

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

@ -45,7 +45,8 @@ MmsMessage::MmsMessage(int32_t aId,
const nsAString& aSubject,
const nsAString& aSmil,
const nsTArray<MmsAttachment>& aAttachments,
uint64_t aExpiryDate)
uint64_t aExpiryDate,
bool aIsReadReportRequested)
: mId(aId),
mThreadId(aThreadId),
mIccId(aIccId),
@ -58,7 +59,8 @@ MmsMessage::MmsMessage(int32_t aId,
mSubject(aSubject),
mSmil(aSmil),
mAttachments(aAttachments),
mExpiryDate(aExpiryDate)
mExpiryDate(aExpiryDate),
mIsReadReportRequested(aIsReadReportRequested)
{
}
@ -74,6 +76,7 @@ MmsMessage::MmsMessage(const mobilemessage::MmsMessageData& aData)
, mSubject(aData.subject())
, mSmil(aData.smil())
, mExpiryDate(aData.expiryDate())
, mIsReadReportRequested(aData.isReadReportRequested())
{
uint32_t len = aData.attachments().Length();
mAttachments.SetCapacity(len);
@ -175,6 +178,7 @@ MmsMessage::Create(int32_t aId,
const nsAString& aSmil,
const JS::Value& aAttachments,
const JS::Value& aExpiryDate,
bool aIsReadReportRequested,
JSContext* aCx,
nsIDOMMozMmsMessage** aMessage)
{
@ -294,7 +298,8 @@ MmsMessage::Create(int32_t aId,
aSubject,
aSmil,
attachments,
expiryDate);
expiryDate,
aIsReadReportRequested);
message.forget(aMessage);
return NS_OK;
}
@ -316,6 +321,7 @@ MmsMessage::GetData(ContentParent* aParent,
aData.subject() = mSubject;
aData.smil() = mSmil;
aData.expiryDate() = mExpiryDate;
aData.isReadReportRequested() = mIsReadReportRequested;
aData.deliveryInfo().SetCapacity(mDeliveryInfo.Length());
for (uint32_t i = 0; i < mDeliveryInfo.Length(); i++) {
@ -614,5 +620,13 @@ MmsMessage::GetExpiryDate(JSContext* cx, JS::Value* aDate)
return NS_OK;
}
NS_IMETHODIMP
MmsMessage::GetIsReadReportRequested(bool* aIsReadReportRequested)
{
*aIsReadReportRequested = mIsReadReportRequested;
return NS_OK;
}
} // namespace dom
} // namespace mozilla

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

@ -39,7 +39,8 @@ public:
const nsAString& aSubject,
const nsAString& aSmil,
const nsTArray<idl::MmsAttachment>& aAttachments,
uint64_t aExpiryDate);
uint64_t aExpiryDate,
bool aIsReadReportRequested);
MmsMessage(const mobilemessage::MmsMessageData& aData);
@ -56,6 +57,7 @@ public:
const nsAString& aSmil,
const JS::Value& aAttachments,
const JS::Value& aExpiryDate,
bool aIsReadReportRequested,
JSContext* aCx,
nsIDOMMozMmsMessage** aMessage);
@ -77,6 +79,7 @@ private:
nsString mSmil;
nsTArray<idl::MmsAttachment> mAttachments;
uint64_t mExpiryDate;
bool mIsReadReportRequested;
};
} // namespace dom

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

@ -397,6 +397,7 @@ MobileMessageManager::GetMessages(nsIDOMMozSmsFilter* aFilter,
NS_IMETHODIMP
MobileMessageManager::MarkMessageRead(int32_t aId, bool aValue,
bool aSendReadReport,
nsIDOMDOMRequest** aRequest)
{
nsCOMPtr<nsIMobileMessageDatabaseService> mobileMessageDBService =
@ -405,7 +406,9 @@ MobileMessageManager::MarkMessageRead(int32_t aId, bool aValue,
nsRefPtr<DOMRequest> request = new DOMRequest(GetOwner());
nsCOMPtr<nsIMobileMessageCallback> msgCallback = new MobileMessageCallback(request);
nsresult rv = mobileMessageDBService->MarkMessageRead(aId, aValue, msgCallback);
nsresult rv = mobileMessageDBService->MarkMessageRead(aId, aValue,
aSendReadReport,
msgCallback);
NS_ENSURE_SUCCESS(rv, rv);
request.forget(aRequest);

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

@ -74,6 +74,7 @@ MobileMessageService::CreateMmsMessage(int32_t aId,
const nsAString& aSmil,
const JS::Value& aAttachments,
const JS::Value& aExpiryDate,
bool aIsReadReportRequested,
JSContext* aCx,
nsIDOMMozMmsMessage** aMessage)
{
@ -90,6 +91,7 @@ MobileMessageService::CreateMmsMessage(int32_t aId,
aSmil,
aAttachments,
aExpiryDate,
aIsReadReportRequested,
aCx,
aMessage);
}

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

@ -58,6 +58,7 @@ MobileMessageDatabaseService::CreateMessageCursor(nsIDOMMozSmsFilter* aFilter,
NS_IMETHODIMP
MobileMessageDatabaseService::MarkMessageRead(int32_t aMessageId,
bool aValue,
bool aSendReadReport,
nsIMobileMessageCallback* aRequest)
{
// TODO: This would need to be implemented as part of Bug 748391

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

@ -41,6 +41,7 @@ MobileMessageDatabaseService::CreateMessageCursor(nsIDOMMozSmsFilter* aFilter,
NS_IMETHODIMP
MobileMessageDatabaseService::MarkMessageRead(int32_t aMessageId,
bool aValue,
bool aSendReadReport,
nsIMobileMessageCallback* aRequest)
{
NS_ERROR("We should not be here!");

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

@ -1626,6 +1626,12 @@ const MMS_PDU_TYPES = (function () {
add(MMS_PDU_TYPE_ACKNOWLEDGE_IND, false, ["x-mms-message-type",
"x-mms-transaction-id",
"x-mms-mms-version"]);
add(MMS_PDU_TYPE_READ_REC_IND, false, ["x-mms-message-type",
"message-id",
"x-mms-mms-version",
"to",
"from",
"x-mms-read-status"]);
return pdus;
})();
@ -1672,7 +1678,7 @@ const MMS_HEADER_FIELDS = (function () {
add("x-mms-transaction-id", 0x18, WSP.TextString);
add("x-mms-retrieve-status", 0x19, RetrieveStatusValue);
add("x-mms-retrieve-text", 0x1A, EncodedStringValue);
//add("x-mms-read-status", 0x1B);
add("x-mms-read-status", 0x1B, BooleanValue);
add("x-mms-reply-charging", 0x1C, ReplyChargingValue);
add("x-mms-reply-charging-deadline", 0x1D, ExpiryValue);
add("x-mms-reply-charging-id", 0x1E, WSP.TextString);

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

@ -138,6 +138,10 @@ XPCOMUtils.defineLazyServiceGetter(this, "gSystemMessenger",
"@mozilla.org/system-message-internal;1",
"nsISystemMessagesInternal");
XPCOMUtils.defineLazyServiceGetter(this, "gRil",
"@mozilla.org/ril;1",
"nsIRadioInterfaceLayer");
XPCOMUtils.defineLazyGetter(this, "MMS", function () {
let MMS = {};
Cu.import("resource://gre/modules/MmsPduHelper.jsm", MMS);
@ -146,9 +150,7 @@ XPCOMUtils.defineLazyGetter(this, "MMS", function () {
function MmsConnection(aServiceId) {
this.serviceId = aServiceId;
let ril = Cc["@mozilla.org/ril;1"]
.getService(Ci["nsIRadioInterfaceLayer"]);
this.radioInterface = ril.getRadioInterface(aServiceId);
this.radioInterface = gRil.getRadioInterface(aServiceId);
};
MmsConnection.prototype = {
@ -1313,6 +1315,47 @@ function getDefaultServiceId() {
return id;
}
/**
* Return M-Read-Rec.ind back to MMSC
*
* @param messageID
* Message-ID of the message.
* @param toAddress
* The address of the recipient of the Read Report, i.e. the originator
* of the original multimedia message.
*
* @see OMA-TS-MMS_ENC-V1_3-20110913-A section 6.7.2
*/
function ReadRecTransaction(mmsConnection, messageID, toAddress) {
this.mmsConnection = mmsConnection;
let headers = {};
// Mandatory fields
headers["x-mms-message-type"] = MMS.MMS_PDU_TYPE_READ_REC_IND;
headers["x-mms-mms-version"] = MMS.MMS_VERSION;
headers["message-id"] = messageID;
let type = MMS.Address.resolveType(toAddress);
let to = {address: toAddress,
type: type}
headers["to"] = to;
headers["from"] = null;
headers["x-mms-read-status"] = true;
this.istream = MMS.PduHelper.compose(null, {headers: headers});
if (!this.istream) {
throw Cr.NS_ERROR_FAILURE;
}
}
ReadRecTransaction.prototype = {
run: function() {
gMmsTransactionHelper.sendRequest(this.mmsConnection,
"POST",
null,
this.istream,
null);
}
};
/**
* MmsService
*/
@ -2135,11 +2178,9 @@ MmsService.prototype = {
// Get the RIL service ID based on the saved MMS message record's ICC ID,
// which could fail when the corresponding SIM card isn't installed.
let ril = Cc["@mozilla.org/ril;1"]
.getService(Ci["nsIRadioInterfaceLayer"]);
let serviceId;
try {
serviceId = ril.getClientIdByIccId(aMessageRecord.iccId);
serviceId = gRil.getClientIdByIccId(aMessageRecord.iccId);
} catch (e) {
if (DEBUG) debug("RIL service is not available for ICC ID.");
aRequest.notifyGetMessageFailed(Ci.nsIMobileMessageCallback.NO_SIM_CARD_ERROR);
@ -2258,6 +2299,32 @@ MmsService.prototype = {
}).bind(this));
},
sendReadReport: function sendReadReport(messageID, toAddress, iccId) {
if (DEBUG) {
debug("messageID: " + messageID + " toAddress: " +
JSON.stringify(toAddress));
}
// Get the RIL service ID based on the saved MMS message record's ICC ID,
// which could fail when the corresponding SIM card isn't installed.
let serviceId;
try {
serviceId = gRil.getClientIdByIccId(iccId);
} catch (e) {
if (DEBUG) debug("RIL service is not available for ICC ID.");
return;
}
let mmsConnection = gMmsConnections.getConnByServiceId(serviceId);
try {
let transaction =
new ReadRecTransaction(mmsConnection, messageID, toAddress);
transaction.run();
} catch (e) {
if (DEBUG) debug("sendReadReport fail. e = " + e);
}
},
// nsIWapPushApplication
receiveWapPush: function receiveWapPush(array, length, offset, options) {

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

@ -24,7 +24,7 @@ const DISABLE_MMS_GROUPING_FOR_RECEIVING = true;
const DB_NAME = "sms";
const DB_VERSION = 16;
const DB_VERSION = 17;
const MESSAGE_STORE_NAME = "sms";
const THREAD_STORE_NAME = "thread";
const PARTICIPANT_STORE_NAME = "participant";
@ -65,6 +65,9 @@ const COLLECT_TIMESTAMP_UNUSED = 0;
XPCOMUtils.defineLazyServiceGetter(this, "gMobileMessageService",
"@mozilla.org/mobilemessage/mobilemessageservice;1",
"nsIMobileMessageService");
XPCOMUtils.defineLazyServiceGetter(this, "gMMSService",
"@mozilla.org/mms/rilmmsservice;1",
"nsIMmsService");
/**
* MobileMessageDatabaseService
@ -230,10 +233,14 @@ MobileMessageDatabaseService.prototype = {
self.upgradeSchema14(event.target.transaction, next);
break;
case 15:
if (DEBUG) debug("Upgrade to version 15. Add ICC ID for each message.");
if (DEBUG) debug("Upgrade to version 16. Add ICC ID for each message.");
self.upgradeSchema15(event.target.transaction, next);
break;
case 16:
if (DEBUG) debug("Upgrade to version 17. Add isReadReportSent for incoming MMS.");
self.upgradeSchema16(event.target.transaction, next);
break;
case 17:
// This will need to be moved for each new version
if (DEBUG) debug("Upgrade finished.");
break;
@ -1072,6 +1079,29 @@ MobileMessageDatabaseService.prototype = {
};
},
/**
* Add isReadReportSent for incoming MMS.
*/
upgradeSchema16: function upgradeSchema16(transaction, next) {
let messageStore = transaction.objectStore(MESSAGE_STORE_NAME);
// Update type attributes.
messageStore.openCursor().onsuccess = function(event) {
let cursor = event.target.result;
if (!cursor) {
next();
return;
}
let messageRecord = cursor.value;
if (messageRecord.type == "mms") {
messageRecord.isReadReportSent = false;
cursor.update(messageRecord);
}
cursor.continue();
};
},
matchParsedPhoneNumbers: function matchParsedPhoneNumbers(addr1, parsedAddr1,
addr2, parsedAddr2) {
if ((parsedAddr1.internationalNumber &&
@ -1181,6 +1211,7 @@ MobileMessageDatabaseService.prototype = {
if (headers["x-mms-expiry"] != undefined) {
expiryDate = aMessageRecord.timestamp + headers["x-mms-expiry"] * 1000;
}
let isReadReportRequested = headers["x-mms-read-report"] || false;
return gMobileMessageService.createMmsMessage(aMessageRecord.id,
aMessageRecord.threadId,
aMessageRecord.iccId,
@ -1193,7 +1224,8 @@ MobileMessageDatabaseService.prototype = {
subject,
smil,
attachments,
expiryDate);
expiryDate,
isReadReportRequested);
}
},
@ -1732,6 +1764,7 @@ MobileMessageDatabaseService.prototype = {
if (aMessage.type == "mms") {
aMessage.transactionIdIndex = aMessage.transactionId;
aMessage.isReadReportSent = false;
}
if (aMessage.type == "sms") {
@ -2059,7 +2092,7 @@ MobileMessageDatabaseService.prototype = {
return cursor;
},
markMessageRead: function markMessageRead(messageId, value, aRequest) {
markMessageRead: function markMessageRead(messageId, value, aSendReadReport, aRequest) {
if (DEBUG) debug("Setting message " + messageId + " read to " + value);
this.newTxn(READ_WRITE, function (error, txn, stores) {
if (error) {
@ -2067,10 +2100,12 @@ MobileMessageDatabaseService.prototype = {
aRequest.notifyMarkMessageReadFailed(Ci.nsIMobileMessageCallback.INTERNAL_ERROR);
return;
}
txn.onerror = function onerror(event) {
if (DEBUG) debug("Caught error on transaction ", event.target.errorCode);
aRequest.notifyMarkMessageReadFailed(Ci.nsIMobileMessageCallback.INTERNAL_ERROR);
};
let messageStore = stores[0];
let threadStore = stores[1];
messageStore.get(messageId).onsuccess = function onsuccess(event) {
@ -2080,6 +2115,7 @@ MobileMessageDatabaseService.prototype = {
aRequest.notifyMarkMessageReadFailed(Ci.nsIMobileMessageCallback.NOT_FOUND_ERROR);
return;
}
if (messageRecord.id != messageId) {
if (DEBUG) {
debug("Retrieve message ID (" + messageId + ") is " +
@ -2088,6 +2124,7 @@ MobileMessageDatabaseService.prototype = {
aRequest.notifyMarkMessageReadFailed(Ci.nsIMobileMessageCallback.UNKNOWN_ERROR);
return;
}
// If the value to be set is the same as the current message `read`
// value, we just notify successfully.
if (messageRecord.read == value) {
@ -2095,8 +2132,22 @@ MobileMessageDatabaseService.prototype = {
aRequest.notifyMessageMarkedRead(messageRecord.read);
return;
}
messageRecord.read = value ? FILTER_READ_READ : FILTER_READ_UNREAD;
messageRecord.readIndex = [messageRecord.read, messageRecord.timestamp];
let readReportMessageId, readReportTo;
if (aSendReadReport &&
messageRecord.type == "mms" &&
messageRecord.delivery == DELIVERY_RECEIVED &&
messageRecord.read == FILTER_READ_READ &&
!messageRecord.isReadReportSent) {
messageRecord.isReadReportSent = true;
let from = messageRecord.headers["from"];
readReportTo = from && from.address;
readReportMessageId = messageRecord.headers["message-id"];
}
if (DEBUG) debug("Message.read set to: " + value);
messageStore.put(messageRecord).onsuccess = function onsuccess(event) {
if (DEBUG) {
@ -2118,6 +2169,11 @@ MobileMessageDatabaseService.prototype = {
" -> " + threadRecord.unreadCount);
}
threadStore.put(threadRecord).onsuccess = function(event) {
if(readReportMessageId && readReportTo) {
gMMSService.sendReadReport(readReportMessageId,
readReportTo,
messageRecord.iccId);
}
aRequest.notifyMessageMarkedRead(messageRecord.read);
};
};

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

@ -62,6 +62,7 @@ struct MarkMessageReadRequest
{
int32_t messageId;
bool value;
bool sendReadReport;
};
struct GetSegmentInfoForTextRequest

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

@ -243,9 +243,10 @@ SmsIPCService::CreateMessageCursor(nsIDOMMozSmsFilter* aFilter,
NS_IMETHODIMP
SmsIPCService::MarkMessageRead(int32_t aMessageId,
bool aValue,
bool aSendReadReport,
nsIMobileMessageCallback* aRequest)
{
return SendRequest(MarkMessageReadRequest(aMessageId, aValue), aRequest);
return SendRequest(MarkMessageReadRequest(aMessageId, aValue, aSendReadReport), aRequest);
}
NS_IMETHODIMP
@ -333,3 +334,12 @@ SmsIPCService::Retrieve(int32_t aId, nsIMobileMessageCallback *aRequest)
{
return SendRequest(RetrieveMessageRequest(aId), aRequest);
}
NS_IMETHODIMP
SmsIPCService::SendReadReport(const nsAString & messageID,
const nsAString & toAddress,
const nsAString & iccId)
{
NS_ERROR("We should not be here!");
return NS_OK;
}

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

@ -542,7 +542,7 @@ SmsRequestParent::DoRequest(const MarkMessageReadRequest& aRequest)
do_GetService(MOBILE_MESSAGE_DATABASE_SERVICE_CONTRACTID);
if (dbService) {
rv = dbService->MarkMessageRead(aRequest.messageId(), aRequest.value(),
this);
aRequest.sendReadReport(), this);
}
if (NS_FAILED(rv)) {

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

@ -68,6 +68,7 @@ struct MmsMessageData
nsString smil;
MmsAttachmentData[] attachments;
uint64_t expiryDate;
bool isReadReportRequested;
};
union MobileMessageData