Bug 674725 - Part X - Use SmsRequest for send() method. r=smaug,cjones
authorMounir Lamouri <mounir.lamouri@gmail.com>
Fri, 13 Jan 2012 14:26:50 +0100
changeset 84709 070bd086ef5b029d470a953a7acc545bfe91db2e
parent 84708 d9531e001bab499515c8f310f89464a31e19a3c6
child 84710 a09cc4f2fbe92ba7c9050f8e7c9928c807ec0067
push id21873
push usermlamouri@mozilla.com
push dateWed, 18 Jan 2012 10:29:07 +0000
treeherdermozilla-central@7538f4d4697c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug, cjones
bugs674725
milestone12.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 674725 - Part X - Use SmsRequest for send() method. r=smaug,cjones
dom/sms/interfaces/nsIDOMSmsManager.idl
dom/sms/interfaces/nsISmsService.idl
dom/sms/src/SmsManager.cpp
dom/sms/src/SmsRequest.cpp
dom/sms/src/SmsRequestManager.cpp
dom/sms/src/SmsRequestManager.h
dom/sms/src/android/SmsService.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
embedding/android/GeckoAppShell.java
embedding/android/GeckoSmsManager.java
mozglue/android/APKOpen.cpp
widget/android/AndroidBridge.cpp
widget/android/AndroidBridge.h
widget/android/AndroidJNI.cpp
--- a/dom/sms/interfaces/nsIDOMSmsManager.idl
+++ b/dom/sms/interfaces/nsIDOMSmsManager.idl
@@ -32,19 +32,20 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsIDOMEventTarget.idl"
 
 interface nsIDOMEventListener;
+interface nsIDOMMozSmsRequest;
 
-[scriptable, function, uuid(09a74bd3-466d-4612-926e-672b021fd08f)]
+[scriptable, function, uuid(1c1f23d7-5f4e-40bf-859b-82e8faa36041)]
 interface nsIDOMMozSmsManager : nsIDOMEventTarget
 {
-  unsigned short getNumberOfMessagesForText(in DOMString text);
-            void send(in DOMString number, in DOMString message);
+  unsigned short      getNumberOfMessagesForText(in DOMString text);
+  nsIDOMMozSmsRequest send(in DOMString number, in DOMString message);
 
   attribute nsIDOMEventListener onreceived;
   attribute nsIDOMEventListener onsent;
   attribute nsIDOMEventListener ondelivered;
 };
--- a/dom/sms/interfaces/nsISmsService.idl
+++ b/dom/sms/interfaces/nsISmsService.idl
@@ -44,17 +44,18 @@ interface nsIDOMMozSmsMessage;
 #define SMS_SERVICE_CONTRACTID "@mozilla.org/sms/smsservice;1"
 %}
 
 [scriptable, builtinclass, uuid(a0fbbe74-5d61-4b7e-b7ab-9b5224f9e5e9)]
 interface nsISmsService : nsISupports
 {
   boolean        hasSupport();
   unsigned short getNumberOfMessagesForText(in DOMString text);
-            void send(in DOMString number, in DOMString message);
+            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 sender,
                                        in DOMString receiver,
                                        in DOMString body,
                                        in jsval     timestamp);
--- a/dom/sms/src/SmsManager.cpp
+++ b/dom/sms/src/SmsManager.cpp
@@ -38,16 +38,18 @@
 #include "SmsManager.h"
 #include "nsIDOMClassInfo.h"
 #include "nsISmsService.h"
 #include "nsIObserverService.h"
 #include "mozilla/Services.h"
 #include "Constants.h"
 #include "SmsEvent.h"
 #include "nsIDOMSmsMessage.h"
+#include "nsIDOMSmsRequest.h"
+#include "SmsRequestManager.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")
@@ -122,22 +124,28 @@ SmsManager::GetNumberOfMessagesForText(c
   NS_ENSURE_TRUE(smsService, NS_OK);
 
   smsService->GetNumberOfMessagesForText(aText, aResult);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-SmsManager::Send(const nsAString& aNumber, const nsAString& aMessage)
+SmsManager::Send(const nsAString& aNumber, const nsAString& aMessage, nsIDOMMozSmsRequest** aRequest)
 {
   nsCOMPtr<nsISmsService> smsService = do_GetService(SMS_SERVICE_CONTRACTID);
   NS_ENSURE_TRUE(smsService, NS_OK);
 
-  smsService->Send(aNumber, aMessage);
+  int requestId =
+    SmsRequestManager::GetInstance()->CreateRequest(mOwner, mScriptContext, aRequest);
+  NS_ASSERTION(*aRequest, "The request object must have been created!");
+
+  NS_ADDREF(*aRequest);
+
+  smsService->Send(aNumber, aMessage, requestId, 0);
 
   return NS_OK;
 }
 
 NS_IMPL_EVENT_HANDLER(SmsManager, received)
 NS_IMPL_EVENT_HANDLER(SmsManager, sent)
 NS_IMPL_EVENT_HANDLER(SmsManager, delivered)
 
--- a/dom/sms/src/SmsRequest.cpp
+++ b/dom/sms/src/SmsRequest.cpp
@@ -54,17 +54,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
   NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(success)
   NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(error)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(SmsRequest,
                                                 nsDOMEventTargetWrapperCache)
   if (tmp->mResultRooted) {
-    tmp->mResult = JSVAL_NULL;
+    tmp->mResult = JSVAL_VOID;
     tmp->UnrootResult();
   }
   NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(success)
   NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(error)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(SmsRequest,
                                                nsDOMEventTargetWrapperCache)
@@ -82,17 +82,17 @@ NS_INTERFACE_MAP_END_INHERITING(nsDOMEve
 
 NS_IMPL_ADDREF_INHERITED(SmsRequest, nsDOMEventTargetWrapperCache)
 NS_IMPL_RELEASE_INHERITED(SmsRequest, nsDOMEventTargetWrapperCache)
 
 NS_IMPL_EVENT_HANDLER(SmsRequest, success)
 NS_IMPL_EVENT_HANDLER(SmsRequest, error)
 
 SmsRequest::SmsRequest(nsPIDOMWindow* aWindow, nsIScriptContext* aScriptContext)
-  : mResult(JSVAL_NULL)
+  : mResult(JSVAL_VOID)
   , mResultRooted(false)
   , mError(eNoError)
   , mDone(false)
 {
   // Those vars come from nsDOMEventTargetHelper.
   mOwner = aWindow;
   mScriptContext = aScriptContext;
 }
@@ -120,17 +120,17 @@ SmsRequest::UnrootResult()
   mResultRooted = false;
 }
 
 void
 SmsRequest::SetSuccess(nsIDOMMozSmsMessage* aMessage)
 {
   NS_PRECONDITION(!mDone, "mDone shouldn't have been set to true already!");
   NS_PRECONDITION(mError == eNoError, "mError shouldn't have been set!");
-  NS_PRECONDITION(mResult == JSVAL_NULL, "mResult shouldn't have been set!");
+  NS_PRECONDITION(mResult == JSVAL_VOID, "mResult shouldn't have been set!");
 
   JSContext* cx = mScriptContext->GetNativeContext();
   NS_ASSERTION(cx, "Failed to get a context!");
 
   JSObject* global = mScriptContext->GetNativeGlobal();
   NS_ASSERTION(global, "Failed to get global object!");
 
   JSAutoRequest ar(cx);
@@ -139,29 +139,29 @@ SmsRequest::SetSuccess(nsIDOMMozSmsMessa
     SetError(eInternalError);
     return;
   }
 
   RootResult();
 
   if (NS_FAILED(nsContentUtils::WrapNative(cx, global, aMessage, &mResult))) {
     UnrootResult();
-    mResult = JSVAL_NULL;
+    mResult = JSVAL_VOID;
     SetError(eInternalError);
   }
 
   mDone = true;
 }
 
 void
 SmsRequest::SetError(ErrorType aError)
 {
   NS_PRECONDITION(!mDone, "mDone shouldn't have been set to true already!");
   NS_PRECONDITION(mError == eNoError, "mError shouldn't have been set!");
-  NS_PRECONDITION(mResult == JSVAL_NULL, "mResult shouldn't have been set!");
+  NS_PRECONDITION(mResult == JSVAL_VOID, "mResult shouldn't have been set!");
 
   mDone = true;
   mError = aError;
 }
 
 NS_IMETHODIMP
 SmsRequest::GetReadyState(nsAString& aReadyState)
 {
@@ -180,17 +180,17 @@ SmsRequest::GetError(nsAString& aError)
   if (!mDone) {
     NS_ASSERTION(mError == eNoError,
                  "There should be no error if the request is still processing!");
 
     SetDOMStringToNull(aError);
     return NS_OK;
   }
 
-  NS_ASSERTION(mError == eNoError || mResult == JSVAL_NULL,
+  NS_ASSERTION(mError == eNoError || mResult == JSVAL_VOID,
                "mResult should be void when there is an error!");
 
   switch (mError) {
     case eNoError:
       SetDOMStringToNull(aError);
       break;
     case eInternalError:
       aError.AssignLiteral("InternalError");
@@ -199,20 +199,20 @@ SmsRequest::GetError(nsAString& aError)
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 SmsRequest::GetResult(jsval* aResult)
 {
   if (!mDone) {
-    NS_ASSERTION(mResult == JSVAL_NULL,
+    NS_ASSERTION(mResult == JSVAL_VOID,
                  "When not done, result should be null!");
 
-    *aResult = JSVAL_NULL;
+    *aResult = JSVAL_VOID;
     return NS_OK;
   }
 
   *aResult = mResult;
   return NS_OK;
 }
 
 } // namespace sms
--- a/dom/sms/src/SmsRequestManager.cpp
+++ b/dom/sms/src/SmsRequestManager.cpp
@@ -32,16 +32,25 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "SmsRequestManager.h"
 #include "SmsRequest.h"
+#include "nsIDOMSmsMessage.h"
+#include "nsDOMEvent.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 SUCCESS_EVENT_NAME NS_LITERAL_STRING("success")
+#define ERROR_EVENT_NAME   NS_LITERAL_STRING("error")
 
 namespace mozilla {
 namespace dom {
 namespace sms {
 
 SmsRequestManager* SmsRequestManager::sInstance = nsnull;
 
 void
@@ -89,11 +98,42 @@ SmsRequestManager::CreateRequest(nsPIDOM
   }
 
 
   mRequests.AppendObject(request);
   NS_ADDREF(*aRequest = request);
   return size;
 }
 
+nsresult
+SmsRequestManager::DispatchTrustedEventToRequest(const nsAString& aEventName,
+                                                 nsIDOMMozSmsRequest* aRequest)
+{
+  nsRefPtr<nsDOMEvent> event = new nsDOMEvent(nsnull, nsnull);
+  nsresult rv = event->InitEvent(aEventName, false, false);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = event->SetTrusted(PR_TRUE);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  bool dummy;
+  return aRequest->DispatchEvent(event, &dummy);
+}
+
+void
+SmsRequestManager::NotifySmsSent(PRInt32 aRequestId, nsIDOMMozSmsMessage* aMessage)
+{
+  NS_ASSERTION(mRequests.Count() > aRequestId && mRequests[aRequestId],
+               "Got an invalid request id or it has been already deleted!");
+
+  // It's safe to use the static_cast here given that we did call
+  // |new SmsRequest()|.
+  SmsRequest* request = static_cast<SmsRequest*>(mRequests[aRequestId]);
+  request->SetSuccess(aMessage);
+
+  DispatchTrustedEventToRequest(SUCCESS_EVENT_NAME, request);
+
+  mRequests.ReplaceObjectAt(nsnull, aRequestId);
+}
+
 } // namespace sms
 } // namespace dom
 } // namespace mozilla
--- a/dom/sms/src/SmsRequestManager.h
+++ b/dom/sms/src/SmsRequestManager.h
@@ -39,35 +39,41 @@
 #ifndef mozilla_dom_sms_SmsRequestManager_h
 #define mozilla_dom_sms_SmsRequestManager_h
 
 #include "nsCOMArray.h"
 
 class nsIDOMMozSmsRequest;
 class nsPIDOMWindow;
 class nsIScriptContext;
+class nsIDOMMozSmsMessage;
 
 namespace mozilla {
 namespace dom {
 namespace sms {
 
 class SmsRequestManager
 {
 public:
   static void Init();
   static void Shutdown();
   static SmsRequestManager* GetInstance();
 
   PRInt32 CreateRequest(nsPIDOMWindow* aWindow,
                         nsIScriptContext* aScriptContext,
                         nsIDOMMozSmsRequest** aRequest);
 
+  void NotifySmsSent(PRInt32 aRequestId, nsIDOMMozSmsMessage* aMessage);
+
 private:
   static SmsRequestManager* sInstance;
 
+  nsresult DispatchTrustedEventToRequest(const nsAString& aEventName,
+                                         nsIDOMMozSmsRequest* aRequest);
+
   nsCOMArray<nsIDOMMozSmsRequest> mRequests;
 };
 
 } // namespace sms
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_sms_SmsRequestManager_h
--- a/dom/sms/src/android/SmsService.cpp
+++ b/dom/sms/src/android/SmsService.cpp
@@ -62,23 +62,25 @@ SmsService::GetNumberOfMessagesForText(c
     return NS_OK;
   }
 
   *aResult = AndroidBridge::Bridge()->GetNumberOfMessagesForText(aText);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-SmsService::Send(const nsAString& aNumber, const nsAString& aMessage)
+SmsService::Send(const nsAString& aNumber, const nsAString& aMessage,
+                 PRInt32 aRequestId, PRUint64 aProcessId)
 {
   if (!AndroidBridge::Bridge()) {
     return NS_OK;
   }
 
-  AndroidBridge::Bridge()->SendMessage(aNumber, aMessage);
+  AndroidBridge::Bridge()->SendMessage(aNumber, aMessage, aRequestId,
+                                       aProcessId);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 SmsService::CreateSmsMessage(PRInt32 aId,
                              const nsAString& aDelivery,
                              const nsAString& aSender,
                              const nsAString& aReceiver,
--- a/dom/sms/src/fallback/SmsService.cpp
+++ b/dom/sms/src/fallback/SmsService.cpp
@@ -57,17 +57,18 @@ NS_IMETHODIMP
 SmsService::GetNumberOfMessagesForText(const nsAString& aText, PRUint16* aResult)
 {
   NS_ERROR("We should not be here!");
   *aResult = 0;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-SmsService::Send(const nsAString& aNumber, const nsAString& aMessage)
+SmsService::Send(const nsAString& aNumber, const nsAString& aMessage,
+                 PRInt32 aRequestId, PRUint64 aProcessId)
 {
   NS_ERROR("We should not be here!");
   return NS_OK;
 }
 
 NS_IMETHODIMP
 SmsService::CreateSmsMessage(PRInt32 aId,
                              const nsAString& aDelivery,
--- a/dom/sms/src/ipc/PSms.ipdl
+++ b/dom/sms/src/ipc/PSms.ipdl
@@ -60,24 +60,28 @@ sync protocol PSms {
 
 child:
     NotifyReceivedMessage(SmsMessageData aMessageData);
 
     NotifySentMessage(SmsMessageData aMessageData);
 
     NotifyDeliveredMessage(SmsMessageData aMessageData);
 
+    NotifyRequestSmsSent(SmsMessageData aMessageData, PRInt32 aRequestId,
+                         PRUint64 aProcessId);
+
 parent:
     sync HasSupport()
         returns (bool aHasSupport);
 
     sync GetNumberOfMessagesForText(nsString aText)
         returns (PRUint16 aNumber);
 
-    SendMessage(nsString aNumber, nsString aMessage);
+    SendMessage(nsString aNumber, nsString aMessage, PRInt32 aRequestId,
+                PRUint64 aProcessId);
 
     sync SaveSentMessage(nsString aReceiver, nsString aBody, PRUint64 aDate)
         returns (PRInt32 aId);
 
     __delete__();
 };
 
 } // namespace sms
--- a/dom/sms/src/ipc/SmsChild.cpp
+++ b/dom/sms/src/ipc/SmsChild.cpp
@@ -35,16 +35,18 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "SmsChild.h"
 #include "SmsMessage.h"
 #include "Constants.h"
 #include "nsIObserverService.h"
 #include "mozilla/Services.h"
+#include "mozilla/dom/ContentChild.h"
+#include "SmsRequestManager.h"
 
 namespace mozilla {
 namespace dom {
 namespace sms {
 
 bool
 SmsChild::RecvNotifyReceivedMessage(const SmsMessageData& aMessageData)
 {
@@ -82,11 +84,26 @@ SmsChild::RecvNotifyDeliveredMessage(con
   }
 
   nsCOMPtr<SmsMessage> message = new SmsMessage(aMessageData);
   obs->NotifyObservers(message, kSmsDeliveredObserverTopic, nsnull);
 
   return true;
 }
 
+bool
+SmsChild::RecvNotifyRequestSmsSent(const SmsMessageData& aMessage,
+                                   const PRInt32& aRequestId,
+                                   const PRUint64& aProcessId)
+{
+  if (ContentChild::GetSingleton()->GetID() != aProcessId) {
+    return true;
+  }
+
+  nsCOMPtr<nsIDOMMozSmsMessage> message = new SmsMessage(aMessage);
+  SmsRequestManager::GetInstance()->NotifySmsSent(aRequestId, message);
+
+  return true;
+}
+
 } // namespace sms
 } // namespace dom
 } // namespace mozilla
--- a/dom/sms/src/ipc/SmsChild.h
+++ b/dom/sms/src/ipc/SmsChild.h
@@ -45,15 +45,16 @@ namespace dom {
 namespace sms {
 
 class SmsChild : public PSmsChild
 {
 public:
   NS_OVERRIDE virtual bool RecvNotifyReceivedMessage(const SmsMessageData& aMessage);
   NS_OVERRIDE virtual bool RecvNotifySentMessage(const SmsMessageData& aMessage);
   NS_OVERRIDE virtual bool RecvNotifyDeliveredMessage(const SmsMessageData& aMessage);
+  NS_OVERRIDE virtual bool RecvNotifyRequestSmsSent(const SmsMessageData& aMessage, const PRInt32& aRequestId, const PRUint64& aProcessId);
 };
 
 } // namespace sms
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_sms_SmsChild_h
--- a/dom/sms/src/ipc/SmsIPCService.cpp
+++ b/dom/sms/src/ipc/SmsIPCService.cpp
@@ -75,19 +75,21 @@ NS_IMETHODIMP
 SmsIPCService::GetNumberOfMessagesForText(const nsAString& aText, PRUint16* aResult)
 {
   GetSmsChild()->SendGetNumberOfMessagesForText(nsString(aText), aResult);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-SmsIPCService::Send(const nsAString& aNumber, const nsAString& aMessage)
+SmsIPCService::Send(const nsAString& aNumber, const nsAString& aMessage,
+                    PRInt32 aRequestId, PRUint64 aProcessId)
 {
-  GetSmsChild()->SendSendMessage(nsString(aNumber), nsString(aMessage));
+  GetSmsChild()->SendSendMessage(nsString(aNumber), nsString(aMessage),
+                                 aRequestId, ContentChild::GetSingleton()->GetID());
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 SmsIPCService::CreateSmsMessage(PRInt32 aId,
                                 const nsAString& aDelivery,
                                 const nsAString& aSender,
--- a/dom/sms/src/ipc/SmsParent.cpp
+++ b/dom/sms/src/ipc/SmsParent.cpp
@@ -44,20 +44,39 @@
 #include "mozilla/unused.h"
 #include "SmsMessage.h"
 #include "nsISmsDatabaseService.h"
 
 namespace mozilla {
 namespace dom {
 namespace sms {
 
+nsTArray<SmsParent*>* SmsParent::gSmsParents = nsnull;
+
 NS_IMPL_ISUPPORTS1(SmsParent, nsIObserver)
 
+/* static */ void
+SmsParent::GetAll(nsTArray<SmsParent*>& aArray)
+{
+  if (!gSmsParents) {
+    aArray.Clear();
+    return;
+  }
+
+  aArray = *gSmsParents;
+}
+
 SmsParent::SmsParent()
 {
+  if (!gSmsParents) {
+    gSmsParents = new nsTArray<SmsParent*>();
+  }
+
+  gSmsParents->AppendElement(this);
+
   nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
   if (!obs) {
     return;
   }
 
   obs->AddObserver(this, kSmsReceivedObserverTopic, false);
   obs->AddObserver(this, kSmsSentObserverTopic, false);
   obs->AddObserver(this, kSmsDeliveredObserverTopic, false);
@@ -69,16 +88,23 @@ SmsParent::ActorDestroy(ActorDestroyReas
   nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
   if (!obs) {
     return;
   }
 
   obs->RemoveObserver(this, kSmsReceivedObserverTopic);
   obs->RemoveObserver(this, kSmsSentObserverTopic);
   obs->RemoveObserver(this, kSmsDeliveredObserverTopic);
+
+  NS_ASSERTION(gSmsParents, "gSmsParents can't be null at that point!");
+  gSmsParents->RemoveElement(this);
+  if (gSmsParents->Length() == 0) {
+    delete gSmsParents;
+    gSmsParents = nsnull;
+  }
 }
 
 NS_IMETHODIMP
 SmsParent::Observe(nsISupports* aSubject, const char* aTopic,
                    const PRUnichar* aData)
 {
   if (!strcmp(aTopic, kSmsReceivedObserverTopic)) {
     nsCOMPtr<nsIDOMMozSmsMessage> message = do_QueryInterface(aSubject);
@@ -136,22 +162,23 @@ SmsParent::RecvGetNumberOfMessagesForTex
   nsCOMPtr<nsISmsService> smsService = do_GetService(SMS_SERVICE_CONTRACTID);
   NS_ENSURE_TRUE(smsService, true);
 
   smsService->GetNumberOfMessagesForText(aText, aResult);
   return true;
 }
 
 bool
-SmsParent::RecvSendMessage(const nsString& aNumber, const nsString& aMessage)
+SmsParent::RecvSendMessage(const nsString& aNumber, const nsString& aMessage,
+                           const PRInt32& aRequestId, const PRUint64& aProcessId)
 {
   nsCOMPtr<nsISmsService> smsService = do_GetService(SMS_SERVICE_CONTRACTID);
   NS_ENSURE_TRUE(smsService, true);
 
-  smsService->Send(aNumber, aMessage);
+  smsService->Send(aNumber, aMessage, aRequestId, aProcessId);
   return true;
 }
 
 bool
 SmsParent::RecvSaveSentMessage(const nsString& aRecipient,
                                const nsString& aBody,
                                const PRUint64& aDate, PRInt32* aId)
 {
--- a/dom/sms/src/ipc/SmsParent.h
+++ b/dom/sms/src/ipc/SmsParent.h
@@ -47,24 +47,29 @@ namespace sms {
 
 class SmsParent : public PSmsParent
                 , public nsIObserver
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
 
+  static void GetAll(nsTArray<SmsParent*>& aArray);
+
   SmsParent();
 
   NS_OVERRIDE virtual bool RecvHasSupport(bool* aHasSupport);
   NS_OVERRIDE virtual bool RecvGetNumberOfMessagesForText(const nsString& aText, PRUint16* aResult);
-  NS_OVERRIDE virtual bool RecvSendMessage(const nsString& aNumber, const nsString& aMessage);
+  NS_OVERRIDE virtual bool RecvSendMessage(const nsString& aNumber, const nsString& aMessage, const PRInt32& aRequestId, const PRUint64& aProcessId);
   NS_OVERRIDE virtual bool RecvSaveSentMessage(const nsString& aRecipient, const nsString& aBody, const PRUint64& aDate, PRInt32* aId);
 
 protected:
   virtual void ActorDestroy(ActorDestroyReason why);
+
+private:
+  static nsTArray<SmsParent*>* gSmsParents;
 };
 
 } // namespace sms
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_sms_SmsParent_h
--- a/embedding/android/GeckoAppShell.java
+++ b/embedding/android/GeckoAppShell.java
@@ -118,17 +118,17 @@ public class GeckoAppShell
     public static native void reportJavaCrash(String stack);
 
     public static native void processNextNativeEvent();
 
     public static native void notifyBatteryChange(double aLevel, boolean aCharging, double aRemainingTime);
 
     public static native void notifySmsReceived(String aSender, String aBody, long aTimestamp);
     public static native int  saveMessageInSentbox(String aReceiver, String aBody, long aTimestamp);
-    public static native void notifySmsSent(int aId, String aReceiver, String aBody, long aTimestamp);
+    public static native void notifySmsSent(int aId, String aReceiver, String aBody, long aTimestamp, int aRequestId, long aProcessId);
     public static native void notifySmsDelivered(int aId, String aReceiver, String aBody, long aTimestamp);
 
     // A looper thread, accessed by GeckoAppShell.getHandler
     private static class LooperThread extends Thread {
         public SynchronousQueue<Handler> mHandlerQueue =
             new SynchronousQueue<Handler>();
         
         public void run() {
@@ -1690,18 +1690,18 @@ public class GeckoAppShell
 
     /*
      * WebSMS related methods.
      */
     public static int getNumberOfMessagesForText(String aText) {
         return GeckoSmsManager.getNumberOfMessagesForText(aText);
     }
 
-    public static void sendMessage(String aNumber, String aMessage) {
-        GeckoSmsManager.send(aNumber, aMessage);
+    public static void sendMessage(String aNumber, String aMessage, int aRequestId, long aProcessId) {
+        GeckoSmsManager.send(aNumber, aMessage, aRequestId, aProcessId);
     }
 
     public static int saveSentMessage(String aRecipient, String aBody, long aDate) {
         return GeckoSmsManager.saveSentMessage(aRecipient, aBody, aDate);
     }
 
     public static boolean isTablet() {
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
--- a/embedding/android/GeckoSmsManager.java
+++ b/embedding/android/GeckoSmsManager.java
@@ -249,18 +249,19 @@ public class GeckoSmsManager
       return;
     }
 
     if (intent.getAction().equals(ACTION_SMS_SENT) ||
         intent.getAction().equals(ACTION_SMS_DELIVERED)) {
       Bundle bundle = intent.getExtras();
 
       if (bundle == null || !bundle.containsKey("envelopeId") ||
-          !bundle.containsKey("number") || !bundle.containsKey("message")) {
-        Log.e("GeckoSmsManager", "Got an invalid ACTION_SMS_SENT!");
+          !bundle.containsKey("number") || !bundle.containsKey("message") ||
+          !bundle.containsKey("requestId") || !bundle.containsKey("processId")) {
+        Log.e("GeckoSmsManager", "Got an invalid ACTION_SMS_SENT/ACTION_SMS_DELIVERED!");
         return;
       }
 
       int envelopeId = bundle.getInt("envelopeId");
       Postman postman = Postman.getInstance();
 
       Envelope envelope = postman.getEnvelope(envelopeId);
       if (envelope == null) {
@@ -296,17 +297,19 @@ public class GeckoSmsManager
       } else {
         if (part == Envelope.SubParts.SENT_PART) {
           String number = bundle.getString("number");
           String message = bundle.getString("message");
           long timestamp = System.currentTimeMillis();
 
           int id = GeckoAppShell.saveMessageInSentbox(number, message, timestamp);
 
-          GeckoAppShell.notifySmsSent(id, number, message, timestamp);
+          GeckoAppShell.notifySmsSent(id, number, message, timestamp,
+                                      bundle.getInt("requestId"),
+                                      bundle.getLong("processId"));
 
           envelope.setMessageId(id);
           envelope.setMessageTimestamp(timestamp);
 
           Log.i("GeckoSmsManager", "SMS sending was successfull!");
         } else {
           GeckoAppShell.notifySmsDelivered(envelope.getMessageId(),
                                            bundle.getString("number"),
@@ -325,33 +328,35 @@ public class GeckoSmsManager
       return;
     }
   }
 
   public static int getNumberOfMessagesForText(String aText) {
     return SmsManager.getDefault().divideMessage(aText).size();
   }
 
-  public static void send(String aNumber, String aMessage) {
+  public static void send(String aNumber, String aMessage, int aRequestId, long aProcessId) {
     /*
      * TODO:
      * This is a basic send method that doesn't handle errors and doesn't listen to
      * delivered messages.
      */
     int envelopeId = Postman.kUnknownEnvelopeId;
 
     try {
       SmsManager sm = SmsManager.getDefault();
 
       Intent sentIntent = new Intent(ACTION_SMS_SENT);
       Intent deliveredIntent = new Intent(ACTION_SMS_DELIVERED);
 
       Bundle bundle = new Bundle();
       bundle.putString("number", aNumber);
       bundle.putString("message", aMessage);
+      bundle.putInt("requestId", aRequestId);
+      bundle.putLong("processId", aProcessId);
 
       if (aMessage.length() <= kMaxMessageSize) {
         envelopeId = Postman.getInstance().createEnvelope(1);
         bundle.putInt("envelopeId", envelopeId);
 
         sentIntent.putExtras(bundle);
         deliveredIntent.putExtras(bundle);
 
--- a/mozglue/android/APKOpen.cpp
+++ b/mozglue/android/APKOpen.cpp
@@ -193,16 +193,52 @@ Java_org_mozilla_gecko_GeckoAppShell_ ##
 typedef return_type (*name ## _t)(JNIEnv *, jclass, type1 one, type2 two, type3 three, type4 four); \
 static name ## _t f_ ## name; \
 extern "C" NS_EXPORT return_type JNICALL \
 Java_org_mozilla_gecko_GeckoAppShell_ ## name(JNIEnv *jenv, jclass jc, type1 one, type2 two, type3 three, type4 four) \
 { \
   return f_ ## name(jenv, jc, one, two, three, four); \
 }
 
+#define SHELL_WRAPPER5(name,type1,type2,type3,type4,type5) \
+typedef void (*name ## _t)(JNIEnv *, jclass, type1 one, type2 two, type3 three, type4 four, type5 five); \
+static name ## _t f_ ## name; \
+extern "C" NS_EXPORT void JNICALL \
+Java_org_mozilla_gecko_GeckoAppShell_ ## name(JNIEnv *jenv, jclass jc, type1 one, type2 two, type3 three, type4 four, type5 five) \
+{ \
+  f_ ## name(jenv, jc, one, two, three, four, five); \
+}
+
+#define SHELL_WRAPPER5_WITH_RETURN(name, return_type, type1, type2, type3, type4, type5) \
+typedef return_type (*name ## _t)(JNIEnv *, jclass, type1 one, type2 two, type3 three, type4 four, type5 five); \
+static name ## _t f_ ## name; \
+extern "C" NS_EXPORT return_type JNICALL \
+Java_org_mozilla_gecko_GeckoAppShell_ ## name(JNIEnv *jenv, jclass jc, type1 one, type2 two, type3 three, type4 four, type5 five) \
+{ \
+  return f_ ## name(jenv, jc, one, two, three, four, five); \
+}
+
+#define SHELL_WRAPPER6(name,type1,type2,type3,type4,type5,type6) \
+typedef void (*name ## _t)(JNIEnv *, jclass, type1 one, type2 two, type3 three, type4 four, type5 five, type6 six); \
+static name ## _t f_ ## name; \
+extern "C" NS_EXPORT void JNICALL \
+Java_org_mozilla_gecko_GeckoAppShell_ ## name(JNIEnv *jenv, jclass jc, type1 one, type2 two, type3 three, type4 four, type5 five, type6 six) \
+{ \
+  f_ ## name(jenv, jc, one, two, three, four, five, six); \
+}
+
+#define SHELL_WRAPPER6_WITH_RETURN(name, return_type, type1, type2, type3, type4, type5, type6) \
+typedef return_type (*name ## _t)(JNIEnv *, jclass, type1 one, type2 two, type3 three, type4 four, type5 five, type6 six); \
+static name ## _t f_ ## name; \
+extern "C" NS_EXPORT return_type JNICALL \
+Java_org_mozilla_gecko_GeckoAppShell_ ## name(JNIEnv *jenv, jclass jc, type1 one, type2 two, type3 three, type4 four, type5 five, type6 six) \
+{ \
+  return f_ ## name(jenv, jc, one, two, three, four, five, six); \
+}
+
 SHELL_WRAPPER0(nativeInit)
 SHELL_WRAPPER1(nativeRun, jstring)
 SHELL_WRAPPER1(notifyGeckoOfEvent, jobject)
 SHELL_WRAPPER0(processNextNativeEvent)
 SHELL_WRAPPER1(setSurfaceView, jobject)
 SHELL_WRAPPER1(setSoftwareLayerClient, jobject)
 SHELL_WRAPPER0(onResume)
 SHELL_WRAPPER0(onLowMemory)
@@ -212,17 +248,17 @@ SHELL_WRAPPER1(onChangeNetworkLinkStatus
 SHELL_WRAPPER1(reportJavaCrash, jstring)
 SHELL_WRAPPER0(executeNextRunnable)
 SHELL_WRAPPER1(cameraCallbackBridge, jbyteArray)
 SHELL_WRAPPER3(notifyBatteryChange, jdouble, jboolean, jdouble);
 SHELL_WRAPPER3(notifySmsReceived, jstring, jstring, jlong);
 SHELL_WRAPPER0(bindWidgetTexture);
 SHELL_WRAPPER0_WITH_RETURN(testDirectTexture, bool);
 SHELL_WRAPPER3_WITH_RETURN(saveMessageInSentbox, jint, jstring, jstring, jlong);
-SHELL_WRAPPER4(notifySmsSent, jint, jstring, jstring, jlong);
+SHELL_WRAPPER6(notifySmsSent, jint, jstring, jstring, jlong, jint, jlong);
 SHELL_WRAPPER4(notifySmsDelivered, jint, jstring, jstring, jlong);
 
 static void * xul_handle = NULL;
 static time_t apk_mtime = 0;
 #ifdef DEBUG
 extern "C" int extractLibs = 1;
 #else
 extern "C" int extractLibs = 0;
--- a/widget/android/AndroidBridge.cpp
+++ b/widget/android/AndroidBridge.cpp
@@ -162,17 +162,17 @@ AndroidBridge::Init(JNIEnv *jEnv,
     jGetCurrentBatteryInformation = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getCurrentBatteryInformation", "()[D");
 
     jGetAccessibilityEnabled = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getAccessibilityEnabled", "()Z");
     jHandleGeckoMessage = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "handleGeckoMessage", "(Ljava/lang/String;)Ljava/lang/String;");
     jCheckUriVisited = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "checkUriVisited", "(Ljava/lang/String;)V");
     jMarkUriVisited = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "markUriVisited", "(Ljava/lang/String;)V");
 
     jNumberOfMessages = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getNumberOfMessagesForText", "(Ljava/lang/String;)I");
-    jSendMessage = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "sendMessage", "(Ljava/lang/String;Ljava/lang/String;)V");
+    jSendMessage = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "sendMessage", "(Ljava/lang/String;Ljava/lang/String;IJ)V");
     jSaveSentMessage = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "saveSentMessage", "(Ljava/lang/String;Ljava/lang/String;J)I");
 
     jEGLContextClass = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("javax/microedition/khronos/egl/EGLContext"));
     jEGL10Class = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("javax/microedition/khronos/egl/EGL10"));
     jEGLSurfaceImplClass = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("com/google/android/gles_jni/EGLSurfaceImpl"));
     jEGLContextImplClass = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("com/google/android/gles_jni/EGLContextImpl"));
     jEGLConfigImplClass = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("com/google/android/gles_jni/EGLConfigImpl"));
     jEGLDisplayImplClass = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("com/google/android/gles_jni/EGLDisplayImpl"));
@@ -1338,25 +1338,25 @@ AndroidBridge::GetNumberOfMessagesForTex
     ALOG_BRIDGE("AndroidBridge::GetNumberOfMessagesForText");
 
     AutoLocalJNIFrame jniFrame;
     jstring jText = GetJNIForThread()->NewString(PromiseFlatString(aText).get(), aText.Length());
     return GetJNIForThread()->CallStaticIntMethod(mGeckoAppShellClass, jNumberOfMessages, jText);
 }
 
 void
-AndroidBridge::SendMessage(const nsAString& aNumber, const nsAString& aMessage)
+AndroidBridge::SendMessage(const nsAString& aNumber, const nsAString& aMessage, PRInt32 aRequestId, PRUint64 aProcessId)
 {
     ALOG_BRIDGE("AndroidBridge::SendMessage");
 
     AutoLocalJNIFrame jniFrame;
     jstring jNumber = GetJNIForThread()->NewString(PromiseFlatString(aNumber).get(), aNumber.Length());
     jstring jMessage = GetJNIForThread()->NewString(PromiseFlatString(aMessage).get(), aMessage.Length());
 
-    GetJNIForThread()->CallStaticVoidMethod(mGeckoAppShellClass, jSendMessage, jNumber, jMessage);
+    GetJNIForThread()->CallStaticVoidMethod(mGeckoAppShellClass, jSendMessage, jNumber, jMessage, aRequestId, aProcessId);
 }
 
 PRInt32
 AndroidBridge::SaveSentMessage(const nsAString& aRecipient,
                                 const nsAString& aBody, PRUint64 aDate)
 {
     ALOG_BRIDGE("AndroidBridge::SaveSentMessage");
 
--- a/widget/android/AndroidBridge.h
+++ b/widget/android/AndroidBridge.h
@@ -330,17 +330,17 @@ public:
 
     void CloseCamera();
 
     void EnableBatteryNotifications();
     void DisableBatteryNotifications();
     void GetCurrentBatteryInformation(hal::BatteryInformation* aBatteryInfo);
 
     PRUint16 GetNumberOfMessagesForText(const nsAString& aText);
-    void SendMessage(const nsAString& aNumber, const nsAString& aText);
+    void SendMessage(const nsAString& aNumber, const nsAString& aText, PRInt32 aRequestId, PRUint64 aProcessId);
     PRInt32 SaveSentMessage(const nsAString& aRecipient, const nsAString& aBody, PRUint64 aDate);
 
     bool IsTablet();
 
 protected:
     static AndroidBridge *sBridge;
 
     // the global JavaVM
--- a/widget/android/AndroidJNI.cpp
+++ b/widget/android/AndroidJNI.cpp
@@ -54,20 +54,24 @@
 #include "mozilla/Services.h"
 #include "nsINetworkLinkService.h"
 
 #ifdef MOZ_CRASHREPORTER
 #include "nsICrashReporter.h"
 #include "nsExceptionHandler.h"
 #endif
 
+#include "mozilla/unused.h"
+
 #include "mozilla/dom/sms/SmsMessage.h"
 #include "mozilla/dom/sms/Constants.h"
 #include "mozilla/dom/sms/Types.h"
 #include "mozilla/dom/sms/PSms.h"
+#include "mozilla/dom/sms/SmsRequestManager.h"
+#include "mozilla/dom/sms/SmsParent.h"
 #include "nsISmsDatabaseService.h"
 
 using namespace mozilla;
 using namespace mozilla::dom::sms;
 
 /* Forward declare all the JNI methods as extern "C" */
 
 extern "C" {
@@ -82,17 +86,17 @@ extern "C" {
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_removeObserver(JNIEnv *jenv, jclass, jstring jObserverKey);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_onChangeNetworkLinkStatus(JNIEnv *, jclass, jstring status);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_reportJavaCrash(JNIEnv *, jclass, jstring stack);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_executeNextRunnable(JNIEnv *, jclass);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifyUriVisited(JNIEnv *, jclass, jstring uri);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifyBatteryChange(JNIEnv* jenv, jclass, jdouble, jboolean, jdouble);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifySmsReceived(JNIEnv* jenv, jclass, jstring, jstring, jlong);
     NS_EXPORT PRInt32 JNICALL Java_org_mozilla_gecko_GeckoAppShell_saveMessageInSentbox(JNIEnv* jenv, jclass, jstring, jstring, jlong);
-    NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifySmsSent(JNIEnv* jenv, jclass, jint, jstring, jstring, jlong);
+    NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifySmsSent(JNIEnv* jenv, jclass, jint, jstring, jstring, jlong, jint, jlong);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifySmsDelivered(JNIEnv* jenv, jclass, jint, jstring, jstring, jlong);
 
 #ifdef MOZ_JAVA_COMPOSITOR
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_bindWidgetTexture(JNIEnv* jenv, jclass);
     NS_EXPORT bool JNICALL Java_org_mozilla_gecko_GeckoAppShell_testDirectTexture(JNIEnv* jenv, jclass);
 #endif
 }
 
@@ -298,45 +302,69 @@ Java_org_mozilla_gecko_GeckoAppShell_sav
     return id;
 }
 
 NS_EXPORT void JNICALL
 Java_org_mozilla_gecko_GeckoAppShell_notifySmsSent(JNIEnv* jenv, jclass,
                                                    jint aId,
                                                    jstring aReceiver,
                                                    jstring aBody,
-                                                   jlong aTimestamp)
+                                                   jlong aTimestamp,
+                                                   jint aRequestId,
+                                                   jlong aProcessId)
 {
     class NotifySmsSentRunnable : public nsRunnable {
     public:
-      NotifySmsSentRunnable(const SmsMessageData& aMessageData)
+      NotifySmsSentRunnable(const SmsMessageData& aMessageData,
+                            PRInt32 aRequestId, PRUint64 aProcessId)
         : mMessageData(aMessageData)
+        , mRequestId(aRequestId)
+        , mProcessId(aProcessId)
       {}
 
       NS_IMETHODIMP Run() {
+        /*
+         * First, we are going to notify all SmsManager that a message has
+         * been sent. Then, we will notify the SmsRequest object about it.
+         */
         nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
         if (!obs) {
           return NS_OK;
         }
 
         nsCOMPtr<nsIDOMMozSmsMessage> message = new SmsMessage(mMessageData);
         obs->NotifyObservers(message, kSmsSentObserverTopic, nsnull);
 
+        if (mProcessId == 0) { // Parent process.
+          SmsRequestManager::GetInstance()->NotifySmsSent(mRequestId, message);
+        } else { // Content process.
+          nsTArray<SmsParent*> spList;
+          SmsParent::GetAll(spList);
+
+          for (PRUint32 i=0; i<spList.Length(); ++i) {
+            unused << spList[i]->SendNotifyRequestSmsSent(mMessageData,
+                                                          mRequestId,
+                                                          mProcessId);
+          }
+        }
+
         return NS_OK;
       }
 
     private:
       SmsMessageData mMessageData;
+      PRInt32        mRequestId;
+      PRUint64       mProcessId;
     };
 
     SmsMessageData message(aId, eDeliveryState_Sent, EmptyString(),
                            nsJNIString(aReceiver, jenv),
                            nsJNIString(aBody, jenv), aTimestamp);
 
-    nsCOMPtr<nsIRunnable> runnable = new NotifySmsSentRunnable(message);
+    nsCOMPtr<nsIRunnable> runnable = new NotifySmsSentRunnable(message, aRequestId, aProcessId);
     NS_DispatchToMainThread(runnable);
 }
 
 NS_EXPORT void JNICALL
 Java_org_mozilla_gecko_GeckoAppShell_notifySmsDelivered(JNIEnv* jenv, jclass,
                                                         jint aId,
                                                         jstring aReceiver,
                                                         jstring aBody,