Bug 888592 - move Telephony and TelephonyCall to webidl. sr=sicking, r=bent
authorHsin-Yi Tsai <htsai@mozilla.com>
Mon, 15 Jul 2013 16:27:19 +0800
changeset 141876 5726180e4834d83a9eed9f4d3bd6bcfccfe8a281
parent 141875 3ba26923ca3ff0f1f81df846c0f8ac6553448074
child 141877 3af6bb32ac84aadd0403e91ee50c12ff5d7db425
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewerssicking, bent
bugs888592
milestone26.0a1
Bug 888592 - move Telephony and TelephonyCall to webidl. sr=sicking, r=bent
dom/base/Navigator.cpp
dom/base/Navigator.h
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfoClasses.h
dom/bindings/Bindings.conf
dom/permission/tests/test_telephony.html
dom/telephony/CallEvent.cpp
dom/telephony/CallEvent.h
dom/telephony/CallsList.cpp
dom/telephony/CallsList.h
dom/telephony/Telephony.cpp
dom/telephony/Telephony.h
dom/telephony/TelephonyCall.cpp
dom/telephony/TelephonyCall.h
dom/telephony/TelephonyCommon.h
dom/telephony/moz.build
dom/telephony/nsIDOMCallEvent.idl
dom/telephony/nsIDOMTelephony.idl
dom/telephony/nsIDOMTelephonyCall.idl
dom/webidl/CallEvent.webidl
dom/webidl/CallsList.webidl
dom/webidl/Navigator.webidl
dom/webidl/Telephony.webidl
dom/webidl/TelephonyCall.webidl
dom/webidl/WebIDL.mk
js/xpconnect/src/event_impl_gen.conf.in
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -1135,17 +1135,17 @@ Navigator::GetMozCellBroadcast(ErrorResu
     if (aRv.Failed()) {
       return nullptr;
     }
   }
 
   return mCellBroadcast;
 }
 
-nsIDOMTelephony*
+telephony::Telephony*
 Navigator::GetMozTelephony(ErrorResult& aRv)
 {
   if (!mTelephony) {
     if (!mWindow) {
       aRv.Throw(NS_ERROR_UNEXPECTED);
       return nullptr;
     }
     mTelephony = telephony::Telephony::Create(mWindow, aRv);
--- a/dom/base/Navigator.h
+++ b/dom/base/Navigator.h
@@ -28,17 +28,16 @@ class systemMessageCallback;
 }
 }
 
 #ifdef MOZ_MEDIA_NAVIGATOR
 #include "nsIDOMNavigatorUserMedia.h"
 #endif
 
 #ifdef MOZ_B2G_RIL
-class nsIDOMTelephony;
 class nsIDOMMozMobileConnection;
 class nsIDOMMozCellBroadcast;
 class nsIDOMMozVoicemail;
 class nsIDOMMozIccManager;
 #endif // MOZ_B2G_RIL
 
 #ifdef MOZ_B2G_BT
 class nsIDOMBluetoothManager;
@@ -81,16 +80,22 @@ class IccManager;
 
 namespace network {
 class Connection;
 #ifdef MOZ_B2G_RIL
 class MobileConnection;
 #endif
 } // namespace Connection;
 
+#ifdef MOZ_B2G_RIL
+namespace telephony {
+class Telephony;
+} // namespace Telephony;
+#endif
+
 namespace power {
 class PowerManager;
 } // namespace power
 
 namespace time {
 class TimeManager;
 } // namespace time
 
@@ -209,17 +214,17 @@ public:
   nsIDOMMozMobileMessageManager* GetMozMobileMessage();
   nsIDOMMozConnection* GetMozConnection();
   nsDOMCameraManager* GetMozCameras(ErrorResult& aRv);
   void MozSetMessageHandler(const nsAString& aType,
                             systemMessageCallback* aCallback,
                             ErrorResult& aRv);
   bool MozHasPendingMessage(const nsAString& aType, ErrorResult& aRv);
 #ifdef MOZ_B2G_RIL
-  nsIDOMTelephony* GetMozTelephony(ErrorResult& aRv);
+  telephony::Telephony* GetMozTelephony(ErrorResult& aRv);
   nsIDOMMozMobileConnection* GetMozMobileConnection(ErrorResult& aRv);
   nsIDOMMozCellBroadcast* GetMozCellBroadcast(ErrorResult& aRv);
   nsIDOMMozVoicemail* GetMozVoicemail(ErrorResult& aRv);
   nsIDOMMozIccManager* GetMozIccManager(ErrorResult& aRv);
 #endif // MOZ_B2G_RIL
 #ifdef MOZ_GAMEPAD
   void GetGamepads(nsTArray<nsRefPtr<Gamepad> >& aGamepads, ErrorResult& aRv);
 #endif // MOZ_GAMEPAD
@@ -304,17 +309,17 @@ private:
   nsRefPtr<nsMimeTypeArray> mMimeTypes;
   nsRefPtr<nsPluginArray> mPlugins;
   nsRefPtr<Geolocation> mGeolocation;
   nsRefPtr<DesktopNotificationCenter> mNotification;
   nsRefPtr<battery::BatteryManager> mBatteryManager;
   nsRefPtr<power::PowerManager> mPowerManager;
   nsRefPtr<MobileMessageManager> mMobileMessageManager;
 #ifdef MOZ_B2G_RIL
-  nsCOMPtr<nsIDOMTelephony> mTelephony;
+  nsRefPtr<telephony::Telephony> mTelephony;
   nsCOMPtr<nsIDOMMozVoicemail> mVoicemail;
 #endif
   nsRefPtr<network::Connection> mConnection;
 #ifdef MOZ_B2G_RIL
   nsRefPtr<network::MobileConnection> mMobileConnection;
   nsCOMPtr<nsIDOMMozCellBroadcast> mCellBroadcast;
   nsRefPtr<icc::IccManager> mIccManager;
 #endif
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -220,18 +220,16 @@ using mozilla::dom::workers::ResolveWork
 #include "nsIDOMMozSmsMessage.h"
 #include "nsIDOMMozMmsMessage.h"
 #include "nsIDOMSmsFilter.h"
 #include "nsIDOMSmsSegmentInfo.h"
 #include "nsIDOMMozMobileMessageThread.h"
 #include "nsIDOMConnection.h"
 
 #ifdef MOZ_B2G_RIL
-#include "Telephony.h"
-#include "TelephonyCall.h"
 #include "nsIDOMMozVoicemail.h"
 #include "nsIDOMIccManager.h"
 #include "nsIDOMMozCellBroadcast.h"
 #include "nsIDOMMobileConnection.h"
 #endif // MOZ_B2G_RIL
 
 #ifdef MOZ_B2G_FM
 #include "FMRadio.h"
@@ -635,20 +633,16 @@ static nsDOMClassInfoData sClassInfoData
 
   NS_DEFINE_CLASSINFO_DATA(CSSPageRule, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(MediaQueryList, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
 #ifdef MOZ_B2G_RIL
-  NS_DEFINE_CLASSINFO_DATA(Telephony, nsEventTargetSH,
-                           EVENTTARGET_SCRIPTABLE_FLAGS)
-  NS_DEFINE_CLASSINFO_DATA(TelephonyCall, nsEventTargetSH,
-                           EVENTTARGET_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(MozVoicemail, nsEventTargetSH,
                            EVENTTARGET_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(MozIccManager, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 #endif
 
 #ifdef MOZ_B2G_FM
   NS_DEFINE_CLASSINFO_DATA(FMRadio, nsEventTargetSH,
@@ -1524,25 +1518,16 @@ nsDOMClassInfo::Init()
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSPageRule)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(MediaQueryList, nsIDOMMediaQueryList)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMMediaQueryList)
   DOM_CLASSINFO_MAP_END
 
 #ifdef MOZ_B2G_RIL
-  DOM_CLASSINFO_MAP_BEGIN(Telephony, nsIDOMTelephony)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMTelephony)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
-  DOM_CLASSINFO_MAP_END
-
-  DOM_CLASSINFO_MAP_BEGIN(TelephonyCall, nsIDOMTelephonyCall)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMTelephonyCall)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
-  DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(MozVoicemail, nsIDOMMozVoicemail)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozVoicemail)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(MozIccManager, nsIDOMMozIccManager)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozIccManager)
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -123,18 +123,16 @@ DOMCI_CLASS(IDBKeyRange)
 DOMCI_CLASS(MozCSSKeyframeRule)
 DOMCI_CLASS(MozCSSKeyframesRule)
 
 DOMCI_CLASS(CSSPageRule)
 
 DOMCI_CLASS(MediaQueryList)
 
 #ifdef MOZ_B2G_RIL
-DOMCI_CLASS(Telephony)
-DOMCI_CLASS(TelephonyCall)
 DOMCI_CLASS(MozVoicemail)
 DOMCI_CLASS(MozIccManager)
 #endif
 
 #ifdef MOZ_B2G_FM
 DOMCI_CLASS(FMRadio)
 #endif
 
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -145,16 +145,26 @@ DOMInterfaces = {
     'workers': True,
 }],
 
 'BatteryManager': {
     'nativeType': 'mozilla::dom::battery::BatteryManager',
     'headerFile': 'BatteryManager.h'
 },
 
+'CallEvent': {
+    'nativeType': 'mozilla::dom::telephony::CallEvent',
+    'headerFile': 'CallEvent.h',
+},
+
+'CallsList': {
+    'nativeType': 'mozilla::dom::telephony::CallsList',
+    'headerFile': 'CallsList.h',
+},
+
 'CameraManager': {
     'nativeType': 'nsDOMCameraManager',
     'headerFile': 'DOMCameraManager.h'
 },
 
 'CanvasRenderingContext2D': {
     'implicitJSContext': [
         'createImageData', 'getImageData', 'mozDash'
@@ -1113,16 +1123,26 @@ DOMInterfaces = {
 'SVGUnitTypes' : {
     'concrete': False,
 },
 
 'SVGZoomAndPan' : {
     'concrete': False,
 },
 
+'Telephony' : {
+    'nativeType': 'mozilla::dom::telephony::Telephony',
+    'headerFile': 'Telephony.h',
+},
+
+'TelephonyCall' : {
+    'nativeType': 'mozilla::dom::telephony::TelephonyCall',
+    'headerFile': 'TelephonyCall.h',
+},
+
 'Text': {
     # Total hack to allow binding code to realize that nsTextNode can
     # in fact be cast to Text.
     'headerFile': 'nsTextNode.h',
 },
 
 'TextDecoder': [
 {
--- a/dom/permission/tests/test_telephony.html
+++ b/dom/permission/tests/test_telephony.html
@@ -17,16 +17,16 @@ https://bugzilla.mozilla.org/show_bug.cg
 <script type="application/javascript;version=1.8" src="file_framework.js"></script>
 <script type="application/javascript;version=1.8">
 
 var gData = [
   {
     perm: ["telephony"],
     needParentPerm: true,
     obj: "mozTelephony",
-    idl: "nsIDOMTelephony",
+    webidl: "Telephony",
   },
 ]
 </script>
 </pre>
 </body>
 </html>
 
new file mode 100644
--- /dev/null
+++ b/dom/telephony/CallEvent.cpp
@@ -0,0 +1,73 @@
+/* -*- 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 "CallEvent.h"
+#include "mozilla/dom/CallEventBinding.h"
+
+#include "TelephonyCall.h"
+
+USING_TELEPHONY_NAMESPACE
+using namespace mozilla::dom;
+
+/* static */
+already_AddRefed<CallEvent>
+CallEvent::Create(EventTarget* aOwner, const nsAString& aType,
+                  TelephonyCall* aCall, bool aCanBubble,
+                  bool aCancelable)
+{
+  nsRefPtr<CallEvent> event = new CallEvent(aOwner, nullptr, nullptr);
+  event->mCall = aCall;
+  event->InitEvent(aType, aCanBubble, aCancelable);
+  return event.forget();
+}
+
+JSObject*
+CallEvent::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
+{
+  return CallEventBinding::Wrap(aCx, aScope, this);
+}
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(CallEvent)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(CallEvent, nsDOMEvent)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mCall)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(CallEvent, nsDOMEvent)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCall)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_ADDREF_INHERITED(CallEvent, nsDOMEvent)
+NS_IMPL_RELEASE_INHERITED(CallEvent, nsDOMEvent)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(CallEvent)
+NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent)
+
+// WebIDL
+
+/* static */
+already_AddRefed<CallEvent>
+CallEvent::Constructor(const GlobalObject& aGlobal, const nsAString& aType,
+                       const CallEventInit& aOptions, ErrorResult& aRv)
+{
+  nsCOMPtr<EventTarget> target = do_QueryInterface(aGlobal.Get());
+
+  if (!target) {
+    aRv.Throw(NS_ERROR_UNEXPECTED);
+    return nullptr;
+  }
+
+  nsRefPtr<CallEvent> event = Create(target, aType, aOptions.mCall, false, false);
+
+  return event.forget();
+}
+
+already_AddRefed<TelephonyCall>
+CallEvent::GetCall() const
+{
+  nsRefPtr<TelephonyCall> call = mCall;
+  return call.forget();
+}
new file mode 100644
--- /dev/null
+++ b/dom/telephony/CallEvent.h
@@ -0,0 +1,61 @@
+/* -*- 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/. */
+
+#ifndef mozilla_dom_telephony_callevent_h
+#define mozilla_dom_telephony_callevent_h
+
+#include "TelephonyCommon.h"
+
+#include "nsDOMEvent.h"
+
+namespace mozilla {
+namespace dom {
+struct CallEventInit;
+}
+}
+
+BEGIN_TELEPHONY_NAMESPACE
+
+class CallEvent MOZ_FINAL : public nsDOMEvent
+{
+  nsRefPtr<TelephonyCall> mCall;
+
+public:
+  NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(CallEvent, nsDOMEvent)
+  NS_FORWARD_TO_NSDOMEVENT
+
+  virtual JSObject*
+  WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
+
+  // WebIDL
+  static already_AddRefed<CallEvent>
+  Constructor(const GlobalObject& aGlobal, const nsAString& aType,
+              const CallEventInit& aOptions, ErrorResult& aRv);
+
+  already_AddRefed<TelephonyCall>
+  GetCall() const;
+
+  static already_AddRefed<CallEvent>
+  Create(EventTarget* aOwner, const nsAString& aType, TelephonyCall* aCall,
+         bool aCanBubble, bool aCancelable);
+
+private:
+  CallEvent(EventTarget* aOwner,
+            nsPresContext* aPresContext,
+            nsEvent* aEvent)
+  : nsDOMEvent(aOwner, aPresContext, aEvent)
+  {
+    SetIsDOMBinding();
+  }
+
+  virtual ~CallEvent()
+  { }
+};
+
+END_TELEPHONY_NAMESPACE
+
+#endif // mozilla_dom_telephony_callevent_h
new file mode 100644
--- /dev/null
+++ b/dom/telephony/CallsList.cpp
@@ -0,0 +1,69 @@
+/* -*- 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 "CallsList.h"
+#include "mozilla/dom/CallsListBinding.h"
+
+#include "Telephony.h"
+#include "TelephonyCall.h"
+
+USING_TELEPHONY_NAMESPACE
+using namespace mozilla::dom;
+
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(CallsList, mTelephony)
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(CallsList)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(CallsList)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CallsList)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
+  NS_INTERFACE_MAP_ENTRY(nsISupports)
+NS_INTERFACE_MAP_END
+
+CallsList::CallsList(Telephony* aTelephony)
+: mTelephony(aTelephony)
+{
+  MOZ_ASSERT(mTelephony);
+
+  SetIsDOMBinding();
+}
+
+CallsList::~CallsList()
+{
+}
+
+nsPIDOMWindow*
+CallsList::GetParentObject() const
+{
+  return mTelephony->GetOwner();
+}
+
+JSObject*
+CallsList::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
+{
+  return CallsListBinding::Wrap(aCx, aScope, this);
+}
+
+already_AddRefed<TelephonyCall>
+CallsList::Item(uint32_t aIndex) const
+{
+  nsRefPtr<TelephonyCall> call = mTelephony->CallsArray().SafeElementAt(aIndex);
+  return call.forget();
+}
+
+uint32_t
+CallsList::Length() const
+{
+  return mTelephony->CallsArray().Length();
+}
+
+already_AddRefed<TelephonyCall>
+CallsList::IndexedGetter(uint32_t aIndex, bool& aFound) const
+{
+  nsRefPtr<TelephonyCall> call = mTelephony->CallsArray().SafeElementAt(aIndex);
+  aFound = call ? true : false;
+  return call.forget();
+}
new file mode 100644
--- /dev/null
+++ b/dom/telephony/CallsList.h
@@ -0,0 +1,50 @@
+/* -*- 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/. */
+
+#ifndef mozilla_dom_telephony_CallsList_h__
+#define mozilla_dom_telephony_CallsList_h__
+
+#include "TelephonyCommon.h"
+
+#include "nsWrapperCache.h"
+
+BEGIN_TELEPHONY_NAMESPACE
+
+class CallsList MOZ_FINAL : public nsISupports,
+                            public nsWrapperCache
+{
+  nsRefPtr<Telephony> mTelephony;
+
+public:
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(CallsList)
+
+  CallsList(Telephony* aTelephony);
+
+  nsPIDOMWindow*
+  GetParentObject() const;
+
+  // WrapperCache
+  virtual JSObject*
+  WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
+
+  // CallsList WebIDL
+  already_AddRefed<TelephonyCall>
+  Item(uint32_t aIndex) const;
+
+  uint32_t
+  Length() const;
+
+  already_AddRefed<TelephonyCall>
+  IndexedGetter(uint32_t aIndex, bool& aFound) const;
+
+private:
+  ~CallsList();
+};
+
+END_TELEPHONY_NAMESPACE
+
+#endif // mozilla_dom_telephony_CallsList_h__
--- a/dom/telephony/Telephony.cpp
+++ b/dom/telephony/Telephony.cpp
@@ -1,32 +1,31 @@
 /* -*- 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 "nsIURI.h"
-#include "nsIDOMCallEvent.h"
 #include "nsPIDOMWindow.h"
 #include "nsIPermissionManager.h"
 
-#include "GeneratedEvents.h"
-#include "jsapi.h"
 #include "nsCharSeparatedTokenizer.h"
 #include "nsContentUtils.h"
 #include "nsCxPusher.h"
-#include "nsDOMClassInfo.h"
 #include "nsNetUtil.h"
 #include "nsServiceManagerUtils.h"
 #include "nsTArrayHelpers.h"
 #include "nsThreadUtils.h"
 
+#include "CallEvent.h"
+#include "CallsList.h"
 #include "TelephonyCall.h"
 
 #define NS_RILCONTENTHELPER_CONTRACTID "@mozilla.org/ril/content-helper;1"
 
 USING_TELEPHONY_NAMESPACE
 using namespace mozilla::dom;
 
 namespace {
@@ -73,53 +72,55 @@ public:
   NS_IMETHOD Run()
   {
     mTelephony->NotifyCallsChanged(nullptr);
     return NS_OK;
   }
 };
 
 Telephony::Telephony()
-: mActiveCall(nullptr), mCallsArray(nullptr), mRooted(false),
-  mEnumerated(false)
+: mActiveCall(nullptr), mEnumerated(false)
 {
   if (!gTelephonyList) {
     gTelephonyList = new TelephonyList();
   }
 
   gTelephonyList->AppendElement(this);
+
+  SetIsDOMBinding();
 }
 
 Telephony::~Telephony()
 {
   if (mListener) {
     mListener->Disconnect();
 
     if (mProvider) {
       mProvider->UnregisterTelephonyMsg(mListener);
     }
   }
 
-  if (mRooted) {
-    mCallsArray = nullptr;
-    NS_DROP_JS_OBJECTS(this, Telephony);
-  }
-
   NS_ASSERTION(gTelephonyList, "This should never be null!");
   NS_ASSERTION(gTelephonyList->Contains(this), "Should be in the list!");
 
   if (gTelephonyList->Length() == 1) {
     delete gTelephonyList;
     gTelephonyList = nullptr;
   }
   else {
     gTelephonyList->RemoveElement(this);
   }
 }
 
+JSObject*
+Telephony::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
+{
+  return TelephonyBinding::Wrap(aCx, aScope, this);
+}
+
 // static
 already_AddRefed<Telephony>
 Telephony::Create(nsPIDOMWindow* aOwner, ErrorResult& aRv)
 {
   NS_ASSERTION(aOwner, "Null owner!");
 
   nsCOMPtr<nsITelephonyProvider> ril =
     do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
@@ -141,16 +142,17 @@ Telephony::Create(nsPIDOMWindow* aOwner,
   }
 
   nsRefPtr<Telephony> telephony = new Telephony();
 
   telephony->BindToOwner(aOwner);
 
   telephony->mProvider = ril;
   telephony->mListener = new Listener(telephony);
+  telephony->mCallsList = new CallsList(telephony);
 
   nsresult rv = ril->EnumerateCalls(telephony->mListener);
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return nullptr;
   }
 
   rv = ril->RegisterTelephonyMsg(telephony->mListener);
@@ -194,216 +196,168 @@ Telephony::NotifyCallsChanged(TelephonyC
     } else if (mActiveCall && mActiveCall->CallIndex() == aCall->CallIndex()) {
       mActiveCall = nullptr;
     }
   }
 
   return DispatchCallEvent(NS_LITERAL_STRING("callschanged"), aCall);
 }
 
-nsresult
+already_AddRefed<TelephonyCall>
 Telephony::DialInternal(bool isEmergency,
                         const nsAString& aNumber,
-                        nsIDOMTelephonyCall** aResult)
+                        ErrorResult& aRv)
 {
-  NS_ENSURE_ARG(!aNumber.IsEmpty());
+  if (aNumber.IsEmpty()) {
+    aRv.Throw(NS_ERROR_INVALID_ARG);
+    return nullptr;
+  }
 
   for (uint32_t index = 0; index < mCalls.Length(); index++) {
     const nsRefPtr<TelephonyCall>& tempCall = mCalls[index];
     if (tempCall->IsOutgoing() &&
         tempCall->CallState() < nsITelephonyProvider::CALL_STATE_CONNECTED) {
       // One call has been dialed already and we only support one outgoing call
       // at a time.
       NS_WARNING("Only permitted to dial one call at a time!");
-      return NS_ERROR_NOT_AVAILABLE;
+      aRv.Throw(NS_ERROR_NOT_AVAILABLE);
+      return nullptr;
     }
   }
 
   nsresult rv;
   if (isEmergency) {
     rv = mProvider->DialEmergency(aNumber);
   } else {
     rv = mProvider->Dial(aNumber);
   }
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_FAILED(rv)) {
+    aRv.Throw(rv);
+    return nullptr;
+  }
 
   nsRefPtr<TelephonyCall> call = CreateNewDialingCall(aNumber);
 
   // Notify other telephony objects that we just dialed.
   for (uint32_t index = 0; index < gTelephonyList->Length(); index++) {
     Telephony*& telephony = gTelephonyList->ElementAt(index);
     if (telephony != this) {
       nsRefPtr<Telephony> kungFuDeathGrip = telephony;
       telephony->NoteDialedCallFromOtherInstance(aNumber);
     }
   }
 
-  call.forget(aResult);
-  return NS_OK;
+  return call.forget();
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(Telephony)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(Telephony,
                                                   nsDOMEventTargetHelper)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
-  for (uint32_t index = 0; index < tmp->mCalls.Length(); index++) {
-    NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mCalls[i]");
-    cb.NoteXPCOMChild(tmp->mCalls[index]->ToISupports());
-  }
-  // Don't traverse mListener because it doesn't keep any reference to
-  // Telephony but a raw pointer instead.
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCalls)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCallsList)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
-NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(Telephony,
-                                               nsDOMEventTargetHelper)
-  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mCallsArray)
-NS_IMPL_CYCLE_COLLECTION_TRACE_END
-
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(Telephony,
                                                 nsDOMEventTargetHelper)
-  tmp->mCalls.Clear();
   tmp->mActiveCall = nullptr;
-  tmp->mCallsArray = nullptr;
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mCalls)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mCallsList)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(Telephony)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMTelephony)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Telephony)
 NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
 
 NS_IMPL_ADDREF_INHERITED(Telephony, nsDOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(Telephony, nsDOMEventTargetHelper)
 
-DOMCI_DATA(Telephony, Telephony)
-
 NS_IMPL_ISUPPORTS1(Telephony::Listener, nsITelephonyListener)
 
-// nsIDOMTelephony
+// Telephony WebIDL
 
-NS_IMETHODIMP
-Telephony::Dial(const nsAString& aNumber, nsIDOMTelephonyCall** aResult)
+already_AddRefed<TelephonyCall>
+Telephony::Dial(const nsAString& aNumber, ErrorResult& aRv)
 {
-  DialInternal(false, aNumber, aResult);
-
-  return NS_OK;
+  nsRefPtr<TelephonyCall> call = DialInternal(false, aNumber, aRv);
+  return call.forget();
 }
 
-NS_IMETHODIMP
-Telephony::DialEmergency(const nsAString& aNumber, nsIDOMTelephonyCall** aResult)
+already_AddRefed<TelephonyCall>
+Telephony::DialEmergency(const nsAString& aNumber, ErrorResult& aRv)
 {
-  DialInternal(true, aNumber, aResult);
-
-  return NS_OK;
+  nsRefPtr<TelephonyCall> call = DialInternal(true, aNumber, aRv);
+  return call.forget();
 }
 
-NS_IMETHODIMP
-Telephony::GetMuted(bool* aMuted)
+bool
+Telephony::GetMuted(ErrorResult& aRv) const
 {
-  nsresult rv = mProvider->GetMicrophoneMuted(aMuted);
-  NS_ENSURE_SUCCESS(rv, rv);
+  bool muted = false;
+  aRv = mProvider->GetMicrophoneMuted(&muted);
 
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-Telephony::SetMuted(bool aMuted)
-{
-  nsresult rv = mProvider->SetMicrophoneMuted(aMuted);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return NS_OK;
+  return muted;
 }
 
-NS_IMETHODIMP
-Telephony::GetSpeakerEnabled(bool* aSpeakerEnabled)
+void
+Telephony::SetMuted(bool aMuted, ErrorResult& aRv)
 {
-  nsresult rv = mProvider->GetSpeakerEnabled(aSpeakerEnabled);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return NS_OK;
+  aRv = mProvider->SetMicrophoneMuted(aMuted);
 }
 
-NS_IMETHODIMP
-Telephony::SetSpeakerEnabled(bool aSpeakerEnabled)
+bool
+Telephony::GetSpeakerEnabled(ErrorResult& aRv) const
 {
-  nsresult rv = mProvider->SetSpeakerEnabled(aSpeakerEnabled);
-  NS_ENSURE_SUCCESS(rv, rv);
+  bool enabled = false;
+  aRv = mProvider->GetSpeakerEnabled(&enabled);
 
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-Telephony::GetActive(nsIDOMTelephonyCall** aActive)
-{
-  nsCOMPtr<nsIDOMTelephonyCall> activeCall = mActiveCall;
-  activeCall.forget(aActive);
-  return NS_OK;
+  return enabled;
 }
 
-NS_IMETHODIMP
-Telephony::GetCalls(JS::Value* aCalls)
+void
+Telephony::SetSpeakerEnabled(bool aEnabled, ErrorResult& aRv)
 {
-  JSObject* calls = mCallsArray;
-  if (!calls) {
-    nsresult rv;
-    nsIScriptContext* sc = GetContextForEventHandlers(&rv);
-    NS_ENSURE_SUCCESS(rv, rv);
-    AutoPushJSContext cx(sc ? sc->GetNativeContext() : nullptr);
-    if (sc) {
-      rv = nsTArrayToJSArray(cx, mCalls, &calls);
-      NS_ENSURE_SUCCESS(rv, rv);
-
-      if (!mRooted) {
-        NS_HOLD_JS_OBJECTS(this, Telephony);
-        mRooted = true;
-      }
-
-      mCallsArray = calls;
-    } else {
-      NS_ENSURE_SUCCESS(rv, rv);
-    }
-  }
-
-  aCalls->setObject(*calls);
-  return NS_OK;
+  aRv = mProvider->SetSpeakerEnabled(aEnabled);
 }
 
-NS_IMETHODIMP
-Telephony::StartTone(const nsAString& aDTMFChar)
+already_AddRefed<TelephonyCall>
+Telephony::GetActive() const
+{
+  nsCOMPtr<TelephonyCall> activeCall = mActiveCall;
+  return activeCall.forget();
+}
+
+already_AddRefed<CallsList>
+Telephony::Calls() const
+{
+  nsRefPtr<CallsList> list = mCallsList;
+  return list.forget();
+}
+
+void
+Telephony::StartTone(const nsAString& aDTMFChar, ErrorResult& aRv)
 {
   if (aDTMFChar.IsEmpty()) {
     NS_WARNING("Empty tone string will be ignored");
-    return NS_OK;
+    return;
   }
 
   if (aDTMFChar.Length() > 1) {
-    return NS_ERROR_INVALID_ARG;
+    aRv.Throw(NS_ERROR_INVALID_ARG);
+    return;
   }
 
-  nsresult rv = mProvider->StartTone(aDTMFChar);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return NS_OK;
+  aRv = mProvider->StartTone(aDTMFChar);
 }
 
-NS_IMETHODIMP
-Telephony::StopTone()
+void
+Telephony::StopTone(ErrorResult& aRv)
 {
-  nsresult rv = mProvider->StopTone();
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return NS_OK;
+  aRv = mProvider->StopTone();
 }
 
-NS_IMPL_EVENT_HANDLER(Telephony, incoming)
-NS_IMPL_EVENT_HANDLER(Telephony, callschanged)
-NS_IMPL_EVENT_HANDLER(Telephony, remoteheld)
-NS_IMPL_EVENT_HANDLER(Telephony, remoteresumed)
-
 // EventTarget
 
 void
 Telephony::EventListenerAdded(nsIAtom* aType)
 {
   if (aType == nsGkAtoms::oncallschanged) {
     // Fire oncallschanged on the next tick if the calls array is ready.
     EnqueueEnumerationAck();
@@ -595,36 +549,29 @@ Telephony::NotifyError(int32_t aCallInde
   // Set the call state to 'disconnected' and remove it from the calls list.
   callToNotify->NotifyError(aError);
 
   return NS_OK;
 }
 
 nsresult
 Telephony::DispatchCallEvent(const nsAString& aType,
-                             nsIDOMTelephonyCall* aCall)
+                             TelephonyCall* aCall)
 {
   // The call may be null in following cases:
   //   1. callschanged when notifying enumeration being completed
   //   2. remoteheld/remoteresumed.
   MOZ_ASSERT(aCall ||
              aType.EqualsLiteral("callschanged") ||
              aType.EqualsLiteral("remoteheld") ||
              aType.EqualsLiteral("remtoeresumed"));
 
-  nsCOMPtr<nsIDOMEvent> event;
-  NS_NewDOMCallEvent(getter_AddRefs(event), this, nullptr, nullptr);
-  NS_ASSERTION(event, "This should never fail!");
+  nsRefPtr<CallEvent> event = CallEvent::Create(this, aType, aCall, false, false);
 
-  nsCOMPtr<nsIDOMCallEvent> callEvent = do_QueryInterface(event);
-  MOZ_ASSERT(callEvent);
-  nsresult rv = callEvent->InitCallEvent(aType, false, false, aCall);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return DispatchTrustedEvent(callEvent);
+  return DispatchTrustedEvent(event);
 }
 
 void
 Telephony::EnqueueEnumerationAck()
 {
   if (!mEnumerated) {
     return;
   }
--- a/dom/telephony/Telephony.h
+++ b/dom/telephony/Telephony.h
@@ -7,27 +7,23 @@
 #ifndef mozilla_dom_telephony_telephony_h__
 #define mozilla_dom_telephony_telephony_h__
 
 #include "TelephonyCommon.h"
 // Need to include TelephonyCall.h because we have inline methods that
 // assume they see the definition of TelephonyCall.
 #include "TelephonyCall.h"
 
-#include "nsIDOMTelephony.h"
-#include "nsIDOMTelephonyCall.h"
 #include "nsITelephonyProvider.h"
 
-class nsIScriptContext;
 class nsPIDOMWindow;
 
 BEGIN_TELEPHONY_NAMESPACE
 
-class Telephony : public nsDOMEventTargetHelper,
-                  public nsIDOMTelephony
+class Telephony MOZ_FINAL : public nsDOMEventTargetHelper
 {
   /**
    * 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.
    */
@@ -36,91 +32,129 @@ class Telephony : public nsDOMEventTarge
   class EnumerationAck;
   friend class EnumerationAck;
 
   nsCOMPtr<nsITelephonyProvider> mProvider;
   nsRefPtr<Listener> mListener;
 
   TelephonyCall* mActiveCall;
   nsTArray<nsRefPtr<TelephonyCall> > mCalls;
+  nsRefPtr<CallsList> mCallsList;
 
-  // Cached calls array object. Cleared whenever mCalls changes and then rebuilt
-  // once a page looks for the liveCalls attribute.
-  JS::Heap<JSObject*> mCallsArray;
-
-  bool mRooted;
   bool mEnumerated;
 
 public:
   NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_NSIDOMTELEPHONY
   NS_DECL_NSITELEPHONYLISTENER
   NS_REALLY_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper)
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(
-                                                   Telephony,
-                                                   nsDOMEventTargetHelper)
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(Telephony,
+                                           nsDOMEventTargetHelper)
+
+  nsPIDOMWindow*
+  GetParentObject() const
+  {
+    return GetOwner();
+  }
+
+  // WrapperCache
+  virtual JSObject*
+  WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
+
+  // WebIDL
+  already_AddRefed<TelephonyCall>
+  Dial(const nsAString& aNumber, ErrorResult& aRv);
+
+  already_AddRefed<TelephonyCall>
+  DialEmergency(const nsAString& aNumber, ErrorResult& aRv);
+
+  bool
+  GetMuted(ErrorResult& aRv) const;
+
+  void
+  SetMuted(bool aMuted, ErrorResult& aRv);
+
+  bool
+  GetSpeakerEnabled(ErrorResult& aRv) const;
+
+  void
+  SetSpeakerEnabled(bool aEnabled, ErrorResult& aRv);
+
+  already_AddRefed<TelephonyCall>
+  GetActive() const;
+
+  already_AddRefed<CallsList>
+  Calls() const;
+
+  void
+  StartTone(const nsAString& aDTMF, ErrorResult& aRv);
+
+  void
+  StopTone(ErrorResult& aRv);
+
+  IMPL_EVENT_HANDLER(incoming)
+  IMPL_EVENT_HANDLER(callschanged)
+  IMPL_EVENT_HANDLER(remoteheld)
+  IMPL_EVENT_HANDLER(remoteresumed)
 
   static already_AddRefed<Telephony>
   Create(nsPIDOMWindow* aOwner, ErrorResult& aRv);
 
   static bool CheckPermission(nsPIDOMWindow* aOwner);
 
-  nsISupports*
-  ToISupports()
-  {
-    return static_cast<EventTarget*>(this);
-  }
-
   void
   AddCall(TelephonyCall* aCall)
   {
     NS_ASSERTION(!mCalls.Contains(aCall), "Already know about this one!");
     mCalls.AppendElement(aCall);
-    mCallsArray = nullptr;
     NotifyCallsChanged(aCall);
   }
 
   void
   RemoveCall(TelephonyCall* aCall)
   {
     NS_ASSERTION(mCalls.Contains(aCall), "Didn't know about this one!");
     mCalls.RemoveElement(aCall);
-    mCallsArray = nullptr;
     NotifyCallsChanged(aCall);
   }
 
   nsITelephonyProvider*
   Provider() const
   {
     return mProvider;
   }
 
+  const nsTArray<nsRefPtr<TelephonyCall> >&
+  CallsArray() const
+  {
+    return mCalls;
+  }
+
   virtual void EventListenerAdded(nsIAtom* aType) MOZ_OVERRIDE;
 
 private:
   Telephony();
   ~Telephony();
 
   already_AddRefed<TelephonyCall>
   CreateNewDialingCall(const nsAString& aNumber);
 
   void
   NoteDialedCallFromOtherInstance(const nsAString& aNumber);
 
   nsresult
   NotifyCallsChanged(TelephonyCall* aCall);
 
-  nsresult
+  already_AddRefed<TelephonyCall>
   DialInternal(bool isEmergency,
                const nsAString& aNumber,
-               nsIDOMTelephonyCall** aResult);
+               ErrorResult& aRv);
 
   nsresult
   DispatchCallEvent(const nsAString& aType,
-                    nsIDOMTelephonyCall* aCall);
+                    TelephonyCall* aCall);
 
   void
   EnqueueEnumerationAck();
 };
 
 END_TELEPHONY_NAMESPACE
 
 #endif // mozilla_dom_telephony_telephony_h__
--- a/dom/telephony/TelephonyCall.cpp
+++ b/dom/telephony/TelephonyCall.cpp
@@ -1,25 +1,24 @@
 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
 /* vim: set ts=2 et sw=2 tw=40: */
 /* 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 "TelephonyCall.h"
-
-#include "nsIDOMCallEvent.h"
+#include "mozilla/dom/TelephonyCallBinding.h"
 
 #include "mozilla/dom/DOMError.h"
-#include "GeneratedEvents.h"
-#include "nsDOMClassInfo.h"
+
+#include "CallEvent.h"
 #include "Telephony.h"
-#include "nsITelephonyProvider.h"
 
 USING_TELEPHONY_NAMESPACE
+using namespace mozilla::dom;
 
 // static
 already_AddRefed<TelephonyCall>
 TelephonyCall::Create(Telephony* aTelephony, const nsAString& aNumber,
                       uint16_t aCallState, uint32_t aCallIndex, bool aEmergency)
 {
   NS_ASSERTION(aTelephony, "Null pointer!");
   NS_ASSERTION(!aNumber.IsEmpty(), "Empty number!");
@@ -41,16 +40,27 @@ TelephonyCall::Create(Telephony* aTeleph
 }
 
 TelephonyCall::TelephonyCall()
   : mCallIndex(kOutgoingPlaceholderCallIndex),
     mCallState(nsITelephonyProvider::CALL_STATE_UNKNOWN),
     mLive(false),
     mOutgoing(false)
 {
+  SetIsDOMBinding();
+}
+
+TelephonyCall::~TelephonyCall()
+{
+}
+
+JSObject*
+TelephonyCall::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
+{
+  return TelephonyCallBinding::Wrap(aCx, aScope, this);
 }
 
 void
 TelephonyCall::ChangeStateInternal(uint16_t aCallState, bool aFireEvents)
 {
   nsRefPtr<TelephonyCall> kungFuDeathGrip(this);
 
   nsString stateString;
@@ -119,30 +129,23 @@ TelephonyCall::ChangeStateInternal(uint1
         NS_WARNING("Failed to dispatch specific event!");
       }
     }
   }
 }
 
 nsresult
 TelephonyCall::DispatchCallEvent(const nsAString& aType,
-                                 nsIDOMTelephonyCall* aCall)
+                                 TelephonyCall* aCall)
 {
   MOZ_ASSERT(aCall);
 
-  nsCOMPtr<nsIDOMEvent> event;
-  NS_NewDOMCallEvent(getter_AddRefs(event), this, nullptr, nullptr);
-  NS_ASSERTION(event, "This should never fail!");
+  nsRefPtr<CallEvent> event = CallEvent::Create(this, aType, aCall, false, false);
 
-  nsCOMPtr<nsIDOMCallEvent> callEvent = do_QueryInterface(event);
-  MOZ_ASSERT(callEvent);
-  nsresult rv = callEvent->InitCallEvent(aType, false, false, aCall);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return DispatchTrustedEvent(callEvent);
+  return DispatchTrustedEvent(event);
 }
 
 void
 TelephonyCall::NotifyError(const nsAString& aError)
 {
   // Set the error string
   NS_ASSERTION(!mError, "Already have an error?");
 
@@ -158,119 +161,92 @@ TelephonyCall::NotifyError(const nsAStri
 }
 
 NS_IMPL_CYCLE_COLLECTION_INHERITED_2(TelephonyCall,
                                      nsDOMEventTargetHelper,
                                      mTelephony,
                                      mError);
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TelephonyCall)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMTelephonyCall)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(TelephonyCall)
 NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
 
 NS_IMPL_ADDREF_INHERITED(TelephonyCall, nsDOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(TelephonyCall, nsDOMEventTargetHelper)
 
-DOMCI_DATA(TelephonyCall, TelephonyCall)
+// TelephonyCall WebIDL
 
-NS_IMETHODIMP
-TelephonyCall::GetNumber(nsAString& aNumber)
+already_AddRefed<DOMError>
+TelephonyCall::GetError() const
 {
-  aNumber.Assign(mNumber);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-TelephonyCall::GetState(nsAString& aState)
-{
-  aState.Assign(mState);
-  return NS_OK;
+  nsRefPtr<DOMError> error = mError;
+  return error.forget();
 }
 
-NS_IMETHODIMP
-TelephonyCall::GetEmergency(bool* aEmergency)
-{
-  *aEmergency = mEmergency;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-TelephonyCall::GetError(nsISupports** aError)
-{
-  NS_IF_ADDREF(*aError = mError);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-TelephonyCall::Answer()
+void
+TelephonyCall::Answer(ErrorResult& aRv)
 {
   if (mCallState != nsITelephonyProvider::CALL_STATE_INCOMING) {
     NS_WARNING("Answer on non-incoming call ignored!");
-    return NS_OK;
+    return;
   }
 
   nsresult rv = mTelephony->Provider()->AnswerCall(mCallIndex);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_FAILED(rv)) {
+    aRv.Throw(rv);
+    return;
+  }
 
   ChangeStateInternal(nsITelephonyProvider::CALL_STATE_CONNECTING, true);
-  return NS_OK;
 }
 
-NS_IMETHODIMP
-TelephonyCall::HangUp()
+void
+TelephonyCall::HangUp(ErrorResult& aRv)
 {
   if (mCallState == nsITelephonyProvider::CALL_STATE_DISCONNECTING ||
       mCallState == nsITelephonyProvider::CALL_STATE_DISCONNECTED) {
     NS_WARNING("HangUp on previously disconnected call ignored!");
-    return NS_OK;
+    return;
   }
 
   nsresult rv = mCallState == nsITelephonyProvider::CALL_STATE_INCOMING ?
                 mTelephony->Provider()->RejectCall(mCallIndex) :
                 mTelephony->Provider()->HangUp(mCallIndex);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_FAILED(rv)) {
+    aRv.Throw(rv);
+    return;
+  }
 
   ChangeStateInternal(nsITelephonyProvider::CALL_STATE_DISCONNECTING, true);
-  return NS_OK;
 }
 
-NS_IMETHODIMP
-TelephonyCall::Hold()
+void
+TelephonyCall::Hold(ErrorResult& aRv)
 {
   if (mCallState != nsITelephonyProvider::CALL_STATE_CONNECTED) {
     NS_WARNING("Hold non-connected call ignored!");
-    return NS_OK;
+    return;
   }
 
   nsresult rv = mTelephony->Provider()->HoldCall(mCallIndex);
-  NS_ENSURE_SUCCESS(rv,rv);
+  if (NS_FAILED(rv)) {
+    aRv.Throw(rv);
+    return;
+  }
 
   ChangeStateInternal(nsITelephonyProvider::CALL_STATE_HOLDING, true);
-  return NS_OK;
 }
 
-NS_IMETHODIMP
-TelephonyCall::Resume()
+void
+TelephonyCall::Resume(ErrorResult& aRv)
 {
   if (mCallState != nsITelephonyProvider::CALL_STATE_HELD) {
     NS_WARNING("Resume non-held call ignored!");
-    return NS_OK;
+    return;
   }
 
   nsresult rv = mTelephony->Provider()->ResumeCall(mCallIndex);
-  NS_ENSURE_SUCCESS(rv,rv);
+  if (NS_FAILED(rv)) {
+    aRv.Throw(rv);
+    return;
+  }
 
   ChangeStateInternal(nsITelephonyProvider::CALL_STATE_RESUMING, true);
-  return NS_OK;
 }
-
-NS_IMPL_EVENT_HANDLER(TelephonyCall, statechange)
-NS_IMPL_EVENT_HANDLER(TelephonyCall, dialing)
-NS_IMPL_EVENT_HANDLER(TelephonyCall, alerting)
-NS_IMPL_EVENT_HANDLER(TelephonyCall, connecting)
-NS_IMPL_EVENT_HANDLER(TelephonyCall, connected)
-NS_IMPL_EVENT_HANDLER(TelephonyCall, disconnecting)
-NS_IMPL_EVENT_HANDLER(TelephonyCall, disconnected)
-NS_IMPL_EVENT_HANDLER(TelephonyCall, holding)
-NS_IMPL_EVENT_HANDLER(TelephonyCall, held)
-NS_IMPL_EVENT_HANDLER(TelephonyCall, resuming)
-NS_IMPL_EVENT_HANDLER(TelephonyCall, error)
--- a/dom/telephony/TelephonyCall.h
+++ b/dom/telephony/TelephonyCall.h
@@ -4,56 +4,103 @@
  * 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_telephonycall_h__
 #define mozilla_dom_telephony_telephonycall_h__
 
 #include "TelephonyCommon.h"
 
-#include "nsIDOMTelephonyCall.h"
 #include "mozilla/dom/DOMError.h"
 
 class nsPIDOMWindow;
 
 BEGIN_TELEPHONY_NAMESPACE
 
-class TelephonyCall : public nsDOMEventTargetHelper,
-                      public nsIDOMTelephonyCall
+class TelephonyCall MOZ_FINAL : public nsDOMEventTargetHelper
 {
   nsRefPtr<Telephony> mTelephony;
 
   nsString mNumber;
   nsString mState;
   bool mEmergency;
   nsRefPtr<mozilla::dom::DOMError> mError;
 
   uint32_t mCallIndex;
   uint16_t mCallState;
   bool mLive;
   bool mOutgoing;
 
 public:
   NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_NSIDOMTELEPHONYCALL
   NS_REALLY_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper)
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(TelephonyCall,
                                            nsDOMEventTargetHelper)
 
+  nsPIDOMWindow*
+  GetParentObject() const
+  {
+    return GetOwner();
+  }
+
+  // WrapperCache
+  virtual JSObject*
+  WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
+
+  // WebIDL
+  void
+  GetNumber(nsString& aNumber) const
+  {
+    aNumber.Assign(mNumber);
+  }
+
+  void
+  GetState(nsString& aState) const
+  {
+    aState.Assign(mState);
+  }
+
+  bool
+  Emergency() const
+  {
+    return mEmergency;
+  }
+
+  already_AddRefed<DOMError>
+  GetError() const;
+
+  void
+  Answer(ErrorResult& aRv);
+
+  void
+  HangUp(ErrorResult& aRv);
+
+  void
+  Hold(ErrorResult& aRv);
+
+  void
+  Resume(ErrorResult& aRv);
+
+  IMPL_EVENT_HANDLER(statechange)
+  IMPL_EVENT_HANDLER(dialing)
+  IMPL_EVENT_HANDLER(alerting)
+  IMPL_EVENT_HANDLER(connecting)
+  IMPL_EVENT_HANDLER(connected)
+  IMPL_EVENT_HANDLER(disconnecting)
+  IMPL_EVENT_HANDLER(disconnected)
+  IMPL_EVENT_HANDLER(holding)
+  IMPL_EVENT_HANDLER(held)
+  IMPL_EVENT_HANDLER(resuming)
+  IMPL_EVENT_HANDLER(error)
+
   static already_AddRefed<TelephonyCall>
   Create(Telephony* aTelephony, const nsAString& aNumber, uint16_t aCallState,
          uint32_t aCallIndex = kOutgoingPlaceholderCallIndex,
          bool aEmergency = false);
 
-  nsISupports*
-  ToISupports()
-  {
-    return static_cast<EventTarget*>(this);
-  }
-
   void
   ChangeState(uint16_t aCallState)
   {
     ChangeStateInternal(aCallState, true);
   }
 
   uint32_t
   CallIndex() const
@@ -88,22 +135,21 @@ public:
   }
 
   void
   NotifyError(const nsAString& aError);
 
 private:
   TelephonyCall();
 
-  ~TelephonyCall()
-  { }
+  ~TelephonyCall();
 
   void
   ChangeStateInternal(uint16_t aCallState, bool aFireEvents);
 
   nsresult
   DispatchCallEvent(const nsAString& aType,
-                    nsIDOMTelephonyCall* aCall);
+                    TelephonyCall* aCall);
 };
 
 END_TELEPHONY_NAMESPACE
 
 #endif // mozilla_dom_telephony_telephonycall_h__
--- a/dom/telephony/TelephonyCommon.h
+++ b/dom/telephony/TelephonyCommon.h
@@ -2,38 +2,38 @@
 /* vim: set ts=2 et sw=2 tw=40: */
 /* 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_telephonycommon_h__
 #define mozilla_dom_telephony_telephonycommon_h__
 
+#include "mozilla/Attributes.h"
+#include "mozilla/ErrorResult.h"
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsDebug.h"
 #include "nsDOMEventTargetHelper.h"
 #include "nsStringGlue.h"
 #include "nsTArray.h"
 
 #define BEGIN_TELEPHONY_NAMESPACE \
   namespace mozilla { namespace dom { namespace telephony {
 #define END_TELEPHONY_NAMESPACE \
   } /* namespace telephony */ } /* namespace dom */ } /* namespace mozilla */
 #define USING_TELEPHONY_NAMESPACE \
   using namespace mozilla::dom::telephony;
 
-class nsIDOMTelephony;
-class nsIDOMTelephonyCall;
-
 BEGIN_TELEPHONY_NAMESPACE
 
 enum {
   kOutgoingPlaceholderCallIndex = UINT32_MAX
 };
 
+class CallsList;
 class Telephony;
 class TelephonyCall;
 
 END_TELEPHONY_NAMESPACE
 
 #endif // mozilla_dom_telephony_telephonycommon_h__
--- a/dom/telephony/moz.build
+++ b/dom/telephony/moz.build
@@ -1,28 +1,27 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 XPIDL_SOURCES += [
-    'nsIDOMCallEvent.idl',
-    'nsIDOMTelephony.idl',
-    'nsIDOMTelephonyCall.idl',
     'nsITelephonyProvider.idl',
 ]
 
 XPIDL_MODULE = 'dom_telephony'
 
 XPIDL_FLAGS += [
     '-I$(topsrcdir)/dom/base',
     '-I$(topsrcdir)/dom/interfaces/base',
     '-I$(topsrcdir)/dom/interfaces/events',
 ]
 
 MODULE = 'dom'
 
 CPP_SOURCES += [
+    'CallEvent.cpp',
+    'CallsList.cpp',
     'Telephony.cpp',
     'TelephonyCall.cpp',
 ]
 
deleted file mode 100644
--- a/dom/telephony/nsIDOMCallEvent.idl
+++ /dev/null
@@ -1,24 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=40: */
-/* 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 "nsIDOMEvent.idl"
-
-interface nsIDOMTelephonyCall;
-
-[scriptable, builtinclass, uuid(476aacec-661e-44ec-80b4-4b7292b927b5)]
-interface nsIDOMCallEvent : nsIDOMEvent
-{
-  readonly attribute nsIDOMTelephonyCall call;
-  [noscript] void initCallEvent(in DOMString aType,
-                                in boolean aCanBubble,
-                                in boolean aCancelable,
-                                in nsIDOMTelephonyCall aCall);
-};
-
-dictionary CallEventInit : EventInit
-{
-  nsIDOMTelephonyCall call;
-};
deleted file mode 100644
--- a/dom/telephony/nsIDOMTelephony.idl
+++ /dev/null
@@ -1,35 +0,0 @@
-/* -*- Mode: IDL; 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 "nsIDOMEventTarget.idl"
-
-interface nsIDOMEventListener;
-interface nsIDOMTelephonyCall;
-
-[scriptable, builtinclass, uuid(5ad8bf8b-958c-447b-9e1a-e6cf598b680f)]
-interface nsIDOMTelephony : nsIDOMEventTarget
-{
-  nsIDOMTelephonyCall dial(in DOMString number);
-  nsIDOMTelephonyCall dialEmergency(in DOMString number);
-
-  attribute boolean muted;
-  attribute boolean speakerEnabled;
-
-  // The call that is "active", i.e. receives microphone input and tones
-  // generated via startTone.
-  readonly attribute nsIDOMTelephonyCall active;
-
-  // Array of all calls that are currently connected.
-  readonly attribute jsval calls;
-
-  void startTone(in DOMString tone);
-  void stopTone();
-
-  [implicit_jscontext] attribute jsval onincoming;
-  [implicit_jscontext] attribute jsval oncallschanged;
-  [implicit_jscontext] attribute jsval onremoteheld;
-  [implicit_jscontext] attribute jsval onremoteresumed;
-};
deleted file mode 100644
--- a/dom/telephony/nsIDOMTelephonyCall.idl
+++ /dev/null
@@ -1,44 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=40: */
-/* 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 "nsIDOMEventTarget.idl"
-
-interface nsIDOMEventListener;
-
-[scriptable, builtinclass, uuid(74d240f5-a379-4ac0-a085-a7f714189a27)]
-interface nsIDOMTelephonyCall : nsIDOMEventTarget
-{
-  readonly attribute DOMString number;
-
-  readonly attribute DOMString state;
-
-  // The property "emergency" indicate whether the call number is an emergency
-  // number. Only the outgoing call could have a value with true and it is
-  // available after dialing state.
-  readonly attribute boolean emergency;
-
-  // This is a DOMError
-  readonly attribute nsISupports error;
-
-  void answer();
-  void hangUp();
-  void hold();
-  void resume();
-
-  [implicit_jscontext] attribute jsval onstatechange;
-
-  [implicit_jscontext] attribute jsval ondialing;
-  [implicit_jscontext] attribute jsval onalerting;
-  [implicit_jscontext] attribute jsval onconnecting;
-  [implicit_jscontext] attribute jsval onconnected;
-  [implicit_jscontext] attribute jsval ondisconnecting;
-  [implicit_jscontext] attribute jsval ondisconnected;
-  [implicit_jscontext] attribute jsval onholding;
-  [implicit_jscontext] attribute jsval onheld;
-  [implicit_jscontext] attribute jsval onresuming;
-
-  [implicit_jscontext] attribute jsval onerror;
-};
--- a/dom/webidl/CallEvent.webidl
+++ b/dom/webidl/CallEvent.webidl
@@ -1,16 +1,15 @@
 /* -*- Mode: IDL; 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/.
  */
-interface TelephonyCall;
 
-[Constructor(DOMString type, optional CallEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"]
+[Constructor(DOMString type, optional CallEventInit eventInitDict)]
 interface CallEvent : Event
 {
   readonly attribute TelephonyCall? call;
 };
 
 dictionary CallEventInit : EventInit
 {
   TelephonyCall? call = null;
new file mode 100644
--- /dev/null
+++ b/dom/webidl/CallsList.webidl
@@ -0,0 +1,11 @@
+/* -*- Mode: IDL; 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/.
+ */
+
+[ArrayClass, NoInterfaceObject]
+interface CallsList {
+  getter TelephonyCall item(unsigned long index);
+  readonly attribute unsigned long length;
+};
--- a/dom/webidl/Navigator.webidl
+++ b/dom/webidl/Navigator.webidl
@@ -247,21 +247,19 @@ callback systemMessageCallback = void (o
 partial interface Navigator {
   [Throws, Pref="dom.sysmsg.enabled"]
   void    mozSetMessageHandler (DOMString type, systemMessageCallback? callback);
   [Throws, Pref="dom.sysmsg.enabled"]
   boolean mozHasPendingMessage (DOMString type);
 };
 
 #ifdef MOZ_B2G_RIL
-interface MozTelephony;
-// nsIDOMNavigatorTelephony
 partial interface Navigator {
   [Throws, Func="Navigator::HasTelephonySupport"]
-  readonly attribute MozTelephony? mozTelephony;
+  readonly attribute Telephony? mozTelephony;
 };
 
 // nsIMozNavigatorMobileConnection
 interface MozMobileConnection;
 partial interface Navigator {
   [Throws, Func="Navigator::HasMobileConnectionSupport"]
   readonly attribute MozMobileConnection mozMobileConnection;
 };
new file mode 100644
--- /dev/null
+++ b/dom/webidl/Telephony.webidl
@@ -0,0 +1,35 @@
+/* -*- Mode: IDL; 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/.
+ */
+
+interface Telephony : EventTarget {
+  [Throws]
+  TelephonyCall dial(DOMString number);
+  [Throws]
+  TelephonyCall dialEmergency(DOMString number);
+
+  [Throws]
+  attribute boolean muted;
+  [Throws]
+  attribute boolean speakerEnabled;
+
+  readonly attribute TelephonyCall? active;
+
+  readonly attribute CallsList calls;
+
+  [Throws]
+  void startTone(DOMString tone);
+  [Throws]
+  void stopTone();
+
+  [SetterThrows]
+  attribute EventHandler onincoming;
+  [SetterThrows]
+  attribute EventHandler oncallschanged;
+  [SetterThrows]
+  attribute EventHandler onremoteheld;
+  [SetterThrows]
+  attribute EventHandler onremoteresumed;
+};
new file mode 100644
--- /dev/null
+++ b/dom/webidl/TelephonyCall.webidl
@@ -0,0 +1,50 @@
+/* -*- Mode: IDL; 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/.
+ */
+
+interface TelephonyCall : EventTarget {
+  readonly attribute DOMString number;
+
+  readonly attribute DOMString state;
+
+  // The property "emergency" indicates whether the call number is an emergency
+  // number. Only the outgoing call could have a value with true and it is
+  // available after dialing state.
+  readonly attribute boolean emergency;
+
+  readonly attribute DOMError? error;
+
+  [Throws]
+  void answer();
+  [Throws]
+  void hangUp();
+  [Throws]
+  void hold();
+  [Throws]
+  void resume();
+
+  [SetterThrows]
+  attribute EventHandler onstatechange;
+  [SetterThrows]
+  attribute EventHandler ondialing;
+  [SetterThrows]
+  attribute EventHandler onalerting;
+  [SetterThrows]
+  attribute EventHandler onconnecting;
+  [SetterThrows]
+  attribute EventHandler onconnected;
+  [SetterThrows]
+  attribute EventHandler ondisconnecting;
+  [SetterThrows]
+  attribute EventHandler ondisconnected;
+  [SetterThrows]
+  attribute EventHandler onholding;
+  [SetterThrows]
+  attribute EventHandler onheld;
+  [SetterThrows]
+  attribute EventHandler onresuming;
+  [SetterThrows]
+  attribute EventHandler onerror;
+};
--- a/dom/webidl/WebIDL.mk
+++ b/dom/webidl/WebIDL.mk
@@ -432,17 +432,20 @@ endif
 ifdef MOZ_GAMEPAD
 webidl_files += \
   Gamepad.webidl \
   $(NULL)
 endif
 
 ifdef MOZ_B2G_RIL
 webidl_files += \
+  CallsList.webidl \
   MozStkCommandEvent.webidl \
+  Telephony.webidl \
+  TelephonyCall.webidl \
   $(NULL)
 endif
 
 webidl_files += \
   BlobEvent.webidl \
   CloseEvent.webidl \
   CustomEvent.webidl \
   DeviceLightEvent.webidl \
--- a/js/xpconnect/src/event_impl_gen.conf.in
+++ b/js/xpconnect/src/event_impl_gen.conf.in
@@ -27,17 +27,16 @@ simple_events = [
     'StyleRuleChangeEvent',
     'StyleSheetChangeEvent',
     'StyleSheetApplicableStateChangeEvent',
 #ifdef MOZ_B2G_BT
     'BluetoothDeviceEvent',
     'BluetoothStatusChangedEvent',
 #endif
 #ifdef MOZ_B2G_RIL
-    'CallEvent',
     'CFStateChangeEvent',
     'DataErrorEvent',
     'IccCardLockErrorEvent',
     'MozWifiStatusChangeEvent',
     'MozWifiConnectionInfoEvent',
     'MozCellBroadcastEvent',
     'MozVoicemailEvent',
     'USSDReceivedEvent',