diff --git a/patch/all/gecko/bug850127.patch b/patch/all/gecko/bug850127.patch new file mode 100644 index 0000000000000000000000000000000000000000..d07b9dcc941c61ba300ea021f061c18d28e9a15d --- /dev/null +++ b/patch/all/gecko/bug850127.patch @@ -0,0 +1,1108 @@ +diff --git a/dom/sms/interfaces/nsIDOMSmsMessage.idl b/dom/sms/interfaces/nsIDOMSmsMessage.idl +--- a/dom/sms/interfaces/nsIDOMSmsMessage.idl ++++ b/dom/sms/interfaces/nsIDOMSmsMessage.idl +@@ -1,19 +1,21 @@ + /* 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 "nsISupports.idl" + +-[scriptable, builtinclass, uuid(59fc5ea8-33fe-40ba-890b-b9abaeb5ac26)] ++[scriptable, builtinclass, uuid(b755a401-d5cb-4d35-a93e-47c89d2e15ca)] + interface nsIDOMMozSmsMessage : nsISupports + { + readonly attribute long id; + ++ readonly attribute unsigned long long threadId; ++ + /** + * Should be "received", "sending", "sent" or "error". + */ + readonly attribute DOMString delivery; + + /** + * Possible delivery status values for above delivery states are: + * +diff --git a/dom/sms/interfaces/nsISmsRequest.idl b/dom/sms/interfaces/nsISmsRequest.idl +--- a/dom/sms/interfaces/nsISmsRequest.idl ++++ b/dom/sms/interfaces/nsISmsRequest.idl +@@ -3,16 +3,17 @@ + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + #include "nsISupports.idl" + + interface nsIDOMMozSmsMessage; + + dictionary SmsThreadListItem + { ++ unsigned long long id; + DOMString senderOrReceiver; + unsigned long long timestamp; + DOMString body; + unsigned long long unreadCount; + }; + + [scriptable, builtinclass, uuid(82a6d16d-cf33-4745-8662-8b5d441f512f)] + interface nsISmsRequest : nsISupports +diff --git a/dom/sms/interfaces/nsISmsService.idl b/dom/sms/interfaces/nsISmsService.idl +--- a/dom/sms/interfaces/nsISmsService.idl ++++ b/dom/sms/interfaces/nsISmsService.idl +@@ -8,29 +8,30 @@ interface nsIDOMMozSmsMessage; + interface nsIDOMMozSmsSegmentInfo; + interface nsISmsRequest; + + %{C++ + #define SMS_SERVICE_CID { 0xbada3cb8, 0xa568, 0x4dff, { 0xb5, 0x43, 0x52, 0xbb, 0xb3, 0x14, 0x31, 0x21 } } + #define SMS_SERVICE_CONTRACTID "@mozilla.org/sms/smsservice;1" + %} + +-[scriptable, builtinclass, uuid(4310bdb5-eefa-4f70-965a-74041228ab26)] ++[scriptable, builtinclass, uuid(944297ed-0dc7-4dee-89a6-c962ea0218d3)] + interface nsISmsService : nsISupports + { + boolean hasSupport(); + + nsIDOMMozSmsSegmentInfo getSegmentInfoForText(in DOMString text); + + void send(in DOMString number, + in DOMString message, + in nsISmsRequest request); + + [implicit_jscontext] + nsIDOMMozSmsMessage createSmsMessage(in long id, ++ in unsigned long long threadId, + in DOMString delivery, + in DOMString deliveryStatus, + in DOMString sender, + in DOMString receiver, + in DOMString body, + in DOMString messageClass, + in jsval timestamp, + in bool read); +diff --git a/dom/sms/src/SmsMessage.cpp b/dom/sms/src/SmsMessage.cpp +--- a/dom/sms/src/SmsMessage.cpp ++++ b/dom/sms/src/SmsMessage.cpp +@@ -20,36 +20,38 @@ NS_INTERFACE_MAP_BEGIN(SmsMessage) + NS_INTERFACE_MAP_ENTRY(nsISupports) + NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozSmsMessage) + NS_INTERFACE_MAP_END + + NS_IMPL_ADDREF(SmsMessage) + NS_IMPL_RELEASE(SmsMessage) + + SmsMessage::SmsMessage(int32_t aId, ++ const uint64_t aThreadId, + DeliveryState aDelivery, + DeliveryStatus aDeliveryStatus, + const nsString& aSender, + const nsString& aReceiver, + const nsString& aBody, + MessageClass aMessageClass, + uint64_t aTimestamp, + bool aRead) +- : mData(aId, aDelivery, aDeliveryStatus, aSender, aReceiver, aBody, ++ : mData(aId, aThreadId, aDelivery, aDeliveryStatus, aSender, aReceiver, aBody, + aMessageClass, aTimestamp, aRead) + { + } + + SmsMessage::SmsMessage(const SmsMessageData& aData) + : mData(aData) + { + } + + /* static */ nsresult + SmsMessage::Create(int32_t aId, ++ const uint64_t aThreadId, + const nsAString& aDelivery, + const nsAString& aDeliveryStatus, + const nsAString& aSender, + const nsAString& aReceiver, + const nsAString& aBody, + const nsAString& aMessageClass, + const jsval& aTimestamp, + const bool aRead, +@@ -57,16 +59,17 @@ SmsMessage::Create(int32_t aId, + nsIDOMMozSmsMessage** aMessage) + { + *aMessage = nullptr; + + // SmsMessageData exposes these as references, so we can simply assign + // to them. + SmsMessageData data; + data.id() = aId; ++ data.threadId() = aThreadId; + data.sender() = nsString(aSender); + data.receiver() = nsString(aReceiver); + data.body() = nsString(aBody); + data.read() = aRead; + + if (aDelivery.Equals(DELIVERY_RECEIVED)) { + data.delivery() = eDeliveryState_Received; + } else if (aDelivery.Equals(DELIVERY_SENDING)) { +@@ -137,16 +140,23 @@ SmsMessage::GetData() const + NS_IMETHODIMP + SmsMessage::GetId(int32_t* aId) + { + *aId = mData.id(); + return NS_OK; + } + + NS_IMETHODIMP ++SmsMessage::GetThreadId(uint64_t* aThreadId) ++{ ++ *aThreadId = mData.threadId(); ++ return NS_OK; ++} ++ ++NS_IMETHODIMP + SmsMessage::GetDelivery(nsAString& aDelivery) + { + switch (mData.delivery()) { + case eDeliveryState_Received: + aDelivery = DELIVERY_RECEIVED; + break; + case eDeliveryState_Sending: + aDelivery = DELIVERY_SENDING; +diff --git a/dom/sms/src/SmsMessage.h b/dom/sms/src/SmsMessage.h +--- a/dom/sms/src/SmsMessage.h ++++ b/dom/sms/src/SmsMessage.h +@@ -19,27 +19,29 @@ namespace sms { + + class SmsMessage MOZ_FINAL : public nsIDOMMozSmsMessage + { + public: + NS_DECL_ISUPPORTS + NS_DECL_NSIDOMMOZSMSMESSAGE + + SmsMessage(int32_t aId, ++ const uint64_t aThreadId, + DeliveryState aDelivery, + DeliveryStatus aDeliveryStatus, + const nsString& aSender, + const nsString& aReceiver, + const nsString& aBody, + MessageClass aMessageClass, + uint64_t aTimestamp, + bool aRead); + SmsMessage(const SmsMessageData& aData); + + static nsresult Create(int32_t aId, ++ const uint64_t aThreadId, + const nsAString& aDelivery, + const nsAString& aDeliveryStatus, + const nsAString& aSender, + const nsAString& aReceiver, + const nsAString& aBody, + const nsAString& aMessageClass, + const JS::Value& aTimestamp, + const bool aRead, +diff --git a/dom/sms/src/SmsRequest.cpp b/dom/sms/src/SmsRequest.cpp +--- a/dom/sms/src/SmsRequest.cpp ++++ b/dom/sms/src/SmsRequest.cpp +@@ -480,16 +480,17 @@ SmsRequest::NotifyThreadList(const jsval + + MOZ_ASSERT(arrayEntry.isObject()); + + SmsThreadListItem item; + nsresult rv = item.Init(aCx, &arrayEntry); + NS_ENSURE_SUCCESS(rv, rv); + + ThreadListItem* ipcItem = ipcItems.AppendElement(); ++ ipcItem->id() = item.id; + ipcItem->senderOrReceiver() = item.senderOrReceiver; + ipcItem->timestamp() = item.timestamp; + ipcItem->body() = item.body; + ipcItem->unreadCount() = item.unreadCount; + } + } + + return SendMessageReply(reply); +@@ -535,16 +536,18 @@ SmsRequest::NotifyThreadList(const Infal + JSObject* array = JS_NewArrayObject(cx, aItems.Length(), nullptr); + NS_ENSURE_TRUE_VOID(array); + + bool ok; + + for (uint32_t i = 0; i < aItems.Length(); i++) { + const ThreadListItem& source = aItems[i]; + ++ jsval id = JS_NumberValue(double(source.id())); ++ + nsString temp = source.senderOrReceiver(); + + jsval senderOrReceiver; + ok = xpc::StringToJsval(cx, temp, &senderOrReceiver); + NS_ENSURE_TRUE_VOID(ok); + + JSObject* timestampObj = JS_NewDateObjectMsec(cx, source.timestamp()); + NS_ENSURE_TRUE_VOID(timestampObj); +@@ -557,16 +560,19 @@ SmsRequest::NotifyThreadList(const Infal + ok = xpc::StringToJsval(cx, temp, &body); + NS_ENSURE_TRUE_VOID(ok); + + jsval unreadCount = JS_NumberValue(double(source.unreadCount())); + + JSObject* elementObj = JS_NewObject(cx, nullptr, nullptr, nullptr); + NS_ENSURE_TRUE_VOID(elementObj); + ++ ok = JS_SetProperty(cx, elementObj, "id", &id); ++ NS_ENSURE_TRUE_VOID(ok); ++ + ok = JS_SetProperty(cx, elementObj, "senderOrReceiver", &senderOrReceiver); + NS_ENSURE_TRUE_VOID(ok); + + ok = JS_SetProperty(cx, elementObj, "timestamp", ×tamp); + NS_ENSURE_TRUE_VOID(ok); + + ok = JS_SetProperty(cx, elementObj, "body", &body); + NS_ENSURE_TRUE_VOID(ok); +diff --git a/dom/sms/src/android/SmsService.cpp b/dom/sms/src/android/SmsService.cpp +--- a/dom/sms/src/android/SmsService.cpp ++++ b/dom/sms/src/android/SmsService.cpp +@@ -48,28 +48,29 @@ SmsService::Send(const nsAString& aNumbe + } + + AndroidBridge::Bridge()->SendMessage(aNumber, aMessage, aRequest); + return NS_OK; + } + + NS_IMETHODIMP + SmsService::CreateSmsMessage(int32_t aId, ++ uint64_t aThreadId, + const nsAString& aDelivery, + const nsAString& aDeliveryStatus, + const nsAString& aSender, + const nsAString& aReceiver, + const nsAString& aBody, + const nsAString& aMessageClass, + const jsval& aTimestamp, + const bool aRead, + JSContext* aCx, + nsIDOMMozSmsMessage** aMessage) + { +- return SmsMessage::Create(aId, aDelivery, aDeliveryStatus, ++ return SmsMessage::Create(aId, aThreadId, aDelivery, aDeliveryStatus, + aSender, aReceiver, + aBody, aMessageClass, aTimestamp, aRead, + aCx, aMessage); + } + + NS_IMETHODIMP + SmsService::CreateSmsSegmentInfo(int32_t aSegments, + int32_t aCharsPerSegment, +diff --git a/dom/sms/src/fallback/SmsService.cpp b/dom/sms/src/fallback/SmsService.cpp +--- a/dom/sms/src/fallback/SmsService.cpp ++++ b/dom/sms/src/fallback/SmsService.cpp +@@ -35,28 +35,29 @@ SmsService::Send(const nsAString& aNumbe + nsISmsRequest* aRequest) + { + NS_ERROR("We should not be here!"); + return NS_OK; + } + + NS_IMETHODIMP + SmsService::CreateSmsMessage(int32_t aId, ++ uint64_t aThreadId, + const nsAString& aDelivery, + const nsAString& aDeliveryStatus, + const nsAString& aSender, + const nsAString& aReceiver, + const nsAString& aBody, + const nsAString& aMessageClass, + const jsval& aTimestamp, + const bool aRead, + JSContext* aCx, + nsIDOMMozSmsMessage** aMessage) + { +- return SmsMessage::Create(aId, aDelivery, aDeliveryStatus, ++ return SmsMessage::Create(aId, aThreadId, aDelivery, aDeliveryStatus, + aSender, aReceiver, + aBody, aMessageClass, aTimestamp, aRead, + aCx, aMessage); + } + + NS_IMETHODIMP + SmsService::CreateSmsSegmentInfo(int32_t aSegments, + int32_t aCharsPerSegment, +diff --git a/dom/sms/src/ipc/PSmsRequest.ipdl b/dom/sms/src/ipc/PSmsRequest.ipdl +--- a/dom/sms/src/ipc/PSmsRequest.ipdl ++++ b/dom/sms/src/ipc/PSmsRequest.ipdl +@@ -82,16 +82,17 @@ struct ReplyMarkeMessageReadFail + }; + + struct ReplyNoMessageInList + { + }; + + struct ThreadListItem + { ++ uint64_t id; + nsString senderOrReceiver; + uint64_t timestamp; + nsString body; + uint64_t unreadCount; + }; + + struct ReplyThreadList + { +diff --git a/dom/sms/src/ipc/SmsIPCService.cpp b/dom/sms/src/ipc/SmsIPCService.cpp +--- a/dom/sms/src/ipc/SmsIPCService.cpp ++++ b/dom/sms/src/ipc/SmsIPCService.cpp +@@ -76,28 +76,29 @@ SmsIPCService::Send(const nsAString& aNu + nsISmsRequest* aRequest) + { + SendRequest(SendMessageRequest(nsString(aNumber), nsString(aMessage)), aRequest); + return NS_OK; + } + + NS_IMETHODIMP + SmsIPCService::CreateSmsMessage(int32_t aId, ++ uint64_t aThreadId, + const nsAString& aDelivery, + const nsAString& aDeliveryStatus, + const nsAString& aSender, + const nsAString& aReceiver, + const nsAString& aBody, + const nsAString& aMessageClass, + const jsval& aTimestamp, + const bool aRead, + JSContext* aCx, + nsIDOMMozSmsMessage** aMessage) + { +- return SmsMessage::Create(aId, aDelivery, aDeliveryStatus, ++ return SmsMessage::Create(aId, aThreadId, aDelivery, aDeliveryStatus, + aSender, aReceiver, + aBody, aMessageClass, aTimestamp, aRead, + aCx, aMessage); + } + + NS_IMETHODIMP + SmsIPCService::CreateSmsSegmentInfo(int32_t aSegments, + int32_t aCharsPerSegment, +diff --git a/dom/sms/src/ipc/SmsTypes.ipdlh b/dom/sms/src/ipc/SmsTypes.ipdlh +--- a/dom/sms/src/ipc/SmsTypes.ipdlh ++++ b/dom/sms/src/ipc/SmsTypes.ipdlh +@@ -20,16 +20,17 @@ struct SmsSegmentInfoData + int32_t segments; + int32_t charsPerSegment; + int32_t charsAvailableInLastSegment; + }; + + struct SmsMessageData + { + int32_t id; ++ uint64_t threadId; + DeliveryState delivery; + DeliveryStatus deliveryStatus; + nsString sender; + nsString receiver; + nsString body; + MessageClass messageClass; + uint64_t timestamp; // ms since epoch. + bool read; +diff --git a/dom/sms/src/ril/SmsDatabaseService.js b/dom/sms/src/ril/SmsDatabaseService.js +--- a/dom/sms/src/ril/SmsDatabaseService.js ++++ b/dom/sms/src/ril/SmsDatabaseService.js +@@ -557,16 +557,17 @@ SmsDatabaseService.prototype = { + }; + }, + + createMessageFromRecord: function createMessageFromRecord(aMessageRecord) { + if (DEBUG) { + debug("createMessageFromRecord: " + JSON.stringify(aMessageRecord)); + } + return gSmsService.createSmsMessage(aMessageRecord.id, ++ aMessageRecord.threadId, + aMessageRecord.delivery, + aMessageRecord.deliveryStatus, + aMessageRecord.sender, + aMessageRecord.receiver, + aMessageRecord.body, + aMessageRecord.messageClass, + aMessageRecord.timestamp, + aMessageRecord.read); +@@ -1773,16 +1774,17 @@ SmsDatabaseService.prototype = { + aRequest.notifyThreadListFailed(Ci.nsISmsRequest.INTERNAL_ERROR); + }; + let request = threadStore.index("lastTimestamp").mozGetAll(); + request.onsuccess = function(event) { + // TODO: keep backward compatibility of original API interface only. + let results = []; + for each (let item in event.target.result) { + results.push({ ++ id: item.id, + senderOrReceiver: item.participantAddresses[0], + timestamp: item.lastTimestamp, + body: item.subject, + unreadCount: item.unreadCount + }); + } + aRequest.notifyThreadList(results); + }; +diff --git a/dom/sms/src/ril/SmsService.cpp b/dom/sms/src/ril/SmsService.cpp +--- a/dom/sms/src/ril/SmsService.cpp ++++ b/dom/sms/src/ril/SmsService.cpp +@@ -54,28 +54,29 @@ SmsService::Send(const nsAString& aNumbe + return NS_OK; + } + mRIL->SendSMS(aNumber, aMessage, aRequest); + return NS_OK; + } + + NS_IMETHODIMP + SmsService::CreateSmsMessage(int32_t aId, ++ uint64_t aThreadId, + const nsAString& aDelivery, + const nsAString& aDeliveryStatus, + const nsAString& aSender, + const nsAString& aReceiver, + const nsAString& aBody, + const nsAString& aMessageClass, + const jsval& aTimestamp, + const bool aRead, + JSContext* aCx, + nsIDOMMozSmsMessage** aMessage) + { +- return SmsMessage::Create(aId, aDelivery, aDeliveryStatus, ++ return SmsMessage::Create(aId, aThreadId, aDelivery, aDeliveryStatus, + aSender, aReceiver, + aBody, aMessageClass, aTimestamp, aRead, + aCx, aMessage); + } + + NS_IMETHODIMP + SmsService::CreateSmsSegmentInfo(int32_t aSegments, + int32_t aCharsPerSegment, +diff --git a/dom/sms/tests/marionette/test_getmessage.js b/dom/sms/tests/marionette/test_getmessage.js +--- a/dom/sms/tests/marionette/test_getmessage.js ++++ b/dom/sms/tests/marionette/test_getmessage.js +@@ -11,16 +11,18 @@ const EMULATOR = "15555215554"; // the e + + let sms = window.navigator.mozSms; + let inText = "Incoming SMS message. Mozilla Firefox OS!"; + let outText = "Outgoing SMS message. Mozilla Firefox OS!"; + let gotSmsOnsent = false; + let gotReqOnsuccess = false; + let inSmsId = 0; + let outSmsId = 0; ++let inThreadId = 0; ++let outThreadId = 0; + let inSmsTimeStamp; + let outSmsTimeStamp; + + function verifyInitialState() { + log("Verifying initial state."); + ok(sms, "mozSms"); + simulateIncomingSms(); + } +@@ -30,16 +32,18 @@ function simulateIncomingSms() { + + sms.onreceived = function onreceived(event) { + log("Received 'onreceived' smsmanager event."); + let incomingSms = event.message; + ok(incomingSms, "incoming sms"); + ok(incomingSms.id, "sms id"); + inSmsId = incomingSms.id; + log("Received SMS (id: " + inSmsId + ")."); ++ ok(incomingSms.threadId, "thread id"); ++ inThreadId = incomingSms.threadId; + is(incomingSms.body, inText, "msg body"); + is(incomingSms.delivery, "received", "delivery"); + is(incomingSms.deliveryStatus, "success", "deliveryStatus"); + is(incomingSms.read, false, "read"); + is(incomingSms.receiver, EMULATOR, "receiver"); + is(incomingSms.sender, REMOTE, "sender"); + is(incomingSms.messageClass, "normal", "messageClass"); + ok(incomingSms.timestamp instanceof Date, "timestamp is instanceof date"); +@@ -57,16 +61,18 @@ function sendSms() { + sms.onsent = function(event) { + log("Received 'onsent' smsmanager event."); + gotSmsOnsent = true; + let sentSms = event.message; + ok(sentSms, "outgoing sms"); + ok(sentSms.id, "sms id"); + outSmsId = sentSms.id; + log("Sent SMS (id: " + outSmsId + ")."); ++ ok(sentSms.threadId, "thread id"); ++ outThreadId = sentSms.threadId; + is(sentSms.body, outText, "msg body"); + is(sentSms.delivery, "sent", "delivery"); + is(sentSms.deliveryStatus, "pending", "deliveryStatus"); + is(sentSms.read, true, "read"); + is(sentSms.receiver, REMOTE, "receiver"); + is(sentSms.sender, EMULATOR, "sender"); + is(sentSms.messageClass, "normal", "messageClass"); + ok(sentSms.timestamp instanceof Date, "timestamp is instanceof date"); +@@ -106,16 +112,17 @@ function getReceivedSms() { + ok(requestRet, "smsrequest obj returned"); + + requestRet.onsuccess = function(event) { + log("Received 'onsuccess' smsrequest event."); + ok(event.target.result, "smsrequest event.target.result"); + let foundSms = event.target.result; + is(foundSms.id, inSmsId, "SMS id matches"); + log("Got SMS (id: " + foundSms.id + ")."); ++ is(foundSms.threadId, inThreadId, "thread id matches"); + is(foundSms.body, inText, "SMS msg text matches"); + is(foundSms.delivery, "received", "delivery"); + is(foundSms.deliveryStatus, "success", "deliveryStatus"); + is(foundSms.read, false, "read"); + is(foundSms.receiver, EMULATOR, "receiver"); + is(foundSms.sender, REMOTE, "sender"); + is(foundSms.messageClass, "normal", "messageClass"); + ok(foundSms.timestamp instanceof Date, "timestamp is instanceof date"); +@@ -139,16 +146,17 @@ function getSentSms() { + ok(requestRet, "smsrequest obj returned"); + + requestRet.onsuccess = function(event) { + log("Received 'onsuccess' smsrequest event."); + ok(event.target.result, "smsrequest event.target.result"); + let foundSms = event.target.result; + is(foundSms.id, outSmsId, "SMS id matches"); + log("Got SMS (id: " + foundSms.id + ")."); ++ is(foundSms.threadId, outThreadId, "thread id matches"); + is(foundSms.body, outText, "SMS msg text matches"); + is(foundSms.delivery, "sent", "delivery"); + is(foundSms.deliveryStatus, "pending", "deliveryStatus"); + is(foundSms.read, true, "read"); + is(foundSms.receiver, REMOTE, "receiver"); + is(foundSms.sender, EMULATOR, "sender"); + is(foundSms.messageClass, "normal", "messageClass"); + ok(foundSms.timestamp instanceof Date, "timestamp is instanceof date"); +diff --git a/dom/sms/tests/marionette/test_getmessages.js b/dom/sms/tests/marionette/test_getmessages.js +--- a/dom/sms/tests/marionette/test_getmessages.js ++++ b/dom/sms/tests/marionette/test_getmessages.js +@@ -185,16 +185,17 @@ function getMsgs(reverse) { + } + + function verifyFoundMsgs(foundSmsList, reverse) { + if (reverse) { + smsList.reverse(); + } + for (var x = 0; x < numberMsgs; x++) { + is(foundSmsList[x].id, smsList[x].id, "id"); ++ is(foundSmsList[x].threadId, smsList[x].threadId, "thread id"); + is(foundSmsList[x].body, smsList[x].body, "body"); + is(foundSmsList[x].delivery, smsList[x].delivery, "delivery"); + is(foundSmsList[x].read, smsList[x].read, "read"); + + // Bug 805799: receiver null when onreceived event is fired, until do a + // getMessage. Default emulator (receiver) phone number is 15555215554 + if (!smsList[x].receiver) { + isIn(foundSmsList[x].receiver, ["15555215554", "+15555215554"], "receiver"); +diff --git a/dom/sms/tests/marionette/test_incoming.js b/dom/sms/tests/marionette/test_incoming.js +--- a/dom/sms/tests/marionette/test_incoming.js ++++ b/dom/sms/tests/marionette/test_incoming.js +@@ -21,16 +21,17 @@ runEmulatorCmd("sms send " + SENDER + " + }); + + sms.onreceived = function onreceived(event) { + log("Received an SMS!"); + + let message = event.message; + ok(message instanceof MozSmsMessage); + ++ ok(message.threadId, "thread id"); + is(message.delivery, "received"); + is(message.deliveryStatus, "success"); + is(message.sender, SENDER); + is(message.receiver, RECEIVER); + is(message.body, body); + is(message.messageClass, "normal"); + ok(message.timestamp instanceof Date); + // SMSC timestamp is in seconds. +diff --git a/dom/sms/tests/marionette/test_incoming_delete.js b/dom/sms/tests/marionette/test_incoming_delete.js +--- a/dom/sms/tests/marionette/test_incoming_delete.js ++++ b/dom/sms/tests/marionette/test_incoming_delete.js +@@ -22,16 +22,17 @@ function simulateIncomingSms() { + log("Simulating incoming SMS."); + + sms.onreceived = function onreceived(event) { + log("Received 'onreceived' smsmanager event."); + let incomingSms = event.message; + ok(incomingSms, "incoming sms"); + ok(incomingSms.id, "sms id"); + log("Received SMS (id: " + incomingSms.id + ")."); ++ ok(incomingSms.threadId, "thread id"); + is(incomingSms.body, msgText, "msg body"); + is(incomingSms.delivery, "received", "delivery"); + is(incomingSms.deliveryStatus, "success", "deliveryStatus"); + is(incomingSms.read, false, "read"); + is(incomingSms.receiver, RECEIVER, "receiver"); + is(incomingSms.sender, SENDER, "sender"); + is(incomingSms.messageClass, "normal", "messageClass"); + ok(incomingSms.timestamp instanceof Date, "timestamp is istanceof date"); +@@ -48,16 +49,17 @@ function verifySmsExists(incomingSms) { + let requestRet = sms.getMessage(incomingSms.id); + ok(requestRet, "smsrequest obj returned"); + + requestRet.onsuccess = function(event) { + log("Received 'onsuccess' smsrequest event."); + ok(event.target.result, "smsrequest event.target.result"); + let foundSms = event.target.result; + is(foundSms.id, incomingSms.id, "found SMS id matches"); ++ is(foundSms.threadId, incomingSms.threadId, "found SMS thread id matches"); + is(foundSms.body, msgText, "found SMS msg text matches"); + is(foundSms.delivery, "received", "delivery"); + is(foundSms.deliveryStatus, "success", "deliveryStatus"); + is(foundSms.read, false, "read"); + is(foundSms.receiver, RECEIVER, "receiver"); + is(foundSms.sender, SENDER, "sender"); + is(foundSms.messageClass, "normal", "messageClass"); + log("Got SMS (id: " + foundSms.id + ") as expected."); +diff --git a/dom/sms/tests/marionette/test_incoming_multipart.js b/dom/sms/tests/marionette/test_incoming_multipart.js +--- a/dom/sms/tests/marionette/test_incoming_multipart.js ++++ b/dom/sms/tests/marionette/test_incoming_multipart.js +@@ -28,16 +28,17 @@ function simulateIncomingSms() { + } + + sms.onreceived = function onreceived(event) { + log("Received 'onreceived' smsmanager event."); + let incomingSms = event.message; + ok(incomingSms, "incoming sms"); + ok(incomingSms.id, "sms id"); + log("Received SMS (id: " + incomingSms.id + ")."); ++ ok(incomingSms.threadId, "thread id"); + is(incomingSms.body, msgText, "msg body"); + is(incomingSms.delivery, "received", "delivery"); + is(incomingSms.read, false, "read"); + is(incomingSms.receiver, RECEIVER, "receiver"); + is(incomingSms.sender, SENDER, "sender"); + ok(incomingSms.timestamp instanceof Date, "timestamp is istanceof date"); + + verifySmsExists(incomingSms); +@@ -52,16 +53,17 @@ function verifySmsExists(incomingSms) { + let requestRet = sms.getMessage(incomingSms.id); + ok(requestRet, "smsrequest obj returned"); + + requestRet.onsuccess = function(event) { + log("Received 'onsuccess' smsrequest event."); + ok(event.target.result, "smsrequest event.target.result"); + let foundSms = event.target.result; + is(foundSms.id, incomingSms.id, "found SMS id matches"); ++ is(foundSms.threadId, incomingSms.threadId, "found SMS thread id matches"); + is(foundSms.body, incomingSms.body, "found SMS msg text matches"); + is(foundSms.delivery, "received", "delivery"); + is(foundSms.read, false, "read"); + is(foundSms.receiver, RECEIVER, "receiver"); + is(foundSms.sender, SENDER, "sender"); + log("Got SMS (id: " + foundSms.id + ") as expected."); + deleteSms(incomingSms); + }; +diff --git a/dom/sms/tests/marionette/test_message_classes.js b/dom/sms/tests/marionette/test_message_classes.js +--- a/dom/sms/tests/marionette/test_message_classes.js ++++ b/dom/sms/tests/marionette/test_message_classes.js +@@ -26,23 +26,28 @@ function sendSmsPduToEmulator(pdu) { + runEmulatorCmd(cmd, function (result) { + --pendingEmulatorCmdCount; + + is(result[0], "OK", "Emulator response"); + }); + } + + const TIMESTAMP = Date.UTC(2000, 0, 1); +-function checkMessage(message, id, messageClass) { ++function checkMessage(message, id, threadId, messageClass) { + ok(message instanceof MozSmsMessage, + "message is instanceof " + message.constructor); + if (id == null) { + ok(message.id > 0, "message.id"); + } else { +- is(message.id, -1, "message.id"); ++ is(message.id, id, "message.id"); ++ } ++ if (threadId == null) { ++ ok(message.threadId > 0, "message.threadId"); ++ } else { ++ is(message.threadId, threadId, "message.threadId"); + } + is(message.delivery, "received", "message.delivery"); + is(message.deliveryStatus, "success", "message.deliveryStatus"); + is(message.sender, "+1", "message.sender"); + is(message.body, "A", "message.body"); + is(message.messageClass, messageClass, "message.messageClass"); + ok(message.timestamp instanceof Date, + "message.timestamp is instanceof " + message.timestamp.constructor); +@@ -57,17 +62,17 @@ function test_message_class_0() { + "F0" // (no name) Group: 1111 + ]; + + function do_test(dcsIndex) { + sms.addEventListener("received", function onReceived(event) { + sms.removeEventListener("received", onReceived); + + let message = event.message; +- checkMessage(message, -1, "class-0"); ++ checkMessage(message, -1, 0, "class-0"); + + // Make sure the message is not stored. + let request = sms.getMessages(null, false); + request.onsuccess = function onsuccess() { + let cursor = request.result; + if (cursor.message) { + // Here we check whether there is any message of the same sender. + isnot(cursor.message.sender, message.sender, "cursor.message.sender"); +@@ -102,17 +107,17 @@ function test_message_class_0() { + } + + function doTestMessageClassGeneric(allDCSs, messageClass, next) { + function do_test(dcsIndex) { + sms.addEventListener("received", function onReceived(event) { + sms.removeEventListener("received", onReceived); + + // Make sure we can correctly receive the message +- checkMessage(event.message, null, messageClass); ++ checkMessage(event.message, null, null, messageClass); + + ++dcsIndex; + if (dcsIndex >= allDCSs.length) { + window.setTimeout(next, 0); + } else { + window.setTimeout(do_test.bind(null, dcsIndex), 0); + } + }); +@@ -152,17 +157,17 @@ function test_message_class_2() { + PDU_PID_USIM_DATA_DOWNLOAD + ]; + + function do_test_dcs(dcsIndex) { + function do_test_pid(pidIndex) { + function onReceived(event) { + if (pidIndex == 0) { + // Make sure we can correctly receive the message +- checkMessage(event.message, null, "class-2"); ++ checkMessage(event.message, null, null, "class-2"); + + next(); + return; + } + + // TODO: Bug 792798 - B2G SMS: develop test cases for Message Class 2 + // Since we have "data download via SMS Point-to-Point" service enabled + // but no working implementation in emulator SIM, all class 2 messages +diff --git a/dom/sms/tests/marionette/test_outgoing.js b/dom/sms/tests/marionette/test_outgoing.js +--- a/dom/sms/tests/marionette/test_outgoing.js ++++ b/dom/sms/tests/marionette/test_outgoing.js +@@ -27,16 +27,17 @@ const LONG_BODY = "Let me not to the mar + + "I never writ, nor no man ever loved. "; + + function checkMessage(message, delivery, body) { + ok(message, "message is valid"); + ok(message instanceof MozSmsMessage, + "message is instanceof " + message.constructor); + + ok(message.id, "message.id"); ++ ok(message.threadId, "message.threadId"); + is(message.delivery, delivery, "message.delivery"); + is(message.deliveryStatus, "pending", "message.deliveryStatus"); + is(message.sender, SENDER, "message.sender"); + ok(message.receiver, "message.receiver"); + is(message.body, body, "message.body"); + is(message.messageClass, "normal", "message.messageClass"); + ok(message.timestamp instanceof Date, + "message.timestamp is instanceof " + message.timestamp.constructor); +diff --git a/dom/sms/tests/marionette/test_outgoing_delete.js b/dom/sms/tests/marionette/test_outgoing_delete.js +--- a/dom/sms/tests/marionette/test_outgoing_delete.js ++++ b/dom/sms/tests/marionette/test_outgoing_delete.js +@@ -27,16 +27,17 @@ function sendSms() { + sms.onsent = function(event) { + log("Received 'onsent' smsmanager event."); + gotSmsOnsent = true; + let sentSms = event.message; + ok(sentSms, "outgoing sms"); + ok(sentSms.id, "sms id"); + smsId = sentSms.id; + log("Sent SMS (id: " + smsId + ")."); ++ ok(sentSms.threadId, "thread id"); + is(sentSms.body, msgText, "msg body"); + is(sentSms.delivery, "sent", "delivery"); + is(sentSms.deliveryStatus, "pending", "deliveryStatus"); + is(sentSms.read, true, "read"); + is(sentSms.receiver, RECEIVER, "receiver"); + is(sentSms.sender, SENDER, "sender"); + is(sentSms.messageClass, "normal", "messageClass"); + ok(sentSms.timestamp instanceof Date, "timestamp is istanceof date"); +diff --git a/dom/sms/tests/test_smsservice_createsmsmessage.js b/dom/sms/tests/test_smsservice_createsmsmessage.js +--- a/dom/sms/tests/test_smsservice_createsmsmessage.js ++++ b/dom/sms/tests/test_smsservice_createsmsmessage.js +@@ -27,41 +27,45 @@ function newMessage() { + function run_test() { + run_next_test(); + } + + /** + * Ensure an SmsMessage object created has sensible initial values. + */ + add_test(function test_interface() { +- let sms = newMessage(null, "sent", "pending", null, null, null, "normal", +- new Date(), true); ++ let sms = newMessage(null, null, "sent", "pending", null, null, null, ++ "normal", new Date(), true); + do_check_true(sms instanceof Ci.nsIDOMMozSmsMessage); + do_check_eq(sms.id, 0); ++ do_check_eq(sms.threadId, 0); + do_check_eq(sms.delivery, "sent"); + do_check_eq(sms.deliveryStatus, "pending"); + do_check_eq(sms.receiver, null); + do_check_eq(sms.sender, null); + do_check_eq(sms.body, null); + do_check_eq(sms.messageClass, "normal"); + do_check_true(sms.timestamp instanceof Date); + do_check_true(sms.read); + run_next_test(); + }); + + /** + * Verify that attributes are read-only. + */ + add_test(function test_readonly_attributes() { +- let sms = newMessage(null, "received", "success", null, null, null, ++ let sms = newMessage(null, null, "received", "success", null, null, null, + "normal", new Date(), true); + + sms.id = 1; + do_check_eq(sms.id, 0); + ++ sms.threadId = 1; ++ do_check_eq(sms.threadId, 0); ++ + sms.delivery = "sent"; + do_check_eq(sms.delivery, "received"); + + sms.deliveryStatus = "pending"; + do_check_eq(sms.deliveryStatus, "success"); + + sms.receiver = "a receiver"; + do_check_eq(sms.receiver, null); +@@ -85,19 +89,20 @@ add_test(function test_readonly_attribut + run_next_test(); + }); + + /** + * Test supplying the timestamp as a number of milliseconds. + */ + add_test(function test_timestamp_number() { + let ts = Date.now(); +- let sms = newMessage(42, "sent", "pending", "the sender", "the receiver", ++ let sms = newMessage(42, 1, "sent", "pending", "the sender", "the receiver", + "the body", "normal", ts, true); + do_check_eq(sms.id, 42); ++ do_check_eq(sms.threadId, 1); + do_check_eq(sms.delivery, "sent"); + do_check_eq(sms.deliveryStatus, "pending"); + do_check_eq(sms.sender, "the sender"); + do_check_eq(sms.receiver, "the receiver"); + do_check_eq(sms.body, "the body"); + do_check_eq(sms.messageClass, "normal"); + do_check_true(sms.timestamp instanceof Date); + do_check_eq(sms.timestamp.getTime(), ts); +@@ -105,19 +110,20 @@ add_test(function test_timestamp_number( + run_next_test(); + }); + + /** + * Test supplying the timestamp as a Date object. + */ + add_test(function test_timestamp_date() { + let date = new Date(); +- let sms = newMessage(42, "sent", "pending", "the sender", "the receiver", ++ let sms = newMessage(42, 1, "sent", "pending", "the sender", "the receiver", + "the body", "normal", date, true); + do_check_eq(sms.id, 42); ++ do_check_eq(sms.threadId, 1); + do_check_eq(sms.delivery, "sent"); + do_check_eq(sms.deliveryStatus, "pending"); + do_check_eq(sms.sender, "the sender"); + do_check_eq(sms.receiver, "the receiver"); + do_check_eq(sms.body, "the body"); + do_check_eq(sms.messageClass, "normal"); + do_check_true(sms.timestamp instanceof Date); + do_check_eq(sms.timestamp.getTime(), date.getTime()); +@@ -125,112 +131,112 @@ add_test(function test_timestamp_date() + run_next_test(); + }); + + /** + * Test that a floating point number for the timestamp is not allowed. + */ + add_test(function test_invalid_timestamp_float() { + do_check_throws(function() { +- newMessage(42, "sent", "pending", "the sender", "the receiver", "the body", +- "normal", 3.1415, true); ++ newMessage(42, 1, "sent", "pending", "the sender", "the receiver", ++ "the body", "normal", 3.1415, true); + }, Cr.NS_ERROR_INVALID_ARG); + run_next_test(); + }); + + /** + * Test that a null value for the timestamp is not allowed. + */ + add_test(function test_invalid_timestamp_null() { + do_check_throws(function() { +- newMessage(42, "sent", "pending", "the sender", "the receiver", "the body", +- "normal", null, true); ++ newMessage(42, 1, "sent", "pending", "the sender", "the receiver", ++ "the body", "normal", null, true); + }, Cr.NS_ERROR_INVALID_ARG); + run_next_test(); + }); + + /** + * Test that undefined for the timestamp is not allowed. + */ + add_test(function test_invalid_timestamp_undefined() { + do_check_throws(function() { +- newMessage(42, "sent", "pending", "the sender", "the receiver", "the body", +- "normal", undefined, true); ++ newMessage(42, 1, "sent", "pending", "the sender", "the receiver", ++ "the body", "normal", undefined, true); + }, Cr.NS_ERROR_INVALID_ARG); + run_next_test(); + }); + + /** + * Test that a random object for the timestamp is not allowed. + */ + add_test(function test_invalid_timestamp_object() { + do_check_throws(function() { +- newMessage(42, "sent", "pending", "the sender", "the receiver", "the body", +- "normal", {}, true); ++ newMessage(42, 1, "sent", "pending", "the sender", "the receiver", ++ "the body", "normal", {}, true); + }, Cr.NS_ERROR_INVALID_ARG); + run_next_test(); + }); + + /** + * Test that an invalid delivery string is not accepted. + */ + add_test(function test_invalid_delivery_string() { + do_check_throws(function() { +- newMessage(42, "this is invalid", "pending", "the sender", "the receiver", +- "the body", "normal", new Date(), true); ++ newMessage(42, 1, "this is invalid", "pending", "the sender", ++ "the receiver", "the body", "normal", new Date(), true); + }, Cr.NS_ERROR_INVALID_ARG); + run_next_test(); + }); + + /** + * Test that a number is not accepted for the 'delivery' argument. + */ + add_test(function test_invalid_delivery_string() { + do_check_throws(function() { +- newMessage(42, 1, "pending", "the sender", "the receiver", "the body", ++ newMessage(42, 1, 1, "pending", "the sender", "the receiver", "the body", + "normal", new Date(), true); + }, Cr.NS_ERROR_INVALID_ARG); + run_next_test(); + }); + + /** + * Test that an invalid delivery status string is not accepted. + */ + add_test(function test_invalid_delivery_status_string() { + do_check_throws(function() { +- newMessage(42, "sent", "this is invalid", "the sender", "the receiver", ++ newMessage(42, 1, "sent", "this is invalid", "the sender", "the receiver", + "the body", "normal", new Date(), true); + }, Cr.NS_ERROR_INVALID_ARG); + run_next_test(); + }); + + /** + * Test that a number is not accepted for the 'deliveryStatus' argument. + */ + add_test(function test_invalid_delivery_status_string() { + do_check_throws(function() { +- newMessage(42, "sent", 1, "the sender", "the receiver", "the body", ++ newMessage(42, 1, "sent", 1, "the sender", "the receiver", "the body", + "normal", new Date(), true); + }, Cr.NS_ERROR_INVALID_ARG); + run_next_test(); + }); + + /** + * Test that an invalid message class string is not accepted. + */ + add_test(function test_invalid_message_class_string() { + do_check_throws(function() { +- newMessage(42, "sent", "pending", "the sender", "the receiver", ++ newMessage(42, 1, "sent", "pending", "the sender", "the receiver", + "the body", "this is invalid", new Date(), true); + }, Cr.NS_ERROR_INVALID_ARG); + run_next_test(); + }); + + /** + * Test that a number is not accepted for the 'messageClass' argument. + */ + add_test(function test_invalid_message_class_string() { + do_check_throws(function() { +- newMessage(42, "sent", "pending", "the sender", "the receiver", "the body", +- 1, new Date(), true); ++ newMessage(42, 1, "sent", "pending", "the sender", "the receiver", ++ "the body", 1, new Date(), true); + }, Cr.NS_ERROR_INVALID_ARG); + run_next_test(); + }); +diff --git a/dom/system/gonk/RadioInterfaceLayer.js b/dom/system/gonk/RadioInterfaceLayer.js +--- a/dom/system/gonk/RadioInterfaceLayer.js ++++ b/dom/system/gonk/RadioInterfaceLayer.js +@@ -1441,16 +1441,17 @@ RadioInterfaceLayer.prototype = { + // At this point we could send a message to content to notify the user + // that storing an incoming SMS failed, most likely due to a full disk. + debug("Could not store SMS " + message.id + ", error code " + rv); + return; + } + + gSystemMessenger.broadcastMessage("sms-received", { + id: message.id, ++ threadId: sms.threadId, + 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 +@@ -1463,16 +1464,17 @@ RadioInterfaceLayer.prototype = { + message.sender || null, + message.fullBody || null, + message.messageClass, + message.timestamp, + notifyReceived); + } else { + message.id = -1; + let sms = gSmsService.createSmsMessage(message.id, ++ 0, + DOM_SMS_DELIVERY_RECEIVED, + RIL.GECKO_SMS_DELIVERY_STATUS_SUCCESS, + message.sender || null, + message.receiver || null, + message.fullBody || null, + message.messageClass, + message.timestamp, + false); +@@ -1508,16 +1510,17 @@ RadioInterfaceLayer.prototype = { + + gSmsDatabaseService.setMessageDelivery(options.sms.id, + DOM_SMS_DELIVERY_SENT, + options.sms.deliveryStatus, + function notifyResult(rv, sms) { + //TODO bug 832140 handle !Components.isSuccessCode(rv) + gSystemMessenger.broadcastMessage("sms-sent", + {id: options.sms.id, ++ threadId: options.sms.threadId, + delivery: DOM_SMS_DELIVERY_SENT, + deliveryStatus: options.sms.deliveryStatus, + sender: message.sender || null, + receiver: options.sms.receiver, + body: options.sms.body, + messageClass: options.sms.messageClass, + timestamp: options.sms.timestamp, + read: true});