Bug 1058397 - Part 1: Separate TelephonyCallback. r=hsinyi
authorSzu-Yu Chen [:aknow] <szchen@mozilla.com>
Wed, 15 Oct 2014 02:50:00 -0400
changeset 210714 1a2f098c634dd890e7f7d7fe8ef8d3eb5bd3e403
parent 210713 491bc426305c085f48f00f3566f76311a144f3b4
child 210715 8ec09ed512d3830642fe2c3859d55ca3135e26b6
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewershsinyi
bugs1058397
milestone36.0a1
Bug 1058397 - Part 1: Separate TelephonyCallback. r=hsinyi
dom/mobileconnection/gonk/MobileConnectionService.js
dom/telephony/Telephony.cpp
dom/telephony/Telephony.h
dom/telephony/TelephonyCallback.cpp
dom/telephony/TelephonyCallback.h
dom/telephony/TelephonyDialCallback.cpp
dom/telephony/TelephonyDialCallback.h
dom/telephony/gonk/TelephonyService.js
dom/telephony/ipc/PTelephonyRequest.ipdl
dom/telephony/ipc/TelephonyChild.cpp
dom/telephony/ipc/TelephonyChild.h
dom/telephony/ipc/TelephonyIPCService.cpp
dom/telephony/ipc/TelephonyParent.cpp
dom/telephony/ipc/TelephonyParent.h
dom/telephony/moz.build
dom/telephony/nsIGonkTelephonyService.idl
dom/telephony/nsITelephonyService.idl
--- a/dom/mobileconnection/gonk/MobileConnectionService.js
+++ b/dom/mobileconnection/gonk/MobileConnectionService.js
@@ -22,18 +22,18 @@ const GONK_MOBILECONNECTIONSERVICE_CID =
 const MOBILECONNECTIONINFO_CID =
   Components.ID("{8162b3c0-664b-45f6-96cd-f07b4e193b0e}");
 const MOBILENETWORKINFO_CID =
   Components.ID("{a6c8416c-09b4-46d1-bf29-6520d677d085}");
 const MOBILECELLINFO_CID =
   Components.ID("{0635d9ab-997e-4cdf-84e7-c1883752dff3}");
 const MOBILECALLFORWARDINGOPTIONS_CID =
   Components.ID("{e0cf4463-ee63-4b05-ab2e-d94bf764836c}");
-const TELEPHONYCALLBACK_CID =
-  Components.ID("{6e1af17e-37f3-11e4-aed3-60a44c237d2b}");
+const TELEPHONYDIALCALLBACK_CID =
+  Components.ID("{c2af1a5d-3649-44ef-a1ff-18e9ac1dec51}");
 
 const NS_XPCOM_SHUTDOWN_OBSERVER_ID      = "xpcom-shutdown";
 const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID  = "nsPref:changed";
 const NS_NETWORK_ACTIVE_CHANGED_TOPIC_ID = "network-active-changed";
 
 const kPrefRilDebuggingEnabled = "ril.debugging.enabled";
 
 XPCOMUtils.defineLazyServiceGetter(this, "gSystemMessenger",
@@ -134,24 +134,24 @@ MobileCallForwardingOptions.prototype = 
   action: Ci.nsIMobileConnection.CALL_FORWARD_ACTION_UNKNOWN,
   reason: Ci.nsIMobileConnection.CALL_FORWARD_REASON_UNKNOWN,
   number: null,
   timeSeconds: -1,
   serviceClass: Ci.nsIMobileConnection.ICC_SERVICE_CLASS_NONE
 }
 
 /**
- * Wrap a MobileConnectionCallback to a TelephonyCallback.
+ * Wrap a MobileConnectionCallback to a TelephonyDialCallback.
  */
-function TelephonyCallback(aCallback) {
+function TelephonyDialCallback(aCallback) {
   this.callback = aCallback;
 }
-TelephonyCallback.prototype = {
-  QueryInterface:   XPCOMUtils.generateQI([Ci.nsITelephonyCallback]),
-  classID:          TELEPHONYCALLBACK_CID,
+TelephonyDialCallback.prototype = {
+  QueryInterface:   XPCOMUtils.generateQI([Ci.nsITelephonyDialCallback]),
+  classID:          TELEPHONYDIALCALLBACK_CID,
 
   _notifySendCancelMmiSuccess: function(aResult) {
     // No additional information.
     if (aResult.additionalInformation === undefined) {
       this.callback.notifySendCancelMmiSuccess(aResult.serviceCode,
                                                aResult.statusMessage);
       return;
     }
@@ -687,18 +687,18 @@ MobileConnectionProvider.prototype = {
       }
 
       aCallback.notifySuccessWithBoolean(aResponse.enabled);
       return false;
     }).bind(this));
   },
 
   sendMMI: function(aMmi, aCallback) {
-    let telephonyCallback = new TelephonyCallback(aCallback);
-    gGonkTelephonyService.dialMMI(this._clientId, aMmi, telephonyCallback);
+    let callback = new TelephonyDialCallback(aCallback);
+    gGonkTelephonyService.dialMMI(this._clientId, aMmi, callback);
   },
 
   cancelMMI: function(aCallback) {
     this._radioInterface.sendWorkerMessage("cancelUSSD", null,
                                            (function(aResponse) {
       if (aResponse.errorMsg) {
         aCallback.notifyError(aResponse.errorMsg);
         return false;
--- a/dom/telephony/Telephony.cpp
+++ b/dom/telephony/Telephony.cpp
@@ -21,17 +21,17 @@
 #include "nsPIDOMWindow.h"
 #include "nsServiceManagerUtils.h"
 #include "nsThreadUtils.h"
 
 #include "CallsList.h"
 #include "TelephonyCall.h"
 #include "TelephonyCallGroup.h"
 #include "TelephonyCallId.h"
-#include "TelephonyCallback.h"
+#include "TelephonyDialCallback.h"
 
 // Service instantiation
 #include "ipc/TelephonyIPCService.h"
 #if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL)
 #include "nsIGonkTelephonyService.h"
 #endif
 #include "nsXULAppAPI.h" // For XRE_GetProcessType()
 
@@ -230,18 +230,18 @@ Telephony::DialInternal(uint32_t aServic
   }
 
   // We only support one outgoing call at a time.
   if (HasDialingCall()) {
     promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
     return promise.forget();
   }
 
-  nsCOMPtr<nsITelephonyCallback> callback =
-    new TelephonyCallback(GetOwner(), this, promise, aServiceId);
+  nsCOMPtr<nsITelephonyDialCallback> callback =
+    new TelephonyDialCallback(GetOwner(), this, promise, aServiceId);
 
   nsresult rv = mService->Dial(aServiceId, aNumber, aEmergency, callback);
   if (NS_FAILED(rv)) {
     promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
     return promise.forget();
   }
 
   return promise.forget();
--- a/dom/telephony/Telephony.h
+++ b/dom/telephony/Telephony.h
@@ -18,17 +18,17 @@
 #include "TelephonyCall.h"
 
 class nsPIDOMWindow;
 
 namespace mozilla {
 namespace dom {
 namespace telephony {
 
-class TelephonyCallback;
+class TelephonyDialCallback;
 
 } // namespace telephony
 
 class OwningTelephonyCallOrTelephonyCallGroup;
 
 class Telephony MOZ_FINAL : public DOMEventTargetHelper,
                             private nsITelephonyListener
 {
@@ -38,17 +38,17 @@ class Telephony MOZ_FINAL : public DOMEv
    * and passes it to nsITelephonyService. The onreceived events are first
    * delivered to mListener and then forwarded to its owner, Telephony. See
    * also bug 775997 comment #51.
    */
   class Listener;
   class EnumerationAck;
 
   friend class EnumerationAck;
-  friend class telephony::TelephonyCallback;
+  friend class telephony::TelephonyDialCallback;
 
   nsCOMPtr<nsITelephonyService> mService;
   nsRefPtr<Listener> mListener;
 
   nsTArray<nsRefPtr<TelephonyCall> > mCalls;
   nsRefPtr<CallsList> mCallsList;
 
   nsRefPtr<TelephonyCallGroup> mGroup;
--- a/dom/telephony/TelephonyCallback.cpp
+++ b/dom/telephony/TelephonyCallback.cpp
@@ -1,139 +1,34 @@
 /* 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 "TelephonyCallback.h"
 
-#include "mozilla/dom/DOMMMIError.h"
-#include "nsServiceManagerUtils.h"
+#include "mozilla/dom/Promise.h"
+#include "nsJSUtils.h"
 
 using namespace mozilla::dom;
 using namespace mozilla::dom::telephony;
 
 NS_IMPL_ISUPPORTS(TelephonyCallback, nsITelephonyCallback)
 
-TelephonyCallback::TelephonyCallback(nsPIDOMWindow* aWindow,
-                                     Telephony* aTelephony,
-                                     Promise* aPromise,
-                                     uint32_t aServiceId)
-  : mWindow(aWindow), mTelephony(aTelephony), mPromise(aPromise),
-    mServiceId(aServiceId)
-{
-  MOZ_ASSERT(mTelephony);
-}
-
-nsresult
-TelephonyCallback::NotifyDialMMISuccess(const nsAString& aStatusMessage)
+TelephonyCallback::TelephonyCallback(Promise* aPromise)
+  : mPromise(aPromise)
 {
-  AutoJSAPI jsapi;
-  if (!NS_WARN_IF(jsapi.Init(mWindow))) {
-    return NS_ERROR_FAILURE;
-  }
-
-  JSContext* cx = jsapi.cx();
-
-  MozMMIResult result;
-
-  result.mServiceCode.Assign(mServiceCode);
-  result.mStatusMessage.Assign(aStatusMessage);
-
-  return NotifyDialMMISuccess(cx, result);
-}
-
-nsresult
-TelephonyCallback::NotifyDialMMISuccess(JSContext* aCx,
-                                        const nsAString& aStatusMessage,
-                                        JS::Handle<JS::Value> aInfo)
-{
-  RootedDictionary<MozMMIResult> result(aCx);
-
-  result.mServiceCode.Assign(mServiceCode);
-  result.mStatusMessage.Assign(aStatusMessage);
-  result.mAdditionalInformation.Construct().SetAsObject() = &aInfo.toObject();
-
-  return NotifyDialMMISuccess(aCx, result);
-}
-
-nsresult
-TelephonyCallback::NotifyDialMMISuccess(JSContext* aCx,
-                                        const MozMMIResult& aResult)
-{
-  JS::Rooted<JS::Value> jsResult(aCx);
-
-  if (!ToJSValue(aCx, aResult, &jsResult)) {
-    JS_ClearPendingException(aCx);
-    return NS_ERROR_TYPE_ERR;
-  }
-
-  return NotifyDialMMISuccess(jsResult);
 }
 
 // nsITelephonyCallback
 
 NS_IMETHODIMP
-TelephonyCallback::NotifyDialMMI(const nsAString& aServiceCode)
-{
-  mMMIRequest = new DOMRequest(mWindow);
-  mServiceCode.Assign(aServiceCode);
-
-  mPromise->MaybeResolve(mMMIRequest);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-TelephonyCallback::NotifyDialError(const nsAString& aError)
+TelephonyCallback::NotifySuccess()
 {
-  mPromise->MaybeRejectBrokenly(aError);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-TelephonyCallback::NotifyDialCallSuccess(uint32_t aCallIndex,
-                                         const nsAString& aNumber)
-{
-  nsRefPtr<TelephonyCallId> id = mTelephony->CreateCallId(aNumber);
-  nsRefPtr<TelephonyCall> call =
-      mTelephony->CreateCall(id, mServiceId, aCallIndex,
-                             nsITelephonyService::CALL_STATE_DIALING);
-
-  mPromise->MaybeResolve(call);
+  mPromise->MaybeResolve(JS::UndefinedHandleValue);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-TelephonyCallback::NotifyDialMMISuccess(JS::Handle<JS::Value> aResult)
-{
-  nsCOMPtr<nsIDOMRequestService> rs = do_GetService(DOMREQUEST_SERVICE_CONTRACTID);
-  NS_ENSURE_TRUE(rs, NS_ERROR_FAILURE);
-
-  return rs->FireSuccessAsync(mMMIRequest, aResult);
-}
-
-NS_IMETHODIMP
-TelephonyCallback::NotifyDialMMIError(const nsAString& aError)
+TelephonyCallback::NotifyError(const nsAString& aError)
 {
-  Nullable<int16_t> info;
-
-  nsRefPtr<DOMError> error =
-      new DOMMMIError(mWindow, aError, EmptyString(), mServiceCode, info);
-
-  nsCOMPtr<nsIDOMRequestService> rs = do_GetService(DOMREQUEST_SERVICE_CONTRACTID);
-  NS_ENSURE_TRUE(rs, NS_ERROR_FAILURE);
-
-  return rs->FireDetailedError(mMMIRequest, error);
+  mPromise->MaybeRejectBrokenly(aError);
+  return NS_OK;
 }
-
-NS_IMETHODIMP
-TelephonyCallback::NotifyDialMMIErrorWithInfo(const nsAString& aError,
-                                              uint16_t aInfo)
-{
-  Nullable<int16_t> info(aInfo);
-
-  nsRefPtr<DOMError> error =
-      new DOMMMIError(mWindow, aError, EmptyString(), mServiceCode, info);
-
-  nsCOMPtr<nsIDOMRequestService> rs = do_GetService(DOMREQUEST_SERVICE_CONTRACTID);
-  NS_ENSURE_TRUE(rs, NS_ERROR_FAILURE);
-
-  return rs->FireDetailedError(mMMIRequest, error);
-}
--- a/dom/telephony/TelephonyCallback.h
+++ b/dom/telephony/TelephonyCallback.h
@@ -1,81 +1,38 @@
 /* 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/. */
 
 #ifndef mozilla_dom_TelephonyCallback_h
 #define mozilla_dom_TelephonyCallback_h
 
-#include "Telephony.h"
-#include "mozilla/dom/DOMRequest.h"
-#include "mozilla/dom/MozMobileConnectionBinding.h"
-#include "mozilla/dom/Promise.h"
-#include "mozilla/dom/ToJSValue.h"
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsITelephonyService.h"
-#include "nsJSUtils.h"
-#include "nsString.h"
-
-class nsPIDOMWindow;
 
 namespace mozilla {
 namespace dom {
+
+class Promise;
+
 namespace telephony {
 
-class TelephonyCallback MOZ_FINAL : public nsITelephonyCallback
+class TelephonyCallback : public nsITelephonyCallback
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSITELEPHONYCALLBACK
 
-  TelephonyCallback(nsPIDOMWindow* aWindow, Telephony* aTelephony,
-                    Promise* aPromise, uint32_t aServiceId);
-
-  nsresult
-  NotifyDialMMISuccess(const nsAString& aStatusMessage);
-
-  template<typename T>
-  nsresult
-  NotifyDialMMISuccess(const nsAString& aStatusMessage, const T& aInfo)
-  {
-    AutoJSAPI jsapi;
-    if (!NS_WARN_IF(jsapi.Init(mWindow))) {
-      return NS_ERROR_FAILURE;
-    }
-
-    JSContext* cx = jsapi.cx();
-    JS::Rooted<JS::Value> info(cx);
+  TelephonyCallback(Promise* aPromise);
 
-    if (!ToJSValue(cx, aInfo, &info)) {
-      JS_ClearPendingException(cx);
-      return NS_ERROR_TYPE_ERR;
-    }
-
-    return NotifyDialMMISuccess(cx, aStatusMessage, info);
-  }
-
-private:
-  ~TelephonyCallback() {}
+protected:
+  virtual ~TelephonyCallback() {}
 
-  nsresult
-  NotifyDialMMISuccess(JSContext* aCx, const nsAString& aStatusMessage,
-                       JS::Handle<JS::Value> aInfo);
-
-  nsresult
-  NotifyDialMMISuccess(JSContext* aCx, const MozMMIResult& aResult);
-
-
-  nsCOMPtr<nsPIDOMWindow> mWindow;
-  nsRefPtr<Telephony> mTelephony;
+protected:
   nsRefPtr<Promise> mPromise;
-  uint32_t mServiceId;
-
-  nsRefPtr<DOMRequest> mMMIRequest;
-  nsString mServiceCode;
 };
 
 } // namespace telephony
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_TelephonyCallback_h
new file mode 100644
--- /dev/null
+++ b/dom/telephony/TelephonyDialCallback.cpp
@@ -0,0 +1,133 @@
+/* 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 "TelephonyDialCallback.h"
+
+#include "mozilla/dom/DOMMMIError.h"
+#include "nsServiceManagerUtils.h"
+
+using namespace mozilla::dom;
+using namespace mozilla::dom::telephony;
+
+NS_IMPL_ISUPPORTS_INHERITED(TelephonyDialCallback, TelephonyCallback,
+                            nsITelephonyDialCallback)
+
+TelephonyDialCallback::TelephonyDialCallback(nsPIDOMWindow* aWindow,
+                                             Telephony* aTelephony,
+                                             Promise* aPromise,
+                                             uint32_t aServiceId)
+  : TelephonyCallback(aPromise), mWindow(aWindow), mTelephony(aTelephony),
+    mServiceId(aServiceId)
+{
+  MOZ_ASSERT(mTelephony);
+}
+
+nsresult
+TelephonyDialCallback::NotifyDialMMISuccess(const nsAString& aStatusMessage)
+{
+  AutoJSAPI jsapi;
+  if (!NS_WARN_IF(jsapi.Init(mWindow))) {
+    return NS_ERROR_FAILURE;
+  }
+
+  JSContext* cx = jsapi.cx();
+
+  MozMMIResult result;
+
+  result.mServiceCode.Assign(mServiceCode);
+  result.mStatusMessage.Assign(aStatusMessage);
+
+  return NotifyDialMMISuccess(cx, result);
+}
+
+nsresult
+TelephonyDialCallback::NotifyDialMMISuccess(JSContext* aCx,
+                                            const nsAString& aStatusMessage,
+                                            JS::Handle<JS::Value> aInfo)
+{
+  RootedDictionary<MozMMIResult> result(aCx);
+
+  result.mServiceCode.Assign(mServiceCode);
+  result.mStatusMessage.Assign(aStatusMessage);
+  result.mAdditionalInformation.Construct().SetAsObject() = &aInfo.toObject();
+
+  return NotifyDialMMISuccess(aCx, result);
+}
+
+nsresult
+TelephonyDialCallback::NotifyDialMMISuccess(JSContext* aCx,
+                                            const MozMMIResult& aResult)
+{
+  JS::Rooted<JS::Value> jsResult(aCx);
+
+  if (!ToJSValue(aCx, aResult, &jsResult)) {
+    JS_ClearPendingException(aCx);
+    return NS_ERROR_TYPE_ERR;
+  }
+
+  return NotifyDialMMISuccess(jsResult);
+}
+
+// nsITelephonyDialCallback
+
+NS_IMETHODIMP
+TelephonyDialCallback::NotifyDialMMI(const nsAString& aServiceCode)
+{
+  mMMIRequest = new DOMRequest(mWindow);
+  mServiceCode.Assign(aServiceCode);
+
+  mPromise->MaybeResolve(mMMIRequest);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+TelephonyDialCallback::NotifyDialCallSuccess(uint32_t aCallIndex,
+                                             const nsAString& aNumber)
+{
+  nsRefPtr<TelephonyCallId> id = mTelephony->CreateCallId(aNumber);
+  nsRefPtr<TelephonyCall> call =
+      mTelephony->CreateCall(id, mServiceId, aCallIndex,
+                             nsITelephonyService::CALL_STATE_DIALING);
+
+  mPromise->MaybeResolve(call);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+TelephonyDialCallback::NotifyDialMMISuccess(JS::Handle<JS::Value> aResult)
+{
+  nsCOMPtr<nsIDOMRequestService> rs = do_GetService(DOMREQUEST_SERVICE_CONTRACTID);
+  NS_ENSURE_TRUE(rs, NS_ERROR_FAILURE);
+
+  return rs->FireSuccessAsync(mMMIRequest, aResult);
+}
+
+NS_IMETHODIMP
+TelephonyDialCallback::NotifyDialMMIError(const nsAString& aError)
+{
+  Nullable<int16_t> info;
+
+  nsRefPtr<DOMError> error =
+      new DOMMMIError(mWindow, aError, EmptyString(), mServiceCode, info);
+
+  nsCOMPtr<nsIDOMRequestService> rs = do_GetService(DOMREQUEST_SERVICE_CONTRACTID);
+  NS_ENSURE_TRUE(rs, NS_ERROR_FAILURE);
+
+  return rs->FireDetailedError(mMMIRequest, error);
+}
+
+NS_IMETHODIMP
+TelephonyDialCallback::NotifyDialMMIErrorWithInfo(const nsAString& aError,
+                                                  uint16_t aInfo)
+{
+  Nullable<int16_t> info(aInfo);
+
+  nsRefPtr<DOMError> error =
+      new DOMMMIError(mWindow, aError, EmptyString(), mServiceCode, info);
+
+  nsCOMPtr<nsIDOMRequestService> rs = do_GetService(DOMREQUEST_SERVICE_CONTRACTID);
+  NS_ENSURE_TRUE(rs, NS_ERROR_FAILURE);
+
+  return rs->FireDetailedError(mMMIRequest, error);
+}
new file mode 100644
--- /dev/null
+++ b/dom/telephony/TelephonyDialCallback.h
@@ -0,0 +1,84 @@
+/* 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/. */
+
+#ifndef mozilla_dom_TelephonyDialCallback_h
+#define mozilla_dom_TelephonyDialCallback_h
+
+#include "Telephony.h"
+#include "mozilla/dom/DOMRequest.h"
+#include "mozilla/dom/MozMobileConnectionBinding.h"
+#include "mozilla/dom/Promise.h"
+#include "mozilla/dom/ToJSValue.h"
+#include "mozilla/dom/telephony/TelephonyCallback.h"
+#include "nsAutoPtr.h"
+#include "nsCOMPtr.h"
+#include "nsITelephonyService.h"
+#include "nsJSUtils.h"
+#include "nsString.h"
+
+class nsPIDOMWindow;
+
+namespace mozilla {
+namespace dom {
+namespace telephony {
+
+class TelephonyDialCallback MOZ_FINAL : public TelephonyCallback,
+                                        public nsITelephonyDialCallback
+{
+public:
+  NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_NSITELEPHONYDIALCALLBACK
+
+  TelephonyDialCallback(nsPIDOMWindow* aWindow, Telephony* aTelephony,
+                        Promise* aPromise, uint32_t aServiceId);
+
+  NS_FORWARD_NSITELEPHONYCALLBACK(TelephonyCallback::)
+
+  nsresult
+  NotifyDialMMISuccess(const nsAString& aStatusMessage);
+
+  template<typename T>
+  nsresult
+  NotifyDialMMISuccess(const nsAString& aStatusMessage, const T& aInfo)
+  {
+    AutoJSAPI jsapi;
+    if (!NS_WARN_IF(jsapi.Init(mWindow))) {
+      return NS_ERROR_FAILURE;
+    }
+
+    JSContext* cx = jsapi.cx();
+    JS::Rooted<JS::Value> info(cx);
+
+    if (!ToJSValue(cx, aInfo, &info)) {
+      JS_ClearPendingException(cx);
+      return NS_ERROR_TYPE_ERR;
+    }
+
+    return NotifyDialMMISuccess(cx, aStatusMessage, info);
+  }
+
+private:
+  ~TelephonyDialCallback() {}
+
+  nsresult
+  NotifyDialMMISuccess(JSContext* aCx, const nsAString& aStatusMessage,
+                       JS::Handle<JS::Value> aInfo);
+
+  nsresult
+  NotifyDialMMISuccess(JSContext* aCx, const MozMMIResult& aResult);
+
+
+  nsCOMPtr<nsPIDOMWindow> mWindow;
+  nsRefPtr<Telephony> mTelephony;
+  uint32_t mServiceId;
+
+  nsRefPtr<DOMRequest> mMMIRequest;
+  nsString mServiceCode;
+};
+
+} // namespace telephony
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_TelephonyDialCallback_h
--- a/dom/telephony/gonk/TelephonyService.js
+++ b/dom/telephony/gonk/TelephonyService.js
@@ -559,75 +559,75 @@ TelephonyService.prototype = {
     if (!aIsDialEmergency) {
       aNumber = gPhoneNumberUtils.normalize(aNumber);
     }
 
     // Validate the number.
     // Note: isPlainPhoneNumber also accepts USSD and SS numbers
     if (!gPhoneNumberUtils.isPlainPhoneNumber(aNumber)) {
       if (DEBUG) debug("Error: Number '" + aNumber + "' is not viable. Drop.");
-      aCallback.notifyDialError(DIAL_ERROR_BAD_NUMBER);
+      aCallback.notifyError(DIAL_ERROR_BAD_NUMBER);
       return;
     }
 
     let mmi = this._parseMMI(aNumber, this._hasCalls(aClientId));
     if (!mmi) {
       this._dialCall(aClientId,
                      { number: aNumber,
                        isDialEmergency: aIsDialEmergency }, aCallback);
     } else if (this._isTemporaryCLIR(mmi)) {
       this._dialCall(aClientId,
                      { number: mmi.dialNumber,
                        clirMode: this._getTemporaryCLIRMode(mmi.procedure),
                        isDialEmergency: aIsDialEmergency }, aCallback);
     } else {
       // Reject MMI code from dialEmergency api.
       if (aIsDialEmergency) {
-        aCallback.notifyDialError(DIAL_ERROR_BAD_NUMBER);
+        aCallback.notifyError(DIAL_ERROR_BAD_NUMBER);
         return;
       }
 
       this._dialMMI(aClientId, mmi, aCallback);
     }
   },
 
   /**
    * @param aOptions.number
    * @param aOptions.clirMode (optional)
    * @param aOptions.isDialEmergency
    */
   _dialCall: function(aClientId, aOptions, aCallback) {
     if (this._isDialing) {
       if (DEBUG) debug("Error: Already has a dialing call.");
-      aCallback.notifyDialError(DIAL_ERROR_INVALID_STATE_ERROR);
+      aCallback.notifyError(DIAL_ERROR_INVALID_STATE_ERROR);
       return;
     }
 
     // We can only have at most two calls on the same line (client).
     if (this._numCallsOnLine(aClientId) >= 2) {
       if (DEBUG) debug("Error: Already has more than 2 calls on line.");
-      aCallback.notifyDialError(DIAL_ERROR_INVALID_STATE_ERROR);
+      aCallback.notifyError(DIAL_ERROR_INVALID_STATE_ERROR);
       return;
     }
 
     // For DSDS, if there is aleady a call on SIM 'aClientId', we cannot place
     // any new call on other SIM.
     if (this._hasCallsOnOtherClient(aClientId)) {
       if (DEBUG) debug("Error: Already has a call on other sim.");
-      aCallback.notifyDialError(DIAL_ERROR_OTHER_CONNECTION_IN_USE);
+      aCallback.notifyError(DIAL_ERROR_OTHER_CONNECTION_IN_USE);
       return;
     }
 
     aOptions.isEmergency = this._isEmergencyNumber(aOptions.number);
     if (aOptions.isEmergency) {
       // Automatically select a proper clientId for emergency call.
       aClientId = gRadioInterfaceLayer.getClientIdForEmergencyCall() ;
       if (aClientId === -1) {
         if (DEBUG) debug("Error: No client is avaialble for emergency call.");
-        aCallback.notifyDialError(DIAL_ERROR_INVALID_STATE_ERROR);
+        aCallback.notifyError(DIAL_ERROR_INVALID_STATE_ERROR);
         return;
       }
     }
 
     // Before we dial, we have to hold the active call first.
     let activeCall = this._getOneActiveCall(aClientId);
     if (!activeCall) {
       this._sendDialCallRequest(aClientId, aOptions, aCallback);
@@ -650,17 +650,17 @@ TelephonyService.prototype = {
 
   _sendDialCallRequest: function(aClientId, aOptions, aCallback) {
     this._isDialing = true;
 
     this._sendToRilWorker(aClientId, "dial", aOptions, response => {
       this._isDialing = false;
 
       if (!response.success) {
-        aCallback.notifyDialError(response.errorMsg);
+        aCallback.notifyError(response.errorMsg);
         return;
       }
 
       let currentCdmaCallIndex = !response.isCdma ? null :
         Object.keys(this._currentCalls[aClientId])[0];
 
       if (currentCdmaCallIndex == null) {
         aCallback.notifyDialCallSuccess(response.callIndex, response.number);
--- a/dom/telephony/ipc/PTelephonyRequest.ipdl
+++ b/dom/telephony/ipc/PTelephonyRequest.ipdl
@@ -11,17 +11,22 @@ namespace mozilla {
 namespace dom {
 namespace telephony {
 
 struct EnumerateCallsResponse
 {
   // empty.
 };
 
-struct DialResponseError
+struct SuccessResponse
+{
+  // empty.
+};
+
+struct ErrorResponse
 {
   nsString name;
 };
 
 struct DialResponseCallSuccess
 {
   uint32_t callIndex;
   nsString number;
@@ -37,18 +42,22 @@ struct DialResponseMMIError
 {
   nsString name;
   AdditionalInformation additionalInformation;
 };
 
 union IPCTelephonyResponse
 {
   EnumerateCallsResponse;
+
+  // General.
+  SuccessResponse;
+  ErrorResponse;
+
   // dial
-  DialResponseError;
   DialResponseCallSuccess;
   DialResponseMMISuccess;
   DialResponseMMIError;
 };
 
 protocol PTelephonyRequest
 {
   manager PTelephony;
--- a/dom/telephony/ipc/TelephonyChild.cpp
+++ b/dom/telephony/ipc/TelephonyChild.cpp
@@ -1,16 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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 "TelephonyChild.h"
 
-#include "mozilla/dom/telephony/TelephonyCallback.h"
+#include "mozilla/dom/telephony/TelephonyDialCallback.h"
 #include "TelephonyIPCService.h"
 
 USING_TELEPHONY_NAMESPACE
 
 /*******************************************************************************
  * TelephonyChild
  ******************************************************************************/
 
@@ -142,18 +142,20 @@ TelephonyRequestChild::ActorDestroy(Acto
 
 bool
 TelephonyRequestChild::Recv__delete__(const IPCTelephonyResponse& aResponse)
 {
   switch (aResponse.type()) {
     case IPCTelephonyResponse::TEnumerateCallsResponse:
       mListener->EnumerateCallStateComplete();
       break;
-    case IPCTelephonyResponse::TDialResponseError:
-      return DoResponse(aResponse.get_DialResponseError());
+    case IPCTelephonyResponse::TSuccessResponse:
+      return DoResponse(aResponse.get_SuccessResponse());
+    case IPCTelephonyResponse::TErrorResponse:
+      return DoResponse(aResponse.get_ErrorResponse());
     case IPCTelephonyResponse::TDialResponseCallSuccess:
       return DoResponse(aResponse.get_DialResponseCallSuccess());
     case IPCTelephonyResponse::TDialResponseMMISuccess:
       return DoResponse(aResponse.get_DialResponseMMISuccess());
     case IPCTelephonyResponse::TDialResponseMMIError:
       return DoResponse(aResponse.get_DialResponseMMIError());
     default:
       MOZ_CRASH("Unknown type!");
@@ -182,45 +184,55 @@ TelephonyRequestChild::RecvNotifyEnumera
                                 aData.isMergeable());
   return true;
 }
 
 bool
 TelephonyRequestChild::RecvNotifyDialMMI(const nsString& aServiceCode)
 {
   MOZ_ASSERT(mCallback);
-
-  mCallback->NotifyDialMMI(aServiceCode);
+  nsCOMPtr<nsITelephonyDialCallback> callback = do_QueryInterface(mCallback);
+  callback->NotifyDialMMI(aServiceCode);
   return true;
 }
 
 bool
-TelephonyRequestChild::DoResponse(const DialResponseError& aResponse)
+TelephonyRequestChild::DoResponse(const SuccessResponse& aResponse)
 {
   MOZ_ASSERT(mCallback);
-  mCallback->NotifyDialError(aResponse.name());
+  mCallback->NotifySuccess();
+  return true;
+}
+
+bool
+TelephonyRequestChild::DoResponse(const ErrorResponse& aResponse)
+{
+  MOZ_ASSERT(mCallback);
+  mCallback->NotifyError(aResponse.name());
   return true;
 }
 
 bool
 TelephonyRequestChild::DoResponse(const DialResponseCallSuccess& aResponse)
 {
   MOZ_ASSERT(mCallback);
-  mCallback->NotifyDialCallSuccess(aResponse.callIndex(), aResponse.number());
+  nsCOMPtr<nsITelephonyDialCallback> callback = do_QueryInterface(mCallback);
+  callback->NotifyDialCallSuccess(aResponse.callIndex(), aResponse.number());
   return true;
 }
 
 bool
 TelephonyRequestChild::DoResponse(const DialResponseMMISuccess& aResponse)
 {
   MOZ_ASSERT(mCallback);
 
   // FIXME: Need to overload NotifyDialMMISuccess in the IDL. mCallback is not
   // necessarily an instance of TelephonyCallback.
-  nsRefPtr<TelephonyCallback> callback = static_cast<TelephonyCallback*>(mCallback.get());
+  nsCOMPtr<nsITelephonyDialCallback> dialCallback = do_QueryInterface(mCallback);
+  nsRefPtr<TelephonyDialCallback> callback = static_cast<TelephonyDialCallback*>(dialCallback.get());
 
   nsAutoString statusMessage(aResponse.statusMessage());
   AdditionalInformation info(aResponse.additionalInformation());
 
   switch (info.type()) {
     case AdditionalInformation::Tvoid_t:
       callback->NotifyDialMMISuccess(statusMessage);
       break;
@@ -237,26 +249,27 @@ TelephonyRequestChild::DoResponse(const 
 
   return true;
 }
 
 bool
 TelephonyRequestChild::DoResponse(const DialResponseMMIError& aResponse)
 {
   MOZ_ASSERT(mCallback);
+  nsCOMPtr<nsITelephonyDialCallback> callback = do_QueryInterface(mCallback);
 
   nsAutoString name(aResponse.name());
   AdditionalInformation info(aResponse.additionalInformation());
 
   switch (info.type()) {
     case AdditionalInformation::Tvoid_t:
-      mCallback->NotifyDialMMIError(name);
+      callback->NotifyDialMMIError(name);
       break;
     case AdditionalInformation::Tuint16_t:
-      mCallback->NotifyDialMMIErrorWithInfo(name, info.get_uint16_t());
+      callback->NotifyDialMMIErrorWithInfo(name, info.get_uint16_t());
       break;
     default:
       MOZ_CRASH("Received invalid type!");
       break;
   }
 
   return true;
 }
--- a/dom/telephony/ipc/TelephonyChild.h
+++ b/dom/telephony/ipc/TelephonyChild.h
@@ -79,17 +79,20 @@ protected:
   RecvNotifyEnumerateCallState(const uint32_t& aClientId,
                                const IPCCallStateData& aData) MOZ_OVERRIDE;
 
   virtual bool
   RecvNotifyDialMMI(const nsString& aServiceCode) MOZ_OVERRIDE;
 
 private:
   bool
-  DoResponse(const DialResponseError& aResponse);
+  DoResponse(const SuccessResponse& aResponse);
+
+  bool
+  DoResponse(const ErrorResponse& aResponse);
 
   bool
   DoResponse(const DialResponseCallSuccess& aResponse);
 
   bool
   DoResponse(const DialResponseMMISuccess& aResponse);
 
   bool
--- a/dom/telephony/ipc/TelephonyIPCService.cpp
+++ b/dom/telephony/ipc/TelephonyIPCService.cpp
@@ -157,17 +157,18 @@ TelephonyIPCService::SendRequest(nsITele
 NS_IMETHODIMP
 TelephonyIPCService::EnumerateCalls(nsITelephonyListener *aListener)
 {
   return SendRequest(aListener, nullptr, EnumerateCallsRequest());
 }
 
 NS_IMETHODIMP
 TelephonyIPCService::Dial(uint32_t aClientId, const nsAString& aNumber,
-                           bool aIsEmergency, nsITelephonyCallback *aCallback)
+                           bool aIsEmergency,
+                           nsITelephonyDialCallback *aCallback)
 {
   return SendRequest(nullptr, aCallback,
                      DialRequest(aClientId, nsString(aNumber), aIsEmergency));
 }
 
 NS_IMETHODIMP
 TelephonyIPCService::HangUp(uint32_t aClientId, uint32_t aCallIndex)
 {
--- a/dom/telephony/ipc/TelephonyParent.cpp
+++ b/dom/telephony/ipc/TelephonyParent.cpp
@@ -380,17 +380,18 @@ TelephonyParent::SupplementaryServiceNot
 }
 
 /*******************************************************************************
  * TelephonyRequestParent
  ******************************************************************************/
 
 NS_IMPL_ISUPPORTS(TelephonyRequestParent,
                   nsITelephonyListener,
-                  nsITelephonyCallback)
+                  nsITelephonyCallback,
+                  nsITelephonyDialCallback)
 
 TelephonyRequestParent::TelephonyRequestParent()
   : mActorDestroyed(false)
 {
 }
 
 void
 TelephonyRequestParent::ActorDestroy(ActorDestroyReason why)
@@ -421,19 +422,19 @@ TelephonyRequestParent::DoRequest(const 
 
 bool
 TelephonyRequestParent::DoRequest(const DialRequest& aRequest)
 {
   nsCOMPtr<nsITelephonyService> service =
     do_GetService(TELEPHONY_SERVICE_CONTRACTID);
   if (service) {
     service->Dial(aRequest.clientId(), aRequest.number(),
-                   aRequest.isEmergency(), this);
+                  aRequest.isEmergency(), this);
   } else {
-    return NS_SUCCEEDED(NotifyDialError(NS_LITERAL_STRING("InvalidStateError")));
+    return NS_SUCCEEDED(NotifyError(NS_LITERAL_STRING("InvalidStateError")));
   }
 
   return true;
 }
 
 nsresult
 TelephonyRequestParent::SendResponse(const IPCTelephonyResponse& aResponse)
 {
@@ -527,30 +528,36 @@ TelephonyRequestParent::NotifyError(uint
 NS_IMETHODIMP
 TelephonyRequestParent::SupplementaryServiceNotification(uint32_t aClientId,
                                                          int32_t aCallIndex,
                                                          uint16_t aNotification)
 {
   MOZ_CRASH("Not a TelephonyParent!");
 }
 
-// nsITelephonyCallback
+// nsITelephonyDialCallback
 
 NS_IMETHODIMP
 TelephonyRequestParent::NotifyDialMMI(const nsAString& aServiceCode)
 {
   NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE);
 
   return SendNotifyDialMMI(nsAutoString(aServiceCode)) ? NS_OK : NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
-TelephonyRequestParent::NotifyDialError(const nsAString& aError)
+TelephonyRequestParent::NotifySuccess()
 {
-  return SendResponse(DialResponseError(nsAutoString(aError)));
+  return SendResponse(SuccessResponse());
+}
+
+NS_IMETHODIMP
+TelephonyRequestParent::NotifyError(const nsAString& aError)
+{
+  return SendResponse(ErrorResponse(nsAutoString(aError)));
 }
 
 NS_IMETHODIMP
 TelephonyRequestParent::NotifyDialCallSuccess(uint32_t aCallIndex,
                                               const nsAString& aNumber)
 {
   return SendResponse(DialResponseCallSuccess(aCallIndex, nsAutoString(aNumber)));
 }
--- a/dom/telephony/ipc/TelephonyParent.h
+++ b/dom/telephony/ipc/TelephonyParent.h
@@ -93,24 +93,25 @@ protected:
 
 private:
   bool mActorDestroyed;
   bool mRegistered;
 };
 
 class TelephonyRequestParent : public PTelephonyRequestParent
                              , public nsITelephonyListener
-                             , public nsITelephonyCallback
+                             , public nsITelephonyDialCallback
 {
   friend class TelephonyParent;
 
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSITELEPHONYLISTENER
   NS_DECL_NSITELEPHONYCALLBACK
+  NS_DECL_NSITELEPHONYDIALCALLBACK
 
 protected:
   TelephonyRequestParent();
   virtual ~TelephonyRequestParent() {}
 
   virtual void
   ActorDestroy(ActorDestroyReason why);
 
--- a/dom/telephony/moz.build
+++ b/dom/telephony/moz.build
@@ -18,28 +18,30 @@ EXPORTS.mozilla.dom += [
     'TelephonyCallId.h',
 ]
 
 EXPORTS.mozilla.dom.telephony += [
     'ipc/TelephonyChild.h',
     'ipc/TelephonyParent.h',
     'TelephonyCallback.h',
     'TelephonyCommon.h',
+    'TelephonyDialCallback.h',
 ]
 
 UNIFIED_SOURCES += [
     'CallsList.cpp',
     'ipc/TelephonyChild.cpp',
     'ipc/TelephonyIPCService.cpp',
     'ipc/TelephonyParent.cpp',
     'Telephony.cpp',
     'TelephonyCall.cpp',
     'TelephonyCallback.cpp',
     'TelephonyCallGroup.cpp',
     'TelephonyCallId.cpp',
+    'TelephonyDialCallback.cpp',
 ]
 
 IPDL_SOURCES += [
     'ipc/PTelephony.ipdl',
     'ipc/PTelephonyRequest.ipdl',
     'ipc/TelephonyTypes.ipdlh'
 ]
 
--- a/dom/telephony/nsIGonkTelephonyService.idl
+++ b/dom/telephony/nsIGonkTelephonyService.idl
@@ -5,17 +5,17 @@
 
 #include "nsITelephonyService.idl"
 
 %{C++
 #define GONK_TELEPHONY_SERVICE_CONTRACTID \
         "@mozilla.org/telephony/gonktelephonyservice;1"
 %}
 
-[scriptable, uuid(8790e2cc-2c68-4ce9-90dc-f68e1b6e4886)]
+[scriptable, uuid(518165dc-2d55-4db3-9549-60dc4062d1c5)]
 interface nsIGonkTelephonyService : nsITelephonyService
 {
   void notifyCallDisconnected(in unsigned long clientId, in jsval call);
 
   void notifyCallRing();
 
   void notifyCallStateChanged(in unsigned long clientId, in jsval call,
                               [optional] in boolean skipStateConversion);
@@ -23,10 +23,10 @@ interface nsIGonkTelephonyService : nsIT
   void notifyCdmaCallWaiting(in unsigned long clientId, in jsval waitingCall);
 
   void notifySupplementaryService(in unsigned long clientId, in long callIndex,
                                   in AString notification);
 
   void notifyConferenceCallStateChanged(in short state);
 
   void dialMMI(in unsigned long clientId, in AString mmiString,
-               in nsITelephonyCallback callback);
+               in nsITelephonyDialCallback callback);
 };
--- a/dom/telephony/nsITelephonyService.idl
+++ b/dom/telephony/nsITelephonyService.idl
@@ -172,39 +172,41 @@ interface nsITelephonyListener : nsISupp
    * @param message
    *        Detailed error message from RIL.
    */
   void notifyConferenceError(in AString name,
                              in AString message);
 };
 
 /**
- * A callback interface for handling asynchronous response of Telephony.dial().
+ * A callback interface for handling asynchronous response.
  */
-[scriptable, uuid(67533db3-cd38-475c-a774-8d0bbf9169fb)]
+[scriptable, uuid(cffc3f9d-2c88-4a14-8ebc-f216caf0cc1d)]
 interface nsITelephonyCallback : nsISupports
 {
+  void notifySuccess();
+  void notifyError(in AString error);
+};
+
+/**
+ * A callback interface for handling asynchronous response for telephony.dial.
+ */
+[scriptable, uuid(4481212f-72e9-4aef-97e1-5397af782113)]
+interface nsITelephonyDialCallback : nsITelephonyCallback
+{
   /**
    * Called when a dial request is treated as an MMI code and it is about to
    * process the request.
    *
    * @param serviceCode
    *        MMI service code key string that defined in MMI_KS_SC_*
    */
   void notifyDialMMI(in AString serviceCode);
 
   /**
-   * Called when a dial request fails.
-   *
-   * @param error
-   *        Error from RIL.
-   */
-  void notifyDialError(in AString error);
-
-  /**
    * Called when a dial request is treated as a call setup and the result
    * succeeds.
    *
    * @param callIndex
    *        Call index from RIL.
    * @param number
    *        Dialed out phone number (ex: Temporary CLIR prefix will be removed)
    */
@@ -233,17 +235,17 @@ interface nsITelephonyCallback : nsISupp
 #define TELEPHONY_SERVICE_CONTRACTID \
   "@mozilla.org/telephony/telephonyservice;1"
 %}
 
 /**
  * XPCOM component (in the content process) that provides the telephony
  * information.
  */
-[scriptable, uuid(4ff3ecb7-b024-4752-9dd6-c3623c6e6b8a)]
+[scriptable, uuid(600929fb-269c-4ae2-a61f-3c8a62cf5456)]
 interface nsITelephonyService : nsISupports
 {
   const unsigned short CALL_STATE_UNKNOWN = 0;
   const unsigned short CALL_STATE_DIALING = 1;
   const unsigned short CALL_STATE_ALERTING = 2;
   const unsigned short CALL_STATE_CONNECTING = 3;
   const unsigned short CALL_STATE_CONNECTED = 4;
   const unsigned short CALL_STATE_HOLDING = 5;
@@ -276,17 +278,17 @@ interface nsITelephonyService : nsISuppo
    * returns false.
    */
   void enumerateCalls(in nsITelephonyListener listener);
 
   /**
    * Functionality for making and managing phone calls.
    */
   void dial(in unsigned long clientId, in DOMString number,
-            in boolean isEmergency, in nsITelephonyCallback callback);
+            in boolean isEmergency, in nsITelephonyDialCallback callback);
   void hangUp(in unsigned long clientId, in unsigned long callIndex);
 
   void startTone(in unsigned long clientId, in DOMString dtmfChar);
   void stopTone(in unsigned long clientId);
 
   void answerCall(in unsigned long clientId, in unsigned long callIndex);
   void rejectCall(in unsigned long clientId, in unsigned long callIndex);
   void holdCall(in unsigned long clientId, in unsigned long callIndex);