Bug 1057170 - Update MediaKey* Uint8Arrays to be ArrayBuffer. r=bz
authorChris Pearce <cpearce@mozilla.com>
Wed, 27 Aug 2014 20:46:56 +1200
changeset 223565 f505272bac5043b5e84d9217c1822ce1d82d2b7c
parent 223564 bae66f96bbd6da29f331108ba0fc39b7cb406362
child 223566 f73be78d1cca07f5e303064447d572d28e70140b
push id3979
push userraliiev@mozilla.com
push dateMon, 13 Oct 2014 16:35:44 +0000
treeherdermozilla-beta@30f2cc610691 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs1057170
milestone34.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 1057170 - Update MediaKey* Uint8Arrays to be ArrayBuffer. r=bz
content/media/eme/CDMProxy.cpp
content/media/eme/CDMProxy.h
content/media/eme/MediaEncryptedEvent.cpp
content/media/eme/MediaKeyMessageEvent.cpp
content/media/eme/MediaKeySession.cpp
content/media/eme/MediaKeySession.h
content/media/eme/MediaKeys.cpp
content/media/eme/MediaKeys.h
dom/webidl/MediaEncryptedEvent.webidl
dom/webidl/MediaKeyMessageEvent.webidl
dom/webidl/MediaKeySession.webidl
dom/webidl/MediaKeys.webidl
--- a/content/media/eme/CDMProxy.cpp
+++ b/content/media/eme/CDMProxy.cpp
@@ -109,26 +109,26 @@ CDMProxy::OnCDMCreated(uint32_t aPromise
   }
   mKeys->OnCDMCreated(aPromiseId);
 }
 
 void
 CDMProxy::CreateSession(dom::SessionType aSessionType,
                         PromiseId aPromiseId,
                         const nsAString& aInitDataType,
-                        const Uint8Array& aInitData)
+                        nsTArray<uint8_t>& aInitData)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mGMPThread);
 
   nsAutoPtr<CreateSessionData> data(new CreateSessionData());
   data->mSessionType = aSessionType;
   data->mPromiseId = aPromiseId;
   data->mInitDataType = NS_ConvertUTF16toUTF8(aInitDataType);
-  data->mInitData.AppendElements(aInitData.Data(), aInitData.Length());
+  data->mInitData = Move(aInitData);
 
   nsRefPtr<nsIRunnable> task(
     NS_NewRunnableMethodWithArg<nsAutoPtr<CreateSessionData>>(this, &CDMProxy::gmp_CreateSession, data));
   mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
 }
 
 GMPSessionType
 ToGMPSessionType(dom::SessionType aSessionType) {
@@ -177,24 +177,24 @@ CDMProxy::gmp_LoadSession(nsAutoPtr<Sess
     RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
   mCDM->LoadSession(aData->mPromiseId, aData->mSessionId);
 }
 
 void
 CDMProxy::SetServerCertificate(PromiseId aPromiseId,
-                               const Uint8Array& aCert)
+                               nsTArray<uint8_t>& aCert)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mGMPThread);
 
   nsAutoPtr<SetServerCertificateData> data;
   data->mPromiseId = aPromiseId;
-  data->mCert.AppendElements(aCert.Data(), aCert.Length());
+  data->mCert = Move(aCert);
   nsRefPtr<nsIRunnable> task(
     NS_NewRunnableMethodWithArg<nsAutoPtr<SetServerCertificateData>>(this, &CDMProxy::gmp_SetServerCertificate, data));
   mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
 }
 
 void
 CDMProxy::gmp_SetServerCertificate(nsAutoPtr<SetServerCertificateData> aData)
 {
@@ -204,26 +204,26 @@ CDMProxy::gmp_SetServerCertificate(nsAut
     return;
   }
   mCDM->SetServerCertificate(aData->mPromiseId, aData->mCert);
 }
 
 void
 CDMProxy::UpdateSession(const nsAString& aSessionId,
                         PromiseId aPromiseId,
-                        const Uint8Array& aResponse)
+                        nsTArray<uint8_t>& aResponse)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mGMPThread);
   NS_ENSURE_TRUE_VOID(!mKeys.IsNull());
 
   nsAutoPtr<UpdateSessionData> data(new UpdateSessionData());
   data->mPromiseId = aPromiseId;
   data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId);
-  data->mResponse.AppendElements(aResponse.Data(), aResponse.Length());
+  data->mResponse = Move(aResponse);
   nsRefPtr<nsIRunnable> task(
     NS_NewRunnableMethodWithArg<nsAutoPtr<UpdateSessionData>>(this, &CDMProxy::gmp_UpdateSession, data));
   mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
 }
 
 void
 CDMProxy::gmp_UpdateSession(nsAutoPtr<UpdateSessionData> aData)
 {
--- a/content/media/eme/CDMProxy.h
+++ b/content/media/eme/CDMProxy.h
@@ -5,17 +5,16 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef CDMProxy_h_
 #define CDMProxy_h_
 
 #include "nsString.h"
 #include "nsAutoPtr.h"
 #include "mozilla/dom/MediaKeys.h"
-#include "mozilla/dom/TypedArray.h"
 #include "mozilla/Monitor.h"
 #include "nsIThread.h"
 #include "GMPDecryptorProxy.h"
 #include "mozilla/CDMCaps.h"
 #include "mp4_demuxer/DecoderData.h"
 
 namespace mozilla {
 
@@ -34,60 +33,59 @@ public:
 
 // Proxies calls GMP/CDM, and proxies calls back.
 // Note: Promises are passed in via a PromiseId, so that the ID can be
 // passed via IPC to the CDM, which can then signal when to reject or
 // resolve the promise using its PromiseId.
 class CDMProxy {
   typedef dom::PromiseId PromiseId;
   typedef dom::SessionType SessionType;
-  typedef dom::Uint8Array Uint8Array;
 public:
 
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CDMProxy)
 
   // Main thread only.
   CDMProxy(dom::MediaKeys* aKeys, const nsAString& aKeySystem);
 
   // Main thread only.
   // Loads the CDM corresponding to mKeySystem.
   // Calls MediaKeys::OnCDMCreated() when the CDM is created.
   void Init(PromiseId aPromiseId);
 
   // Main thread only.
   // Uses the CDM to create a key session.
-  // Caller is responsible for calling aInitData.ComputeLengthAndData().
   // Calls MediaKeys::OnSessionActivated() when session is created.
+  // Assumes ownership of (Move()s) aInitData's contents.
   void CreateSession(dom::SessionType aSessionType,
                      PromiseId aPromiseId,
                      const nsAString& aInitDataType,
-                     const Uint8Array& aInitData);
+                     nsTArray<uint8_t>& aInitData);
 
   // Main thread only.
   // Uses the CDM to load a presistent session stored on disk.
   // Calls MediaKeys::OnSessionActivated() when session is loaded.
   void LoadSession(PromiseId aPromiseId,
                    const nsAString& aSessionId);
 
   // Main thread only.
   // Sends a new certificate to the CDM.
-  // Caller is responsible for calling aCert.ComputeLengthAndData().
   // Calls MediaKeys->ResolvePromise(aPromiseId) after the CDM has
   // processed the request.
+  // Assumes ownership of (Move()s) aCert's contents.
   void SetServerCertificate(PromiseId aPromiseId,
-                            const Uint8Array& aCert);
+                            nsTArray<uint8_t>& aCert);
 
   // Main thread only.
   // Sends an update to the CDM.
-  // Caller is responsible for calling aResponse.ComputeLengthAndData().
   // Calls MediaKeys->ResolvePromise(aPromiseId) after the CDM has
   // processed the request.
+  // Assumes ownership of (Move()s) aResponse's contents.
   void UpdateSession(const nsAString& aSessionId,
                      PromiseId aPromiseId,
-                     const Uint8Array& aResponse);
+                     nsTArray<uint8_t>& aResponse);
 
   // Main thread only.
   // Calls MediaKeys->ResolvePromise(aPromiseId) after the CDM has
   // processed the request.
   // If processing this operation results in the session actually closing,
   // we also call MediaKeySession::OnClosed(), which in turn calls
   // MediaKeys::OnSessionClosed().
   void CloseSession(const nsAString& aSessionId,
--- a/content/media/eme/MediaEncryptedEvent.cpp
+++ b/content/media/eme/MediaEncryptedEvent.cpp
@@ -4,16 +4,17 @@
  * 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 "MediaEncryptedEvent.h"
 #include "mozilla/dom/MediaEncryptedEventBinding.h"
 #include "nsContentUtils.h"
 #include "jsfriendapi.h"
 #include "nsINode.h"
+#include "mozilla/dom/MediaKeys.h"
 
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(MediaEncryptedEvent)
 
 NS_IMPL_ADDREF_INHERITED(MediaEncryptedEvent, Event)
 NS_IMPL_RELEASE_INHERITED(MediaEncryptedEvent, Event)
@@ -72,17 +73,19 @@ MediaEncryptedEvent::Constructor(const G
   nsCOMPtr<EventTarget> owner = do_QueryInterface(aGlobal.GetAsSupports());
   nsRefPtr<MediaEncryptedEvent> e = new MediaEncryptedEvent(owner);
   bool trusted = e->Init(owner);
   e->InitEvent(aType, aEventInitDict.mBubbles, aEventInitDict.mCancelable);
   e->mInitDataType = aEventInitDict.mInitDataType;
   if (!aEventInitDict.mInitData.IsNull()) {
     const auto& a = aEventInitDict.mInitData.Value();
     a.ComputeLengthAndData();
-    e->mInitData = Uint8Array::Create(aGlobal.Context(), owner, a.Length(), a.Data());
+    e->mInitData = ArrayBuffer::Create(aGlobal.Context(),
+                                       a.Length(),
+                                       a.Data());
     if (!e->mInitData) {
       aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
       return nullptr;
     }
   }
   e->SetTrusted(trusted);
   return e.forget();
 }
@@ -94,20 +97,19 @@ MediaEncryptedEvent::GetInitDataType(nsS
 }
 
 void
 MediaEncryptedEvent::GetInitData(JSContext* cx,
                                  JS::MutableHandle<JSObject*> aData,
                                  ErrorResult& aRv)
 {
   if (mRawInitData.Length()) {
-    mInitData = Uint8Array::Create(cx,
-                                   this,
-                                   mRawInitData.Length(),
-                                   mRawInitData.Elements());
+    mInitData = ArrayBuffer::Create(cx,
+                                    mRawInitData.Length(),
+                                    mRawInitData.Elements());
     if (!mInitData) {
       aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
       return;
     }
     mRawInitData.Clear();
   }
   if (mInitData) {
     JS::ExposeObjectToActiveJS(mInitData);
--- a/content/media/eme/MediaKeyMessageEvent.cpp
+++ b/content/media/eme/MediaKeyMessageEvent.cpp
@@ -8,16 +8,17 @@
 #include "mozilla/dom/MediaKeyMessageEventBinding.h"
 #include "js/GCAPI.h"
 #include "jsfriendapi.h"
 #include "mozilla/dom/Nullable.h"
 #include "mozilla/dom/PrimitiveConversions.h"
 #include "mozilla/HoldDropJSObjects.h"
 #include "mozilla/dom/TypedArray.h"
 #include "nsContentUtils.h"
+#include "mozilla/dom/MediaKeys.h"
 
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(MediaKeyMessageEvent)
 
 NS_IMPL_ADDREF_INHERITED(MediaKeyMessageEvent, Event)
 NS_IMPL_RELEASE_INHERITED(MediaKeyMessageEvent, Event)
@@ -78,42 +79,43 @@ MediaKeyMessageEvent::Constructor(const 
                                   const nsAString& aType,
                                   const MediaKeyMessageEventInit& aEventInitDict,
                                   ErrorResult& aRv)
 {
   nsCOMPtr<EventTarget> owner = do_QueryInterface(aGlobal.GetAsSupports());
   nsRefPtr<MediaKeyMessageEvent> e = new MediaKeyMessageEvent(owner);
   bool trusted = e->Init(owner);
   e->InitEvent(aType, aEventInitDict.mBubbles, aEventInitDict.mCancelable);
+  const uint8_t* data = nullptr;
+  size_t length = 0;
   if (aEventInitDict.mMessage.WasPassed()) {
     const auto& a = aEventInitDict.mMessage.Value();
     a.ComputeLengthAndData();
-    e->mMessage = Uint8Array::Create(aGlobal.Context(), owner, a.Length(), a.Data());
-  } else {
-    e->mMessage = Uint8Array::Create(aGlobal.Context(), owner, 0, nullptr);
+    data = a.Data();
+    length = a.Length();
   }
+  e->mMessage = ArrayBuffer::Create(aGlobal.Context(), length, data);
   if (!e->mMessage) {
     aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
     return nullptr;
   }
   e->mDestinationURL = aEventInitDict.mDestinationURL;
   e->SetTrusted(trusted);
   return e.forget();
 }
 
 void
 MediaKeyMessageEvent::GetMessage(JSContext* cx,
                                  JS::MutableHandle<JSObject*> aMessage,
                                  ErrorResult& aRv)
 {
   if (!mMessage) {
-    mMessage = Uint8Array::Create(cx,
-                                  this,
-                                  mRawMessage.Length(),
-                                  mRawMessage.Elements());
+    mMessage = ArrayBuffer::Create(cx,
+                                   mRawMessage.Length(),
+                                   mRawMessage.Elements());
     if (!mMessage) {
       aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
       return;
     }
     mRawMessage.Clear();
   }
   JS::ExposeObjectToActiveJS(mMessage);
   aMessage.set(mMessage);
--- a/content/media/eme/MediaKeySession.cpp
+++ b/content/media/eme/MediaKeySession.cpp
@@ -7,16 +7,17 @@
 #include "mozilla/dom/HTMLMediaElement.h"
 #include "mozilla/dom/MediaKeySession.h"
 #include "mozilla/dom/MediaKeyError.h"
 #include "mozilla/dom/MediaKeyMessageEvent.h"
 #include "mozilla/dom/MediaEncryptedEvent.h"
 #include "nsCycleCollectionParticipant.h"
 #include "mozilla/CDMProxy.h"
 #include "mozilla/AsyncEventDispatcher.h"
+#include "mozilla/Move.h"
 
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_CYCLE_COLLECTION_INHERITED(MediaKeySession,
                                    DOMEventTargetHelper,
                                    mMediaKeyError,
                                    mKeys,
@@ -90,32 +91,32 @@ MediaKeySession::Expiration() const
 
 Promise*
 MediaKeySession::Closed() const
 {
   return mClosed;
 }
 
 already_AddRefed<Promise>
-MediaKeySession::Update(const Uint8Array& aResponse, ErrorResult& aRv)
+MediaKeySession::Update(const ArrayBufferViewOrArrayBuffer& aResponse, ErrorResult& aRv)
 {
   nsRefPtr<Promise> promise(mKeys->MakePromise(aRv));
   if (aRv.Failed()) {
     return nullptr;
   }
-  aResponse.ComputeLengthAndData();
+  nsTArray<uint8_t> data;
   if (IsClosed() ||
       !mKeys->GetCDMProxy() ||
-      !aResponse.Length()) {
+      !CopyArrayBufferViewOrArrayBufferData(aResponse, data)) {
     promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
     return promise.forget();
   }
   mKeys->GetCDMProxy()->UpdateSession(mSessionId,
                                       mKeys->StorePromise(promise),
-                                      aResponse);
+                                      data);
   return promise.forget();
 }
 
 already_AddRefed<Promise>
 MediaKeySession::Close(ErrorResult& aRv)
 {
   nsRefPtr<Promise> promise(mKeys->MakePromise(aRv));
   if (aRv.Failed()) {
--- a/content/media/eme/MediaKeySession.h
+++ b/content/media/eme/MediaKeySession.h
@@ -13,16 +13,17 @@
 #include "mozilla/DOMEventTargetHelper.h"
 #include "nsCOMPtr.h"
 #include "mozilla/dom/TypedArray.h"
 #include "mozilla/Mutex.h"
 #include "mozilla/dom/Date.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/MediaKeySessionBinding.h"
 #include "mozilla/dom/MediaKeysBinding.h"
+#include "mozilla/dom/UnionTypes.h"
 
 struct JSContext;
 
 namespace mozilla {
 
 class CDMProxy;
 
 namespace dom {
@@ -57,17 +58,17 @@ public:
 
   // Number of ms since epoch at which expiration occurs, or NaN if unknown.
   // TODO: The type of this attribute is still under contention.
   // https://www.w3.org/Bugs/Public/show_bug.cgi?id=25902
   double Expiration() const;
 
   Promise* Closed() const;
 
-  already_AddRefed<Promise> Update(const Uint8Array& response,
+  already_AddRefed<Promise> Update(const ArrayBufferViewOrArrayBuffer& response,
                                    ErrorResult& aRv);
 
   already_AddRefed<Promise> Close(ErrorResult& aRv);
 
   already_AddRefed<Promise> Remove(ErrorResult& aRv);
 
   void DispatchKeyMessage(const nsTArray<uint8_t>& aMessage,
                           const nsAString& aURL);
--- a/content/media/eme/MediaKeys.cpp
+++ b/content/media/eme/MediaKeys.cpp
@@ -84,24 +84,30 @@ MediaKeys::WrapObject(JSContext* aCx)
 
 void
 MediaKeys::GetKeySystem(nsString& retval) const
 {
   retval = mKeySystem;
 }
 
 already_AddRefed<Promise>
-MediaKeys::SetServerCertificate(const Uint8Array& aCert, ErrorResult& aRv)
+MediaKeys::SetServerCertificate(const ArrayBufferViewOrArrayBuffer& aCert, ErrorResult& aRv)
 {
-  aCert.ComputeLengthAndData();
   nsRefPtr<Promise> promise(MakePromise(aRv));
   if (aRv.Failed()) {
     return nullptr;
   }
-  mProxy->SetServerCertificate(StorePromise(promise), aCert);
+
+  nsTArray<uint8_t> data;
+  if (!CopyArrayBufferViewOrArrayBufferData(aCert, data)) {
+    promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
+    return promise.forget();
+  }
+
+  mProxy->SetServerCertificate(StorePromise(promise), data);
   return promise.forget();
 }
 
 static bool
 IsSupportedKeySystem(const nsAString& aKeySystem)
 {
   return aKeySystem.EqualsASCII("org.w3.clearkey") ||
 #ifdef XP_WIN
@@ -300,40 +306,44 @@ MediaKeys::LoadSession(const nsAString& 
   mPendingSessions.Put(pid, session);
   mProxy->LoadSession(pid, aSessionId);
 
   return promise.forget();
 }
 
 already_AddRefed<Promise>
 MediaKeys::CreateSession(const nsAString& initDataType,
-                         const Uint8Array& aInitData,
+                         const ArrayBufferViewOrArrayBuffer& aInitData,
                          SessionType aSessionType,
                          ErrorResult& aRv)
 {
-  aInitData.ComputeLengthAndData();
   nsRefPtr<Promise> promise(MakePromise(aRv));
   if (aRv.Failed()) {
     return nullptr;
   }
+
+  nsTArray<uint8_t> data;
+  if (initDataType.IsEmpty() ||
+      !CopyArrayBufferViewOrArrayBufferData(aInitData, data)) {
+    promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
+    return promise.forget();
+  }
+
   nsRefPtr<MediaKeySession> session = new MediaKeySession(GetParentObject(),
                                                           this,
                                                           mKeySystem,
-                                                          aSessionType, aRv);
-  if (aRv.Failed()) {
-    return nullptr;
-  }
-
+                                                          aSessionType,
+                                                          aRv);
   auto pid = StorePromise(promise);
   // Hang onto session until the CDM has finished setting it up.
   mPendingSessions.Put(pid, session);
   mProxy->CreateSession(aSessionType,
                         pid,
                         initDataType,
-                        aInitData);
+                        data);
 
   return promise.forget();
 }
 
 void
 MediaKeys::OnSessionCreated(PromiseId aId, const nsAString& aSessionId)
 {
   nsRefPtr<Promise> promise(RetrievePromise(aId));
@@ -393,10 +403,28 @@ MediaKeys::GetOrigin(nsString& aOutOrigi
 
   nsresult res = nsContentUtils::GetUTFOrigin(principal, aOutOrigin);
 
   EME_LOG("EME Origin = '%s'", NS_ConvertUTF16toUTF8(aOutOrigin).get());
 
   return res;
 }
 
+bool
+CopyArrayBufferViewOrArrayBufferData(const ArrayBufferViewOrArrayBuffer& aBufferOrView,
+                                     nsTArray<uint8_t>& aOutData)
+{
+  if (aBufferOrView.IsArrayBuffer()) {
+    const ArrayBuffer& buffer = aBufferOrView.GetAsArrayBuffer();
+    buffer.ComputeLengthAndData();
+    aOutData.AppendElements(buffer.Data(), buffer.Length());
+  } else if (aBufferOrView.IsArrayBufferView()) {
+    const ArrayBufferView& bufferview = aBufferOrView.GetAsArrayBufferView();
+    bufferview.ComputeLengthAndData();
+    aOutData.AppendElements(bufferview.Data(), bufferview.Length());
+  } else {
+    return false;
+  }
+  return true;
+}
+
 } // namespace dom
 } // namespace mozilla
--- a/content/media/eme/MediaKeys.h
+++ b/content/media/eme/MediaKeys.h
@@ -12,30 +12,37 @@
 #include "nsISupports.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/RefPtr.h"
 #include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsRefPtrHashtable.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/MediaKeysBinding.h"
+#include "mozilla/dom/UnionTypes.h"
 
 namespace mozilla {
 
 class CDMProxy;
 
 namespace dom {
 
 class MediaKeySession;
 
 typedef nsRefPtrHashtable<nsStringHashKey, MediaKeySession> KeySessionHashMap;
 typedef nsRefPtrHashtable<nsUint32HashKey, dom::Promise> PromiseHashMap;
 typedef nsRefPtrHashtable<nsUint32HashKey, MediaKeySession> PendingKeySessionsHashMap;
 typedef uint32_t PromiseId;
 
+// Helper function to extract data coming in from JS in an
+// (ArrayBuffer or ArrayBufferView) IDL typed function argument.
+bool
+CopyArrayBufferViewOrArrayBufferData(const ArrayBufferViewOrArrayBuffer& aBufferOrView,
+                                     nsTArray<uint8_t>& aOutData);
+
 // This class is used on the main thread only.
 // Note: it's addref/release is not (and can't be) thread safe!
 class MediaKeys MOZ_FINAL : public nsISupports,
                             public nsWrapperCache
 {
   ~MediaKeys();
 
 public:
@@ -48,26 +55,26 @@ public:
 
   virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
 
   // Javascript: readonly attribute DOMString keySystem;
   void GetKeySystem(nsString& retval) const;
 
   // JavaScript: MediaKeys.createSession()
   already_AddRefed<Promise> CreateSession(const nsAString& aInitDataType,
-                                          const Uint8Array& aInitData,
+                                          const ArrayBufferViewOrArrayBuffer& aInitData,
                                           SessionType aSessionType,
                                           ErrorResult& aRv);
 
   // JavaScript: MediaKeys.loadSession()
   already_AddRefed<Promise> LoadSession(const nsAString& aSessionId,
                                         ErrorResult& aRv);
 
   // JavaScript: MediaKeys.SetServerCertificate()
-  already_AddRefed<Promise> SetServerCertificate(const Uint8Array& aServerCertificate,
+  already_AddRefed<Promise> SetServerCertificate(const ArrayBufferViewOrArrayBuffer& aServerCertificate,
                                                  ErrorResult& aRv);
 
   // JavaScript: MediaKeys.create()
   static
   already_AddRefed<Promise> Create(const GlobalObject& aGlobal,
                                    const nsAString& aKeySystem,
                                    ErrorResult& aRv);
 
--- a/dom/webidl/MediaEncryptedEvent.webidl
+++ b/dom/webidl/MediaEncryptedEvent.webidl
@@ -9,15 +9,15 @@
  * Copyright © 2014 W3C® (MIT, ERCIM, Keio, Beihang), All Rights Reserved.
  * W3C liability, trademark and document use rules apply.
  */
 
 [Pref="media.eme.enabled", Constructor(DOMString type, optional MediaKeyNeededEventInit eventInitDict)]
 interface MediaEncryptedEvent : Event {
   readonly attribute DOMString initDataType;
   [Throws]
-  readonly attribute Uint8Array? initData;
+  readonly attribute ArrayBuffer? initData;
 };
 
 dictionary MediaKeyNeededEventInit : EventInit {
   DOMString initDataType = "";
-  Uint8Array? initData = null;
+  ArrayBuffer? initData = null;
 };
--- a/dom/webidl/MediaKeyMessageEvent.webidl
+++ b/dom/webidl/MediaKeyMessageEvent.webidl
@@ -8,16 +8,16 @@
  *
  * Copyright © 2014 W3C® (MIT, ERCIM, Keio, Beihang), All Rights Reserved.
  * W3C liability, trademark and document use rules apply.
  */
 
 [Pref="media.eme.enabled", Constructor(DOMString type, optional MediaKeyMessageEventInit eventInitDict)]
 interface MediaKeyMessageEvent : Event {
   [Throws]
-  readonly attribute Uint8Array message;
+  readonly attribute ArrayBuffer message;
   readonly attribute DOMString? destinationURL;
 };
 
 dictionary MediaKeyMessageEventInit : EventInit {
-  Uint8Array message;
-  DOMString? destinationURL = "";
+  ArrayBuffer message;
+  DOMString? destinationURL = null;
 };
--- a/dom/webidl/MediaKeySession.webidl
+++ b/dom/webidl/MediaKeySession.webidl
@@ -26,17 +26,17 @@ interface MediaKeySession : EventTarget 
   readonly attribute unrestricted double expiration;
 
   // void, not any: https://www.w3.org/Bugs/Public/show_bug.cgi?id=26457
   readonly attribute Promise<void> closed;
 
   // session operations
   // void, not any: https://www.w3.org/Bugs/Public/show_bug.cgi?id=26457
   [NewObject, Throws]
-  Promise<void> update(Uint8Array response);
+  Promise<void> update((ArrayBufferView or ArrayBuffer) response);
 
   // void, not any: https://www.w3.org/Bugs/Public/show_bug.cgi?id=26457
   [NewObject, Throws]
   Promise<void> close();
 
   // void, not any: https://www.w3.org/Bugs/Public/show_bug.cgi?id=26457
   [NewObject, Throws]
   Promise<void> remove();
--- a/dom/webidl/MediaKeys.webidl
+++ b/dom/webidl/MediaKeys.webidl
@@ -13,22 +13,22 @@
 enum IsTypeSupportedResult { "" /* empty string */, "maybe", "probably" };
 enum SessionType { "temporary", "persistent" };
 
 [Pref="media.eme.enabled"]
 interface MediaKeys {
   readonly attribute DOMString keySystem;
 
   [NewObject, Throws]
-  Promise<MediaKeySession> createSession(DOMString initDataType, Uint8Array initData, optional SessionType sessionType = "temporary");
+  Promise<MediaKeySession> createSession(DOMString initDataType, (ArrayBufferView or ArrayBuffer) initData, optional SessionType sessionType = "temporary");
 
   [NewObject, Throws]
   Promise<MediaKeySession> loadSession(DOMString sessionId);
 
   // void, not any: https://www.w3.org/Bugs/Public/show_bug.cgi?id=26457
   [NewObject, Throws]
-  Promise<void> setServerCertificate(Uint8Array serverCertificate);
+  Promise<void> setServerCertificate((ArrayBufferView or ArrayBuffer) serverCertificate);
 
   [Throws,NewObject]
   static Promise<MediaKeys> create(DOMString keySystem);
   static IsTypeSupportedResult isTypeSupported(DOMString keySystem, optional DOMString initDataType, optional DOMString contentType, optional DOMString capability);
 
 };