Bug 742790 - Part 2/5: DOM implementation, r=mounir
authorVicamo Yang <vyang@mozilla.com>
Tue, 30 Oct 2012 18:53:24 +0800
changeset 111889 289f2d39289c776e711d45ec6292a1c412e16237
parent 111888 853062e5abc5742edb6df14f8ee98164a357b0b8
child 111890 95642feb675f26b4eac08ae3bb71a82413eafc6a
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
reviewersmounir
bugs742790
milestone19.0a1
Bug 742790 - Part 2/5: DOM implementation, r=mounir
content/base/src/nsGkAtomList.h
dom/sms/interfaces/nsISmsDatabaseService.idl
dom/sms/interfaces/nsISmsService.idl
dom/sms/src/Constants.cpp
dom/sms/src/Constants.h
dom/sms/src/SmsManager.cpp
dom/sms/src/SmsMessage.cpp
dom/sms/src/SmsMessage.h
dom/sms/src/Types.h
dom/sms/src/android/SmsDatabaseService.cpp
dom/sms/src/android/SmsService.cpp
dom/sms/src/fallback/SmsDatabaseService.cpp
dom/sms/src/fallback/SmsService.cpp
dom/sms/src/ipc/PSms.ipdl
dom/sms/src/ipc/SmsChild.cpp
dom/sms/src/ipc/SmsChild.h
dom/sms/src/ipc/SmsIPCService.cpp
dom/sms/src/ipc/SmsParent.cpp
dom/sms/src/ipc/SmsParent.h
dom/sms/src/ril/SmsService.cpp
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -656,17 +656,18 @@ GK_ATOM(oncompositionupdate, "oncomposit
 GK_ATOM(onconnected, "onconnected")
 GK_ATOM(onconnecting, "onconnecting")
 GK_ATOM(oncontextmenu, "oncontextmenu")
 GK_ATOM(oncopy, "oncopy")
 GK_ATOM(oncut, "oncut")
 GK_ATOM(ondatachange, "ondatachange")
 GK_ATOM(ondataerror, "ondataerror")
 GK_ATOM(ondblclick, "ondblclick")
-GK_ATOM(ondelivered, "ondelivered")
+GK_ATOM(ondeliverysuccess, "ondeliverysuccess")
+GK_ATOM(ondeliveryerror, "ondeliveryerror")
 GK_ATOM(ondevicecreated, "ondevicecreated")
 GK_ATOM(ondevicedisappeared, "ondevicedisappeared")
 GK_ATOM(ondevicefound, "ondevicefound")
 GK_ATOM(ondialing, "ondialing")
 GK_ATOM(ondisabled, "ondisabled")
 GK_ATOM(ondischargingtimechange, "ondischargingtimechange")
 GK_ATOM(ondisconnected, "ondisconnected")
 GK_ATOM(ondisconnecting, "ondisconnecting")
--- a/dom/sms/interfaces/nsISmsDatabaseService.idl
+++ b/dom/sms/interfaces/nsISmsDatabaseService.idl
@@ -8,23 +8,24 @@
 #define SMS_DATABASE_SERVICE_CID \
 { 0x2454c2a1, 0xefdd, 0x4d96,    \
 { 0x83, 0xbd, 0x51, 0xa2, 0x9a, 0x21, 0xf5, 0xab } }
 #define SMS_DATABASE_SERVICE_CONTRACTID "@mozilla.org/sms/smsdatabaseservice;1"
 %}
 
 interface nsIDOMMozSmsFilter;
 
-[scriptable, uuid(30e8cdfb-155d-44c7-8fb3-6bcd9c1c3f99)]
+[scriptable, uuid(d6318c22-1ebd-4262-b991-432f61a96237)]
 interface nsISmsDatabaseService : nsISupports
 {
   // Takes some information required to save the message and returns its id.
   long saveReceivedMessage(in DOMString aSender, in DOMString aBody, in unsigned long long aDate);
   // Takes some information required to save the message and returns its id.
   long saveSentMessage(in DOMString aReceiver, in DOMString aBody, in unsigned long long aDate);
+  void setMessageDeliveryStatus(in long aMessageId, in DOMString aDeliveryStatus);
 
   [binaryname(GetMessageMoz)] void getMessage(in long messageId, in long requestId, [optional] in unsigned long long processId);
   void deleteMessage(in long messageId, in long requestId, [optional] in unsigned long long processId);
 
   void createMessageList(in nsIDOMMozSmsFilter filter, in boolean reverse, in long requestId, [optional] in unsigned long long processId);
   void getNextMessageInList(in long listId, in long requestId, [optional] in unsigned long long processId);
   void clearMessageList(in long listId);
   void markMessageRead(in long messageId, in boolean value, in long requestId, [optional] in unsigned long long processId);
--- a/dom/sms/interfaces/nsISmsService.idl
+++ b/dom/sms/interfaces/nsISmsService.idl
@@ -6,25 +6,26 @@
 
 interface nsIDOMMozSmsMessage;
 
 %{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(00d23a50-6ed1-48b4-b1e9-5987b155e54b)]
+[scriptable, builtinclass, uuid(a1367149-c09f-4e8c-a890-5812406bed61)]
 interface nsISmsService : nsISupports
 {
   boolean        hasSupport();
   unsigned short getNumberOfMessagesForText(in DOMString text);
             void send(in DOMString number, in DOMString message,
                       in long requestId, [optional] in unsigned long long processId);
 
   [implicit_jscontext]
   nsIDOMMozSmsMessage createSmsMessage(in long      id,
                                        in DOMString delivery,
+                                       in DOMString deliveryStatus,
                                        in DOMString sender,
                                        in DOMString receiver,
                                        in DOMString body,
                                        in jsval     timestamp,
                                        in bool      read);
 };
--- a/dom/sms/src/Constants.cpp
+++ b/dom/sms/src/Constants.cpp
@@ -2,15 +2,16 @@
 /* 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/. */
 
 namespace mozilla {
 namespace dom {
 namespace sms {
 
-const char* kSmsReceivedObserverTopic  = "sms-received";
-const char* kSmsSentObserverTopic      = "sms-sent";
-const char* kSmsDeliveredObserverTopic = "sms-delivered";
+const char* kSmsReceivedObserverTopic        = "sms-received";
+const char* kSmsSentObserverTopic            = "sms-sent";
+const char* kSmsDeliverySuccessObserverTopic = "sms-delivery-success";
+const char* kSmsDeliveryErrorObserverTopic   = "sms-delivery-error";
 
 } // namespace sms
 } // namespace dom
 } // namespace mozilla
--- a/dom/sms/src/Constants.h
+++ b/dom/sms/src/Constants.h
@@ -5,20 +5,26 @@
 
 #ifndef mozilla_dom_sms_Constants_h
 #define mozilla_dom_sms_Constants_h
 
 namespace mozilla {
 namespace dom {
 namespace sms {
 
-extern const char* kSmsReceivedObserverTopic;  // Defined in the .cpp.
-extern const char* kSmsSentObserverTopic;      // Defined in the .cpp.
-extern const char* kSmsDeliveredObserverTopic; // Defined in the .cpp.
+extern const char* kSmsReceivedObserverTopic;        // Defined in the .cpp.
+extern const char* kSmsSentObserverTopic;            // Defined in the .cpp.
+extern const char* kSmsDeliverySuccessObserverTopic; // Defined in the .cpp.
+extern const char* kSmsDeliveryErrorObserverTopic;   // Defined in the .cpp.
 
 #define DELIVERY_RECEIVED NS_LITERAL_STRING("received")
 #define DELIVERY_SENT     NS_LITERAL_STRING("sent")
 
+#define DELIVERY_STATUS_NOT_APPLICABLE NS_LITERAL_STRING("not-applicable")
+#define DELIVERY_STATUS_SUCCESS        NS_LITERAL_STRING("success")
+#define DELIVERY_STATUS_PENDING        NS_LITERAL_STRING("pending")
+#define DELIVERY_STATUS_ERROR          NS_LITERAL_STRING("error")
+
 } // namespace sms
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_sms_Constants_h
--- a/dom/sms/src/SmsManager.cpp
+++ b/dom/sms/src/SmsManager.cpp
@@ -20,19 +20,20 @@
 #include "nsISmsDatabaseService.h"
 #include "nsIXPConnect.h"
 #include "nsIPermissionManager.h"
 
 /**
  * We have to use macros here because our leak analysis tool things we are
  * leaking strings when we have |static const nsString|. Sad :(
  */
-#define RECEIVED_EVENT_NAME  NS_LITERAL_STRING("received")
-#define SENT_EVENT_NAME      NS_LITERAL_STRING("sent")
-#define DELIVERED_EVENT_NAME NS_LITERAL_STRING("delivered")
+#define RECEIVED_EVENT_NAME         NS_LITERAL_STRING("received")
+#define SENT_EVENT_NAME             NS_LITERAL_STRING("sent")
+#define DELIVERY_SUCCESS_EVENT_NAME NS_LITERAL_STRING("deliverysuccess")
+#define DELIVERY_ERROR_EVENT_NAME   NS_LITERAL_STRING("deliveryerror")
 
 DOMCI_DATA(MozSmsManager, mozilla::dom::sms::SmsManager)
 
 namespace mozilla {
 namespace dom {
 namespace sms {
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(SmsManager)
@@ -52,17 +53,18 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozSmsManager)
 NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
 
 NS_IMPL_ADDREF_INHERITED(SmsManager, nsDOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(SmsManager, nsDOMEventTargetHelper)
 
 NS_IMPL_EVENT_HANDLER(SmsManager, received)
 NS_IMPL_EVENT_HANDLER(SmsManager, sent)
-NS_IMPL_EVENT_HANDLER(SmsManager, delivered)
+NS_IMPL_EVENT_HANDLER(SmsManager, deliverysuccess)
+NS_IMPL_EVENT_HANDLER(SmsManager, deliveryerror)
 
 /* static */already_AddRefed<SmsManager>
 SmsManager::CreateInstanceIfAllowed(nsPIDOMWindow* aWindow)
 {
   NS_ASSERTION(aWindow, "Null pointer!");
 
 #ifndef MOZ_WEBSMS_BACKEND
   return nullptr;
@@ -108,31 +110,33 @@ SmsManager::Init(nsPIDOMWindow *aWindow)
   nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
   // GetObserverService() can return null is some situations like shutdown.
   if (!obs) {
     return;
   }
 
   obs->AddObserver(this, kSmsReceivedObserverTopic, false);
   obs->AddObserver(this, kSmsSentObserverTopic, false);
-  obs->AddObserver(this, kSmsDeliveredObserverTopic, false);
+  obs->AddObserver(this, kSmsDeliverySuccessObserverTopic, false);
+  obs->AddObserver(this, kSmsDeliveryErrorObserverTopic, false);
 }
 
 void
 SmsManager::Shutdown()
 {
   nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
   // GetObserverService() can return null is some situations like shutdown.
   if (!obs) {
     return;
   }
 
   obs->RemoveObserver(this, kSmsReceivedObserverTopic);
   obs->RemoveObserver(this, kSmsSentObserverTopic);
-  obs->RemoveObserver(this, kSmsDeliveredObserverTopic);
+  obs->RemoveObserver(this, kSmsDeliverySuccessObserverTopic);
+  obs->RemoveObserver(this, kSmsDeliveryErrorObserverTopic);
 }
 
 NS_IMETHODIMP
 SmsManager::GetNumberOfMessagesForText(const nsAString& aText, uint16_t* aResult)
 {
   nsCOMPtr<nsISmsService> smsService = do_GetService(SMS_SERVICE_CONTRACTID);
   NS_ENSURE_TRUE(smsService, NS_OK);
 
@@ -376,24 +380,35 @@ SmsManager::Observe(nsISupports* aSubjec
       NS_ERROR("Got a 'sms-sent' topic without a valid message!");
       return NS_OK;
     }
 
     DispatchTrustedSmsEventToSelf(SENT_EVENT_NAME, message);
     return NS_OK;
   }
 
-  if (!strcmp(aTopic, kSmsDeliveredObserverTopic)) {
+  if (!strcmp(aTopic, kSmsDeliverySuccessObserverTopic)) {
     nsCOMPtr<nsIDOMMozSmsMessage> message = do_QueryInterface(aSubject);
     if (!message) {
-      NS_ERROR("Got a 'sms-delivered' topic without a valid message!");
+      NS_ERROR("Got a 'sms-delivery-success' topic without a valid message!");
       return NS_OK;
     }
 
-    DispatchTrustedSmsEventToSelf(DELIVERED_EVENT_NAME, message);
+    DispatchTrustedSmsEventToSelf(DELIVERY_SUCCESS_EVENT_NAME, message);
+    return NS_OK;
+  }
+
+  if (!strcmp(aTopic, kSmsDeliveryErrorObserverTopic)) {
+    nsCOMPtr<nsIDOMMozSmsMessage> message = do_QueryInterface(aSubject);
+    if (!message) {
+      NS_ERROR("Got a 'sms-delivery-error' topic without a valid message!");
+      return NS_OK;
+    }
+
+    DispatchTrustedSmsEventToSelf(DELIVERY_ERROR_EVENT_NAME, message);
     return NS_OK;
   }
 
   return NS_OK;
 }
 
 } // namespace sms
 } // namespace dom
--- a/dom/sms/src/SmsMessage.cpp
+++ b/dom/sms/src/SmsMessage.cpp
@@ -19,31 +19,38 @@ NS_INTERFACE_MAP_BEGIN(SmsMessage)
   NS_INTERFACE_MAP_ENTRY(nsIDOMMozSmsMessage)
   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, DeliveryState aDelivery,
-                       const nsString& aSender, const nsString& aReceiver,
-                       const nsString& aBody, uint64_t aTimestamp, bool aRead)
-  : mData(aId, aDelivery, aSender, aReceiver, aBody, aTimestamp, aRead)
+SmsMessage::SmsMessage(int32_t aId,
+                       DeliveryState aDelivery,
+                       DeliveryStatus aDeliveryStatus,
+                       const nsString& aSender,
+                       const nsString& aReceiver,
+                       const nsString& aBody,
+                       uint64_t aTimestamp,
+                       bool aRead)
+  : mData(aId, aDelivery, aDeliveryStatus, aSender, aReceiver, aBody,
+          aTimestamp, aRead)
 {
 }
 
 SmsMessage::SmsMessage(const SmsMessageData& aData)
   : mData(aData)
 {
 }
 
 /* static */ nsresult
 SmsMessage::Create(int32_t aId,
                    const nsAString& aDelivery,
+                   const nsAString& aDeliveryStatus,
                    const nsAString& aSender,
                    const nsAString& aReceiver,
                    const nsAString& aBody,
                    const jsval& aTimestamp,
                    const bool aRead,
                    JSContext* aCx,
                    nsIDOMMozSmsMessage** aMessage)
 {
@@ -61,16 +68,28 @@ SmsMessage::Create(int32_t aId,
   if (aDelivery.Equals(DELIVERY_RECEIVED)) {
     data.delivery() = eDeliveryState_Received;
   } else if (aDelivery.Equals(DELIVERY_SENT)) {
     data.delivery() = eDeliveryState_Sent;
   } else {
     return NS_ERROR_INVALID_ARG;
   }
 
+  if (aDeliveryStatus.Equals(DELIVERY_STATUS_NOT_APPLICABLE)) {
+    data.deliveryStatus() = eDeliveryStatus_NotApplicable;
+  } else if (aDeliveryStatus.Equals(DELIVERY_STATUS_SUCCESS)) {
+    data.deliveryStatus() = eDeliveryStatus_Success;
+  } else if (aDeliveryStatus.Equals(DELIVERY_STATUS_PENDING)) {
+    data.deliveryStatus() = eDeliveryStatus_Pending;
+  } else if (aDeliveryStatus.Equals(DELIVERY_STATUS_ERROR)) {
+    data.deliveryStatus() = eDeliveryStatus_Error;
+  } else {
+    return NS_ERROR_INVALID_ARG;
+  }
+
   // We support both a Date object and a millisecond timestamp as a number.
   if (aTimestamp.isObject()) {
     JSObject& obj = aTimestamp.toObject();
     if (!JS_ObjectIsDate(aCx, &obj)) {
       return NS_ERROR_INVALID_ARG;
     }
     data.timestamp() = js_DateGetMsecSinceEpoch(&obj);
   } else {
@@ -110,17 +129,42 @@ SmsMessage::GetDelivery(nsAString& aDeli
       aDelivery = DELIVERY_RECEIVED;
       break;
     case eDeliveryState_Sent:
       aDelivery = DELIVERY_SENT;
       break;
     case eDeliveryState_Unknown:
     case eDeliveryState_EndGuard:
     default:
-      NS_ASSERTION(true, "We shouldn't get any other delivery state!");
+      MOZ_NOT_REACHED("We shouldn't get any other delivery state!");
+      return NS_ERROR_UNEXPECTED;
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+SmsMessage::GetDeliveryStatus(nsAString& aDeliveryStatus)
+{
+  switch (mData.deliveryStatus()) {
+    case eDeliveryStatus_NotApplicable:
+      aDeliveryStatus = DELIVERY_STATUS_NOT_APPLICABLE;
+      break;
+    case eDeliveryStatus_Success:
+      aDeliveryStatus = DELIVERY_STATUS_SUCCESS;
+      break;
+    case eDeliveryStatus_Pending:
+      aDeliveryStatus = DELIVERY_STATUS_PENDING;
+      break;
+    case eDeliveryStatus_Error:
+      aDeliveryStatus = DELIVERY_STATUS_ERROR;
+      break;
+    case eDeliveryStatus_EndGuard:
+    default:
+      MOZ_NOT_REACHED("We shouldn't get any other delivery status!");
       return NS_ERROR_UNEXPECTED;
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 SmsMessage::GetSender(nsAString& aSender)
--- a/dom/sms/src/SmsMessage.h
+++ b/dom/sms/src/SmsMessage.h
@@ -18,23 +18,29 @@ namespace dom {
 namespace sms {
 
 class SmsMessage MOZ_FINAL : public nsIDOMMozSmsMessage
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMMOZSMSMESSAGE
 
-  SmsMessage(int32_t aId, DeliveryState aDelivery, const nsString& aSender,
-             const nsString& aReceiver, const nsString& aBody,
-             uint64_t aTimestamp, bool aRead);
+  SmsMessage(int32_t aId,
+             DeliveryState aDelivery,
+             DeliveryStatus aDeliveryStatus,
+             const nsString& aSender,
+             const nsString& aReceiver,
+             const nsString& aBody,
+             uint64_t aTimestamp,
+             bool aRead);
   SmsMessage(const SmsMessageData& aData);
 
   static nsresult Create(int32_t aId,
                          const nsAString& aDelivery,
+                         const nsAString& aDeliveryStatus,
                          const nsAString& aSender,
                          const nsAString& aReceiver,
                          const nsAString& aBody,
                          const JS::Value& aTimestamp,
                          const bool aRead,
                          JSContext* aCx,
                          nsIDOMMozSmsMessage** aMessage);
   const SmsMessageData& GetData() const;
--- a/dom/sms/src/Types.h
+++ b/dom/sms/src/Types.h
@@ -18,16 +18,26 @@ namespace sms {
 enum DeliveryState {
   eDeliveryState_Sent = 0,
   eDeliveryState_Received,
   eDeliveryState_Unknown,
   // This state should stay at the end.
   eDeliveryState_EndGuard
 };
 
+// For SmsMessageData.deliveryStatus.
+enum DeliveryStatus {
+  eDeliveryStatus_NotApplicable = 0,
+  eDeliveryStatus_Success,
+  eDeliveryStatus_Pending,
+  eDeliveryStatus_Error,
+  // This state should stay at the end.
+  eDeliveryStatus_EndGuard
+};
+
 // For SmsFilterData.read
 enum ReadState {
   eReadState_Unknown = -1,
   eReadState_Unread,
   eReadState_Read,
   // This state should stay at the end.
   eReadState_EndGuard
 };
@@ -44,16 +54,26 @@ namespace IPC {
 template <>
 struct ParamTraits<mozilla::dom::sms::DeliveryState>
   : public EnumSerializer<mozilla::dom::sms::DeliveryState,
                           mozilla::dom::sms::eDeliveryState_Sent,
                           mozilla::dom::sms::eDeliveryState_EndGuard>
 {};
 
 /**
+ * Delivery status serializer.
+ */
+template <>
+struct ParamTraits<mozilla::dom::sms::DeliveryStatus>
+  : public EnumSerializer<mozilla::dom::sms::DeliveryStatus,
+                          mozilla::dom::sms::eDeliveryStatus_NotApplicable,
+                          mozilla::dom::sms::eDeliveryStatus_EndGuard>
+{};
+
+/**
  * Read state serializer.
  */
 template <>
 struct ParamTraits<mozilla::dom::sms::ReadState>
   : public EnumSerializer<mozilla::dom::sms::ReadState,
                           mozilla::dom::sms::eReadState_Unknown,
                           mozilla::dom::sms::eReadState_EndGuard>
 {};
--- a/dom/sms/src/android/SmsDatabaseService.cpp
+++ b/dom/sms/src/android/SmsDatabaseService.cpp
@@ -34,16 +34,24 @@ SmsDatabaseService::SaveSentMessage(cons
     return NS_OK;
   }
 
   *aId = AndroidBridge::Bridge()->SaveSentMessage(aReceiver, aBody, aDate);
   return NS_OK;
 }
 
 NS_IMETHODIMP
+SmsDatabaseService::SetMessageDeliveryStatus(int32_t aMessageId,
+                                             const nsAString& aDeliveryStatus)
+{
+  // TODO: Bug 803828: update delivery status for sent messages in Android.
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 SmsDatabaseService::GetMessageMoz(int32_t aMessageId, int32_t aRequestId,
                                   uint64_t aProcessId)
 {
   if (!AndroidBridge::Bridge()) {
     return NS_OK;
   }
 
   AndroidBridge::Bridge()->GetMessage(aMessageId, aRequestId, aProcessId);
--- a/dom/sms/src/android/SmsService.cpp
+++ b/dom/sms/src/android/SmsService.cpp
@@ -44,23 +44,26 @@ SmsService::Send(const nsAString& aNumbe
   AndroidBridge::Bridge()->SendMessage(aNumber, aMessage, aRequestId,
                                        aProcessId);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 SmsService::CreateSmsMessage(int32_t aId,
                              const nsAString& aDelivery,
+                             const nsAString& aDeliveryStatus,
                              const nsAString& aSender,
                              const nsAString& aReceiver,
                              const nsAString& aBody,
                              const jsval& aTimestamp,
                              const bool aRead,
                              JSContext* aCx,
                              nsIDOMMozSmsMessage** aMessage)
 {
-  return SmsMessage::Create(aId, aDelivery, aSender, aReceiver, aBody,
-                            aTimestamp, aRead, aCx, aMessage);
+  return SmsMessage::Create(aId, aDelivery, aDeliveryStatus,
+                            aSender, aReceiver,
+                            aBody, aTimestamp, aRead,
+                            aCx, aMessage);
 }
 
 } // namespace sms
 } // namespace dom
 } // namespace mozilla
--- a/dom/sms/src/fallback/SmsDatabaseService.cpp
+++ b/dom/sms/src/fallback/SmsDatabaseService.cpp
@@ -27,16 +27,24 @@ SmsDatabaseService::SaveSentMessage(cons
                                     uint64_t aDate, int32_t* aId)
 {
   *aId = -1;
   NS_ERROR("We should not be here!");
   return NS_OK;
 }
 
 NS_IMETHODIMP
+SmsDatabaseService::SetMessageDeliveryStatus(int32_t aMessageId,
+                                             const nsAString& aDeliveryStatus)
+{
+  NS_ERROR("We should not be here!");
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 SmsDatabaseService::GetMessageMoz(int32_t aMessageId, int32_t aRequestId,
                                   uint64_t aProcessId)
 {
   NS_ERROR("We should not be here!");
   return NS_OK;
 }
 
 NS_IMETHODIMP
--- a/dom/sms/src/fallback/SmsService.cpp
+++ b/dom/sms/src/fallback/SmsService.cpp
@@ -34,23 +34,26 @@ SmsService::Send(const nsAString& aNumbe
 {
   NS_ERROR("We should not be here!");
   return NS_OK;
 }
 
 NS_IMETHODIMP
 SmsService::CreateSmsMessage(int32_t aId,
                              const nsAString& aDelivery,
+                             const nsAString& aDeliveryStatus,
                              const nsAString& aSender,
                              const nsAString& aReceiver,
                              const nsAString& aBody,
                              const jsval& aTimestamp,
                              const bool aRead,
                              JSContext* aCx,
                              nsIDOMMozSmsMessage** aMessage)
 {
-  return SmsMessage::Create(aId, aDelivery, aSender, aReceiver, aBody,
-                            aTimestamp, aRead, aCx, aMessage);
+  return SmsMessage::Create(aId, aDelivery, aDeliveryStatus,
+                            aSender, aReceiver,
+                            aBody, aTimestamp, aRead,
+                            aCx, aMessage);
 }
 
 } // namespace sms
 } // namespace dom
 } // namespace mozilla
--- a/dom/sms/src/ipc/PSms.ipdl
+++ b/dom/sms/src/ipc/PSms.ipdl
@@ -3,30 +3,32 @@
 /* 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 protocol PContent;
 include "mozilla/dom/sms/Types.h";
 
 using DeliveryState;
+using DeliveryStatus;
 using ReadState;
 
 namespace mozilla {
 namespace dom {
 namespace sms {
 
 struct SmsMessageData {
-  int32_t       id;
-  DeliveryState delivery;
-  nsString      sender;
-  nsString      receiver;
-  nsString      body;
-  uint64_t      timestamp; // ms since epoch.
-  bool          read;
+  int32_t        id;
+  DeliveryState  delivery;
+  DeliveryStatus deliveryStatus;
+  nsString       sender;
+  nsString       receiver;
+  nsString       body;
+  uint64_t       timestamp; // ms since epoch.
+  bool           read;
 };
 
 struct SmsFilterData {
   uint64_t      startDate;
   uint64_t      endDate;
   nsString[]    numbers;
   DeliveryState delivery;
   ReadState     read;  
@@ -35,17 +37,19 @@ struct SmsFilterData {
 sync protocol PSms {
     manager PContent;
 
 child:
     NotifyReceivedMessage(SmsMessageData aMessageData);
 
     NotifySentMessage(SmsMessageData aMessageData);
 
-    NotifyDeliveredMessage(SmsMessageData aMessageData);
+    NotifyDeliverySuccessMessage(SmsMessageData aMessageData);
+
+    NotifyDeliveryErrorMessage(SmsMessageData aMessageData);
 
     NotifyRequestSmsSent(SmsMessageData aMessageData, int32_t aRequestId,
                          uint64_t aProcessId);
 
     NotifyRequestSmsSendFailed(int32_t aError, int32_t aRequestId,
                                uint64_t aProcessId);
 
     NotifyRequestGotSms(SmsMessageData aMessageData, int32_t aRequestId,
@@ -84,16 +88,18 @@ parent:
                 uint64_t aProcessId);
 
     sync SaveReceivedMessage(nsString aSender, nsString aBody, uint64_t aDate)
         returns (int32_t aId);
 
     sync SaveSentMessage(nsString aReceiver, nsString aBody, uint64_t aDate)
         returns (int32_t aId);
 
+    SetMessageDeliveryStatus(int32_t aMessageId, nsString aDeliveryStatus);
+
     GetMessage(int32_t aMessageId, int32_t aRequestId, uint64_t aProcessId);
 
     DeleteMessage(int32_t aMessageId, int32_t aRequestId, uint64_t aProcessId);
 
     CreateMessageList(SmsFilterData aFilter, bool aReverse, int32_t aRequestId, uint64_t aProcessId);
 
     GetNextMessageInList(int32_t aListId, int32_t aRequestId, uint64_t aProcessId);
 
--- a/dom/sms/src/ipc/SmsChild.cpp
+++ b/dom/sms/src/ipc/SmsChild.cpp
@@ -7,59 +7,65 @@
 #include "SmsMessage.h"
 #include "Constants.h"
 #include "nsIObserverService.h"
 #include "mozilla/Services.h"
 #include "mozilla/dom/ContentChild.h"
 #include "SmsRequestManager.h"
 #include "SmsRequest.h"
 
+using namespace mozilla;
+using namespace mozilla::dom::sms;
+
+namespace {
+
+void
+NotifyObserversWithSmsMessage(const char* aEventName,
+                              const SmsMessageData& aMessageData)
+{
+  nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
+  if (!obs) {
+    return;
+  }
+
+  nsCOMPtr<SmsMessage> message = new SmsMessage(aMessageData);
+  obs->NotifyObservers(message, aEventName, nullptr);
+}
+
+} // anonymous namespace
+
 namespace mozilla {
 namespace dom {
 namespace sms {
 
 bool
 SmsChild::RecvNotifyReceivedMessage(const SmsMessageData& aMessageData)
 {
-  nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
-  if (!obs) {
-    return true;
-  }
-
-  nsCOMPtr<SmsMessage> message = new SmsMessage(aMessageData);
-  obs->NotifyObservers(message, kSmsReceivedObserverTopic, nullptr);
-
+  NotifyObserversWithSmsMessage(kSmsReceivedObserverTopic, aMessageData);
   return true;
 }
 
 bool
 SmsChild::RecvNotifySentMessage(const SmsMessageData& aMessageData)
 {
-  nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
-  if (!obs) {
-    return true;
-  }
-
-  nsCOMPtr<SmsMessage> message = new SmsMessage(aMessageData);
-  obs->NotifyObservers(message, kSmsSentObserverTopic, nullptr);
-
+  NotifyObserversWithSmsMessage(kSmsSentObserverTopic, aMessageData);
   return true;
 }
 
 bool
-SmsChild::RecvNotifyDeliveredMessage(const SmsMessageData& aMessageData)
+SmsChild::RecvNotifyDeliverySuccessMessage(const SmsMessageData& aMessageData)
 {
-  nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
-  if (!obs) {
-    return true;
-  }
+  NotifyObserversWithSmsMessage(kSmsDeliverySuccessObserverTopic, aMessageData);
+  return true;
+}
 
-  nsCOMPtr<SmsMessage> message = new SmsMessage(aMessageData);
-  obs->NotifyObservers(message, kSmsDeliveredObserverTopic, nullptr);
-
+bool
+SmsChild::RecvNotifyDeliveryErrorMessage(const SmsMessageData& aMessageData)
+{
+  NotifyObserversWithSmsMessage(kSmsDeliveryErrorObserverTopic, aMessageData);
   return true;
 }
 
 bool
 SmsChild::RecvNotifyRequestSmsSent(const SmsMessageData& aMessage,
                                    const int32_t& aRequestId,
                                    const uint64_t& aProcessId)
 {
--- a/dom/sms/src/ipc/SmsChild.h
+++ b/dom/sms/src/ipc/SmsChild.h
@@ -12,17 +12,18 @@ namespace mozilla {
 namespace dom {
 namespace sms {
 
 class SmsChild : public PSmsChild
 {
 public:
   virtual bool RecvNotifyReceivedMessage(const SmsMessageData& aMessage) MOZ_OVERRIDE;
   virtual bool RecvNotifySentMessage(const SmsMessageData& aMessage) MOZ_OVERRIDE;
-  virtual bool RecvNotifyDeliveredMessage(const SmsMessageData& aMessage) MOZ_OVERRIDE;
+  virtual bool RecvNotifyDeliverySuccessMessage(const SmsMessageData& aMessage) MOZ_OVERRIDE;
+  virtual bool RecvNotifyDeliveryErrorMessage(const SmsMessageData& aMessage) MOZ_OVERRIDE;
   virtual bool RecvNotifyRequestSmsSent(const SmsMessageData& aMessage, const int32_t& aRequestId, const uint64_t& aProcessId) MOZ_OVERRIDE;
   virtual bool RecvNotifyRequestSmsSendFailed(const int32_t& aError, const int32_t& aRequestId, const uint64_t& aProcessId) MOZ_OVERRIDE;
   virtual bool RecvNotifyRequestGotSms(const SmsMessageData& aMessage, const int32_t& aRequestId, const uint64_t& aProcessId) MOZ_OVERRIDE;
   virtual bool RecvNotifyRequestGetSmsFailed(const int32_t& aError, const int32_t& aRequestId, const uint64_t& aProcessId) MOZ_OVERRIDE;
   virtual bool RecvNotifyRequestSmsDeleted(const bool& aDeleted, const int32_t& aRequestId, const uint64_t& aProcessId) MOZ_OVERRIDE;
   virtual bool RecvNotifyRequestSmsDeleteFailed(const int32_t& aError, const int32_t& aRequestId, const uint64_t& aProcessId) MOZ_OVERRIDE;
   virtual bool RecvNotifyRequestNoMessageInList(const int32_t& aRequestId, const uint64_t& aProcessId) MOZ_OVERRIDE;
   virtual bool RecvNotifyRequestCreateMessageList(const int32_t& aListId, const SmsMessageData& aMessage, const int32_t& aRequestId, const uint64_t& aProcessId) MOZ_OVERRIDE;
--- a/dom/sms/src/ipc/SmsIPCService.cpp
+++ b/dom/sms/src/ipc/SmsIPCService.cpp
@@ -56,26 +56,29 @@ SmsIPCService::Send(const nsAString& aNu
                                  aRequestId, ContentChild::GetSingleton()->GetID());
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 SmsIPCService::CreateSmsMessage(int32_t aId,
                                 const nsAString& aDelivery,
+                                const nsAString& aDeliveryStatus,
                                 const nsAString& aSender,
                                 const nsAString& aReceiver,
                                 const nsAString& aBody,
                                 const jsval& aTimestamp,
                                 const bool aRead,
                                 JSContext* aCx,
                                 nsIDOMMozSmsMessage** aMessage)
 {
-  return SmsMessage::Create(aId, aDelivery, aSender, aReceiver, aBody,
-                            aTimestamp, aRead, aCx, aMessage);
+  return SmsMessage::Create(aId, aDelivery, aDeliveryStatus,
+                            aSender, aReceiver,
+                            aBody, aTimestamp, aRead,
+                            aCx, aMessage);
 }
 
 /*
  * Implementation of nsISmsDatabaseService.
  */
 NS_IMETHODIMP
 SmsIPCService::SaveReceivedMessage(const nsAString& aSender,
                                    const nsAString& aBody,
@@ -94,16 +97,26 @@ SmsIPCService::SaveSentMessage(const nsA
 {
   GetSmsChild()->SendSaveSentMessage(nsString(aReceiver), nsString(aBody),
                                      aDate, aId);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
+SmsIPCService::SetMessageDeliveryStatus(int32_t aMessageId,
+                                        const nsAString& aDeliveryStatus)
+{
+  GetSmsChild()->SendSetMessageDeliveryStatus(aMessageId,
+                                              nsString(aDeliveryStatus));
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 SmsIPCService::GetMessageMoz(int32_t aMessageId, int32_t aRequestId,
                              uint64_t aProcessId)
 {
   GetSmsChild()->SendGetMessage(aMessageId, aRequestId,
                                 ContentChild::GetSingleton()->GetID());
   return NS_OK;
 }
 
--- a/dom/sms/src/ipc/SmsParent.cpp
+++ b/dom/sms/src/ipc/SmsParent.cpp
@@ -43,30 +43,32 @@ SmsParent::SmsParent()
 
   nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
   if (!obs) {
     return;
   }
 
   obs->AddObserver(this, kSmsReceivedObserverTopic, false);
   obs->AddObserver(this, kSmsSentObserverTopic, false);
-  obs->AddObserver(this, kSmsDeliveredObserverTopic, false);
+  obs->AddObserver(this, kSmsDeliverySuccessObserverTopic, false);
+  obs->AddObserver(this, kSmsDeliveryErrorObserverTopic, false);
 }
 
 void
 SmsParent::ActorDestroy(ActorDestroyReason why)
 {
   nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
   if (!obs) {
     return;
   }
 
   obs->RemoveObserver(this, kSmsReceivedObserverTopic);
   obs->RemoveObserver(this, kSmsSentObserverTopic);
-  obs->RemoveObserver(this, kSmsDeliveredObserverTopic);
+  obs->RemoveObserver(this, kSmsDeliverySuccessObserverTopic);
+  obs->RemoveObserver(this, kSmsDeliveryErrorObserverTopic);
 
   NS_ASSERTION(gSmsParents, "gSmsParents can't be null at that point!");
   gSmsParents->RemoveElement(this);
   if (gSmsParents->Length() == 0) {
     delete gSmsParents;
     gSmsParents = nullptr;
   }
 }
@@ -92,24 +94,35 @@ SmsParent::Observe(nsISupports* aSubject
       NS_ERROR("Got a 'sms-sent' topic without a valid message!");
       return NS_OK;
     }
 
     unused << SendNotifySentMessage(static_cast<SmsMessage*>(message.get())->GetData());
     return NS_OK;
   }
 
-  if (!strcmp(aTopic, kSmsDeliveredObserverTopic)) {
+  if (!strcmp(aTopic, kSmsDeliverySuccessObserverTopic)) {
     nsCOMPtr<nsIDOMMozSmsMessage> message = do_QueryInterface(aSubject);
     if (!message) {
-      NS_ERROR("Got a 'sms-delivered' topic without a valid message!");
+      NS_ERROR("Got a 'sms-delivery-success' topic without a valid message!");
       return NS_OK;
     }
 
-    unused << SendNotifyDeliveredMessage(static_cast<SmsMessage*>(message.get())->GetData());
+    unused << SendNotifyDeliverySuccessMessage(static_cast<SmsMessage*>(message.get())->GetData());
+    return NS_OK;
+  }
+
+  if (!strcmp(aTopic, kSmsDeliveryErrorObserverTopic)) {
+    nsCOMPtr<nsIDOMMozSmsMessage> message = do_QueryInterface(aSubject);
+    if (!message) {
+      NS_ERROR("Got a 'sms-delivery-error' topic without a valid message!");
+      return NS_OK;
+    }
+
+    unused << SendNotifyDeliveryErrorMessage(static_cast<SmsMessage*>(message.get())->GetData());
     return NS_OK;
   }
 
   return NS_OK;
 }
 
 bool
 SmsParent::RecvHasSupport(bool* aHasSupport)
@@ -172,16 +185,28 @@ SmsParent::RecvSaveSentMessage(const nsS
     do_GetService(SMS_DATABASE_SERVICE_CONTRACTID);
   NS_ENSURE_TRUE(smsDBService, true);
 
   smsDBService->SaveSentMessage(aRecipient, aBody, aDate, aId);
   return true;
 }
 
 bool
+SmsParent::RecvSetMessageDeliveryStatus(const int32_t& aMessageId,
+                                        const nsString& aDeliveryStatus)
+{
+  nsCOMPtr<nsISmsDatabaseService> smsDBService =
+    do_GetService(SMS_DATABASE_SERVICE_CONTRACTID);
+  NS_ENSURE_TRUE(smsDBService, true);
+
+  smsDBService->SetMessageDeliveryStatus(aMessageId, aDeliveryStatus);
+  return true;
+}
+
+bool
 SmsParent::RecvGetMessage(const int32_t& aMessageId, const int32_t& aRequestId,
                           const uint64_t& aProcessId)
 {
   nsCOMPtr<nsISmsDatabaseService> smsDBService =
     do_GetService(SMS_DATABASE_SERVICE_CONTRACTID);
   NS_ENSURE_TRUE(smsDBService, true);
 
   smsDBService->GetMessageMoz(aMessageId, aRequestId, aProcessId);
--- a/dom/sms/src/ipc/SmsParent.h
+++ b/dom/sms/src/ipc/SmsParent.h
@@ -24,16 +24,17 @@ public:
 
   SmsParent();
 
   virtual bool RecvHasSupport(bool* aHasSupport) MOZ_OVERRIDE;
   virtual bool RecvGetNumberOfMessagesForText(const nsString& aText, uint16_t* aResult) MOZ_OVERRIDE;
   virtual bool RecvSendMessage(const nsString& aNumber, const nsString& aMessage, const int32_t& aRequestId, const uint64_t& aProcessId) MOZ_OVERRIDE;
   virtual bool RecvSaveReceivedMessage(const nsString& aSender, const nsString& aBody, const uint64_t& aDate, int32_t* aId) MOZ_OVERRIDE;
   virtual bool RecvSaveSentMessage(const nsString& aRecipient, const nsString& aBody, const uint64_t& aDate, int32_t* aId) MOZ_OVERRIDE;
+  virtual bool RecvSetMessageDeliveryStatus(const int32_t& aMessageId, const nsString& aDeliveryStatus) MOZ_OVERRIDE;
   virtual bool RecvGetMessage(const int32_t& aMessageId, const int32_t& aRequestId, const uint64_t& aProcessId) MOZ_OVERRIDE;
   virtual bool RecvDeleteMessage(const int32_t& aMessageId, const int32_t& aRequestId, const uint64_t& aProcessId) MOZ_OVERRIDE;
   virtual bool RecvCreateMessageList(const SmsFilterData& aFilter, const bool& aReverse, const int32_t& aRequestId, const uint64_t& aProcessId) MOZ_OVERRIDE;
   virtual bool RecvGetNextMessageInList(const int32_t& aListId, const int32_t& aRequestId, const uint64_t& aProcessId) MOZ_OVERRIDE;
   virtual bool RecvClearMessageList(const int32_t& aListId) MOZ_OVERRIDE;
   virtual bool RecvMarkMessageRead(const int32_t& aMessageId, const bool& aValue, const int32_t& aRequestId, const uint64_t& aProcessId) MOZ_OVERRIDE;
 
 protected:
--- a/dom/sms/src/ril/SmsService.cpp
+++ b/dom/sms/src/ril/SmsService.cpp
@@ -59,23 +59,26 @@ SmsService::Send(const nsAString& aNumbe
 
   mRIL->SendSMS(aNumber, aMessage, aRequestId, aProcessId);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 SmsService::CreateSmsMessage(int32_t aId,
                              const nsAString& aDelivery,
+                             const nsAString& aDeliveryStatus,
                              const nsAString& aSender,
                              const nsAString& aReceiver,
                              const nsAString& aBody,
                              const jsval& aTimestamp,
                              const bool aRead,
                              JSContext* aCx,
                              nsIDOMMozSmsMessage** aMessage)
 {
-  return SmsMessage::Create(aId, aDelivery, aSender, aReceiver, aBody,
-                            aTimestamp, aRead, aCx, aMessage);
+  return SmsMessage::Create(aId, aDelivery, aDeliveryStatus,
+                            aSender, aReceiver,
+                            aBody, aTimestamp, aRead,
+                            aCx, aMessage);
 }
 
 } // namespace sms
 } // namespace dom
 } // namespace mozilla