Bug 969218 - Part 4: Use promise for dial and dialEmergency - dom. r=khuey
authorSzu-Yu Chen [:aknow] <szchen@mozilla.com>
Thu, 27 Feb 2014 14:12:30 +0800
changeset 170922 1492c73fa69afd2b777e5f28fa9ce8e236f632b8
parent 170921 607545e9bb6c7325239402778fe14f1d2f20e343
child 170923 a381a07fffb436bd8c32a18707498b7961d76c7a
push id26305
push usercbook@mozilla.com
push dateThu, 27 Feb 2014 14:19:43 +0000
treeherdermozilla-central@f8e801b991bc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskhuey
bugs969218
milestone30.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 969218 - Part 4: Use promise for dial and dialEmergency - dom. r=khuey
dom/telephony/Telephony.cpp
dom/telephony/Telephony.h
--- a/dom/telephony/Telephony.cpp
+++ b/dom/telephony/Telephony.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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 "Telephony.h"
 #include "mozilla/dom/TelephonyBinding.h"
+#include "mozilla/dom/Promise.h"
 
 #include "nsIURI.h"
 #include "nsPIDOMWindow.h"
 #include "nsIPermissionManager.h"
 
 #include "mozilla/dom/UnionTypes.h"
 #include "mozilla/Preferences.h"
 #include "nsCharSeparatedTokenizer.h"
@@ -56,16 +57,54 @@ public:
   void
   Disconnect()
   {
     MOZ_ASSERT(mTelephony);
     mTelephony = nullptr;
   }
 };
 
+class Telephony::Callback : public nsITelephonyCallback
+{
+  nsRefPtr<Telephony> mTelephony;
+  nsRefPtr<Promise> mPromise;
+  uint32_t mServiceId;
+  nsString mNumber;
+
+public:
+  NS_DECL_ISUPPORTS
+
+  Callback(Telephony* aTelephony, Promise* aPromise, uint32_t aServiceId,
+           const nsAString& aNumber)
+    : mTelephony(aTelephony), mPromise(aPromise), mServiceId(aServiceId),
+      mNumber(aNumber)
+  {
+    MOZ_ASSERT(mTelephony);
+  }
+
+  virtual ~Callback() {}
+
+  NS_IMETHODIMP
+  NotifyDialError(const nsAString& aError)
+  {
+    mPromise->MaybeReject(aError);
+    return NS_OK;
+  }
+
+  NS_IMETHODIMP
+  NotifyDialSuccess()
+  {
+    nsRefPtr<TelephonyCall> call =
+      mTelephony->CreateNewDialingCall(mServiceId, mNumber);
+
+    mPromise->MaybeResolve(call);
+    return NS_OK;
+  }
+};
+
 class Telephony::EnumerationAck : public nsRunnable
 {
   nsRefPtr<Telephony> mTelephony;
 
 public:
   EnumerationAck(Telephony* aTelephony)
   : mTelephony(aTelephony)
   {
@@ -75,18 +114,17 @@ public:
   NS_IMETHOD Run()
   {
     mTelephony->NotifyCallsChanged(nullptr);
     return NS_OK;
   }
 };
 
 Telephony::Telephony(nsPIDOMWindow* aOwner)
-  : nsDOMEventTargetHelper(aOwner),
-    mActiveCall(nullptr), mEnumerated(false)
+  : nsDOMEventTargetHelper(aOwner), mActiveCall(nullptr), mEnumerated(false)
 {
   if (!gTelephonyList) {
     gTelephonyList = new TelephonyList();
   }
 
   gTelephonyList->AppendElement(this);
 }
 
@@ -230,73 +268,62 @@ Telephony::HasDialingCall()
 bool
 Telephony::MatchActiveCall(TelephonyCall* aCall)
 {
   return (mActiveCall &&
           mActiveCall->CallIndex() == aCall->CallIndex() &&
           mActiveCall->ServiceId() == aCall->ServiceId());
 }
 
-already_AddRefed<TelephonyCall>
+already_AddRefed<Promise>
 Telephony::DialInternal(uint32_t aServiceId, const nsAString& aNumber,
-                        bool aIsEmergency, ErrorResult& aRv)
+                        bool aIsEmergency)
 {
+  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
+  if (!global) {
+    return nullptr;
+  }
+
+  nsRefPtr<Promise> promise = new Promise(global);
+
   if (!IsValidNumber(aNumber) || !IsValidServiceId(aServiceId)) {
-    aRv.Throw(NS_ERROR_INVALID_ARG);
-    return nullptr;
+    promise->MaybeReject(NS_LITERAL_STRING("InvalidAccessError"));
+    return promise.forget();
   }
 
   // We only support one outgoing call at a time.
   if (HasDialingCall()) {
-    NS_WARNING("Only permitted to dial one call at a time!");
-    aRv.Throw(NS_ERROR_NOT_AVAILABLE);
-    return nullptr;
-  }
-
-  nsresult rv = mProvider->Dial(aServiceId, aNumber, aIsEmergency);
-  if (NS_FAILED(rv)) {
-    aRv.Throw(rv);
-    return nullptr;
+    promise->MaybeReject(NS_LITERAL_STRING("InvalidStateError"));
+    return promise.forget();
   }
 
-  nsRefPtr<TelephonyCall> call = CreateNewDialingCall(aServiceId, aNumber);
-
-  // Notify other telephony objects that we just dialed.
-  for (uint32_t i = 0; i < gTelephonyList->Length(); i++) {
-    Telephony*& telephony = gTelephonyList->ElementAt(i);
-    if (telephony != this) {
-      nsRefPtr<Telephony> kungFuDeathGrip = telephony;
-      telephony->NoteDialedCallFromOtherInstance(aServiceId, aNumber);
-    }
+  nsCOMPtr<nsITelephonyCallback> callback =
+    new Callback(this, promise, aServiceId, aNumber);
+  nsresult rv = mProvider->Dial(aServiceId, aNumber, aIsEmergency, callback);
+  if (NS_FAILED(rv)) {
+    promise->MaybeReject(NS_LITERAL_STRING("InvalidStateError"));
+    return promise.forget();
   }
 
-  return call.forget();
+  return promise.forget();
 }
 
 already_AddRefed<TelephonyCall>
 Telephony::CreateNewDialingCall(uint32_t aServiceId, const nsAString& aNumber)
 {
   nsRefPtr<TelephonyCall> call =
     TelephonyCall::Create(this, aServiceId, aNumber,
                           nsITelephonyProvider::CALL_STATE_DIALING);
   NS_ASSERTION(call, "This should never fail!");
 
   NS_ASSERTION(mCalls.Contains(call), "Should have auto-added new call!");
 
   return call.forget();
 }
 
-void
-Telephony::NoteDialedCallFromOtherInstance(uint32_t aServiceId,
-                                           const nsAString& aNumber)
-{
-  // We don't need to hang on to this call object, it is held alive by mCalls.
-  nsRefPtr<TelephonyCall> call = CreateNewDialingCall(aServiceId, aNumber);
-}
-
 nsresult
 Telephony::NotifyCallsChanged(TelephonyCall* aCall)
 {
   return DispatchCallEvent(NS_LITERAL_STRING("callschanged"), aCall);
 }
 
 void
 Telephony::UpdateActiveCall(TelephonyCall* aCall, bool aIsActive)
@@ -377,36 +404,35 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(Telephony)
 NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
 
 NS_IMPL_ADDREF_INHERITED(Telephony, nsDOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(Telephony, nsDOMEventTargetHelper)
 
 NS_IMPL_ISUPPORTS1(Telephony::Listener, nsITelephonyListener)
+NS_IMPL_ISUPPORTS1(Telephony::Callback, nsITelephonyCallback)
 
 // Telephony WebIDL
 
-already_AddRefed<TelephonyCall>
-Telephony::Dial(const nsAString& aNumber, const Optional<uint32_t>& aServiceId,
-                ErrorResult& aRv)
+already_AddRefed<Promise>
+Telephony::Dial(const nsAString& aNumber, const Optional<uint32_t>& aServiceId)
 {
   uint32_t serviceId = ProvidedOrDefaultServiceId(aServiceId);
-  nsRefPtr<TelephonyCall> call = DialInternal(serviceId, aNumber, false, aRv);
-  return call.forget();
+  nsRefPtr<Promise> promise = DialInternal(serviceId, aNumber, false);
+  return promise.forget();
 }
 
-already_AddRefed<TelephonyCall>
+already_AddRefed<Promise>
 Telephony::DialEmergency(const nsAString& aNumber,
-                         const Optional<uint32_t>& aServiceId,
-                         ErrorResult& aRv)
+                         const Optional<uint32_t>& aServiceId)
 {
   uint32_t serviceId = ProvidedOrDefaultServiceId(aServiceId);
-  nsRefPtr<TelephonyCall> call = DialInternal(serviceId, aNumber, true, aRv);
-  return call.forget();
+  nsRefPtr<Promise> promise = DialInternal(serviceId, aNumber, true);
+  return promise.forget();
 }
 
 void
 Telephony::StartTone(const nsAString& aDTMFChar,
                      const Optional<uint32_t>& aServiceId,
                      ErrorResult& aRv)
 {
   uint32_t serviceId = ProvidedOrDefaultServiceId(aServiceId);
@@ -639,17 +665,17 @@ Telephony::EnumerateCallState(uint32_t a
 }
 
 NS_IMETHODIMP
 Telephony::SupplementaryServiceNotification(uint32_t aServiceId,
                                             int32_t aCallIndex,
                                             uint16_t aNotification)
 {
   nsRefPtr<TelephonyCall> associatedCall;
-  if (!mCalls.IsEmpty() && aCallIndex != -1) {
+  if (!mCalls.IsEmpty()) {
     associatedCall = GetCall(aServiceId, aCallIndex);
   }
 
   nsresult rv;
   switch (aNotification) {
     case nsITelephonyProvider::NOTIFICATION_REMOTE_HELD:
       rv = DispatchCallEvent(NS_LITERAL_STRING("remoteheld"), associatedCall);
       break;
@@ -670,21 +696,17 @@ Telephony::NotifyError(uint32_t aService
                        int32_t aCallIndex,
                        const nsAString& aError)
 {
   if (mCalls.IsEmpty()) {
     NS_ERROR("No existing call!");
     return NS_ERROR_UNEXPECTED;
   }
 
-  nsRefPtr<TelephonyCall> callToNotify;
-
-  callToNotify = (aCallIndex == -1) ? GetOutgoingCall()
-                                    : GetCall(aServiceId, aCallIndex);
-
+  nsRefPtr<TelephonyCall> callToNotify = GetCall(aServiceId, aCallIndex);
   if (!callToNotify) {
     NS_ERROR("Don't call me with a bad call index!");
     return NS_ERROR_UNEXPECTED;
   }
 
   UpdateActiveCall(callToNotify, false);
 
   // Set the call state to 'disconnected' and remove it from the calls list.
--- a/dom/telephony/Telephony.h
+++ b/dom/telephony/Telephony.h
@@ -3,16 +3,17 @@
 /* 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_telephony_telephony_h__
 #define mozilla_dom_telephony_telephony_h__
 
 #include "mozilla/dom/BindingDeclarations.h"
+#include "mozilla/dom/Promise.h"
 #include "mozilla/dom/telephony/TelephonyCommon.h"
 
 #include "nsITelephonyProvider.h"
 
 // Need to include TelephonyCall.h because we have inline methods that
 // assume they see the definition of TelephonyCall.
 #include "TelephonyCall.h"
 
@@ -29,16 +30,19 @@ class Telephony MOZ_FINAL : public nsDOM
    * Class Telephony doesn't actually inherit nsITelephonyListener.
    * Instead, it owns an nsITelephonyListener derived instance mListener
    * and passes it to nsITelephonyProvider. The onreceived events are first
    * delivered to mListener and then forwarded to its owner, Telephony. See
    * also bug 775997 comment #51.
    */
   class Listener;
 
+  class Callback;
+  friend class Callback;
+
   class EnumerationAck;
   friend class EnumerationAck;
 
   nsCOMPtr<nsITelephonyProvider> mProvider;
   nsRefPtr<Listener> mListener;
 
   TelephonyCall* mActiveCall;
   nsTArray<nsRefPtr<TelephonyCall> > mCalls;
@@ -61,23 +65,21 @@ public:
     return GetOwner();
   }
 
   // WrapperCache
   virtual JSObject*
   WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 
   // WebIDL
-  already_AddRefed<TelephonyCall>
-  Dial(const nsAString& aNumber, const Optional<uint32_t>& aServiceId,
-       ErrorResult& aRv);
+  already_AddRefed<Promise>
+  Dial(const nsAString& aNumber, const Optional<uint32_t>& aServiceId);
 
-  already_AddRefed<TelephonyCall>
-  DialEmergency(const nsAString& aNumber, const Optional<uint32_t>& aServiceId,
-                ErrorResult& aRv);
+  already_AddRefed<Promise>
+  DialEmergency(const nsAString& aNumber, const Optional<uint32_t>& aServiceId);
 
   void
   StartTone(const nsAString& aDTMFChar, const Optional<uint32_t>& aServiceId,
             ErrorResult& aRv);
 
   void
   StopTone(const Optional<uint32_t>& aServiceId, ErrorResult& aRv);
 
@@ -165,27 +167,22 @@ private:
   ProvidedOrDefaultServiceId(const Optional<uint32_t>& aServiceId);
 
   bool
   HasDialingCall();
 
   bool
   MatchActiveCall(TelephonyCall* aCall);
 
-  already_AddRefed<TelephonyCall>
-  DialInternal(uint32_t aServiceId, const nsAString& aNumber,
-               bool isEmergency, ErrorResult& aRv);
+  already_AddRefed<Promise>
+  DialInternal(uint32_t aServiceId, const nsAString& aNumber, bool isEmergency);
 
   already_AddRefed<TelephonyCall>
   CreateNewDialingCall(uint32_t aServiceId, const nsAString& aNumber);
 
-  void
-  NoteDialedCallFromOtherInstance(uint32_t aServiceId,
-                                  const nsAString& aNumber);
-
   nsresult
   NotifyCallsChanged(TelephonyCall* aCall);
 
   nsresult
   DispatchCallEvent(const nsAString& aType, TelephonyCall* aCall);
 
   void
   EnqueueEnumerationAck();