Bug 1284192 - Make CDMProxy be a base class and move the logic into subclass. r=cpearce
authorJames Cheng <jacheng@mozilla.com>
Mon, 18 Jul 2016 22:13:00 +0200
changeset 330783 813a61c61c6ce325f60801b2c6cc377e1801fd59
parent 330782 564fdbb916ba41e6186031ac633f733d5405ed92
child 330784 340f2259b820df20fe88a489763c9f82eb4918b0
push id9858
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 14:37:10 +0000
treeherdermozilla-aurora@203106ef6cb6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscpearce
bugs1284192
milestone50.0a1
Bug 1284192 - Make CDMProxy be a base class and move the logic into subclass. r=cpearce MozReview-Commit-ID: 4Lr3uqVexFD
dom/media/eme/CDMProxy.cpp
dom/media/eme/CDMProxy.h
dom/media/eme/MediaKeys.cpp
dom/media/eme/moz.build
dom/media/gmp/GMPCDMCallbackProxy.cpp
dom/media/gmp/GMPCDMCallbackProxy.h
dom/media/gmp/GMPCDMProxy.cpp
dom/media/gmp/GMPCDMProxy.h
dom/media/gmp/moz.build
--- a/dom/media/eme/CDMProxy.h
+++ b/dom/media/eme/CDMProxy.h
@@ -3,302 +3,187 @@
 /* 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 CDMProxy_h_
 #define CDMProxy_h_
 
 #include "mozilla/CDMCaps.h"
-#include "mozilla/Monitor.h"
 #include "mozilla/MozPromise.h"
 
+#include "mozilla/dom/MediaKeyMessageEvent.h"
 #include "mozilla/dom/MediaKeys.h"
 
 #include "nsIThread.h"
-#include "nsString.h"
-#include "nsAutoPtr.h"
-#include "GMPDecryptorProxy.h"
 
 namespace mozilla {
 class MediaRawData;
-class GMPCDMCallbackProxy;
-
-namespace dom {
-class MediaKeySession;
-} // namespace dom
 
 struct DecryptResult {
   DecryptResult(GMPErr aStatus, MediaRawData* aSample)
     : mStatus(aStatus)
     , mSample(aSample)
   {}
   GMPErr mStatus;
   RefPtr<MediaRawData> mSample;
 };
 
-// Proxies calls GMP/CDM, and proxies calls back.
+// Proxies calls 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 {
+protected:
   typedef dom::PromiseId PromiseId;
   typedef dom::SessionType SessionType;
 public:
 
-  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CDMProxy)
+  NS_IMETHOD_(MozExternalRefCountType) AddRef(void) = 0;
+  NS_IMETHOD_(MozExternalRefCountType) Release(void) = 0;
 
   typedef MozPromise<DecryptResult, DecryptResult, /* IsExclusive = */ true> DecryptPromise;
 
   // Main thread only.
-  CDMProxy(dom::MediaKeys* aKeys, const nsAString& aKeySystem);
+  CDMProxy(dom::MediaKeys* aKeys, const nsAString& aKeySystem)
+  : mKeys(aKeys), mKeySystem(aKeySystem)
+  {}
 
   // Main thread only.
   // Loads the CDM corresponding to mKeySystem.
   // Calls MediaKeys::OnCDMCreated() when the CDM is created.
-  void Init(PromiseId aPromiseId,
-            const nsAString& aOrigin,
-            const nsAString& aTopLevelOrigin,
-            const nsAString& aGMPName,
-            bool aInPrivateBrowsing,
-            GMPCrashHelper* aHelper);
+  virtual void Init(PromiseId aPromiseId,
+                    const nsAString& aOrigin,
+                    const nsAString& aTopLevelOrigin,
+                    const nsAString& aName,
+                    bool aInPrivateBrowsing) = 0;
 
   // Main thread only.
   // Uses the CDM to create a key session.
   // Calls MediaKeys::OnSessionActivated() when session is created.
   // Assumes ownership of (Move()s) aInitData's contents.
-  void CreateSession(uint32_t aCreateSessionToken,
-                     dom::SessionType aSessionType,
-                     PromiseId aPromiseId,
-                     const nsAString& aInitDataType,
-                     nsTArray<uint8_t>& aInitData);
+  virtual void CreateSession(uint32_t aCreateSessionToken,
+                             dom::SessionType aSessionType,
+                             PromiseId aPromiseId,
+                             const nsAString& aInitDataType,
+                             nsTArray<uint8_t>& aInitData) = 0;
 
   // 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);
+  virtual void LoadSession(PromiseId aPromiseId,
+                           const nsAString& aSessionId) = 0;
 
   // Main thread only.
   // Sends a new certificate to the CDM.
   // Calls MediaKeys->ResolvePromise(aPromiseId) after the CDM has
   // processed the request.
   // Assumes ownership of (Move()s) aCert's contents.
-  void SetServerCertificate(PromiseId aPromiseId,
-                            nsTArray<uint8_t>& aCert);
+  virtual void SetServerCertificate(PromiseId aPromiseId,
+                                    nsTArray<uint8_t>& aCert) = 0;
 
   // Main thread only.
   // Sends an update to the CDM.
   // 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,
-                     nsTArray<uint8_t>& aResponse);
+  virtual void UpdateSession(const nsAString& aSessionId,
+                             PromiseId aPromiseId,
+                             nsTArray<uint8_t>& aResponse) = 0;
 
   // 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,
-                    PromiseId aPromiseId);
+  virtual void CloseSession(const nsAString& aSessionId,
+                            PromiseId aPromiseId) = 0;
 
   // Main thread only.
   // Removes all data for a persisent session.
   // Calls MediaKeys->ResolvePromise(aPromiseId) after the CDM has
   // processed the request.
-  void RemoveSession(const nsAString& aSessionId,
-                     PromiseId aPromiseId);
+  virtual void RemoveSession(const nsAString& aSessionId,
+                             PromiseId aPromiseId) = 0;
 
   // Main thread only.
-  void Shutdown();
+  virtual void Shutdown() = 0;
 
   // Main thread only.
-  void Terminated();
+  virtual void Terminated() = 0;
 
   // Threadsafe.
-  const nsCString& GetNodeId() const;
+  virtual const nsCString& GetNodeId() const = 0;
 
   // Main thread only.
-  void OnSetSessionId(uint32_t aCreateSessionToken,
-                      const nsAString& aSessionId);
+  virtual void OnSetSessionId(uint32_t aCreateSessionToken,
+                              const nsAString& aSessionId) = 0;
 
   // Main thread only.
-  void OnResolveLoadSessionPromise(uint32_t aPromiseId, bool aSuccess);
+  virtual void OnResolveLoadSessionPromise(uint32_t aPromiseId,
+                                           bool aSuccess) = 0;
 
   // Main thread only.
-  void OnSessionMessage(const nsAString& aSessionId,
-                        GMPSessionMessageType aMessageType,
-                        nsTArray<uint8_t>& aMessage);
+  virtual void OnSessionMessage(const nsAString& aSessionId,
+                                dom::MediaKeyMessageType aMessageType,
+                                nsTArray<uint8_t>& aMessage) = 0;
 
   // Main thread only.
-  void OnExpirationChange(const nsAString& aSessionId,
-                          GMPTimestamp aExpiryTime);
+  virtual void OnExpirationChange(const nsAString& aSessionId,
+                                  int64_t aExpiryTime) = 0;
 
   // Main thread only.
-  void OnSessionClosed(const nsAString& aSessionId);
+  virtual void OnSessionClosed(const nsAString& aSessionId) = 0;
 
   // Main thread only.
-  void OnSessionError(const nsAString& aSessionId,
-                      nsresult aException,
-                      uint32_t aSystemCode,
-                      const nsAString& aMsg);
+  virtual void OnSessionError(const nsAString& aSessionId,
+                              nsresult aException,
+                              uint32_t aSystemCode,
+                              const nsAString& aMsg) = 0;
 
   // Main thread only.
-  void OnRejectPromise(uint32_t aPromiseId,
-                       nsresult aDOMException,
-                       const nsCString& aMsg);
+  virtual void OnRejectPromise(uint32_t aPromiseId,
+                               nsresult aDOMException,
+                               const nsCString& aMsg) = 0;
 
-  RefPtr<DecryptPromise> Decrypt(MediaRawData* aSample);
+  virtual RefPtr<DecryptPromise> Decrypt(MediaRawData* aSample) = 0;
+
+  // Owner thread only.
+  virtual void OnDecrypted(uint32_t aId,
+                           GMPErr aResult,
+                           const nsTArray<uint8_t>& aDecryptedData) = 0;
 
   // Reject promise with DOMException corresponding to aExceptionCode.
   // Can be called from any thread.
-  void RejectPromise(PromiseId aId, nsresult aExceptionCode,
-                     const nsCString& aReason);
+  virtual void RejectPromise(PromiseId aId,
+                             nsresult aExceptionCode,
+                             const nsCString& aReason) = 0;
 
   // Resolves promise with "undefined".
   // Can be called from any thread.
-  void ResolvePromise(PromiseId aId);
+  virtual void ResolvePromise(PromiseId aId) = 0;
 
   // Threadsafe.
-  const nsString& KeySystem() const;
-
-  // GMP thread only.
-  void gmp_Decrypted(uint32_t aId,
-                     GMPErr aResult,
-                     const nsTArray<uint8_t>& aDecryptedData);
-
-  CDMCaps& Capabilites();
-
-  // Main thread only.
-  void OnKeyStatusesChange(const nsAString& aSessionId);
-
-  void GetSessionIdsForKeyId(const nsTArray<uint8_t>& aKeyId,
-                             nsTArray<nsCString>& aSessionIds);
-
-#ifdef DEBUG
-  bool IsOnGMPThread();
-#endif
+  virtual const nsString& KeySystem() const = 0;
 
-private:
-  friend class gmp_InitDoneCallback;
-  friend class gmp_InitGetGMPDecryptorCallback;
-
-  struct InitData {
-    uint32_t mPromiseId;
-    nsString mOrigin;
-    nsString mTopLevelOrigin;
-    nsString mGMPName;
-    RefPtr<GMPCrashHelper> mCrashHelper;
-    bool mInPrivateBrowsing;
-  };
-
-  // GMP thread only.
-  void gmp_Init(nsAutoPtr<InitData>&& aData);
-  void gmp_InitDone(GMPDecryptorProxy* aCDM, nsAutoPtr<InitData>&& aData);
-  void gmp_InitGetGMPDecryptor(nsresult aResult,
-                               const nsACString& aNodeId,
-                               nsAutoPtr<InitData>&& aData);
-
-  // GMP thread only.
-  void gmp_Shutdown();
+  virtual  CDMCaps& Capabilites() = 0;
 
   // Main thread only.
-  void OnCDMCreated(uint32_t aPromiseId);
-
-  struct CreateSessionData {
-    dom::SessionType mSessionType;
-    uint32_t mCreateSessionToken;
-    PromiseId mPromiseId;
-    nsCString mInitDataType;
-    nsTArray<uint8_t> mInitData;
-  };
-  // GMP thread only.
-  void gmp_CreateSession(nsAutoPtr<CreateSessionData> aData);
-
-  struct SessionOpData {
-    PromiseId mPromiseId;
-    nsCString mSessionId;
-  };
-  // GMP thread only.
-  void gmp_LoadSession(nsAutoPtr<SessionOpData> aData);
+  virtual void OnKeyStatusesChange(const nsAString& aSessionId) = 0;
 
-  struct SetServerCertificateData {
-    PromiseId mPromiseId;
-    nsTArray<uint8_t> mCert;
-  };
-  // GMP thread only.
-  void gmp_SetServerCertificate(nsAutoPtr<SetServerCertificateData> aData);
-
-  struct UpdateSessionData {
-    PromiseId mPromiseId;
-    nsCString mSessionId;
-    nsTArray<uint8_t> mResponse;
-  };
-  // GMP thread only.
-  void gmp_UpdateSession(nsAutoPtr<UpdateSessionData> aData);
-
-  // GMP thread only.
-  void gmp_CloseSession(nsAutoPtr<SessionOpData> aData);
-
-  // GMP thread only.
-  void gmp_RemoveSession(nsAutoPtr<SessionOpData> aData);
-
-  class DecryptJob {
-  public:
-    NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DecryptJob)
+  virtual void GetSessionIdsForKeyId(const nsTArray<uint8_t>& aKeyId,
+                                     nsTArray<nsCString>& aSessionIds) = 0;
 
-    explicit DecryptJob(MediaRawData* aSample)
-      : mId(0)
-      , mSample(aSample)
-    {
-    }
-
-    void PostResult(GMPErr aResult, const nsTArray<uint8_t>& aDecryptedData);
-    void PostResult(GMPErr aResult);
-
-    RefPtr<DecryptPromise> Ensure() {
-      return mPromise.Ensure(__func__);
-    }
-
-    uint32_t mId;
-    RefPtr<MediaRawData> mSample;
-  private:
-    ~DecryptJob() {}
-    MozPromiseHolder<DecryptPromise> mPromise;
-  };
-  // GMP thread only.
-  void gmp_Decrypt(RefPtr<DecryptJob> aJob);
+#ifdef DEBUG
+  virtual bool IsOnOwnerThread() = 0;
+#endif
 
-  class RejectPromiseTask : public Runnable {
-  public:
-    RejectPromiseTask(CDMProxy* aProxy,
-                      PromiseId aId,
-                      nsresult aCode,
-                      const nsCString& aReason)
-      : mProxy(aProxy)
-      , mId(aId)
-      , mCode(aCode)
-      , mReason(aReason)
-    {
-    }
-    NS_METHOD Run() {
-      mProxy->RejectPromise(mId, mCode, mReason);
-      return NS_OK;
-    }
-  private:
-    RefPtr<CDMProxy> mProxy;
-    PromiseId mId;
-    nsresult mCode;
-    nsCString mReason;
-  };
-
-  ~CDMProxy();
+protected:
+  virtual ~CDMProxy() {}
 
   // Helper to enforce that a raw pointer is only accessed on the main thread.
   template<class Type>
   class MainThreadOnlyRawPtr {
   public:
     explicit MainThreadOnlyRawPtr(Type* aPtr)
       : mPtr(aPtr)
     {
@@ -325,38 +210,21 @@ private:
 
   // Our reference back to the MediaKeys object.
   // WARNING: This is a non-owning reference that is cleared by MediaKeys
   // destructor. only use on main thread, and always nullcheck before using!
   MainThreadOnlyRawPtr<dom::MediaKeys> mKeys;
 
   const nsString mKeySystem;
 
-  // Gecko Media Plugin thread. All interactions with the out-of-process
-  // EME plugin must come from this thread.
-  RefPtr<nsIThread> mGMPThread;
+  // Onwer specified thread. e.g. Gecko Media Plugin thread.
+  // All interactions with the out-of-process EME plugin must come from this thread.
+  RefPtr<nsIThread> mOwnerThread;
 
   nsCString mNodeId;
 
-  GMPDecryptorProxy* mCDM;
   CDMCaps mCapabilites;
-  nsAutoPtr<GMPCDMCallbackProxy> mCallback;
-
-  // Decryption jobs sent to CDM, awaiting result.
-  // GMP thread only.
-  nsTArray<RefPtr<DecryptJob>> mDecryptionJobs;
-
-  // Number of buffers we've decrypted. Used to uniquely identify
-  // decryption jobs sent to CDM. Note we can't just use the length of
-  // mDecryptionJobs as that shrinks as jobs are completed and removed
-  // from it.
-  // GMP thread only.
-  uint32_t mDecryptionJobCount;
-
-  // True if CDMProxy::gmp_Shutdown was called.
-  // GMP thread only.
-  bool mShutdownCalled;
 };
 
 
 } // namespace mozilla
 
 #endif // CDMProxy_h_
--- a/dom/media/eme/MediaKeys.cpp
+++ b/dom/media/eme/MediaKeys.cpp
@@ -8,17 +8,17 @@
 #include "GMPService.h"
 #include "mozilla/dom/HTMLMediaElement.h"
 #include "mozilla/dom/MediaKeysBinding.h"
 #include "mozilla/dom/MediaKeyMessageEvent.h"
 #include "mozilla/dom/MediaKeyError.h"
 #include "mozilla/dom/MediaKeySession.h"
 #include "mozilla/dom/DOMException.h"
 #include "mozilla/dom/UnionTypes.h"
-#include "mozilla/CDMProxy.h"
+#include "GMPCDMProxy.h"
 #include "mozilla/EMEUtils.h"
 #include "nsContentUtils.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsContentTypeParser.h"
 #ifdef MOZ_FMP4
 #include "MP4Decoder.h"
 #endif
 #ifdef XP_WIN
@@ -308,17 +308,17 @@ already_AddRefed<DetailedPromise>
 MediaKeys::Init(ErrorResult& aRv)
 {
   RefPtr<DetailedPromise> promise(MakePromise(aRv,
     NS_LITERAL_CSTRING("MediaKeys::Init()")));
   if (aRv.Failed()) {
     return nullptr;
   }
 
-  mProxy = new CDMProxy(this, mKeySystem);
+  mProxy = new GMPCDMProxy(this, mKeySystem, new MediaKeysGMPCrashHelper(this));
 
   // Determine principal (at creation time) of the MediaKeys object.
   nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(GetParentObject());
   if (!sop) {
     promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR,
                          NS_LITERAL_CSTRING("Couldn't get script principal in MediaKeys::Init"));
     return promise.forget();
   }
@@ -382,18 +382,17 @@ MediaKeys::Init(ErrorResult& aRv)
   // rejected.
   MOZ_ASSERT(!mCreatePromiseId, "Should only be created once!");
   mCreatePromiseId = StorePromise(promise);
   AddRef();
   mProxy->Init(mCreatePromiseId,
                origin,
                topLevelOrigin,
                KeySystemToGMPName(mKeySystem),
-               inPrivateBrowsing,
-               new MediaKeysGMPCrashHelper(this));
+               inPrivateBrowsing);
 
   return promise.forget();
 }
 
 void
 MediaKeys::OnCDMCreated(PromiseId aId, const nsACString& aNodeId, const uint32_t aPluginId)
 {
   RefPtr<DetailedPromise> promise(RetrievePromise(aId));
--- a/dom/media/eme/moz.build
+++ b/dom/media/eme/moz.build
@@ -19,17 +19,16 @@ EXPORTS.mozilla += [
     'CDMCaps.h',
     'CDMProxy.h',
     'DetailedPromise.h',
     'EMEUtils.h',
 ]
 
 UNIFIED_SOURCES += [
     'CDMCaps.cpp',
-    'CDMProxy.cpp',
     'DetailedPromise.cpp',
     'EMEUtils.cpp',
     'MediaEncryptedEvent.cpp',
     'MediaKeyError.cpp',
     'MediaKeyMessageEvent.cpp',
     'MediaKeys.cpp',
     'MediaKeySession.cpp',
     'MediaKeyStatusMap.cpp',
--- a/dom/media/gmp/GMPCDMCallbackProxy.cpp
+++ b/dom/media/gmp/GMPCDMCallbackProxy.cpp
@@ -43,17 +43,17 @@ public:
   uint32_t mToken;
   nsString mSid;
 };
 
 void
 GMPCDMCallbackProxy::SetSessionId(uint32_t aToken,
                                   const nsCString& aSessionId)
 {
-  MOZ_ASSERT(mProxy->IsOnGMPThread());
+  MOZ_ASSERT(mProxy->IsOnOwnerThread());
 
   nsCOMPtr<nsIRunnable> task(new SetSessionIdTask(mProxy,
                                                   aToken,
                                                   aSessionId));
   NS_DispatchToMainThread(task);
 }
 
 class LoadSessionTask : public Runnable {
@@ -76,28 +76,28 @@ public:
   dom::PromiseId mPid;
   bool mSuccess;
 };
 
 void
 GMPCDMCallbackProxy::ResolveLoadSessionPromise(uint32_t aPromiseId,
                                                bool aSuccess)
 {
-  MOZ_ASSERT(mProxy->IsOnGMPThread());
+  MOZ_ASSERT(mProxy->IsOnOwnerThread());
 
   nsCOMPtr<nsIRunnable> task(new LoadSessionTask(mProxy,
                                                  aPromiseId,
                                                  aSuccess));
   NS_DispatchToMainThread(task);
 }
 
 void
 GMPCDMCallbackProxy::ResolvePromise(uint32_t aPromiseId)
 {
-  MOZ_ASSERT(mProxy->IsOnGMPThread());
+  MOZ_ASSERT(mProxy->IsOnOwnerThread());
 
   // Note: CDMProxy proxies this from non-main threads to main thread.
   mProxy->ResolvePromise(aPromiseId);
 }
 
 class RejectPromiseTask : public Runnable {
 public:
   RejectPromiseTask(CDMProxy* aProxy,
@@ -123,57 +123,68 @@ public:
 };
 
 
 void
 GMPCDMCallbackProxy::RejectPromise(uint32_t aPromiseId,
                                    nsresult aException,
                                    const nsCString& aMessage)
 {
-  MOZ_ASSERT(mProxy->IsOnGMPThread());
+  MOZ_ASSERT(mProxy->IsOnOwnerThread());
 
   nsCOMPtr<nsIRunnable> task;
   task = new RejectPromiseTask(mProxy,
                                aPromiseId,
                                aException,
                                aMessage);
   NS_DispatchToMainThread(task);
 }
 
+static dom::MediaKeyMessageType
+ToMediaKeyMessageType(GMPSessionMessageType aMessageType) {
+  switch (aMessageType) {
+    case kGMPLicenseRequest: return dom::MediaKeyMessageType::License_request;
+    case kGMPLicenseRenewal: return dom::MediaKeyMessageType::License_renewal;
+    case kGMPLicenseRelease: return dom::MediaKeyMessageType::License_release;
+    case kGMPIndividualizationRequest: return dom::MediaKeyMessageType::Individualization_request;
+    default: return dom::MediaKeyMessageType::License_request;
+  };
+};
+
 class SessionMessageTask : public Runnable {
 public:
   SessionMessageTask(CDMProxy* aProxy,
                      const nsCString& aSessionId,
                      GMPSessionMessageType aMessageType,
                      const nsTArray<uint8_t>& aMessage)
     : mProxy(aProxy)
     , mSid(NS_ConvertUTF8toUTF16(aSessionId))
     , mMsgType(aMessageType)
   {
     mMsg.AppendElements(aMessage);
   }
 
   NS_IMETHOD Run() {
-    mProxy->OnSessionMessage(mSid, mMsgType, mMsg);
+    mProxy->OnSessionMessage(mSid, ToMediaKeyMessageType(mMsgType), mMsg);
     return NS_OK;
   }
 
   RefPtr<CDMProxy> mProxy;
   dom::PromiseId mPid;
   nsString mSid;
   GMPSessionMessageType mMsgType;
   nsTArray<uint8_t> mMsg;
 };
 
 void
 GMPCDMCallbackProxy::SessionMessage(const nsCString& aSessionId,
                                     GMPSessionMessageType aMessageType,
                                     const nsTArray<uint8_t>& aMessage)
 {
-  MOZ_ASSERT(mProxy->IsOnGMPThread());
+  MOZ_ASSERT(mProxy->IsOnOwnerThread());
 
   nsCOMPtr<nsIRunnable> task;
   task = new SessionMessageTask(mProxy,
                                 aSessionId,
                                 aMessageType,
                                 aMessage);
   NS_DispatchToMainThread(task);
 }
@@ -197,29 +208,29 @@ public:
   nsString mSid;
   GMPTimestamp mTimestamp;
 };
 
 void
 GMPCDMCallbackProxy::ExpirationChange(const nsCString& aSessionId,
                                       GMPTimestamp aExpiryTime)
 {
-  MOZ_ASSERT(mProxy->IsOnGMPThread());
+  MOZ_ASSERT(mProxy->IsOnOwnerThread());
 
   nsCOMPtr<nsIRunnable> task;
   task = new ExpirationChangeTask(mProxy,
                                   aSessionId,
                                   aExpiryTime);
   NS_DispatchToMainThread(task);
 }
 
 void
 GMPCDMCallbackProxy::SessionClosed(const nsCString& aSessionId)
 {
-  MOZ_ASSERT(mProxy->IsOnGMPThread());
+  MOZ_ASSERT(mProxy->IsOnOwnerThread());
 
   bool keyStatusesChange = false;
   {
     CDMCaps::AutoLock caps(mProxy->Capabilites());
     keyStatusesChange = caps.RemoveKeysForSession(NS_ConvertUTF8toUTF16(aSessionId));
   }
   if (keyStatusesChange) {
     nsCOMPtr<nsIRunnable> task;
@@ -264,33 +275,33 @@ public:
 };
 
 void
 GMPCDMCallbackProxy::SessionError(const nsCString& aSessionId,
                                   nsresult aException,
                                   uint32_t aSystemCode,
                                   const nsCString& aMessage)
 {
-  MOZ_ASSERT(mProxy->IsOnGMPThread());
+  MOZ_ASSERT(mProxy->IsOnOwnerThread());
 
   nsCOMPtr<nsIRunnable> task;
   task = new SessionErrorTask(mProxy,
                               aSessionId,
                               aException,
                               aSystemCode,
                               aMessage);
   NS_DispatchToMainThread(task);
 }
 
 void
 GMPCDMCallbackProxy::KeyStatusChanged(const nsCString& aSessionId,
                                       const nsTArray<uint8_t>& aKeyId,
                                       GMPMediaKeyStatus aStatus)
 {
-  MOZ_ASSERT(mProxy->IsOnGMPThread());
+  MOZ_ASSERT(mProxy->IsOnOwnerThread());
 
   bool keyStatusesChange = false;
   {
     CDMCaps::AutoLock caps(mProxy->Capabilites());
     keyStatusesChange = caps.SetKeyStatus(aKeyId,
                                           NS_ConvertUTF8toUTF16(aSessionId),
                                           aStatus);
   }
@@ -303,22 +314,22 @@ GMPCDMCallbackProxy::KeyStatusChanged(co
   }
 }
 
 void
 GMPCDMCallbackProxy::Decrypted(uint32_t aId,
                                GMPErr aResult,
                                const nsTArray<uint8_t>& aDecryptedData)
 {
-  MOZ_ASSERT(mProxy->IsOnGMPThread());
+  MOZ_ASSERT(mProxy->IsOnOwnerThread());
 
-  mProxy->gmp_Decrypted(aId, aResult, aDecryptedData);
+  mProxy->OnDecrypted(aId, aResult, aDecryptedData);
 }
 
 void
 GMPCDMCallbackProxy::Terminated()
 {
-  MOZ_ASSERT(mProxy->IsOnGMPThread());
+  MOZ_ASSERT(mProxy->IsOnOwnerThread());
   nsCOMPtr<nsIRunnable> task = NewRunnableMethod(mProxy, &CDMProxy::Terminated);
   NS_DispatchToMainThread(task);
 }
 
 } // namespace mozilla
--- a/dom/media/gmp/GMPCDMCallbackProxy.h
+++ b/dom/media/gmp/GMPCDMCallbackProxy.h
@@ -51,17 +51,17 @@ public:
                  GMPErr aResult,
                  const nsTArray<uint8_t>& aDecryptedData) override;
 
   void Terminated() override;
 
   ~GMPCDMCallbackProxy() {}
 
 private:
-  friend class CDMProxy;
+  friend class GMPCDMProxy;
   explicit GMPCDMCallbackProxy(CDMProxy* aProxy);
 
   // Warning: Weak ref.
   CDMProxy* mProxy;
 };
 
 } // namespace mozilla
 
rename from dom/media/eme/CDMProxy.cpp
rename to dom/media/gmp/GMPCDMProxy.cpp
--- a/dom/media/eme/CDMProxy.cpp
+++ b/dom/media/gmp/GMPCDMProxy.cpp
@@ -1,188 +1,191 @@
 /* -*- 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 "mozilla/CDMProxy.h"
-#include "nsString.h"
+#include "GMPCDMProxy.h"
+#include "mozilla/EMEUtils.h"
+#include "mozilla/PodOperations.h"
+
 #include "mozilla/dom/MediaKeys.h"
 #include "mozilla/dom/MediaKeySession.h"
+
 #include "mozIGeckoMediaPluginService.h"
 #include "nsContentCID.h"
+#include "nsIConsoleService.h"
+#include "nsPrintfCString.h"
 #include "nsServiceManagerUtils.h"
-#include "MainThreadUtils.h"
-#include "mozilla/EMEUtils.h"
-#include "nsIConsoleService.h"
+#include "nsString.h"
 #include "prenv.h"
-#include "mozilla/PodOperations.h"
 #include "GMPCDMCallbackProxy.h"
+#include "GMPService.h"
+#include "MainThreadUtils.h"
 #include "MediaData.h"
-#include "nsPrintfCString.h"
-#include "GMPService.h"
 
 namespace mozilla {
 
-CDMProxy::CDMProxy(dom::MediaKeys* aKeys, const nsAString& aKeySystem)
-  : mKeys(aKeys)
-  , mKeySystem(aKeySystem)
+GMPCDMProxy::GMPCDMProxy(dom::MediaKeys* aKeys,
+                         const nsAString& aKeySystem,
+                         GMPCrashHelper* aCrashHelper)
+  : CDMProxy(aKeys, aKeySystem)
+  , mCrashHelper(aCrashHelper)
   , mCDM(nullptr)
   , mDecryptionJobCount(0)
   , mShutdownCalled(false)
 {
   MOZ_ASSERT(NS_IsMainThread());
-  MOZ_COUNT_CTOR(CDMProxy);
+  MOZ_COUNT_CTOR(GMPCDMProxy);
 }
 
-CDMProxy::~CDMProxy()
+GMPCDMProxy::~GMPCDMProxy()
 {
-  MOZ_COUNT_DTOR(CDMProxy);
+  MOZ_COUNT_DTOR(GMPCDMProxy);
 }
 
 void
-CDMProxy::Init(PromiseId aPromiseId,
-               const nsAString& aOrigin,
-               const nsAString& aTopLevelOrigin,
-               const nsAString& aGMPName,
-               bool aInPrivateBrowsing,
-               GMPCrashHelper* aCrashHelper)
+GMPCDMProxy::Init(PromiseId aPromiseId,
+                  const nsAString& aOrigin,
+                  const nsAString& aTopLevelOrigin,
+                  const nsAString& aGMPName,
+                  bool aInPrivateBrowsing)
 {
   MOZ_ASSERT(NS_IsMainThread());
   NS_ENSURE_TRUE_VOID(!mKeys.IsNull());
 
-  EME_LOG("CDMProxy::Init (%s, %s) %s",
+  EME_LOG("GMPCDMProxy::Init (%s, %s) %s",
           NS_ConvertUTF16toUTF8(aOrigin).get(),
           NS_ConvertUTF16toUTF8(aTopLevelOrigin).get(),
           (aInPrivateBrowsing ? "PrivateBrowsing" : "NonPrivateBrowsing"));
 
   nsCString pluginVersion;
-  if (!mGMPThread) {
+  if (!mOwnerThread) {
     nsCOMPtr<mozIGeckoMediaPluginService> mps =
       do_GetService("@mozilla.org/gecko-media-plugin-service;1");
     if (!mps) {
       RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
-                    NS_LITERAL_CSTRING("Couldn't get MediaPluginService in CDMProxy::Init"));
+                    NS_LITERAL_CSTRING("Couldn't get MediaPluginService in GMPCDMProxy::Init"));
       return;
     }
-    mps->GetThread(getter_AddRefs(mGMPThread));
-    if (!mGMPThread) {
+    mps->GetThread(getter_AddRefs(mOwnerThread));
+    if (!mOwnerThread) {
       RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
-                    NS_LITERAL_CSTRING("Couldn't get GMP thread CDMProxy::Init"));
+                    NS_LITERAL_CSTRING("Couldn't get GMP thread GMPCDMProxy::Init"));
       return;
     }
   }
 
   if (aGMPName.IsEmpty()) {
     RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
       nsPrintfCString("Unknown GMP for keysystem '%s'", NS_ConvertUTF16toUTF8(mKeySystem).get()));
     return;
   }
 
   nsAutoPtr<InitData> data(new InitData());
   data->mPromiseId = aPromiseId;
   data->mOrigin = aOrigin;
   data->mTopLevelOrigin = aTopLevelOrigin;
   data->mGMPName = aGMPName;
   data->mInPrivateBrowsing = aInPrivateBrowsing;
-  data->mCrashHelper = aCrashHelper;
+  data->mCrashHelper = mCrashHelper;
   nsCOMPtr<nsIRunnable> task(
     NewRunnableMethod<nsAutoPtr<InitData>>(this,
-                                           &CDMProxy::gmp_Init,
+                                           &GMPCDMProxy::gmp_Init,
                                            Move(data)));
-  mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
+  mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
 }
 
 #ifdef DEBUG
 bool
-CDMProxy::IsOnGMPThread()
+GMPCDMProxy::IsOnOwnerThread()
 {
-  return NS_GetCurrentThread() == mGMPThread;
+  return NS_GetCurrentThread() == mOwnerThread;
 }
 #endif
 
 void
-CDMProxy::gmp_InitDone(GMPDecryptorProxy* aCDM, nsAutoPtr<InitData>&& aData)
+GMPCDMProxy::gmp_InitDone(GMPDecryptorProxy* aCDM, nsAutoPtr<InitData>&& aData)
 {
-  EME_LOG("CDMProxy::gmp_InitDone");
+  EME_LOG("GMPCDMProxy::gmp_InitDone");
   if (mShutdownCalled) {
     if (aCDM) {
       aCDM->Close();
     }
     RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
-                  NS_LITERAL_CSTRING("CDMProxy was shut down before init could complete"));
+                  NS_LITERAL_CSTRING("GMPCDMProxy was shut down before init could complete"));
     return;
   }
   if (!aCDM) {
     RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
                   NS_LITERAL_CSTRING("GetGMPDecryptor failed to return a CDM"));
     return;
   }
 
   mCDM = aCDM;
   mCallback = new GMPCDMCallbackProxy(this);
   mCDM->Init(mCallback);
   nsCOMPtr<nsIRunnable> task(
     NewRunnableMethod<uint32_t>(this,
-                                &CDMProxy::OnCDMCreated,
+                                &GMPCDMProxy::OnCDMCreated,
                                 aData->mPromiseId));
   NS_DispatchToMainThread(task);
 }
 
 class gmp_InitDoneCallback : public GetGMPDecryptorCallback
 {
 public:
-  gmp_InitDoneCallback(CDMProxy* aCDMProxy,
-                       nsAutoPtr<CDMProxy::InitData>&& aData)
-    : mCDMProxy(aCDMProxy),
+  gmp_InitDoneCallback(GMPCDMProxy* aGMPCDMProxy,
+                       nsAutoPtr<GMPCDMProxy::InitData>&& aData)
+    : mGMPCDMProxy(aGMPCDMProxy),
       mData(Move(aData))
   {
   }
 
   void Done(GMPDecryptorProxy* aCDM)
   {
-    mCDMProxy->gmp_InitDone(aCDM, Move(mData));
+    mGMPCDMProxy->gmp_InitDone(aCDM, Move(mData));
   }
 
 private:
-  RefPtr<CDMProxy> mCDMProxy;
-  nsAutoPtr<CDMProxy::InitData> mData;
+  RefPtr<GMPCDMProxy> mGMPCDMProxy;
+  nsAutoPtr<GMPCDMProxy::InitData> mData;
 };
 
 class gmp_InitGetGMPDecryptorCallback : public GetNodeIdCallback
 {
 public:
-  gmp_InitGetGMPDecryptorCallback(CDMProxy* aCDMProxy,
-                                  nsAutoPtr<CDMProxy::InitData>&& aData)
-    : mCDMProxy(aCDMProxy),
+  gmp_InitGetGMPDecryptorCallback(GMPCDMProxy* aGMPCDMProxy,
+                                  nsAutoPtr<GMPCDMProxy::InitData>&& aData)
+    : mGMPCDMProxy(aGMPCDMProxy),
       mData(aData)
   {
   }
 
   void Done(nsresult aResult, const nsACString& aNodeId)
   {
-    mCDMProxy->gmp_InitGetGMPDecryptor(aResult, aNodeId, Move(mData));
+    mGMPCDMProxy->gmp_InitGetGMPDecryptor(aResult, aNodeId, Move(mData));
   }
 
 private:
-  RefPtr<CDMProxy> mCDMProxy;
-  nsAutoPtr<CDMProxy::InitData> mData;
+  RefPtr<GMPCDMProxy> mGMPCDMProxy;
+  nsAutoPtr<GMPCDMProxy::InitData> mData;
 };
 
 void
-CDMProxy::gmp_Init(nsAutoPtr<InitData>&& aData)
+GMPCDMProxy::gmp_Init(nsAutoPtr<InitData>&& aData)
 {
-  MOZ_ASSERT(IsOnGMPThread());
+  MOZ_ASSERT(IsOnOwnerThread());
 
   nsCOMPtr<mozIGeckoMediaPluginService> mps =
     do_GetService("@mozilla.org/gecko-media-plugin-service;1");
   if (!mps) {
     RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
-                  NS_LITERAL_CSTRING("Couldn't get MediaPluginService in CDMProxy::gmp_Init"));
+                  NS_LITERAL_CSTRING("Couldn't get MediaPluginService in GMPCDMProxy::gmp_Init"));
     return;
   }
 
   // Make a copy before we transfer ownership of aData to the
   // gmp_InitGetGMPDecryptorCallback.
   InitData data(*aData);
   UniquePtr<GetNodeIdCallback> callback(
     new gmp_InitGetGMPDecryptorCallback(this, Move(aData)));
@@ -193,39 +196,39 @@ CDMProxy::gmp_Init(nsAutoPtr<InitData>&&
                                Move(callback));
   if (NS_FAILED(rv)) {
     RejectPromise(data.mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
                   NS_LITERAL_CSTRING("Call to GetNodeId() failed early"));
   }
 }
 
 void
-CDMProxy::gmp_InitGetGMPDecryptor(nsresult aResult,
-                                  const nsACString& aNodeId,
-                                  nsAutoPtr<InitData>&& aData)
+GMPCDMProxy::gmp_InitGetGMPDecryptor(nsresult aResult,
+                                     const nsACString& aNodeId,
+                                     nsAutoPtr<InitData>&& aData)
 {
   uint32_t promiseID = aData->mPromiseId;
   if (NS_FAILED(aResult)) {
     RejectPromise(promiseID, NS_ERROR_DOM_INVALID_STATE_ERR,
                   NS_LITERAL_CSTRING("GetNodeId() called back, but with a failure result"));
     return;
   }
 
   mNodeId = aNodeId;
   MOZ_ASSERT(!GetNodeId().IsEmpty());
 
   nsCOMPtr<mozIGeckoMediaPluginService> mps =
     do_GetService("@mozilla.org/gecko-media-plugin-service;1");
   if (!mps) {
     RejectPromise(promiseID, NS_ERROR_DOM_INVALID_STATE_ERR,
-                  NS_LITERAL_CSTRING("Couldn't get MediaPluginService in CDMProxy::gmp_InitGetGMPDecryptor"));
+                  NS_LITERAL_CSTRING("Couldn't get MediaPluginService in GMPCDMProxy::gmp_InitGetGMPDecryptor"));
     return;
   }
 
-  EME_LOG("CDMProxy::gmp_Init (%s, %s) %s NodeId=%s",
+  EME_LOG("GMPCDMProxy::gmp_Init (%s, %s) %s NodeId=%s",
           NS_ConvertUTF16toUTF8(aData->mOrigin).get(),
           NS_ConvertUTF16toUTF8(aData->mTopLevelOrigin).get(),
           (aData->mInPrivateBrowsing ? "PrivateBrowsing" : "NonPrivateBrowsing"),
           GetNodeId().get());
 
   nsTArray<nsCString> tags;
   tags.AppendElement(NS_ConvertUTF16toUTF8(mKeySystem));
 
@@ -237,236 +240,236 @@ CDMProxy::gmp_InitGetGMPDecryptor(nsresu
   nsresult rv = mps->GetGMPDecryptor(crashHelper, &tags, GetNodeId(), Move(callback));
   if (NS_FAILED(rv)) {
     RejectPromise(promiseID, NS_ERROR_DOM_INVALID_STATE_ERR,
                   NS_LITERAL_CSTRING("Call to GetGMPDecryptor() failed early"));
   }
 }
 
 void
-CDMProxy::OnCDMCreated(uint32_t aPromiseId)
+GMPCDMProxy::OnCDMCreated(uint32_t aPromiseId)
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (mKeys.IsNull()) {
     return;
   }
   MOZ_ASSERT(!GetNodeId().IsEmpty());
   if (mCDM) {
     mKeys->OnCDMCreated(aPromiseId, GetNodeId(), mCDM->GetPluginId());
   } else {
     // No CDM? Just reject the promise.
     mKeys->RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
                          NS_LITERAL_CSTRING("Null CDM in OnCDMCreated()"));
   }
 }
 
 void
-CDMProxy::CreateSession(uint32_t aCreateSessionToken,
-                        dom::SessionType aSessionType,
-                        PromiseId aPromiseId,
-                        const nsAString& aInitDataType,
-                        nsTArray<uint8_t>& aInitData)
+GMPCDMProxy::CreateSession(uint32_t aCreateSessionToken,
+                           dom::SessionType aSessionType,
+                           PromiseId aPromiseId,
+                           const nsAString& aInitDataType,
+                           nsTArray<uint8_t>& aInitData)
 {
   MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(mGMPThread);
+  MOZ_ASSERT(mOwnerThread);
 
   nsAutoPtr<CreateSessionData> data(new CreateSessionData());
   data->mSessionType = aSessionType;
   data->mCreateSessionToken = aCreateSessionToken;
   data->mPromiseId = aPromiseId;
   data->mInitDataType = NS_ConvertUTF16toUTF8(aInitDataType);
   data->mInitData = Move(aInitData);
 
   nsCOMPtr<nsIRunnable> task(
-    NewRunnableMethod<nsAutoPtr<CreateSessionData>>(this, &CDMProxy::gmp_CreateSession, data));
-  mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
+    NewRunnableMethod<nsAutoPtr<CreateSessionData>>(this, &GMPCDMProxy::gmp_CreateSession, data));
+  mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
 }
 
 GMPSessionType
 ToGMPSessionType(dom::SessionType aSessionType) {
   switch (aSessionType) {
     case dom::SessionType::Temporary: return kGMPTemporySession;
     case dom::SessionType::Persistent: return kGMPPersistentSession;
     default: return kGMPTemporySession;
   };
 };
 
 void
-CDMProxy::gmp_CreateSession(nsAutoPtr<CreateSessionData> aData)
+GMPCDMProxy::gmp_CreateSession(nsAutoPtr<CreateSessionData> aData)
 {
-  MOZ_ASSERT(IsOnGMPThread());
+  MOZ_ASSERT(IsOnOwnerThread());
   if (!mCDM) {
     RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
                   NS_LITERAL_CSTRING("Null CDM in gmp_CreateSession"));
     return;
   }
   mCDM->CreateSession(aData->mCreateSessionToken,
                       aData->mPromiseId,
                       aData->mInitDataType,
                       aData->mInitData,
                       ToGMPSessionType(aData->mSessionType));
 }
 
 void
-CDMProxy::LoadSession(PromiseId aPromiseId,
-                      const nsAString& aSessionId)
+GMPCDMProxy::LoadSession(PromiseId aPromiseId,
+                         const nsAString& aSessionId)
 {
   MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(mGMPThread);
+  MOZ_ASSERT(mOwnerThread);
 
   nsAutoPtr<SessionOpData> data(new SessionOpData());
   data->mPromiseId = aPromiseId;
   data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId);
   nsCOMPtr<nsIRunnable> task(
-    NewRunnableMethod<nsAutoPtr<SessionOpData>>(this, &CDMProxy::gmp_LoadSession, data));
-  mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
+    NewRunnableMethod<nsAutoPtr<SessionOpData>>(this, &GMPCDMProxy::gmp_LoadSession, data));
+  mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
 }
 
 void
-CDMProxy::gmp_LoadSession(nsAutoPtr<SessionOpData> aData)
+GMPCDMProxy::gmp_LoadSession(nsAutoPtr<SessionOpData> aData)
 {
-  MOZ_ASSERT(IsOnGMPThread());
+  MOZ_ASSERT(IsOnOwnerThread());
 
   if (!mCDM) {
     RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
                   NS_LITERAL_CSTRING("Null CDM in gmp_LoadSession"));
     return;
   }
   mCDM->LoadSession(aData->mPromiseId, aData->mSessionId);
 }
 
 void
-CDMProxy::SetServerCertificate(PromiseId aPromiseId,
-                               nsTArray<uint8_t>& aCert)
+GMPCDMProxy::SetServerCertificate(PromiseId aPromiseId,
+                                  nsTArray<uint8_t>& aCert)
 {
   MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(mGMPThread);
+  MOZ_ASSERT(mOwnerThread);
 
   nsAutoPtr<SetServerCertificateData> data(new SetServerCertificateData());
   data->mPromiseId = aPromiseId;
   data->mCert = Move(aCert);
   nsCOMPtr<nsIRunnable> task(
-    NewRunnableMethod<nsAutoPtr<SetServerCertificateData>>(this, &CDMProxy::gmp_SetServerCertificate, data));
-  mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
+    NewRunnableMethod<nsAutoPtr<SetServerCertificateData>>(this, &GMPCDMProxy::gmp_SetServerCertificate, data));
+  mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
 }
 
 void
-CDMProxy::gmp_SetServerCertificate(nsAutoPtr<SetServerCertificateData> aData)
+GMPCDMProxy::gmp_SetServerCertificate(nsAutoPtr<SetServerCertificateData> aData)
 {
-  MOZ_ASSERT(IsOnGMPThread());
+  MOZ_ASSERT(IsOnOwnerThread());
   if (!mCDM) {
     RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
                   NS_LITERAL_CSTRING("Null CDM in gmp_SetServerCertificate"));
     return;
   }
   mCDM->SetServerCertificate(aData->mPromiseId, aData->mCert);
 }
 
 void
-CDMProxy::UpdateSession(const nsAString& aSessionId,
-                        PromiseId aPromiseId,
-                        nsTArray<uint8_t>& aResponse)
+GMPCDMProxy::UpdateSession(const nsAString& aSessionId,
+                           PromiseId aPromiseId,
+                           nsTArray<uint8_t>& aResponse)
 {
   MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(mGMPThread);
+  MOZ_ASSERT(mOwnerThread);
   NS_ENSURE_TRUE_VOID(!mKeys.IsNull());
 
   nsAutoPtr<UpdateSessionData> data(new UpdateSessionData());
   data->mPromiseId = aPromiseId;
   data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId);
   data->mResponse = Move(aResponse);
   nsCOMPtr<nsIRunnable> task(
-    NewRunnableMethod<nsAutoPtr<UpdateSessionData>>(this, &CDMProxy::gmp_UpdateSession, data));
-  mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
+    NewRunnableMethod<nsAutoPtr<UpdateSessionData>>(this, &GMPCDMProxy::gmp_UpdateSession, data));
+  mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
 }
 
 void
-CDMProxy::gmp_UpdateSession(nsAutoPtr<UpdateSessionData> aData)
+GMPCDMProxy::gmp_UpdateSession(nsAutoPtr<UpdateSessionData> aData)
 {
-  MOZ_ASSERT(IsOnGMPThread());
+  MOZ_ASSERT(IsOnOwnerThread());
   if (!mCDM) {
     RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
                   NS_LITERAL_CSTRING("Null CDM in gmp_UpdateSession"));
     return;
   }
   mCDM->UpdateSession(aData->mPromiseId,
                       aData->mSessionId,
                       aData->mResponse);
 }
 
 void
-CDMProxy::CloseSession(const nsAString& aSessionId,
-                       PromiseId aPromiseId)
+GMPCDMProxy::CloseSession(const nsAString& aSessionId,
+                          PromiseId aPromiseId)
 {
   MOZ_ASSERT(NS_IsMainThread());
   NS_ENSURE_TRUE_VOID(!mKeys.IsNull());
 
   nsAutoPtr<SessionOpData> data(new SessionOpData());
   data->mPromiseId = aPromiseId;
   data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId);
   nsCOMPtr<nsIRunnable> task(
-    NewRunnableMethod<nsAutoPtr<SessionOpData>>(this, &CDMProxy::gmp_CloseSession, data));
-  mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
+    NewRunnableMethod<nsAutoPtr<SessionOpData>>(this, &GMPCDMProxy::gmp_CloseSession, data));
+  mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
 }
 
 void
-CDMProxy::gmp_CloseSession(nsAutoPtr<SessionOpData> aData)
+GMPCDMProxy::gmp_CloseSession(nsAutoPtr<SessionOpData> aData)
 {
-  MOZ_ASSERT(IsOnGMPThread());
+  MOZ_ASSERT(IsOnOwnerThread());
   if (!mCDM) {
     RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
                   NS_LITERAL_CSTRING("Null CDM in gmp_CloseSession"));
     return;
   }
   mCDM->CloseSession(aData->mPromiseId, aData->mSessionId);
 }
 
 void
-CDMProxy::RemoveSession(const nsAString& aSessionId,
-                        PromiseId aPromiseId)
+GMPCDMProxy::RemoveSession(const nsAString& aSessionId,
+                           PromiseId aPromiseId)
 {
   MOZ_ASSERT(NS_IsMainThread());
   NS_ENSURE_TRUE_VOID(!mKeys.IsNull());
 
   nsAutoPtr<SessionOpData> data(new SessionOpData());
   data->mPromiseId = aPromiseId;
   data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId);
   nsCOMPtr<nsIRunnable> task(
-    NewRunnableMethod<nsAutoPtr<SessionOpData>>(this, &CDMProxy::gmp_RemoveSession, data));
-  mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
+    NewRunnableMethod<nsAutoPtr<SessionOpData>>(this, &GMPCDMProxy::gmp_RemoveSession, data));
+  mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
 }
 
 void
-CDMProxy::gmp_RemoveSession(nsAutoPtr<SessionOpData> aData)
+GMPCDMProxy::gmp_RemoveSession(nsAutoPtr<SessionOpData> aData)
 {
-  MOZ_ASSERT(IsOnGMPThread());
+  MOZ_ASSERT(IsOnOwnerThread());
   if (!mCDM) {
     RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
                   NS_LITERAL_CSTRING("Null CDM in gmp_RemoveSession"));
     return;
   }
   mCDM->RemoveSession(aData->mPromiseId, aData->mSessionId);
 }
 
 void
-CDMProxy::Shutdown()
+GMPCDMProxy::Shutdown()
 {
   MOZ_ASSERT(NS_IsMainThread());
   mKeys.Clear();
-  // Note: This may end up being the last owning reference to the CDMProxy.
-  nsCOMPtr<nsIRunnable> task(NewRunnableMethod(this, &CDMProxy::gmp_Shutdown));
-  if (mGMPThread) {
-    mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
+  // Note: This may end up being the last owning reference to the GMPCDMProxy.
+  nsCOMPtr<nsIRunnable> task(NewRunnableMethod(this, &GMPCDMProxy::gmp_Shutdown));
+  if (mOwnerThread) {
+    mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
   }
 }
 
 void
-CDMProxy::gmp_Shutdown()
+GMPCDMProxy::gmp_Shutdown()
 {
-  MOZ_ASSERT(IsOnGMPThread());
+  MOZ_ASSERT(IsOnOwnerThread());
 
   mShutdownCalled = true;
 
   // Abort any pending decrypt jobs, to awaken any clients waiting on a job.
   for (size_t i = 0; i < mDecryptionJobs.Length(); i++) {
     DecryptJob* job = mDecryptionJobs[i];
     job->PostResult(GMPAbortedErr);
   }
@@ -474,230 +477,228 @@ CDMProxy::gmp_Shutdown()
 
   if (mCDM) {
     mCDM->Close();
     mCDM = nullptr;
   }
 }
 
 void
-CDMProxy::RejectPromise(PromiseId aId, nsresult aCode,
-                        const nsCString& aReason)
+GMPCDMProxy::RejectPromise(PromiseId aId, nsresult aCode,
+                           const nsCString& aReason)
 {
   if (NS_IsMainThread()) {
     if (!mKeys.IsNull()) {
       mKeys->RejectPromise(aId, aCode, aReason);
     }
   } else {
     nsCOMPtr<nsIRunnable> task(new RejectPromiseTask(this, aId, aCode,
                                                      aReason));
     NS_DispatchToMainThread(task);
   }
 }
 
 void
-CDMProxy::ResolvePromise(PromiseId aId)
+GMPCDMProxy::ResolvePromise(PromiseId aId)
 {
   if (NS_IsMainThread()) {
     if (!mKeys.IsNull()) {
       mKeys->ResolvePromise(aId);
     } else {
-      NS_WARNING("CDMProxy unable to resolve promise!");
+      NS_WARNING("GMPCDMProxy unable to resolve promise!");
     }
   } else {
     nsCOMPtr<nsIRunnable> task;
     task = NewRunnableMethod<PromiseId>(this,
-                                        &CDMProxy::ResolvePromise,
+                                        &GMPCDMProxy::ResolvePromise,
                                         aId);
     NS_DispatchToMainThread(task);
   }
 }
 
 const nsCString&
-CDMProxy::GetNodeId() const
+GMPCDMProxy::GetNodeId() const
 {
   return mNodeId;
 }
 
 void
-CDMProxy::OnSetSessionId(uint32_t aCreateSessionToken,
-                         const nsAString& aSessionId)
+GMPCDMProxy::OnSetSessionId(uint32_t aCreateSessionToken,
+                            const nsAString& aSessionId)
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (mKeys.IsNull()) {
     return;
   }
 
   RefPtr<dom::MediaKeySession> session(mKeys->GetPendingSession(aCreateSessionToken));
   if (session) {
     session->SetSessionId(aSessionId);
   }
 }
 
 void
-CDMProxy::OnResolveLoadSessionPromise(uint32_t aPromiseId, bool aSuccess)
+GMPCDMProxy::OnResolveLoadSessionPromise(uint32_t aPromiseId, bool aSuccess)
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (mKeys.IsNull()) {
     return;
   }
   mKeys->OnSessionLoaded(aPromiseId, aSuccess);
 }
 
-static dom::MediaKeyMessageType
-ToMediaKeyMessageType(GMPSessionMessageType aMessageType) {
-  switch (aMessageType) {
-    case kGMPLicenseRequest: return dom::MediaKeyMessageType::License_request;
-    case kGMPLicenseRenewal: return dom::MediaKeyMessageType::License_renewal;
-    case kGMPLicenseRelease: return dom::MediaKeyMessageType::License_release;
-    case kGMPIndividualizationRequest: return dom::MediaKeyMessageType::Individualization_request;
-    default: return dom::MediaKeyMessageType::License_request;
-  };
-};
-
 void
-CDMProxy::OnSessionMessage(const nsAString& aSessionId,
-                           GMPSessionMessageType aMessageType,
-                           nsTArray<uint8_t>& aMessage)
+GMPCDMProxy::OnSessionMessage(const nsAString& aSessionId,
+                              dom::MediaKeyMessageType aMessageType,
+                              nsTArray<uint8_t>& aMessage)
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (mKeys.IsNull()) {
     return;
   }
   RefPtr<dom::MediaKeySession> session(mKeys->GetSession(aSessionId));
   if (session) {
-    session->DispatchKeyMessage(ToMediaKeyMessageType(aMessageType), aMessage);
+    session->DispatchKeyMessage(aMessageType, aMessage);
   }
 }
 
 void
-CDMProxy::OnKeyStatusesChange(const nsAString& aSessionId)
+GMPCDMProxy::OnKeyStatusesChange(const nsAString& aSessionId)
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (mKeys.IsNull()) {
     return;
   }
   RefPtr<dom::MediaKeySession> session(mKeys->GetSession(aSessionId));
   if (session) {
     session->DispatchKeyStatusesChange();
   }
 }
 
 void
-CDMProxy::OnExpirationChange(const nsAString& aSessionId,
-                             GMPTimestamp aExpiryTime)
+GMPCDMProxy::OnExpirationChange(const nsAString& aSessionId,
+                                GMPTimestamp aExpiryTime)
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (mKeys.IsNull()) {
     return;
   }
   RefPtr<dom::MediaKeySession> session(mKeys->GetSession(aSessionId));
   if (session) {
     session->SetExpiration(static_cast<double>(aExpiryTime));
   }
 }
 
 void
-CDMProxy::OnSessionClosed(const nsAString& aSessionId)
+GMPCDMProxy::OnSessionClosed(const nsAString& aSessionId)
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (mKeys.IsNull()) {
     return;
   }
   RefPtr<dom::MediaKeySession> session(mKeys->GetSession(aSessionId));
   if (session) {
     session->OnClosed();
   }
 }
 
+void
+GMPCDMProxy::OnDecrypted(uint32_t aId,
+                         GMPErr aResult,
+                         const nsTArray<uint8_t>& aDecryptedData)
+{
+  MOZ_ASSERT(IsOnOwnerThread());
+  gmp_Decrypted(aId, aResult, aDecryptedData);
+}
+
 static void
 LogToConsole(const nsAString& aMsg)
 {
   nsCOMPtr<nsIConsoleService> console(
     do_GetService("@mozilla.org/consoleservice;1"));
   if (!console) {
     NS_WARNING("Failed to log message to console.");
     return;
   }
   nsAutoString msg(aMsg);
   console->LogStringMessage(msg.get());
 }
 
 void
-CDMProxy::OnSessionError(const nsAString& aSessionId,
+GMPCDMProxy::OnSessionError(const nsAString& aSessionId,
                          nsresult aException,
                          uint32_t aSystemCode,
                          const nsAString& aMsg)
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (mKeys.IsNull()) {
     return;
   }
   RefPtr<dom::MediaKeySession> session(mKeys->GetSession(aSessionId));
   if (session) {
     session->DispatchKeyError(aSystemCode);
   }
   LogToConsole(aMsg);
 }
 
 void
-CDMProxy::OnRejectPromise(uint32_t aPromiseId,
+GMPCDMProxy::OnRejectPromise(uint32_t aPromiseId,
                           nsresult aDOMException,
                           const nsCString& aMsg)
 {
   MOZ_ASSERT(NS_IsMainThread());
   RejectPromise(aPromiseId, aDOMException, aMsg);
 }
 
 const nsString&
-CDMProxy::KeySystem() const
+GMPCDMProxy::KeySystem() const
 {
   return mKeySystem;
 }
 
 CDMCaps&
-CDMProxy::Capabilites() {
+GMPCDMProxy::Capabilites() {
   return mCapabilites;
 }
 
-RefPtr<CDMProxy::DecryptPromise>
-CDMProxy::Decrypt(MediaRawData* aSample)
+RefPtr<GMPCDMProxy::DecryptPromise>
+GMPCDMProxy::Decrypt(MediaRawData* aSample)
 {
   RefPtr<DecryptJob> job(new DecryptJob(aSample));
   RefPtr<DecryptPromise> promise(job->Ensure());
 
   nsCOMPtr<nsIRunnable> task(
-    NewRunnableMethod<RefPtr<DecryptJob>>(this, &CDMProxy::gmp_Decrypt, job));
-  mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
+    NewRunnableMethod<RefPtr<DecryptJob>>(this, &GMPCDMProxy::gmp_Decrypt, job));
+  mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
   return promise;
 }
 
 void
-CDMProxy::gmp_Decrypt(RefPtr<DecryptJob> aJob)
+GMPCDMProxy::gmp_Decrypt(RefPtr<DecryptJob> aJob)
 {
-  MOZ_ASSERT(IsOnGMPThread());
+  MOZ_ASSERT(IsOnOwnerThread());
 
   if (!mCDM) {
     aJob->PostResult(GMPAbortedErr);
     return;
   }
 
   aJob->mId = ++mDecryptionJobCount;
   nsTArray<uint8_t> data;
   data.AppendElements(aJob->mSample->Data(), aJob->mSample->Size());
   mCDM->Decrypt(aJob->mId, aJob->mSample->mCrypto, data);
   mDecryptionJobs.AppendElement(aJob.forget());
 }
 
 void
-CDMProxy::gmp_Decrypted(uint32_t aId,
-                        GMPErr aResult,
-                        const nsTArray<uint8_t>& aDecryptedData)
+GMPCDMProxy::gmp_Decrypted(uint32_t aId,
+                           GMPErr aResult,
+                           const nsTArray<uint8_t>& aDecryptedData)
 {
-  MOZ_ASSERT(IsOnGMPThread());
+  MOZ_ASSERT(IsOnOwnerThread());
 #ifdef DEBUG
   bool jobIdFound = false;
 #endif
   for (size_t i = 0; i < mDecryptionJobs.Length(); i++) {
     DecryptJob* job = mDecryptionJobs[i];
     if (job->mId == aId) {
 #ifdef DEBUG
       jobIdFound = true;
@@ -709,24 +710,25 @@ CDMProxy::gmp_Decrypted(uint32_t aId,
 #ifdef DEBUG
   if (!jobIdFound) {
     NS_WARNING("GMPDecryptorChild returned incorrect job ID");
   }
 #endif
 }
 
 void
-CDMProxy::DecryptJob::PostResult(GMPErr aResult)
+GMPCDMProxy::DecryptJob::PostResult(GMPErr aResult)
 {
   nsTArray<uint8_t> empty;
   PostResult(aResult, empty);
 }
 
 void
-CDMProxy::DecryptJob::PostResult(GMPErr aResult, const nsTArray<uint8_t>& aDecryptedData)
+GMPCDMProxy::DecryptJob::PostResult(GMPErr aResult,
+                                    const nsTArray<uint8_t>& aDecryptedData)
 {
   if (aDecryptedData.Length() != mSample->Size()) {
     NS_WARNING("CDM returned incorrect number of decrypted bytes");
   }
   if (GMP_SUCCEEDED(aResult)) {
     nsAutoPtr<MediaRawDataWriter> writer(mSample->CreateWriter());
     PodCopy(writer->Data(),
             aDecryptedData.Elements(),
@@ -739,25 +741,25 @@ CDMProxy::DecryptJob::PostResult(GMPErr 
     nsAutoCString str("CDM returned decode failure GMPErr=");
     str.AppendInt(aResult);
     NS_WARNING(str.get());
   }
   mPromise.Resolve(DecryptResult(aResult, mSample), __func__);
 }
 
 void
-CDMProxy::GetSessionIdsForKeyId(const nsTArray<uint8_t>& aKeyId,
-                                nsTArray<nsCString>& aSessionIds)
+GMPCDMProxy::GetSessionIdsForKeyId(const nsTArray<uint8_t>& aKeyId,
+                                   nsTArray<nsCString>& aSessionIds)
 {
   CDMCaps::AutoLock caps(Capabilites());
   caps.GetSessionIdsForKeyId(aKeyId, aSessionIds);
 }
 
 void
-CDMProxy::Terminated()
+GMPCDMProxy::Terminated()
 {
   MOZ_ASSERT(NS_IsMainThread());
   NS_WARNING("CDM terminated");
   if (!mKeys.IsNull()) {
     mKeys->Terminated();
   }
 }
 
copy from dom/media/eme/CDMProxy.h
copy to dom/media/gmp/GMPCDMProxy.h
--- a/dom/media/eme/CDMProxy.h
+++ b/dom/media/gmp/GMPCDMProxy.h
@@ -1,188 +1,115 @@
 /* -*- 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 CDMProxy_h_
-#define CDMProxy_h_
+#ifndef GMPCDMProxy_h_
+#define GMPCDMProxy_h_
 
-#include "mozilla/CDMCaps.h"
-#include "mozilla/Monitor.h"
-#include "mozilla/MozPromise.h"
-
-#include "mozilla/dom/MediaKeys.h"
-
-#include "nsIThread.h"
-#include "nsString.h"
-#include "nsAutoPtr.h"
+#include "mozilla/CDMProxy.h"
+#include "GMPCDMCallbackProxy.h"
 #include "GMPDecryptorProxy.h"
 
 namespace mozilla {
 class MediaRawData;
-class GMPCDMCallbackProxy;
 
-namespace dom {
-class MediaKeySession;
-} // namespace dom
-
-struct DecryptResult {
-  DecryptResult(GMPErr aStatus, MediaRawData* aSample)
-    : mStatus(aStatus)
-    , mSample(aSample)
-  {}
-  GMPErr mStatus;
-  RefPtr<MediaRawData> mSample;
-};
-
-// 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;
+// Implementation of CDMProxy which is based on GMP architecture.
+class GMPCDMProxy : public CDMProxy {
 public:
 
-  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CDMProxy)
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPCDMProxy, override)
 
   typedef MozPromise<DecryptResult, DecryptResult, /* IsExclusive = */ true> DecryptPromise;
 
-  // Main thread only.
-  CDMProxy(dom::MediaKeys* aKeys, const nsAString& aKeySystem);
+  GMPCDMProxy(dom::MediaKeys* aKeys,
+              const nsAString& aKeySystem,
+              GMPCrashHelper* aCrashHelper);
 
-  // Main thread only.
-  // Loads the CDM corresponding to mKeySystem.
-  // Calls MediaKeys::OnCDMCreated() when the CDM is created.
   void Init(PromiseId aPromiseId,
             const nsAString& aOrigin,
             const nsAString& aTopLevelOrigin,
             const nsAString& aGMPName,
-            bool aInPrivateBrowsing,
-            GMPCrashHelper* aHelper);
+            bool aInPrivateBrowsing) override;
 
-  // Main thread only.
-  // Uses the CDM to create a key session.
-  // Calls MediaKeys::OnSessionActivated() when session is created.
-  // Assumes ownership of (Move()s) aInitData's contents.
   void CreateSession(uint32_t aCreateSessionToken,
                      dom::SessionType aSessionType,
                      PromiseId aPromiseId,
                      const nsAString& aInitDataType,
-                     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);
+                     nsTArray<uint8_t>& aInitData) override;
 
-  // Main thread only.
-  // Sends a new certificate to the CDM.
-  // Calls MediaKeys->ResolvePromise(aPromiseId) after the CDM has
-  // processed the request.
-  // Assumes ownership of (Move()s) aCert's contents.
+  void LoadSession(PromiseId aPromiseId,
+                   const nsAString& aSessionId) override;
+
   void SetServerCertificate(PromiseId aPromiseId,
-                            nsTArray<uint8_t>& aCert);
+                            nsTArray<uint8_t>& aCert) override;
 
-  // Main thread only.
-  // Sends an update to the CDM.
-  // 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,
-                     nsTArray<uint8_t>& aResponse);
+                     nsTArray<uint8_t>& aResponse) override;
 
-  // 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,
-                    PromiseId aPromiseId);
+                    PromiseId aPromiseId) override;
 
-  // Main thread only.
-  // Removes all data for a persisent session.
-  // Calls MediaKeys->ResolvePromise(aPromiseId) after the CDM has
-  // processed the request.
   void RemoveSession(const nsAString& aSessionId,
-                     PromiseId aPromiseId);
+                     PromiseId aPromiseId) override;
+
+  void Shutdown() override;
 
-  // Main thread only.
-  void Shutdown();
+  void Terminated() override;
 
-  // Main thread only.
-  void Terminated();
+  const nsCString& GetNodeId() const override;
 
-  // Threadsafe.
-  const nsCString& GetNodeId() const;
+  void OnSetSessionId(uint32_t aCreateSessionToken,
+                      const nsAString& aSessionId) override;
 
-  // Main thread only.
-  void OnSetSessionId(uint32_t aCreateSessionToken,
-                      const nsAString& aSessionId);
+  void OnResolveLoadSessionPromise(uint32_t aPromiseId, bool aSuccess) override;
 
-  // Main thread only.
-  void OnResolveLoadSessionPromise(uint32_t aPromiseId, bool aSuccess);
-
-  // Main thread only.
   void OnSessionMessage(const nsAString& aSessionId,
-                        GMPSessionMessageType aMessageType,
-                        nsTArray<uint8_t>& aMessage);
+                        dom::MediaKeyMessageType aMessageType,
+                        nsTArray<uint8_t>& aMessage) override;
 
-  // Main thread only.
   void OnExpirationChange(const nsAString& aSessionId,
-                          GMPTimestamp aExpiryTime);
+                          GMPTimestamp aExpiryTime) override;
 
-  // Main thread only.
-  void OnSessionClosed(const nsAString& aSessionId);
+  void OnSessionClosed(const nsAString& aSessionId) override;
 
-  // Main thread only.
   void OnSessionError(const nsAString& aSessionId,
                       nsresult aException,
                       uint32_t aSystemCode,
-                      const nsAString& aMsg);
+                      const nsAString& aMsg) override;
 
-  // Main thread only.
   void OnRejectPromise(uint32_t aPromiseId,
                        nsresult aDOMException,
-                       const nsCString& aMsg);
+                       const nsCString& aMsg) override;
 
-  RefPtr<DecryptPromise> Decrypt(MediaRawData* aSample);
+  RefPtr<DecryptPromise> Decrypt(MediaRawData* aSample) override;
 
-  // Reject promise with DOMException corresponding to aExceptionCode.
-  // Can be called from any thread.
-  void RejectPromise(PromiseId aId, nsresult aExceptionCode,
-                     const nsCString& aReason);
-
-  // Resolves promise with "undefined".
-  // Can be called from any thread.
-  void ResolvePromise(PromiseId aId);
+  void OnDecrypted(uint32_t aId,
+                   GMPErr aResult,
+                   const nsTArray<uint8_t>& aDecryptedData) override;
 
-  // Threadsafe.
-  const nsString& KeySystem() const;
+  void RejectPromise(PromiseId aId, nsresult aExceptionCode,
+                     const nsCString& aReason) override;
+
+  void ResolvePromise(PromiseId aId) override;
 
-  // GMP thread only.
-  void gmp_Decrypted(uint32_t aId,
-                     GMPErr aResult,
-                     const nsTArray<uint8_t>& aDecryptedData);
+  const nsString& KeySystem() const override;
 
-  CDMCaps& Capabilites();
+  CDMCaps& Capabilites() override;
 
-  // Main thread only.
-  void OnKeyStatusesChange(const nsAString& aSessionId);
+  void OnKeyStatusesChange(const nsAString& aSessionId) override;
 
   void GetSessionIdsForKeyId(const nsTArray<uint8_t>& aKeyId,
-                             nsTArray<nsCString>& aSessionIds);
+                             nsTArray<nsCString>& aSessionIds) override;
 
 #ifdef DEBUG
-  bool IsOnGMPThread();
+  bool IsOnOwnerThread() override;
 #endif
 
 private:
   friend class gmp_InitDoneCallback;
   friend class gmp_InitGetGMPDecryptorCallback;
 
   struct InitData {
     uint32_t mPromiseId;
@@ -265,98 +192,66 @@ private:
     RefPtr<MediaRawData> mSample;
   private:
     ~DecryptJob() {}
     MozPromiseHolder<DecryptPromise> mPromise;
   };
   // GMP thread only.
   void gmp_Decrypt(RefPtr<DecryptJob> aJob);
 
+  // GMP thread only.
+  void gmp_Decrypted(uint32_t aId,
+                     GMPErr aResult,
+                     const nsTArray<uint8_t>& aDecryptedData);
+
   class RejectPromiseTask : public Runnable {
   public:
-    RejectPromiseTask(CDMProxy* aProxy,
+    RejectPromiseTask(GMPCDMProxy* aProxy,
                       PromiseId aId,
                       nsresult aCode,
                       const nsCString& aReason)
       : mProxy(aProxy)
       , mId(aId)
       , mCode(aCode)
       , mReason(aReason)
     {
     }
     NS_METHOD Run() {
       mProxy->RejectPromise(mId, mCode, mReason);
       return NS_OK;
     }
   private:
-    RefPtr<CDMProxy> mProxy;
+    RefPtr<GMPCDMProxy> mProxy;
     PromiseId mId;
     nsresult mCode;
     nsCString mReason;
   };
 
-  ~CDMProxy();
-
-  // Helper to enforce that a raw pointer is only accessed on the main thread.
-  template<class Type>
-  class MainThreadOnlyRawPtr {
-  public:
-    explicit MainThreadOnlyRawPtr(Type* aPtr)
-      : mPtr(aPtr)
-    {
-      MOZ_ASSERT(NS_IsMainThread());
-    }
-
-    bool IsNull() const {
-      MOZ_ASSERT(NS_IsMainThread());
-      return !mPtr;
-    }
+  ~GMPCDMProxy();
 
-    void Clear() {
-      MOZ_ASSERT(NS_IsMainThread());
-      mPtr = nullptr;
-    }
-
-    Type* operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN {
-      MOZ_ASSERT(NS_IsMainThread());
-      return mPtr;
-    }
-  private:
-    Type* mPtr;
-  };
-
-  // Our reference back to the MediaKeys object.
-  // WARNING: This is a non-owning reference that is cleared by MediaKeys
-  // destructor. only use on main thread, and always nullcheck before using!
-  MainThreadOnlyRawPtr<dom::MediaKeys> mKeys;
-
-  const nsString mKeySystem;
-
-  // Gecko Media Plugin thread. All interactions with the out-of-process
-  // EME plugin must come from this thread.
-  RefPtr<nsIThread> mGMPThread;
-
-  nsCString mNodeId;
+  GMPCrashHelper* mCrashHelper;
 
   GMPDecryptorProxy* mCDM;
+
   CDMCaps mCapabilites;
+
   nsAutoPtr<GMPCDMCallbackProxy> mCallback;
 
   // Decryption jobs sent to CDM, awaiting result.
   // GMP thread only.
   nsTArray<RefPtr<DecryptJob>> mDecryptionJobs;
 
   // Number of buffers we've decrypted. Used to uniquely identify
   // decryption jobs sent to CDM. Note we can't just use the length of
   // mDecryptionJobs as that shrinks as jobs are completed and removed
   // from it.
   // GMP thread only.
   uint32_t mDecryptionJobCount;
 
-  // True if CDMProxy::gmp_Shutdown was called.
+  // True if GMPCDMProxy::gmp_Shutdown was called.
   // GMP thread only.
   bool mShutdownCalled;
 };
 
 
 } // namespace mozilla
 
-#endif // CDMProxy_h_
+#endif // GMPCDMProxy_h_
--- a/dom/media/gmp/moz.build
+++ b/dom/media/gmp/moz.build
@@ -31,16 +31,17 @@ EXPORTS += [
     'gmp-api/gmp-video-host.h',
     'gmp-api/gmp-video-plane.h',
     'GMPAudioDecoderChild.h',
     'GMPAudioDecoderParent.h',
     'GMPAudioDecoderProxy.h',
     'GMPAudioHost.h',
     'GMPCallbackBase.h',
     'GMPCDMCallbackProxy.h',
+    'GMPCDMProxy.h',
     'GMPChild.h',
     'GMPContentChild.h',
     'GMPContentParent.h',
     'GMPCrashHelperHolder.h',
     'GMPDecryptorChild.h',
     'GMPDecryptorParent.h',
     'GMPDecryptorProxy.h',
     'GMPEncryptedBufferDataImpl.h',
@@ -82,16 +83,17 @@ if CONFIG['OS_TARGET'] == 'Android':
         'rlz',
     ]
 
 UNIFIED_SOURCES += [
     'GMPAudioDecoderChild.cpp',
     'GMPAudioDecoderParent.cpp',
     'GMPAudioHost.cpp',
     'GMPCDMCallbackProxy.cpp',
+    'GMPCDMProxy.cpp',
     'GMPChild.cpp',
     'GMPContentChild.cpp',
     'GMPContentParent.cpp',
     'GMPDecryptorChild.cpp',
     'GMPDecryptorParent.cpp',
     'GMPDiskStorage.cpp',
     'GMPEncryptedBufferDataImpl.cpp',
     'GMPMemoryStorage.cpp',