Bug 969218 - Part 4: dom r=khuey
☠☠ backed out by 677c0fa83472 ☠ ☠
authorSzu-Yu Chen [:aknow] <szchen@mozilla.com>
Wed, 26 Feb 2014 11:03:56 -0800
changeset 171157 75219ceb5175014a94b6a8a767981f1ddb8dd1a9
parent 171156 b9f4ba525eec6122aa1f9c61b3ac51942e33069d
child 171158 46fa16a18c2775c5a72a1bd7aecbbdaebae897a2
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
reviewerskhuey
bugs969218
milestone30.0a1
Bug 969218 - Part 4: 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,48 @@ 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);
+  }
+
+  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 +108,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 +262,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<nsPIDOMWindow> window = GetOwner();
+  if (!window) {
+    return nullptr;
+  }
+
+  nsRefPtr<Promise> promise = new Promise(window);
+
   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 +398,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 +659,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 +690,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();