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 155703 5726180e4834d83a9eed9f4d3bd6bcfccfe8a281
parent 155702 3ba26923ca3ff0f1f81df846c0f8ac6553448074
child 155704 3af6bb32ac84aadd0403e91ee50c12ff5d7db425
push id407
push userlsblakk@mozilla.com
push dateTue, 03 Dec 2013 03:32:50 +0000
treeherdermozilla-release@babf8c9ebc52 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssicking, bent
bugs888592
milestone26.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 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',