Bug 1318965 - Converts gmp-clearkey to use Chromium ContentDecryptionModule8 interface used by widevine r?cpearce draft
authorJay Harris <jharris@mozilla.com>
Thu, 12 Jan 2017 09:52:05 +1300
changeset 459506 b1e98ecd166954f0a9e7e9ad8544504210998f49
parent 459505 f58a37aa26250971d9f27039b7cb323cec26ef92
child 459507 a2d545834d4d033073a58940416a8d26765af2af
push id41243
push userbmo:jharris@mozilla.com
push dateThu, 12 Jan 2017 02:54:07 +0000
reviewerscpearce
bugs1318965
milestone53.0a1
Bug 1318965 - Converts gmp-clearkey to use Chromium ContentDecryptionModule8 interface used by widevine r?cpearce MozReview-Commit-ID: 6lOzItuuvdd
dom/media/gmp/moz.build
media/gmp-clearkey/0.1/AnnexB.cpp
media/gmp-clearkey/0.1/AnnexB.h
media/gmp-clearkey/0.1/ClearKeyAsyncShutdown.cpp
media/gmp-clearkey/0.1/ClearKeyAsyncShutdown.h
media/gmp-clearkey/0.1/ClearKeyCDM.cpp
media/gmp-clearkey/0.1/ClearKeyCDM.h
media/gmp-clearkey/0.1/ClearKeyDecryptionManager.cpp
media/gmp-clearkey/0.1/ClearKeyDecryptionManager.h
media/gmp-clearkey/0.1/ClearKeyPersistence.cpp
media/gmp-clearkey/0.1/ClearKeyPersistence.h
media/gmp-clearkey/0.1/ClearKeySession.cpp
media/gmp-clearkey/0.1/ClearKeySession.h
media/gmp-clearkey/0.1/ClearKeySessionManager.cpp
media/gmp-clearkey/0.1/ClearKeySessionManager.h
media/gmp-clearkey/0.1/ClearKeyStorage.cpp
media/gmp-clearkey/0.1/ClearKeyStorage.h
media/gmp-clearkey/0.1/ClearKeyUtils.cpp
media/gmp-clearkey/0.1/ClearKeyUtils.h
media/gmp-clearkey/0.1/RefCounted.h
media/gmp-clearkey/0.1/VideoDecoder.cpp
media/gmp-clearkey/0.1/VideoDecoder.h
media/gmp-clearkey/0.1/WMFH264Decoder.cpp
media/gmp-clearkey/0.1/WMFH264Decoder.h
media/gmp-clearkey/0.1/WMFUtils.h
media/gmp-clearkey/0.1/gmp-clearkey.cpp
media/gmp-clearkey/0.1/gmp-task-utils-generated.h
media/gmp-clearkey/0.1/gmp-task-utils.h
media/gmp-clearkey/0.1/moz.build
--- a/dom/media/gmp/moz.build
+++ b/dom/media/gmp/moz.build
@@ -67,16 +67,17 @@ EXPORTS += [
     'GMPVideoDecoderProxy.h',
     'GMPVideoEncodedFrameImpl.h',
     'GMPVideoEncoderChild.h',
     'GMPVideoEncoderParent.h',
     'GMPVideoEncoderProxy.h',
     'GMPVideoHost.h',
     'GMPVideoi420FrameImpl.h',
     'GMPVideoPlaneImpl.h',
+    'widevine-adapter/content_decryption_module.h',
 ]
 
 # We link GMPLoader into xul on Android and Linux as its code does not
 # need to be covered by a DRM vendor's voucher.
 if CONFIG['OS_ARCH'] == 'Linux':
     SOURCES += [
       'GMPLoader.cpp',
     ]
@@ -114,17 +115,17 @@ UNIFIED_SOURCES += [
     'GMPUtils.cpp',
     'GMPVideoDecoderChild.cpp',
     'GMPVideoDecoderParent.cpp',
     'GMPVideoEncodedFrameImpl.cpp',
     'GMPVideoEncoderChild.cpp',
     'GMPVideoEncoderParent.cpp',
     'GMPVideoHost.cpp',
     'GMPVideoi420FrameImpl.cpp',
-    'GMPVideoPlaneImpl.cpp',
+    'GMPVideoPlaneImpl.cpp'
 ]
 
 DIRS += [
     'rlz',
     'widevine-adapter',
 ]
 
 IPDL_SOURCES += [
deleted file mode 100644
--- a/media/gmp-clearkey/0.1/AnnexB.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright 2015, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "AnnexB.h"
-#include "BigEndian.h"
-
-#include <cstring>
-
-using mozilla::BigEndian;
-
-static const uint8_t kAnnexBDelimiter[] = { 0, 0, 0, 1 };
-
-/* static */ void
-AnnexB::ConvertFrameInPlace(std::vector<uint8_t>& aBuffer)
-{
-  for (size_t i = 0; i < aBuffer.size() - 4 - sizeof(kAnnexBDelimiter) + 1; ) {
-    uint32_t nalLen = BigEndian::readUint32(&aBuffer[i]);
-    memcpy(&aBuffer[i], kAnnexBDelimiter, sizeof(kAnnexBDelimiter));
-    i += nalLen + 4;
-  }
-}
-
-static void
-ConvertParamSetToAnnexB(std::vector<uint8_t>::const_iterator& aIter,
-                        size_t aCount,
-                        std::vector<uint8_t>& aOutAnnexB)
-{
-  for (size_t i = 0; i < aCount; i++) {
-    aOutAnnexB.insert(aOutAnnexB.end(), kAnnexBDelimiter,
-                      kAnnexBDelimiter + sizeof(kAnnexBDelimiter));
-
-    uint16_t len = BigEndian::readUint16(&*aIter); aIter += 2;
-    aOutAnnexB.insert(aOutAnnexB.end(), aIter, aIter + len); aIter += len;
-  }
-}
-
-/* static */ void
-AnnexB::ConvertConfig(const std::vector<uint8_t>& aBuffer,
-                      std::vector<uint8_t>& aOutAnnexB)
-{
-  // Skip past irrelevant headers
-  auto it = aBuffer.begin() + 5;
-
-  if (it >= aBuffer.end()) {
-    return;
-  }
-
-  size_t count = *(it++) & 31;
-
-  // Check that we have enough bytes for the Annex B conversion
-  // and the next size field. Bail if not.
-  if (it + count * 2 >= aBuffer.end()) {
-    return;
-  }
-
-  ConvertParamSetToAnnexB(it, count, aOutAnnexB);
-
-  // Check that we have enough bytes for the Annex B conversion.
-  count = *(it++);
-  if (it + count * 2 > aBuffer.end()) {
-    aOutAnnexB.clear();
-    return;
-  }
-
-  ConvertParamSetToAnnexB(it, count, aOutAnnexB);
-}
deleted file mode 100644
--- a/media/gmp-clearkey/0.1/AnnexB.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2015, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __AnnexB_h__
-#define __AnnexB_h__
-
-#include <cstdint>
-#include <vector>
-
-class AnnexB
-{
-public:
-  static void ConvertFrameInPlace(std::vector<uint8_t>& aBuffer);
-
-  static void ConvertConfig(const std::vector<uint8_t>& aBuffer,
-                            std::vector<uint8_t>& aOutAnnexB);
-};
-
-#endif // __AnnexB_h__
deleted file mode 100644
--- a/media/gmp-clearkey/0.1/ClearKeyAsyncShutdown.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2015, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "ClearKeyAsyncShutdown.h"
-#include "gmp-task-utils.h"
-
-ClearKeyAsyncShutdown::ClearKeyAsyncShutdown(GMPAsyncShutdownHost *aHostAPI)
-  : mHost(aHostAPI)
-{
-  CK_LOGD("ClearKeyAsyncShutdown::ClearKeyAsyncShutdown");
-  AddRef();
-}
-
-ClearKeyAsyncShutdown::~ClearKeyAsyncShutdown()
-{
-  CK_LOGD("ClearKeyAsyncShutdown::~ClearKeyAsyncShutdown");
-}
-
-void ShutdownTask(ClearKeyAsyncShutdown* aSelf, GMPAsyncShutdownHost* aHost)
-{
-  // Dumb implementation that just immediately reports completion.
-  // Real GMPs should ensure they are properly shutdown.
-  CK_LOGD("ClearKeyAsyncShutdown::BeginShutdown calling ShutdownComplete");
-  aHost->ShutdownComplete();
-  aSelf->Release();
-}
-
-void ClearKeyAsyncShutdown::BeginShutdown()
-{
-  CK_LOGD("ClearKeyAsyncShutdown::BeginShutdown dispatching asynchronous shutdown task");
-  GetPlatform()->runonmainthread(WrapTaskNM(ShutdownTask, this, mHost));
-}
deleted file mode 100644
--- a/media/gmp-clearkey/0.1/ClearKeyAsyncShutdown.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2015, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __ClearKeyAsyncShutdown_h__
-#define __ClearKeyAsyncShutdown_h__
-
-#include "gmp-api/gmp-async-shutdown.h"
-#include "RefCounted.h"
-
-class ClearKeyAsyncShutdown : public GMPAsyncShutdown
-                            , public RefCounted
-{
-public:
-  explicit ClearKeyAsyncShutdown(GMPAsyncShutdownHost *aHostAPI);
-
-  void BeginShutdown() override;
-
-private:
-  virtual ~ClearKeyAsyncShutdown();
-
-  GMPAsyncShutdownHost* mHost;
-};
-
-#endif // __ClearKeyAsyncShutdown_h__
new file mode 100644
--- /dev/null
+++ b/media/gmp-clearkey/0.1/ClearKeyCDM.cpp
@@ -0,0 +1,195 @@
+#include "ClearKeyCDM.h"
+
+#include "ClearKeyUtils.h"
+
+using namespace cdm;
+
+ClearKeyCDM::ClearKeyCDM(Host_8* aHost)
+{
+  mHost = aHost;
+  mSessionManager = new ClearKeySessionManager(mHost);
+}
+
+void
+ClearKeyCDM::Initialize(bool aAllowDistinctiveIdentifier,
+                        bool aAllowPersistentState)
+{
+  mSessionManager->Init(aAllowDistinctiveIdentifier,
+                        aAllowPersistentState);
+
+#ifdef ENABLE_WMF
+  mVideoDecoder = new VideoDecoder(mHost);
+#endif
+}
+
+void
+ClearKeyCDM::SetServerCertificate(uint32_t aPromiseId,
+                                  const uint8_t* aServerCertificateData,
+                                  uint32_t aServerCertificateDataSize)
+{
+  mSessionManager->SetServerCertificate(aPromiseId,
+                                        aServerCertificateData,
+                                        aServerCertificateDataSize);
+}
+
+void
+ClearKeyCDM::CreateSessionAndGenerateRequest(uint32_t aPromiseId,
+                                             SessionType aSessionType,
+                                             InitDataType aInitDataType,
+                                             const uint8_t* aInitData,
+                                             uint32_t aInitDataSize)
+{
+  mSessionManager->CreateSession(aPromiseId,
+                                 aInitDataType,
+                                 aInitData,
+                                 aInitDataSize,
+                                 aSessionType);
+}
+
+void
+ClearKeyCDM::LoadSession(uint32_t aPromiseId,
+                         SessionType aSessionType,
+                         const char* aSessionId,
+                         uint32_t aSessionIdSize)
+{
+  mSessionManager->LoadSession(aPromiseId,
+                               aSessionId,
+                               aSessionIdSize);
+}
+
+void
+ClearKeyCDM::UpdateSession(uint32_t aPromiseId,
+                           const char* aSessionId,
+                           uint32_t aSessionIdSize,
+                           const uint8_t* aResponse,
+                           uint32_t aResponseSize)
+{
+  mSessionManager->UpdateSession(aPromiseId,
+                                 aSessionId,
+                                 aSessionIdSize,
+                                 aResponse,
+                                 aResponseSize);
+}
+
+void
+ClearKeyCDM::CloseSession(uint32_t aPromiseId,
+                          const char* aSessionId,
+                          uint32_t aSessionIdSize)
+{
+  mSessionManager->CloseSession(aPromiseId,
+                                aSessionId,
+                                aSessionIdSize);
+}
+
+void
+ClearKeyCDM::RemoveSession(uint32_t aPromiseId,
+                           const char* aSessionId,
+                           uint32_t aSessionIdSize)
+{
+  mSessionManager->RemoveSession(aPromiseId,
+                                 aSessionId,
+                                 aSessionIdSize);
+}
+
+void
+ClearKeyCDM::TimerExpired(void* aContext)
+{
+  // Clearkey is not interested in timers, so this method has not been
+  // implemented.
+  assert(false);
+}
+
+Status
+ClearKeyCDM::Decrypt(const InputBuffer& aEncryptedBuffer,
+                     DecryptedBlock* aDecryptedBuffer)
+{
+  return mSessionManager->Decrypt(aEncryptedBuffer, aDecryptedBuffer);
+}
+
+Status
+ClearKeyCDM::InitializeAudioDecoder(
+  const AudioDecoderConfig& aAudioDecoderConfig)
+{
+  // Audio decoding is not supported by Clearkey because Widevine doesn't
+  // support it and Clearkey's raison d'etre is to provide test coverage
+  // for paths that Widevine will exercise in the wild.
+  return Status::kDecodeError;
+}
+
+Status
+ClearKeyCDM::InitializeVideoDecoder(
+  const VideoDecoderConfig& aVideoDecoderConfig)
+{
+#ifdef ENABLE_WMF
+  return mVideoDecoder->InitDecode(aVideoDecoderConfig);
+#else
+  return Status::kDecodeError;
+#endif
+}
+
+void
+ClearKeyCDM::DeinitializeDecoder(StreamType aDecoderType)
+{
+#ifdef ENABLE_WMF
+  if (aDecoderType == StreamType::kStreamTypeVideo) {
+    mVideoDecoder->Reset();
+  }
+#endif
+}
+
+void
+ClearKeyCDM::ResetDecoder(StreamType aDecoderType)
+{
+#ifdef ENABLE_WMF
+  if (aDecoderType == StreamType::kStreamTypeVideo) {
+    mVideoDecoder->Reset();
+  }
+#endif
+}
+
+Status
+ClearKeyCDM::DecryptAndDecodeFrame(const InputBuffer& aEncryptedBuffer,
+                                   VideoFrame* aVideoFrame)
+{
+#ifdef ENABLE_WMF
+  return mVideoDecoder->Decode(aEncryptedBuffer, aVideoFrame);
+#else
+  return Status::kDecodeError;
+#endif
+}
+
+Status
+ClearKeyCDM::DecryptAndDecodeSamples(const InputBuffer& aEncryptedBuffer,
+                                     AudioFrames* aAudioFrame)
+{
+  // Audio decoding is not supported by Clearkey because Widevine doesn't
+  // support it and Clearkey's raison d'etre is to provide test coverage
+  // for paths that Widevine will exercise in the wild.
+  return Status::kDecodeError;
+}
+
+void
+ClearKeyCDM::OnPlatformChallengeResponse(
+  const PlatformChallengeResponse& aResponse)
+{
+  // This function should never be called and is not supported.
+  assert(false);
+}
+
+void
+ClearKeyCDM::OnQueryOutputProtectionStatus(QueryResult aResult,
+                                           uint32_t aLinkMask,
+                                           uint32_t aOutputProtectionMask)
+{
+  // This function should never be called and is not supported.
+  assert(false);
+}
+
+void
+ClearKeyCDM::Destroy()
+{
+  mSessionManager->DecryptingComplete();
+#ifdef ENABLE_WMF
+  mVideoDecoder->DecodingComplete();
+#endif
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/media/gmp-clearkey/0.1/ClearKeyCDM.h
@@ -0,0 +1,98 @@
+#ifndef ClearKeyCDM_h_
+#define ClearKeyCDM_h_
+
+#include "ClearKeySessionManager.h"
+
+// This include is required in order for content_decryption_module to work
+// on Unix systems.
+#include "stddef.h"
+#include "content_decryption_module.h"
+
+#ifdef ENABLE_WMF
+#include "WMFUtils.h"
+#include "VideoDecoder.h"
+#endif
+
+class ClearKeyCDM : public cdm::ContentDecryptionModule_8
+{
+private:
+  RefPtr<ClearKeySessionManager> mSessionManager;
+#ifdef ENABLE_WMF
+  RefPtr<VideoDecoder> mVideoDecoder;
+#endif
+
+protected:
+  cdm::Host_8* mHost;
+
+public:
+  explicit ClearKeyCDM(cdm::Host_8* mHost);
+
+  void Initialize(bool aAllowDistinctiveIdentifier,
+                  bool aAllowPersistentState) override;
+
+  void SetServerCertificate(uint32_t aPromiseId,
+                            const uint8_t* aServerCertificateData,
+                            uint32_t aServerCertificateDataSize)
+                            override;
+
+  void CreateSessionAndGenerateRequest(uint32_t aPromiseId,
+                                       cdm::SessionType aSessionType,
+                                       cdm::InitDataType aInitDataType,
+                                       const uint8_t* aInitData,
+                                       uint32_t aInitDataSize)
+                                       override;
+
+  void LoadSession(uint32_t aPromiseId,
+                   cdm::SessionType aSessionType,
+                   const char* aSessionId,
+                   uint32_t aSessionIdSize) override;
+
+  void UpdateSession(uint32_t aPromiseId,
+                     const char* aSessionId,
+                     uint32_t aSessionIdSize,
+                     const uint8_t* aResponse,
+                     uint32_t aResponseSize) override;
+
+  void CloseSession(uint32_t aPromiseId,
+                    const char* aSessionId,
+                    uint32_t aSessionIdSize) override;
+
+  void RemoveSession(uint32_t aPromiseId,
+                     const char* aSessionId,
+                     uint32_t aSessionIdSize) override;
+
+  void TimerExpired(void* aContext) override;
+
+  cdm::Status Decrypt(const cdm::InputBuffer& aEncryptedBuffer,
+                      cdm::DecryptedBlock* aDecryptedBuffer) override;
+
+  cdm::Status InitializeAudioDecoder(
+    const cdm::AudioDecoderConfig& aAudioDecoderConfig) override;
+
+  cdm::Status InitializeVideoDecoder(
+    const cdm::VideoDecoderConfig& aVideoDecoderConfig) override;
+
+  void DeinitializeDecoder(cdm::StreamType aDecoderType) override;
+
+  void ResetDecoder(cdm::StreamType aDecoderType) override;
+
+  cdm::Status DecryptAndDecodeFrame(
+    const cdm::InputBuffer& aEncryptedBuffer,
+    cdm::VideoFrame* aVideoFrame) override;
+
+  cdm::Status DecryptAndDecodeSamples(
+    const cdm::InputBuffer& aEncryptedBuffer,
+    cdm::AudioFrames* aAudioFrame) override;
+
+  void OnPlatformChallengeResponse(
+    const cdm::PlatformChallengeResponse& aResponse) override;
+
+  void
+    OnQueryOutputProtectionStatus(cdm::QueryResult aResult,
+                                  uint32_t aLinkMask,
+                                  uint32_t aOutputProtectionMask) override;
+
+  void Destroy() override;
+};
+
+#endif
\ No newline at end of file
--- a/media/gmp-clearkey/0.1/ClearKeyDecryptionManager.cpp
+++ b/media/gmp-clearkey/0.1/ClearKeyDecryptionManager.cpp
@@ -9,45 +9,48 @@
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
+#include "ClearKeyDecryptionManager.h"
+
+#include "psshparser/PsshParser.h"
+
+#include <assert.h>
 #include <string.h>
 #include <vector>
 
-#include "ClearKeyDecryptionManager.h"
-#include "psshparser/PsshParser.h"
-#include "gmp-api/gmp-decryption.h"
-#include <assert.h>
+using namespace cdm;
 
 class ClearKeyDecryptor : public RefCounted
 {
 public:
   ClearKeyDecryptor();
 
   void InitKey(const Key& aKey);
   bool HasKey() const { return !!mKey.size(); }
 
-  GMPErr Decrypt(uint8_t* aBuffer, uint32_t aBufferSize,
+  Status Decrypt(uint8_t* aBuffer, uint32_t aBufferSize,
                  const CryptoMetaData& aMetadata);
 
   const Key& DecryptionKey() const { return mKey; }
 
 private:
   ~ClearKeyDecryptor();
 
   Key mKey;
 };
 
 
-/* static */ ClearKeyDecryptionManager* ClearKeyDecryptionManager::sInstance = nullptr;
+/* static */ ClearKeyDecryptionManager*
+ClearKeyDecryptionManager::sInstance = nullptr;
 
 /* static */ ClearKeyDecryptionManager*
 ClearKeyDecryptionManager::Get()
 {
   if (!sInstance) {
     sInstance = new ClearKeyDecryptionManager();
   }
   return sInstance;
@@ -68,24 +71,27 @@ ClearKeyDecryptionManager::~ClearKeyDecr
     it->second->Release();
   }
   mDecryptors.clear();
 }
 
 bool
 ClearKeyDecryptionManager::HasSeenKeyId(const KeyId& aKeyId) const
 {
-  CK_LOGD("ClearKeyDecryptionManager::SeenKeyId %s", mDecryptors.find(aKeyId) != mDecryptors.end() ? "t" : "f");
+  CK_LOGD("ClearKeyDecryptionManager::SeenKeyId %s",
+          mDecryptors.find(aKeyId) != mDecryptors.end() ? "t" : "f");
   return mDecryptors.find(aKeyId) != mDecryptors.end();
 }
 
 bool
 ClearKeyDecryptionManager::IsExpectingKeyForKeyId(const KeyId& aKeyId) const
 {
-  CK_LOGD("ClearKeyDecryptionManager::IsExpectingKeyForId %08x...", *(uint32_t*)&aKeyId[0]);
+  CK_LOGARRAY("ClearKeyDecryptionManager::IsExpectingKeyForId ",
+              aKeyId.data(),
+              aKeyId.size());
   const auto& decryptor = mDecryptors.find(aKeyId);
   return decryptor != mDecryptors.end() && !decryptor->second->HasKey();
 }
 
 bool
 ClearKeyDecryptionManager::HasKeyForKeyId(const KeyId& aKeyId) const
 {
   CK_LOGD("ClearKeyDecryptionManager::HasKeyForKeyId");
@@ -98,26 +104,33 @@ ClearKeyDecryptionManager::GetDecryption
 {
   assert(HasKeyForKeyId(aKeyId));
   return mDecryptors[aKeyId]->DecryptionKey();
 }
 
 void
 ClearKeyDecryptionManager::InitKey(KeyId aKeyId, Key aKey)
 {
-  CK_LOGD("ClearKeyDecryptionManager::InitKey %08x...", *(uint32_t*)&aKeyId[0]);
+  CK_LOGD("ClearKeyDecryptionManager::InitKey ",
+          aKeyId.data(),
+          aKeyId.size());
   if (IsExpectingKeyForKeyId(aKeyId)) {
+    CK_LOGARRAY("Initialized Key ", aKeyId.data(), aKeyId.size());
     mDecryptors[aKeyId]->InitKey(aKey);
+  } else {
+    CK_LOGARRAY("Failed to initialize key ", aKeyId.data(), aKeyId.size());
   }
 }
 
 void
 ClearKeyDecryptionManager::ExpectKeyId(KeyId aKeyId)
 {
-  CK_LOGD("ClearKeyDecryptionManager::ExpectKeyId %08x...", *(uint32_t*)&aKeyId[0]);
+  CK_LOGD("ClearKeyDecryptionManager::ExpectKeyId ",
+          aKeyId.data(),
+          aKeyId.size());
   if (!HasSeenKeyId(aKeyId)) {
     mDecryptors[aKeyId] = new ClearKeyDecryptor();
   }
   mDecryptors[aKeyId]->AddRef();
 }
 
 void
 ClearKeyDecryptionManager::ReleaseKeyId(KeyId aKeyId)
@@ -126,56 +139,66 @@ ClearKeyDecryptionManager::ReleaseKeyId(
   assert(HasSeenKeyId(aKeyId));
 
   ClearKeyDecryptor* decryptor = mDecryptors[aKeyId];
   if (!decryptor->Release()) {
     mDecryptors.erase(aKeyId);
   }
 }
 
-GMPErr
+Status
 ClearKeyDecryptionManager::Decrypt(std::vector<uint8_t>& aBuffer,
                                    const CryptoMetaData& aMetadata)
 {
   return Decrypt(&aBuffer[0], aBuffer.size(), aMetadata);
 }
 
-GMPErr
+Status
 ClearKeyDecryptionManager::Decrypt(uint8_t* aBuffer, uint32_t aBufferSize,
                                    const CryptoMetaData& aMetadata)
 {
   CK_LOGD("ClearKeyDecryptionManager::Decrypt");
   if (!HasKeyForKeyId(aMetadata.mKeyId)) {
-    return GMPNoKeyErr;
+    CK_LOGARRAY("Unable to find decryptor for keyId: ",
+                aMetadata.mKeyId.data(),
+                aMetadata.mKeyId.size());
+    return Status::kNoKey;
   }
 
-  return mDecryptors[aMetadata.mKeyId]->Decrypt(aBuffer, aBufferSize, aMetadata);
+  CK_LOGARRAY("Found decryptor for keyId: ",
+              aMetadata.mKeyId.data(),
+              aMetadata.mKeyId.size());
+  return mDecryptors[aMetadata.mKeyId]->Decrypt(aBuffer,
+                                                aBufferSize,
+                                                aMetadata);
 }
 
 ClearKeyDecryptor::ClearKeyDecryptor()
 {
   CK_LOGD("ClearKeyDecryptor ctor");
 }
 
 ClearKeyDecryptor::~ClearKeyDecryptor()
 {
   if (HasKey()) {
-    CK_LOGD("ClearKeyDecryptor dtor; key = %08x...", *(uint32_t*)&mKey[0]);
+    CK_LOGARRAY("ClearKeyDecryptor dtor; key = ",
+                mKey.data(),
+                mKey.size());
   } else {
     CK_LOGD("ClearKeyDecryptor dtor");
   }
 }
 
 void
 ClearKeyDecryptor::InitKey(const Key& aKey)
 {
   mKey = aKey;
 }
 
-GMPErr
+Status
 ClearKeyDecryptor::Decrypt(uint8_t* aBuffer, uint32_t aBufferSize,
                            const CryptoMetaData& aMetadata)
 {
   CK_LOGD("ClearKeyDecryptor::Decrypt");
   // If the sample is split up into multiple encrypted subsamples, we need to
   // stitch them into one continuous buffer for decryption.
   std::vector<uint8_t> tmp(aBufferSize);
 
@@ -184,17 +207,17 @@ ClearKeyDecryptor::Decrypt(uint8_t* aBuf
     // continuous encrypted buffer.
     uint8_t* data = aBuffer;
     uint8_t* iter = &tmp[0];
     for (size_t i = 0; i < aMetadata.NumSubsamples(); i++) {
       data += aMetadata.mClearBytes[i];
       uint32_t cipherBytes = aMetadata.mCipherBytes[i];
       if (data + cipherBytes > aBuffer + aBufferSize) {
         // Trying to read past the end of the buffer!
-        return GMPCryptoErr;
+        return Status::kDecryptError;
       }
 
       memcpy(iter, data, cipherBytes);
 
       data += cipherBytes;
       iter += cipherBytes;
     }
 
@@ -222,10 +245,10 @@ ClearKeyDecryptor::Decrypt(uint8_t* aBuf
 
       data += cipherBytes;
       iter += cipherBytes;
     }
   } else {
     memcpy(aBuffer, &tmp[0], aBufferSize);
   }
 
-  return GMPNoErr;
+  return Status::kSuccess;
 }
--- a/media/gmp-clearkey/0.1/ClearKeyDecryptionManager.h
+++ b/media/gmp-clearkey/0.1/ClearKeyDecryptionManager.h
@@ -12,59 +12,70 @@
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 #ifndef __ClearKeyDecryptionManager_h__
 #define __ClearKeyDecryptionManager_h__
 
-#include <map>
+#include "ClearKeyUtils.h"
+// This include is required in order for content_decryption_module to work
+// on Unix systems.
+#include "stddef.h"
+#include "content_decryption_module.h"
+#include "RefCounted.h"
 
-#include "ClearKeyUtils.h"
-#include "RefCounted.h"
+#include <map>
 
 class ClearKeyDecryptor;
 
-class CryptoMetaData {
+class CryptoMetaData
+{
 public:
   CryptoMetaData() {}
 
-  explicit CryptoMetaData(const GMPEncryptedBufferMetadata* aCrypto)
+  explicit CryptoMetaData(const cdm::InputBuffer* aInputBuffer)
   {
-    Init(aCrypto);
+    Init(aInputBuffer);
   }
 
-  void Init(const GMPEncryptedBufferMetadata* aCrypto)
+  void Init(const cdm::InputBuffer* aInputBuffer)
   {
-    if (!aCrypto) {
+    if (!aInputBuffer) {
       assert(!IsValid());
       return;
     }
-    Assign(mKeyId, aCrypto->KeyId(), aCrypto->KeyIdSize());
-    Assign(mIV, aCrypto->IV(), aCrypto->IVSize());
-    Assign(mClearBytes, aCrypto->ClearBytes(), aCrypto->NumSubsamples());
-    Assign(mCipherBytes, aCrypto->CipherBytes(), aCrypto->NumSubsamples());
+
+    Assign(mKeyId, aInputBuffer->key_id, aInputBuffer->key_id_size);
+    Assign(mIV, aInputBuffer->iv, aInputBuffer->iv_size);
+
+    for (uint32_t i = 0; i < aInputBuffer->num_subsamples; ++i) {
+      const cdm::SubsampleEntry& subsample = aInputBuffer->subsamples[i];
+
+      mCipherBytes.push_back(subsample.cipher_bytes);
+      mClearBytes.push_back(subsample.clear_bytes);
+    }
   }
 
   bool IsValid() const {
     return !mKeyId.empty() &&
            !mIV.empty() &&
            !mCipherBytes.empty() &&
            !mClearBytes.empty();
   }
 
   size_t NumSubsamples() const {
     assert(mClearBytes.size() == mCipherBytes.size());
     return mClearBytes.size();
   }
 
   std::vector<uint8_t> mKeyId;
   std::vector<uint8_t> mIV;
-  std::vector<uint16_t> mClearBytes;
+  std::vector<uint32_t> mClearBytes;
   std::vector<uint32_t> mCipherBytes;
 };
 
 class ClearKeyDecryptionManager : public RefCounted
 {
 private:
   ClearKeyDecryptionManager();
   ~ClearKeyDecryptionManager();
@@ -80,22 +91,20 @@ public:
   const Key& GetDecryptionKey(const KeyId& aKeyId);
 
   // Create a decryptor for the given KeyId if one does not already exist.
   void InitKey(KeyId aKeyId, Key aKey);
   void ExpectKeyId(KeyId aKeyId);
   void ReleaseKeyId(KeyId aKeyId);
 
   // Decrypts buffer *in place*.
-  GMPErr Decrypt(uint8_t* aBuffer, uint32_t aBufferSize,
-                 const CryptoMetaData& aMetadata);
-  GMPErr Decrypt(std::vector<uint8_t>& aBuffer,
-                 const CryptoMetaData& aMetadata);
-
-  void Shutdown();
+  cdm::Status Decrypt(uint8_t* aBuffer, uint32_t aBufferSize,
+                      const CryptoMetaData& aMetadata);
+  cdm::Status Decrypt(std::vector<uint8_t>& aBuffer,
+                      const CryptoMetaData& aMetadata);
 
 private:
   bool IsExpectingKeyForKeyId(const KeyId& aKeyId) const;
 
   std::map<KeyId, ClearKeyDecryptor*> mDecryptors;
 };
 
 #endif // __ClearKeyDecryptionManager_h__
--- a/media/gmp-clearkey/0.1/ClearKeyPersistence.cpp
+++ b/media/gmp-clearkey/0.1/ClearKeyPersistence.cpp
@@ -10,251 +10,159 @@
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 #include "ClearKeyPersistence.h"
+
 #include "ClearKeyUtils.h"
 #include "ClearKeyStorage.h"
 #include "ClearKeySessionManager.h"
 #include "RefCounted.h"
 
+#include <assert.h>
 #include <stdint.h>
+#include <sstream>
 #include <string.h>
-#include <set>
-#include <vector>
-#include <sstream>
-#include <assert.h>
 
 using namespace std;
+using namespace cdm;
 
-// Whether we've loaded the persistent session ids from GMPStorage yet.
-enum PersistentKeyState {
-  UNINITIALIZED,
-  LOADING,
-  LOADED
-};
-static PersistentKeyState sPersistentKeyState = UNINITIALIZED;
+void
+ClearKeyPersistence::ReadAllRecordsFromIndex(function<void()>&& aOnComplete) {
+  // Clear what we think the index file contains, we're about to read it again.
+  mPersistentSessionIds.clear();
 
-// Set of session Ids of the persistent sessions created or residing in
-// storage.
-static set<uint32_t> sPersistentSessionIds;
-
-static vector<GMPTask*> sTasksBlockedOnSessionIdLoad;
+  // Hold a reference to the persistence manager, so it isn't released before
+  // we try and use it.
+  RefPtr<ClearKeyPersistence> self(this);
+  function<void(const uint8_t*, uint32_t)> onIndexSuccess =
+    [self, aOnComplete] (const uint8_t* data, uint32_t size)
+  {
+    CK_LOGD("ClearKeyPersistence: Loaded index file!");
+    const char* charData = (const char*)data;
 
-static void
-ReadAllRecordsFromIterator(GMPRecordIterator* aRecordIterator,
-                           void* aUserArg,
-                           GMPErr aStatus)
-{
-  assert(sPersistentKeyState == LOADING);
-  if (GMP_SUCCEEDED(aStatus)) {
-    // Extract the record names which are valid uint32_t's; they're
-    // the persistent session ids.
-    const char* name = nullptr;
-    uint32_t len = 0;
-    while (GMP_SUCCEEDED(aRecordIterator->GetName(&name, &len))) {
-      if (ClearKeyUtils::IsValidSessionId(name, len)) {
-        assert(name[len] == 0);
-        sPersistentSessionIds.insert(atoi(name));
+    stringstream ss(string(charData, charData + size));
+    string name;
+    while (getline(ss, name)) {
+      if (ClearKeyUtils::IsValidSessionId(name.data(), name.size())) {
+        self->mPersistentSessionIds.insert(atoi(name.c_str()));
       }
-      aRecordIterator->NextRecord();
     }
-  }
-  sPersistentKeyState = LOADED;
-  aRecordIterator->Close();
+
+    self->mPersistentKeyState = PersistentKeyState::LOADED;
+    aOnComplete();
+  };
 
-  for (size_t i = 0; i < sTasksBlockedOnSessionIdLoad.size(); i++) {
-    sTasksBlockedOnSessionIdLoad[i]->Run();
-    sTasksBlockedOnSessionIdLoad[i]->Destroy();
-  }
-  sTasksBlockedOnSessionIdLoad.clear();
+  function<void()> onIndexFailed =
+    [self, aOnComplete] ()
+  {
+    CK_LOGD("ClearKeyPersistence: Failed to load index file (it might not exist");
+    self->mPersistentKeyState = PersistentKeyState::LOADED;
+    aOnComplete();
+  };
+
+  string filename = "index";
+  ReadData(mHost, filename, move(onIndexSuccess), move(onIndexFailed));
 }
 
-/* static */ void
-ClearKeyPersistence::EnsureInitialized()
+void
+ClearKeyPersistence::WriteIndex() {
+  function <void()> onIndexSuccess =
+    [] ()
+  {
+    CK_LOGD("ClearKeyPersistence: Wrote index file");
+  };
+
+  function <void()> onIndexFail =
+    [] ()
+  {
+    CK_LOGD("ClearKeyPersistence: Failed to write index file (this is bad)");
+  };
+
+  stringstream ss;
+
+  for (const uint32_t& sessionId : mPersistentSessionIds) {
+    ss << sessionId;
+    ss << '\n';
+  }
+
+  string dataString = ss.str();
+  uint8_t* dataArray = (uint8_t*)dataString.data();
+  vector<uint8_t> data(dataArray, dataArray + dataString.size());
+
+  string filename = "index";
+  WriteData(mHost,
+            filename,
+            data,
+            move(onIndexSuccess),
+            move(onIndexFail));
+}
+
+
+ClearKeyPersistence::ClearKeyPersistence(Host_8* aHost)
 {
-  if (sPersistentKeyState == UNINITIALIZED) {
-    sPersistentKeyState = LOADING;
-    if (GMP_FAILED(EnumRecordNames(&ReadAllRecordsFromIterator))) {
-      sPersistentKeyState = LOADED;
-    }
+  this->mHost = aHost;
+}
+
+void
+ClearKeyPersistence::EnsureInitialized(bool aPersistentStateAllowed,
+                                       function<void()>&& aOnInitialized)
+{
+  if (aPersistentStateAllowed &&
+      mPersistentKeyState == PersistentKeyState::UNINITIALIZED) {
+    mPersistentKeyState = LOADING;
+    ReadAllRecordsFromIndex(move(aOnInitialized));
+  } else {
+    mPersistentKeyState = PersistentKeyState::LOADED;
+    aOnInitialized();
   }
 }
 
-/* static */ string
-ClearKeyPersistence::GetNewSessionId(GMPSessionType aSessionType)
+bool ClearKeyPersistence::IsLoaded() const
+{
+  return mPersistentKeyState == PersistentKeyState::LOADED;
+}
+
+string
+ClearKeyPersistence::GetNewSessionId(SessionType aSessionType)
 {
   static uint32_t sNextSessionId = 1;
 
   // Ensure we don't re-use a session id that was persisted.
-  while (Contains(sPersistentSessionIds, sNextSessionId)) {
+  while (Contains(mPersistentSessionIds, sNextSessionId)) {
     sNextSessionId++;
   }
 
   string sessionId;
   stringstream ss;
   ss << sNextSessionId;
   ss >> sessionId;
 
-  if (aSessionType == kGMPPersistentSession) {
-    sPersistentSessionIds.insert(sNextSessionId);
+  if (aSessionType == SessionType::kPersistentLicense) {
+    mPersistentSessionIds.insert(sNextSessionId);
+
+    // Save the updated index file.
+    WriteIndex();
   }
 
   sNextSessionId++;
 
   return sessionId;
 }
 
-
-class CreateSessionTask : public GMPTask {
-public:
-  CreateSessionTask(ClearKeySessionManager* aTarget,
-                    uint32_t aCreateSessionToken,
-                    uint32_t aPromiseId,
-                    const string& aInitDataType,
-                    const uint8_t* aInitData,
-                    uint32_t aInitDataSize,
-                    GMPSessionType aSessionType)
-    : mTarget(aTarget)
-    , mCreateSessionToken(aCreateSessionToken)
-    , mPromiseId(aPromiseId)
-    , mInitDataType(aInitDataType)
-    , mSessionType(aSessionType)
-  {
-    mInitData.insert(mInitData.end(),
-                     aInitData,
-                     aInitData + aInitDataSize);
-  }
-  virtual void Run() override {
-    mTarget->CreateSession(mCreateSessionToken,
-                           mPromiseId,
-                           mInitDataType.c_str(),
-                           mInitDataType.size(),
-                           &mInitData.front(),
-                           mInitData.size(),
-                           mSessionType);
-  }
-  virtual void Destroy() override {
-    delete this;
-  }
-private:
-  RefPtr<ClearKeySessionManager> mTarget;
-  uint32_t mCreateSessionToken;
-  uint32_t mPromiseId;
-  const string mInitDataType;
-  vector<uint8_t> mInitData;
-  GMPSessionType mSessionType;
-};
-
-
-/* static */ bool
-ClearKeyPersistence::DeferCreateSessionIfNotReady(ClearKeySessionManager* aInstance,
-                                                  uint32_t aCreateSessionToken,
-                                                  uint32_t aPromiseId,
-                                                  const string& aInitDataType,
-                                                  const uint8_t* aInitData,
-                                                  uint32_t aInitDataSize,
-                                                  GMPSessionType aSessionType)
+bool
+ClearKeyPersistence::IsPersistentSessionId(const string& aSessionId)
 {
-  if (sPersistentKeyState >= LOADED)  {
-    return false;
-  }
-  GMPTask* t = new CreateSessionTask(aInstance,
-                                     aCreateSessionToken,
-                                     aPromiseId,
-                                     aInitDataType,
-                                     aInitData,
-                                     aInitDataSize,
-                                     aSessionType);
-  sTasksBlockedOnSessionIdLoad.push_back(t);
-  return true;
+  return Contains(mPersistentSessionIds, atoi(aSessionId.c_str()));
 }
 
-class LoadSessionTask : public GMPTask {
-public:
-  LoadSessionTask(ClearKeySessionManager* aTarget,
-                  uint32_t aPromiseId,
-                  const char* aSessionId,
-                  uint32_t aSessionIdLength)
-    : mTarget(aTarget)
-    , mPromiseId(aPromiseId)
-    , mSessionId(aSessionId, aSessionId + aSessionIdLength)
-  {
-  }
-  virtual void Run() override {
-    mTarget->LoadSession(mPromiseId,
-                         mSessionId.c_str(),
-                         mSessionId.size());
-  }
-  virtual void Destroy() override {
-    delete this;
-  }
-private:
-  RefPtr<ClearKeySessionManager> mTarget;
-  uint32_t mPromiseId;
-  string mSessionId;
-};
-
-/* static */ bool
-ClearKeyPersistence::DeferLoadSessionIfNotReady(ClearKeySessionManager* aInstance,
-                                                uint32_t aPromiseId,
-                                                const char* aSessionId,
-                                                uint32_t aSessionIdLength)
+void
+ClearKeyPersistence::PersistentSessionRemoved(string& aSessionId)
 {
-  if (sPersistentKeyState >= LOADED)  {
-    return false;
-  }
-  GMPTask* t = new LoadSessionTask(aInstance,
-                                   aPromiseId,
-                                   aSessionId,
-                                   aSessionIdLength);
-  sTasksBlockedOnSessionIdLoad.push_back(t);
-  return true;
-}
+  mPersistentSessionIds.erase(atoi(aSessionId.c_str()));
 
-/* static */ bool
-ClearKeyPersistence::IsPersistentSessionId(const string& aSessionId)
-{
-  return Contains(sPersistentSessionIds, atoi(aSessionId.c_str()));
+  // Update the index file.
+  WriteIndex();
 }
-
-class LoadSessionFromKeysTask : public ReadContinuation {
-public:
-  LoadSessionFromKeysTask(ClearKeySessionManager* aTarget,
-                          const string& aSessionId,
-                          uint32_t aPromiseId)
-    : mTarget(aTarget)
-    , mSessionId(aSessionId)
-    , mPromiseId(aPromiseId)
-  {
-  }
-
-  virtual void ReadComplete(GMPErr aStatus,
-                            const uint8_t* aData,
-                            uint32_t aLength) override
-  {
-    mTarget->PersistentSessionDataLoaded(aStatus, mPromiseId, mSessionId, aData, aLength);
-  }
-private:
-  RefPtr<ClearKeySessionManager> mTarget;
-  string mSessionId;
-  uint32_t mPromiseId;
-};
-
-/* static */ void
-ClearKeyPersistence::LoadSessionData(ClearKeySessionManager* aInstance,
-                                     const string& aSid,
-                                     uint32_t aPromiseId)
-{
-  LoadSessionFromKeysTask* loadTask =
-    new LoadSessionFromKeysTask(aInstance, aSid, aPromiseId);
-  ReadData(aSid, loadTask);
-}
-
-/* static */ void
-ClearKeyPersistence::PersistentSessionRemoved(const string& aSessionId)
-{
-  sPersistentSessionIds.erase(atoi(aSessionId.c_str()));
-}
--- a/media/gmp-clearkey/0.1/ClearKeyPersistence.h
+++ b/media/gmp-clearkey/0.1/ClearKeyPersistence.h
@@ -12,42 +12,56 @@
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 #ifndef __ClearKeyPersistence_h__
 #define __ClearKeyPersistence_h__
 
+// This include is required in order for content_decryption_module to work
+// on Unix systems.
+#include "stddef.h"
+#include "content_decryption_module.h"
+#include "RefCounted.h"
+
+#include <functional>
+#include <set>
 #include <string>
-#include "gmp-api/gmp-decryption.h"
+#include <vector>
+
 
 class ClearKeySessionManager;
 
-class ClearKeyPersistence {
+// Whether we've loaded the persistent session ids yet.
+enum PersistentKeyState {
+  UNINITIALIZED,
+  LOADING,
+  LOADED
+};
+
+class ClearKeyPersistence : public RefCounted
+{
 public:
-  static void EnsureInitialized();
+  explicit ClearKeyPersistence(cdm::Host_8* aHost);
 
-  static std::string GetNewSessionId(GMPSessionType aSessionType);
+  void EnsureInitialized(bool aPersistentStateAllowed,
+                         std::function<void()>&& aOnInitialized);
 
-  static bool DeferCreateSessionIfNotReady(ClearKeySessionManager* aInstance,
-                                           uint32_t aCreateSessionToken,
-                                           uint32_t aPromiseId,
-                                           const std::string& aInitDataType,
-                                           const uint8_t* aInitData,
-                                           uint32_t aInitDataSize,
-                                           GMPSessionType aSessionType);
+  bool IsLoaded() const;
+
+  std::string GetNewSessionId(cdm::SessionType aSessionType);
+
+  bool IsPersistentSessionId(const std::string& aSid);
 
-  static bool DeferLoadSessionIfNotReady(ClearKeySessionManager* aInstance,
-                                         uint32_t aPromiseId,
-                                         const char* aSessionId,
-                                         uint32_t aSessionIdLength);
+  void PersistentSessionRemoved(std::string& aSid);
+private:
+  cdm::Host_8* mHost = nullptr;
 
-  static bool IsPersistentSessionId(const std::string& aSid);
+  PersistentKeyState mPersistentKeyState = PersistentKeyState::UNINITIALIZED;
 
-  static void LoadSessionData(ClearKeySessionManager* aInstance,
-                              const std::string& aSid,
-                              uint32_t aPromiseId);
+  std::set<uint32_t> mPersistentSessionIds;
 
-  static void PersistentSessionRemoved(const std::string& aSid);
+  void ReadAllRecordsFromIndex(std::function<void()>&& aOnComplete);
+  void WriteIndex();
 };
 
 #endif // __ClearKeyPersistence_h__
--- a/media/gmp-clearkey/0.1/ClearKeySession.cpp
+++ b/media/gmp-clearkey/0.1/ClearKeySession.cpp
@@ -15,78 +15,64 @@
  */
 
 #include "BigEndian.h"
 #include "ClearKeyDecryptionManager.h"
 #include "ClearKeySession.h"
 #include "ClearKeyUtils.h"
 #include "ClearKeyStorage.h"
 #include "psshparser/PsshParser.h"
-#include "gmp-task-utils.h"
-#include "gmp-api/gmp-decryption.h"
+
 #include <assert.h>
 #include <string.h>
 
 using namespace mozilla;
+using namespace cdm;
+using namespace std;
 
 ClearKeySession::ClearKeySession(const std::string& aSessionId,
-                                 GMPDecryptorCallback* aCallback,
-                                 GMPSessionType aSessionType)
+                                 SessionType aSessionType)
   : mSessionId(aSessionId)
-  , mCallback(aCallback)
   , mSessionType(aSessionType)
 {
   CK_LOGD("ClearKeySession ctor %p", this);
 }
 
 ClearKeySession::~ClearKeySession()
 {
   CK_LOGD("ClearKeySession dtor %p", this);
-
-  std::vector<GMPMediaKeyInfo> key_infos;
-  for (const KeyId& keyId : mKeyIds) {
-    assert(ClearKeyDecryptionManager::Get()->HasSeenKeyId(keyId));
-    ClearKeyDecryptionManager::Get()->ReleaseKeyId(keyId);
-    key_infos.push_back(GMPMediaKeyInfo(&keyId[0], keyId.size(), kGMPUnknown));
-  }
-  mCallback->BatchedKeyStatusChanged(&mSessionId[0], mSessionId.size(),
-                                     key_infos.data(), key_infos.size());
 }
 
-void
-ClearKeySession::Init(uint32_t aCreateSessionToken,
-                      uint32_t aPromiseId,
-                      const std::string& aInitDataType,
-                      const uint8_t* aInitData, uint32_t aInitDataSize)
+bool
+ClearKeySession::Init(InitDataType aInitDataType,
+                      const uint8_t* aInitData,
+                      uint32_t aInitDataSize)
 {
   CK_LOGD("ClearKeySession::Init");
 
-  if (aInitDataType == "cenc") {
+  if (aInitDataType == InitDataType::kCenc) {
     ParseCENCInitData(aInitData, aInitDataSize, mKeyIds);
-  } else if (aInitDataType == "keyids") {
+  } else if (aInitDataType == InitDataType::kKeyIds) {
     ClearKeyUtils::ParseKeyIdsInitData(aInitData, aInitDataSize, mKeyIds);
-  } else if (aInitDataType == "webm" && aInitDataSize <= kMaxWebmInitDataSize) {
+  } else if (aInitDataType == InitDataType::kWebM &&
+             aInitDataSize <= kMaxWebmInitDataSize) {
     // "webm" initData format is simply the raw bytes of the keyId.
     vector<uint8_t> keyId;
     keyId.assign(aInitData, aInitData+aInitDataSize);
     mKeyIds.push_back(keyId);
   }
 
   if (!mKeyIds.size()) {
-    const char message[] = "Couldn't parse init data";
-    mCallback->RejectPromise(aPromiseId, kGMPTypeError, message, strlen(message));
-    return;
+    return false;
   }
 
-  mCallback->SetSessionId(aCreateSessionToken, &mSessionId[0], mSessionId.length());
-
-  mCallback->ResolvePromise(aPromiseId);
+  return true;
 }
 
-GMPSessionType
+SessionType
 ClearKeySession::Type() const
 {
   return mSessionType;
 }
 
 void
 ClearKeySession::AddKeyId(const KeyId& aKeyId)
 {
--- a/media/gmp-clearkey/0.1/ClearKeySession.h
+++ b/media/gmp-clearkey/0.1/ClearKeySession.h
@@ -13,46 +13,43 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 #ifndef __ClearKeySession_h__
 #define __ClearKeySession_h__
 
 #include "ClearKeyUtils.h"
-#include "gmp-api/gmp-decryption.h"
+// This include is required in order for content_decryption_module to work
+// on Unix systems.
+#include "stddef.h"
+#include "content_decryption_module.h"
 
-class GMPBuffer;
-class GMPDecryptorCallback;
-class GMPDecryptorHost;
-class GMPEncryptedBufferMetadata;
+#include <string>
+#include <vector>
 
 class ClearKeySession
 {
 public:
   explicit ClearKeySession(const std::string& aSessionId,
-                           GMPDecryptorCallback* aCallback,
-                           GMPSessionType aSessionType);
+                           cdm::SessionType aSessionType);
 
   ~ClearKeySession();
 
   const std::vector<KeyId>& GetKeyIds() const { return mKeyIds; }
 
-  void Init(uint32_t aCreateSessionToken,
-            uint32_t aPromiseId,
-            const string& aInitDataType,
+  bool Init(cdm::InitDataType aInitDataType,
             const uint8_t* aInitData, uint32_t aInitDataSize);
 
-  GMPSessionType Type() const;
+  cdm::SessionType Type() const;
 
   void AddKeyId(const KeyId& aKeyId);
 
   const std::string& Id() const { return mSessionId; }
 
 private:
   const std::string mSessionId;
   std::vector<KeyId> mKeyIds;
 
-  GMPDecryptorCallback* mCallback;
-  const GMPSessionType mSessionType;
+  const cdm::SessionType mSessionType;
 };
 
 #endif // __ClearKeySession_h__
--- a/media/gmp-clearkey/0.1/ClearKeySessionManager.cpp
+++ b/media/gmp-clearkey/0.1/ClearKeySessionManager.cpp
@@ -9,98 +9,151 @@
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-
 #include "ClearKeyDecryptionManager.h"
 #include "ClearKeySessionManager.h"
 #include "ClearKeyUtils.h"
 #include "ClearKeyStorage.h"
 #include "ClearKeyPersistence.h"
-#include "gmp-task-utils.h"
+// This include is required in order for content_decryption_module to work
+// on Unix systems.
+#include "stddef.h"
+#include "content_decryption_module.h"
+#include "psshparser/PsshParser.h"
+
 #include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
 
 using namespace std;
+using namespace cdm;
 
-ClearKeySessionManager::ClearKeySessionManager()
+ClearKeySessionManager::ClearKeySessionManager(Host_8* aHost)
   : mDecryptionManager(ClearKeyDecryptionManager::Get())
 {
   CK_LOGD("ClearKeySessionManager ctor %p", this);
   AddRef();
 
-  if (GetPlatform()->createthread(&mThread) != GMPNoErr) {
-    CK_LOGD("failed to create thread in clearkey cdm");
-    mThread = nullptr;
-  }
+  mHost = aHost;
+  mPersistence = new ClearKeyPersistence(mHost);
 }
 
 ClearKeySessionManager::~ClearKeySessionManager()
 {
   CK_LOGD("ClearKeySessionManager dtor %p", this);
 }
 
 void
-ClearKeySessionManager::Init(GMPDecryptorCallback* aCallback,
-                             bool aDistinctiveIdentifierAllowed,
+ClearKeySessionManager::Init(bool aDistinctiveIdentifierAllowed,
                              bool aPersistentStateAllowed)
 {
   CK_LOGD("ClearKeySessionManager::Init");
-  mCallback = aCallback;
-  ClearKeyPersistence::EnsureInitialized();
+
+  RefPtr<ClearKeySessionManager> self(this);
+  function<void()> onPersistentStateLoaded =
+    [self] ()
+  {
+    while (!self->mDeferredInitialize.empty()) {
+      function<void()> func = self->mDeferredInitialize.front();
+      self->mDeferredInitialize.pop();
+
+      func();
+    }
+  };
+
+  mPersistence->EnsureInitialized(aPersistentStateAllowed,
+                                  move(onPersistentStateLoaded));
 }
 
 void
-ClearKeySessionManager::CreateSession(uint32_t aCreateSessionToken,
-                                      uint32_t aPromiseId,
-                                      const char* aInitDataType,
-                                      uint32_t aInitDataTypeSize,
+ClearKeySessionManager::CreateSession(uint32_t aPromiseId,
+                                      InitDataType aInitDataType,
                                       const uint8_t* aInitData,
                                       uint32_t aInitDataSize,
-                                      GMPSessionType aSessionType)
+                                      SessionType aSessionType)
 {
-  CK_LOGD("ClearKeySessionManager::CreateSession type:%s", aInitDataType);
+  // Copy the init data so it is correctly captured by the lambda
+  vector<uint8_t> initData(aInitData, aInitData + aInitDataSize);
 
-  string initDataType(aInitDataType, aInitDataType + aInitDataTypeSize);
-  // initDataType must be "cenc", "keyids", or "webm".
-  if (initDataType != "cenc" &&
-      initDataType != "keyids" &&
-      initDataType != "webm") {
-    string message = "'" + initDataType + "' is an initDataType unsupported by ClearKey";
-    mCallback->RejectPromise(aPromiseId, kGMPNotSupportedError,
-                             message.c_str(), message.size());
+  RefPtr<ClearKeySessionManager> self(this);
+  function<void()> deferrer =
+    [self, aPromiseId, aInitDataType, initData, aSessionType] ()
+  {
+    self->CreateSession(aPromiseId,
+                        aInitDataType,
+                        initData.data(),
+                        initData.size(),
+                        aSessionType);
+  };
+
+  // If we haven't loaded, don't do this yet
+  if (MaybeDeferTillInitialized(deferrer)) {
     return;
   }
 
-  if (ClearKeyPersistence::DeferCreateSessionIfNotReady(this,
-                                                        aCreateSessionToken,
-                                                        aPromiseId,
-                                                        initDataType,
-                                                        aInitData,
-                                                        aInitDataSize,
-                                                        aSessionType)) {
+  CK_LOGD("ClearKeySessionManager::CreateSession type:%s", aInitDataType);
+
+  CK_LOGARRAY("ClearKeySessionManager::CreateSession initdata: ",
+              aInitData,
+              aInitDataSize);
+
+  // If 'DecryptingComplete' has been called mHost will be null so we can't
+  // won't be able to resolve our promise
+  if (!mHost) {
+    CK_LOGD("ClearKeySessionManager::CreateSession: mHost is nullptr")
     return;
   }
 
-  string sessionId = ClearKeyPersistence::GetNewSessionId(aSessionType);
+  // initDataType must be "cenc", "keyids", or "webm".
+  if (aInitDataType != InitDataType::kCenc &&
+      aInitDataType != InitDataType::kKeyIds &&
+      aInitDataType != InitDataType::kWebM) {
+
+    string message = "initDataType is not supported by ClearKey";
+    mHost->OnRejectPromise(aPromiseId,
+                           Error::kNotSupportedError,
+                           0,
+                           message.c_str(),
+                           message.size());
+
+    return;
+  }
+
+  string sessionId = mPersistence->GetNewSessionId(aSessionType);
   assert(mSessions.find(sessionId) == mSessions.end());
 
-  ClearKeySession* session = new ClearKeySession(sessionId, mCallback, aSessionType);
-  session->Init(aCreateSessionToken, aPromiseId, initDataType, aInitData, aInitDataSize);
+  ClearKeySession* session = new ClearKeySession(sessionId,
+                                                 aSessionType);
+
+  if (!session->Init(aInitDataType, aInitData, aInitDataSize)) {
+
+    CK_LOGD("Failed to initialize session: %s", sessionId.c_str());
+
+    const static char* message = "Failed to initialize session";
+    mHost->OnRejectPromise(aPromiseId,
+                           Error::kUnknownError,
+                           0,
+                           message,
+                           strlen(message));
+
+    return;
+  }
+
   mSessions[sessionId] = session;
 
   const vector<KeyId>& sessionKeys = session->GetKeyIds();
   vector<KeyId> neededKeys;
+
   for (auto it = sessionKeys.begin(); it != sessionKeys.end(); it++) {
     // Need to request this key ID from the client. We always send a key
     // request, whether or not another session has sent a request with the same
     // key ID. Otherwise a script can end up waiting for another script to
     // respond to the request (which may not necessarily happen).
     neededKeys.push_back(*it);
     mDecryptionManager->ExpectKeyId(*it);
   }
@@ -108,73 +161,120 @@ ClearKeySessionManager::CreateSession(ui
   if (neededKeys.empty()) {
     CK_LOGD("No keys needed from client.");
     return;
   }
 
   // Send a request for needed key data.
   string request;
   ClearKeyUtils::MakeKeyRequest(neededKeys, request, aSessionType);
-  mCallback->SessionMessage(&sessionId[0], sessionId.length(),
-                            kGMPLicenseRequest,
-                            (uint8_t*)&request[0], request.length());
+
+  // Resolve the promise with the new session information.
+  mHost->OnResolveNewSessionPromise(aPromiseId,
+                                    sessionId.c_str(),
+                                    sessionId.size());
+
+  mHost->OnSessionMessage(sessionId.c_str(),
+                          sessionId.size(),
+                          MessageType::kLicenseRequest,
+                          request.c_str(),
+                          request.size(),
+                          nullptr,
+                          0);
 }
 
 void
 ClearKeySessionManager::LoadSession(uint32_t aPromiseId,
                                     const char* aSessionId,
                                     uint32_t aSessionIdLength)
 {
-  CK_LOGD("ClearKeySessionManager::LoadSession");
+  // Copy the sessionId into a string so the lambda captures it properly.
+  string sessionId(aSessionId, aSessionId + aSessionIdLength);
 
-  if (!ClearKeyUtils::IsValidSessionId(aSessionId, aSessionIdLength)) {
-    mCallback->ResolveLoadSessionPromise(aPromiseId, false);
+  // Hold a reference to the SessionManager so that it isn't released before
+  // we try to use it.
+  RefPtr<ClearKeySessionManager> self(this);
+  function<void()> deferrer =
+    [self, aPromiseId, sessionId] ()
+  {
+    self->LoadSession(aPromiseId, sessionId.data(), sessionId.size());
+  };
+
+  if (MaybeDeferTillInitialized(deferrer)) {
     return;
   }
 
-  if (ClearKeyPersistence::DeferLoadSessionIfNotReady(this,
-                                                      aPromiseId,
-                                                      aSessionId,
-                                                      aSessionIdLength)) {
+  CK_LOGD("ClearKeySessionManager::LoadSession");
+
+  // If the SessionManager has been shutdown mHost will be null and we won't
+  // be able to resolve the promise.
+  if (!mHost) {
     return;
   }
 
-  string sid(aSessionId, aSessionId + aSessionIdLength);
-  if (!ClearKeyPersistence::IsPersistentSessionId(sid)) {
-    mCallback->ResolveLoadSessionPromise(aPromiseId, false);
+  if (!ClearKeyUtils::IsValidSessionId(aSessionId, aSessionIdLength)) {
+    mHost->OnResolveNewSessionPromise(aPromiseId, nullptr, 0);
+    return;
+  }
+
+  if (!mPersistence->IsPersistentSessionId(sessionId)) {
+    mHost->OnResolveNewSessionPromise(aPromiseId, nullptr, 0);
     return;
   }
 
-  // Callsback PersistentSessionDataLoaded with results...
-  ClearKeyPersistence::LoadSessionData(this, sid, aPromiseId);
+  function<void(const uint8_t*, uint32_t)> success =
+    [self, sessionId, aPromiseId] (const uint8_t* data, uint32_t size)
+  {
+    self->PersistentSessionDataLoaded(aPromiseId,
+                                      sessionId,
+                                      data,
+                                      size);
+  };
+
+  function<void()> failure = [self, sessionId, aPromiseId] {
+    if (!self->mHost) {
+      return;
+    }
+    // As per the API described in ContentDecryptionModule_8
+    self->mHost->OnResolveNewSessionPromise(aPromiseId, nullptr, 0);
+  };
+
+  ReadData(mHost, sessionId, move(success), move(failure));
 }
 
 void
-ClearKeySessionManager::PersistentSessionDataLoaded(GMPErr aStatus,
-                                                    uint32_t aPromiseId,
+ClearKeySessionManager::PersistentSessionDataLoaded(uint32_t aPromiseId,
                                                     const string& aSessionId,
                                                     const uint8_t* aKeyData,
                                                     uint32_t aKeyDataSize)
 {
   CK_LOGD("ClearKeySessionManager::PersistentSessionDataLoaded");
-  if (GMP_FAILED(aStatus) ||
-      Contains(mSessions, aSessionId) ||
+
+  // Check that the SessionManager has not been shut down before we try and
+  // resolve any promises.
+  if (!mHost) {
+    return;
+  }
+
+  if (Contains(mSessions, aSessionId) ||
       (aKeyDataSize % (2 * CENC_KEY_LEN)) != 0) {
-    mCallback->ResolveLoadSessionPromise(aPromiseId, false);
+
+    // As per the instructions in ContentDecryptionModule_8
+    mHost->OnResolveNewSessionPromise(aPromiseId, nullptr, 0);
     return;
   }
 
   ClearKeySession* session = new ClearKeySession(aSessionId,
-                                                 mCallback,
-                                                 kGMPPersistentSession);
+                                                 SessionType::kPersistentLicense);
+
   mSessions[aSessionId] = session;
 
   uint32_t numKeys = aKeyDataSize / (2 * CENC_KEY_LEN);
 
-  vector<GMPMediaKeyInfo> key_infos;
+  vector<KeyInformation> keyInfos;
   vector<KeyIdPair> keyPairs;
   for (uint32_t i = 0; i < numKeys; i ++) {
     const uint8_t* base = aKeyData + 2 * CENC_KEY_LEN * i;
 
     KeyIdPair keyPair;
 
     keyPair.mKeyId = KeyId(base, base + CENC_KEY_LEN);
     assert(keyPair.mKeyId.size() == CENC_KEY_LEN);
@@ -182,91 +282,173 @@ ClearKeySessionManager::PersistentSessio
     keyPair.mKey = Key(base + CENC_KEY_LEN, base + 2 * CENC_KEY_LEN);
     assert(keyPair.mKey.size() == CENC_KEY_LEN);
 
     session->AddKeyId(keyPair.mKeyId);
 
     mDecryptionManager->ExpectKeyId(keyPair.mKeyId);
     mDecryptionManager->InitKey(keyPair.mKeyId, keyPair.mKey);
     mKeyIds.insert(keyPair.mKey);
+    keyPairs.push_back(keyPair);
 
-    keyPairs.push_back(keyPair);
-    key_infos.push_back(GMPMediaKeyInfo(&keyPairs[i].mKeyId[0],
-                                        keyPairs[i].mKeyId.size(),
-                                        kGMPUsable));
+    KeyInformation keyInfo = KeyInformation();
+    keyInfo.key_id = &keyPairs.back().mKeyId[0];
+    keyInfo.key_id_size = keyPair.mKeyId.size();
+    keyInfo.status = KeyStatus::kUsable;
+
+    keyInfos.push_back(keyInfo);
   }
-  mCallback->BatchedKeyStatusChanged(&aSessionId[0], aSessionId.size(),
-                                     key_infos.data(), key_infos.size());
 
-  mCallback->ResolveLoadSessionPromise(aPromiseId, true);
+  mHost->OnSessionKeysChange(&aSessionId[0],
+                             aSessionId.size(),
+                             true,
+                             keyInfos.data(),
+                             keyInfos.size());
+
+  mHost->OnResolveNewSessionPromise(aPromiseId,
+                                    aSessionId.c_str(),
+                                    aSessionId.size());
 }
 
 void
 ClearKeySessionManager::UpdateSession(uint32_t aPromiseId,
                                       const char* aSessionId,
                                       uint32_t aSessionIdLength,
                                       const uint8_t* aResponse,
                                       uint32_t aResponseSize)
 {
+  // Copy the method arguments so we can capture them in the lambda
+  string sessionId(aSessionId, aSessionId + aSessionIdLength);
+  vector<uint8_t> response(aResponse, aResponse + aResponseSize);
+
+  // Hold  a reference to the SessionManager so it isn't released before we
+  // callback.
+  RefPtr<ClearKeySessionManager> self(this);
+  function<void()> deferrer =
+    [self, aPromiseId, sessionId, response] ()
+  {
+    self->UpdateSession(aPromiseId,
+                        sessionId.data(),
+                        sessionId.size(),
+                        response.data(),
+                        response.size());
+  };
+
+  // If we haven't fully loaded, defer calling this method
+  if (MaybeDeferTillInitialized(deferrer)) {
+    return;
+  }
+
+  // Make sure the SessionManager has not been shutdown before we try and
+  // resolve any promises.
+  if (!mHost) {
+    return;
+  }
+
   CK_LOGD("ClearKeySessionManager::UpdateSession");
-  string sessionId(aSessionId, aSessionId + aSessionIdLength);
+  CK_LOGD("Updating session: %s", sessionId.c_str());
 
   auto itr = mSessions.find(sessionId);
   if (itr == mSessions.end() || !(itr->second)) {
     CK_LOGW("ClearKey CDM couldn't resolve session ID in UpdateSession.");
-    mCallback->RejectPromise(aPromiseId, kGMPNotFoundError, nullptr, 0);
+    CK_LOGD("Unable to find session: %s", sessionId.c_str());
+    mHost->OnRejectPromise(aPromiseId,
+                           Error::kInvalidAccessError,
+                           0,
+                           nullptr,
+                           0);
+
     return;
   }
   ClearKeySession* session = itr->second;
 
   // Verify the size of session response.
   if (aResponseSize >= kMaxSessionResponseLength) {
     CK_LOGW("Session response size is not within a reasonable size.");
-    mCallback->RejectPromise(aPromiseId, kGMPTypeError, nullptr, 0);
+    CK_LOGD("Failed to parse response for session %s", sessionId.c_str());
+
+    mHost->OnRejectPromise(aPromiseId,
+                           Error::kInvalidAccessError,
+                           0,
+                           nullptr,
+                           0);
+
     return;
   }
 
   // Parse the response for any (key ID, key) pairs.
   vector<KeyIdPair> keyPairs;
-  if (!ClearKeyUtils::ParseJWK(aResponse, aResponseSize, keyPairs, session->Type())) {
+  if (!ClearKeyUtils::ParseJWK(aResponse,
+                               aResponseSize,
+                               keyPairs,
+                               session->Type())) {
     CK_LOGW("ClearKey CDM failed to parse JSON Web Key.");
-    mCallback->RejectPromise(aPromiseId, kGMPTypeError, nullptr, 0);
+
+    mHost->OnRejectPromise(aPromiseId,
+                           Error::kInvalidAccessError,
+                           0,
+                           nullptr,
+                           0);
+
     return;
   }
 
-  vector<GMPMediaKeyInfo> key_infos;
+  vector<KeyInformation> keyInfos;
   for (size_t i = 0; i < keyPairs.size(); i++) {
     KeyIdPair& keyPair = keyPairs[i];
     mDecryptionManager->InitKey(keyPair.mKeyId, keyPair.mKey);
     mKeyIds.insert(keyPair.mKeyId);
-    key_infos.push_back(GMPMediaKeyInfo(&keyPair.mKeyId[0],
-                                        keyPair.mKeyId.size(),
-                                        kGMPUsable));
+
+    KeyInformation keyInfo = KeyInformation();
+    keyInfo.key_id = &keyPair.mKeyId[0];
+    keyInfo.key_id_size = keyPair.mKeyId.size();
+    keyInfo.status = KeyStatus::kUsable;
+
+    keyInfos.push_back(keyInfo);
   }
-  mCallback->BatchedKeyStatusChanged(aSessionId, aSessionIdLength,
-                                     key_infos.data(), key_infos.size());
 
-  if (session->Type() != kGMPPersistentSession) {
-    mCallback->ResolvePromise(aPromiseId);
+  mHost->OnSessionKeysChange(aSessionId,
+                             aSessionIdLength,
+                             true,
+                             keyInfos.data(),
+                             keyInfos.size());
+
+  if (session->Type() != SessionType::kPersistentLicense) {
+    mHost->OnResolvePromise(aPromiseId);
     return;
   }
 
   // Store the keys on disk. We store a record whose name is the sessionId,
   // and simply append each keyId followed by its key.
   vector<uint8_t> keydata;
   Serialize(session, keydata);
-  GMPTask* resolve = WrapTask(mCallback, &GMPDecryptorCallback::ResolvePromise, aPromiseId);
-  static const char* message = "Couldn't store cenc key init data";
-  GMPTask* reject = WrapTask(mCallback,
-                             &GMPDecryptorCallback::RejectPromise,
-                             aPromiseId,
-                             kGMPInvalidStateError,
-                             message,
-                             strlen(message));
-  StoreData(sessionId, keydata, resolve, reject);
+
+  function<void()> resolve = [self, aPromiseId] ()
+  {
+    if (!self->mHost) {
+      return;
+    }
+    self->mHost->OnResolvePromise(aPromiseId);
+  };
+
+  function<void()> reject = [self, aPromiseId] ()
+  {
+    if (!self->mHost) {
+      return;
+    }
+
+    static const char* message = "Couldn't store cenc key init data";
+    self->mHost->OnRejectPromise(aPromiseId,
+                                 Error::kInvalidStateError,
+                                 0,
+                                 message,
+                                 strlen(message));
+  };
+
+  WriteData(mHost, sessionId, keydata, move(resolve), move(reject));
 }
 
 void
 ClearKeySessionManager::Serialize(const ClearKeySession* aSession,
                                   std::vector<uint8_t>& aOutKeyData)
 {
   const std::vector<KeyId>& keyIds = aSession->GetKeyIds();
   for (size_t i = 0; i < keyIds.size(); i++) {
@@ -282,137 +464,205 @@ ClearKeySessionManager::Serialize(const 
   }
 }
 
 void
 ClearKeySessionManager::CloseSession(uint32_t aPromiseId,
                                      const char* aSessionId,
                                      uint32_t aSessionIdLength)
 {
+  // Copy the sessionId into a string so we capture it properly.
+  string sessionId(aSessionId, aSessionId + aSessionIdLength);
+  // Hold a reference to the session manager, so it doesn't get deleted
+  // before we need to use it.
+  RefPtr<ClearKeySessionManager> self(this);
+  function<void()> deferrer =
+    [self, aPromiseId, sessionId] ()
+  {
+    self->CloseSession(aPromiseId, sessionId.data(), sessionId.size());
+  };
+
+  // If we haven't loaded, call this method later.
+  if (MaybeDeferTillInitialized(deferrer)) {
+    return;
+  }
+
   CK_LOGD("ClearKeySessionManager::CloseSession");
 
-  string sessionId(aSessionId, aSessionId + aSessionIdLength);
+  // If DecryptingComplete has been called mHost will be null and we won't
+  // be able to resolve our promise.
+  if (!mHost) {
+    return;
+  }
+
   auto itr = mSessions.find(sessionId);
   if (itr == mSessions.end()) {
     CK_LOGW("ClearKey CDM couldn't close non-existent session.");
-    mCallback->RejectPromise(aPromiseId, kGMPNotFoundError, nullptr, 0);
+    mHost->OnRejectPromise(aPromiseId,
+                           Error::kInvalidAccessError,
+                           0,
+                           nullptr,
+                           0);
+
     return;
   }
 
   ClearKeySession* session = itr->second;
   assert(session);
 
   ClearInMemorySessionData(session);
-  mCallback->SessionClosed(aSessionId, aSessionIdLength);
-  mCallback->ResolvePromise(aPromiseId);
+
+  mHost->OnSessionClosed(aSessionId, aSessionIdLength);
+  mHost->OnResolvePromise(aPromiseId);
 }
 
 void
 ClearKeySessionManager::ClearInMemorySessionData(ClearKeySession* aSession)
 {
   mSessions.erase(aSession->Id());
   delete aSession;
 }
 
 void
 ClearKeySessionManager::RemoveSession(uint32_t aPromiseId,
                                       const char* aSessionId,
                                       uint32_t aSessionIdLength)
 {
+  // Copy the sessionId into a string so it can be captured for the lambda.
+  string sessionId(aSessionId, aSessionId + aSessionIdLength);
+
+  // Hold a reference to the SessionManager, so it isn't released before we
+  // try and use it.
+  RefPtr<ClearKeySessionManager> self(this);
+  function<void()> deferrer =
+    [self, aPromiseId, sessionId] ()
+  {
+    self->RemoveSession(aPromiseId, sessionId.data(), sessionId.size());
+  };
+
+  // If we haven't fully loaded, defer calling this method.
+  if (MaybeDeferTillInitialized(deferrer)) {
+    return;
+  }
+
+  // Check that the SessionManager has not been shutdown before we try and
+  // resolve any promises.
+  if (!mHost) {
+    return;
+  }
+
   CK_LOGD("ClearKeySessionManager::RemoveSession");
-  string sessionId(aSessionId, aSessionId + aSessionIdLength);
   auto itr = mSessions.find(sessionId);
   if (itr == mSessions.end()) {
     CK_LOGW("ClearKey CDM couldn't remove non-existent session.");
-    mCallback->RejectPromise(aPromiseId, kGMPNotFoundError, nullptr, 0);
+
+    mHost->OnRejectPromise(aPromiseId,
+                           Error::kInvalidAccessError,
+                           0,
+                           nullptr,
+                           0);
+
     return;
   }
 
   ClearKeySession* session = itr->second;
   assert(session);
   string sid = session->Id();
-  bool isPersistent = session->Type() == kGMPPersistentSession;
+  bool isPersistent = session->Type() == SessionType::kPersistentLicense;
   ClearInMemorySessionData(session);
 
   if (!isPersistent) {
-    mCallback->ResolvePromise(aPromiseId);
+    mHost->OnResolvePromise(aPromiseId);
     return;
   }
 
-  ClearKeyPersistence::PersistentSessionRemoved(sid);
+  mPersistence->PersistentSessionRemoved(sid);
 
-  // Overwrite the record storing the sessionId's key data with a zero
-  // length record to delete it.
   vector<uint8_t> emptyKeydata;
-  GMPTask* resolve = WrapTask(mCallback, &GMPDecryptorCallback::ResolvePromise, aPromiseId);
-  static const char* message = "Could not remove session";
-  GMPTask* reject = WrapTask(mCallback,
-                             &GMPDecryptorCallback::RejectPromise,
-                             aPromiseId,
-                             kGMPInvalidAccessError,
-                             message,
-                             strlen(message));
-  StoreData(sessionId, emptyKeydata, resolve, reject);
+
+  function<void()> resolve = [self, aPromiseId, sessionId] ()
+  {
+    if (!self->mHost) {
+      return;
+    }
+    self->mHost->OnResolvePromise(aPromiseId);
+  };
+
+  function<void()> reject = [self, aPromiseId, sessionId] ()
+  {
+    if (!self->mHost) {
+      return;
+    }
+    static const char* message = "Could not remove session";
+    self->mHost->OnRejectPromise(aPromiseId,
+                                 Error::kInvalidAccessError,
+                                 0,
+                                 message,
+                                 strlen(message));
+  };
+
+  WriteData(mHost, sessionId, emptyKeydata, move(resolve), move(reject));
 }
 
 void
 ClearKeySessionManager::SetServerCertificate(uint32_t aPromiseId,
                                              const uint8_t* aServerCert,
                                              uint32_t aServerCertSize)
 {
   // ClearKey CDM doesn't support this method by spec.
   CK_LOGD("ClearKeySessionManager::SetServerCertificate");
-  mCallback->RejectPromise(aPromiseId, kGMPNotSupportedError,
-                           nullptr /* message */, 0 /* messageLen */);
+  mHost->OnRejectPromise(aPromiseId,
+                         Error::kNotSupportedError,
+                         0,
+                         nullptr /* message */,
+                         0 /* messageLen */);
 }
 
-void
-ClearKeySessionManager::Decrypt(GMPBuffer* aBuffer,
-                                GMPEncryptedBufferMetadata* aMetadata)
+Status
+ClearKeySessionManager::Decrypt(const InputBuffer& aBuffer,
+                                DecryptedBlock* aDecryptedBlock)
 {
   CK_LOGD("ClearKeySessionManager::Decrypt");
 
-  if (!mThread) {
-    CK_LOGW("No decrypt thread");
-    mCallback->Decrypted(aBuffer, GMPGenericErr);
-    return;
-  }
+  CK_LOGARRAY("Key: ", aBuffer.key_id, aBuffer.key_id_size);
 
-  mThread->Post(WrapTaskRefCounted(this,
-                                   &ClearKeySessionManager::DoDecrypt,
-                                   aBuffer, aMetadata));
-}
+  Buffer* buffer = mHost->Allocate(aBuffer.data_size);
+  assert(buffer != nullptr);
+  assert(buffer->Data() != nullptr);
+  assert(buffer->Capacity() >= aBuffer.data_size);
+
+  memcpy(buffer->Data(), aBuffer.data, aBuffer.data_size);
 
-void
-ClearKeySessionManager::DoDecrypt(GMPBuffer* aBuffer,
-                                  GMPEncryptedBufferMetadata* aMetadata)
-{
-  CK_LOGD("ClearKeySessionManager::DoDecrypt");
+  Status status = mDecryptionManager->Decrypt(buffer->Data(),
+                                              buffer->Size(),
+                                              CryptoMetaData(&aBuffer));
 
-  GMPErr rv = mDecryptionManager->Decrypt(aBuffer->Data(), aBuffer->Size(),
-                                          CryptoMetaData(aMetadata));
-  CK_LOGD("DeDecrypt finished with code %x\n", rv);
-  mCallback->Decrypted(aBuffer, rv);
-}
+  aDecryptedBlock->SetDecryptedBuffer(buffer);
+  aDecryptedBlock->SetTimestamp(aBuffer.timestamp);
 
-void
-ClearKeySessionManager::Shutdown()
-{
-  CK_LOGD("ClearKeySessionManager::Shutdown %p", this);
-
-  for (auto it = mSessions.begin(); it != mSessions.end(); it++) {
-    delete it->second;
-  }
-  mSessions.clear();
+  return status;
 }
 
 void
 ClearKeySessionManager::DecryptingComplete()
 {
   CK_LOGD("ClearKeySessionManager::DecryptingComplete %p", this);
 
-  GMPThread* thread = mThread;
-  thread->Join();
+  for (auto it = mSessions.begin(); it != mSessions.end(); it++) {
+    delete it->second;
+  }
+  mSessions.clear();
 
-  Shutdown();
   mDecryptionManager = nullptr;
+  mHost = nullptr;
+
   Release();
 }
+
+bool ClearKeySessionManager::MaybeDeferTillInitialized(function<void()> aMaybeDefer)
+{
+  if (mPersistence->IsLoaded()) {
+    return false;
+  }
+
+  mDeferredInitialize.emplace(move(aMaybeDefer));
+  return true;
+}
--- a/media/gmp-clearkey/0.1/ClearKeySessionManager.h
+++ b/media/gmp-clearkey/0.1/ClearKeySessionManager.h
@@ -1,100 +1,102 @@
 /*
- * Copyright 2015, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
+* Copyright 2015, Mozilla Foundation and contributors
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
 
 #ifndef __ClearKeyDecryptor_h__
 #define __ClearKeyDecryptor_h__
 
+#include "ClearKeyDecryptionManager.h"
+#include "ClearKeyPersistence.h"
+#include "ClearKeySession.h"
+#include "ClearKeyUtils.h"
+// This include is required in order for content_decryption_module to work
+// on Unix systems.
+#include "stddef.h"
+#include "content_decryption_module.h"
+#include "RefCounted.h"
+
+#include <functional>
 #include <map>
+#include <queue>
 #include <set>
 #include <string>
-#include <vector>
 
-#include "ClearKeyDecryptionManager.h"
-#include "ClearKeySession.h"
-#include "ClearKeyUtils.h"
-#include "gmp-api/gmp-decryption.h"
-#include "RefCounted.h"
-
-class ClearKeySessionManager final : public GMPDecryptor
-                                   , public RefCounted
+class ClearKeySessionManager final : public RefCounted
 {
 public:
-  ClearKeySessionManager();
+  explicit ClearKeySessionManager(cdm::Host_8* aHost);
 
-  virtual void Init(GMPDecryptorCallback* aCallback,
-                    bool aDistinctiveIdentifierAllowed,
-                    bool aPersistentStateAllowed) override;
+  void Init(bool aDistinctiveIdentifierAllowed,
+            bool aPersistentStateAllowed);
 
-  virtual void CreateSession(uint32_t aCreateSessionToken,
-                             uint32_t aPromiseId,
-                             const char* aInitDataType,
-                             uint32_t aInitDataTypeSize,
-                             const uint8_t* aInitData,
-                             uint32_t aInitDataSize,
-                             GMPSessionType aSessionType) override;
+  void CreateSession(uint32_t aPromiseId,
+                     cdm::InitDataType aInitDataType,
+                     const uint8_t* aInitData,
+                     uint32_t aInitDataSize,
+                     cdm::SessionType aSessionType);
 
-  virtual void LoadSession(uint32_t aPromiseId,
-                           const char* aSessionId,
-                           uint32_t aSessionIdLength) override;
+  void LoadSession(uint32_t aPromiseId,
+                   const char* aSessionId,
+                   uint32_t aSessionIdLength);
 
-  virtual void UpdateSession(uint32_t aPromiseId,
-                             const char* aSessionId,
-                             uint32_t aSessionIdLength,
-                             const uint8_t* aResponse,
-                             uint32_t aResponseSize) override;
+  void UpdateSession(uint32_t aPromiseId,
+                     const char* aSessionId,
+                     uint32_t aSessionIdLength,
+                     const uint8_t* aResponse,
+                     uint32_t aResponseSize);
 
-  virtual void CloseSession(uint32_t aPromiseId,
-                            const char* aSessionId,
-                            uint32_t aSessionIdLength) override;
+  void CloseSession(uint32_t aPromiseId,
+                    const char* aSessionId,
+                    uint32_t aSessionIdLength);
 
-  virtual void RemoveSession(uint32_t aPromiseId,
-                             const char* aSessionId,
-                             uint32_t aSessionIdLength) override;
+  void RemoveSession(uint32_t aPromiseId,
+                     const char* aSessionId,
+                     uint32_t aSessionIdLength);
 
-  virtual void SetServerCertificate(uint32_t aPromiseId,
-                                    const uint8_t* aServerCert,
-                                    uint32_t aServerCertSize) override;
+  void SetServerCertificate(uint32_t aPromiseId,
+                            const uint8_t* aServerCert,
+                            uint32_t aServerCertSize);
 
-  virtual void Decrypt(GMPBuffer* aBuffer,
-                       GMPEncryptedBufferMetadata* aMetadata) override;
+  cdm::Status
+  Decrypt(const cdm::InputBuffer& aBuffer,
+          cdm::DecryptedBlock* aDecryptedBlock);
 
-  virtual void DecryptingComplete() override;
+  void DecryptingComplete();
 
-  void PersistentSessionDataLoaded(GMPErr aStatus,
-                                   uint32_t aPromiseId,
+  void PersistentSessionDataLoaded(uint32_t aPromiseId,
                                    const std::string& aSessionId,
                                    const uint8_t* aKeyData,
                                    uint32_t aKeyDataSize);
 
 private:
   ~ClearKeySessionManager();
 
-  void DoDecrypt(GMPBuffer* aBuffer, GMPEncryptedBufferMetadata* aMetadata);
-  void Shutdown();
-
   void ClearInMemorySessionData(ClearKeySession* aSession);
-  void Serialize(const ClearKeySession* aSession, std::vector<uint8_t>& aOutKeyData);
+  bool MaybeDeferTillInitialized(std::function<void()> aMaybeDefer);
+  void Serialize(const ClearKeySession* aSession,
+                 std::vector<uint8_t>& aOutKeyData);
 
   RefPtr<ClearKeyDecryptionManager> mDecryptionManager;
+  RefPtr<ClearKeyPersistence> mPersistence;
 
-  GMPDecryptorCallback* mCallback;
-  GMPThread* mThread;
+  cdm::Host_8* mHost = nullptr;
 
   std::set<KeyId> mKeyIds;
   std::map<std::string, ClearKeySession*> mSessions;
+
+  std::queue<std::function<void()>> mDeferredInitialize;
 };
 
 #endif // __ClearKeyDecryptor_h__
--- a/media/gmp-clearkey/0.1/ClearKeyStorage.cpp
+++ b/media/gmp-clearkey/0.1/ClearKeyStorage.cpp
@@ -10,185 +10,217 @@
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 #include "ClearKeyStorage.h"
+
 #include "ClearKeyUtils.h"
 
-#include "gmp-task-utils.h"
+// This include is required in order for content_decryption_module to work
+// on Unix systems.
+#include "stddef.h"
+#include "content_decryption_module.h"
 
 #include <assert.h>
 #include "ArrayUtils.h"
-
 #include <vector>
 
-static GMPErr
-RunOnMainThread(GMPTask* aTask)
-{
-  return GetPlatform()->runonmainthread(aTask);
-}
+using namespace cdm;
+using namespace std;
 
-GMPErr
-OpenRecord(const char* aName,
-           uint32_t aNameLength,
-           GMPRecord** aOutRecord,
-           GMPRecordClient* aClient)
+class WriteRecordClient : public FileIOClient
 {
-  return GetPlatform()->createrecord(aName, aNameLength, aOutRecord, aClient);
-}
-
-class WriteRecordClient : public GMPRecordClient {
 public:
   /*
    * This function will take the memory ownership of the parameters and
    * delete them when done.
    */
-  static void Write(const std::string& aRecordName,
-                    const std::vector<uint8_t>& aData,
-                    GMPTask* aOnSuccess,
-                    GMPTask* aOnFailure) {
-    (new WriteRecordClient(aData, aOnSuccess, aOnFailure))->Do(aRecordName);
+  static void Write(Host_8* aHost,
+                    string& aRecordName,
+                    const vector<uint8_t>& aData,
+                    function<void()>&& aOnSuccess,
+                    function<void()>&& aOnFailure)
+{
+    WriteRecordClient* client = new WriteRecordClient(aData,
+                                                      move(aOnSuccess),
+                                                      move(aOnFailure));
+    client->Do(aRecordName, aHost);
   }
 
-  virtual void OpenComplete(GMPErr aStatus) override {
-    if (GMP_FAILED(aStatus) ||
-        GMP_FAILED(mRecord->Write(&mData.front(), mData.size()))) {
-      Done(mOnFailure, mOnSuccess);
+  void OnOpenComplete(Status aStatus) override
+  {
+    // If we hit an error, fail.
+    if (aStatus != Status::kSuccess) {
+      Done(aStatus);
+    } else if (mFileIO) { // Otherwise, write our data to the file.
+      mFileIO->Write(&mData[0], mData.size());
     }
   }
 
-  virtual void ReadComplete(GMPErr aStatus,
-                            const uint8_t* aData,
-                            uint32_t aDataSize) override {
-    assert(false); // Should not reach here.
+  void OnReadComplete(Status aStatus,
+                      const uint8_t* aData,
+                      uint32_t aDataSize) override
+  {
+    // This function should never be called, we only ever write data with this
+    // client.
+    assert(false);
   }
 
-  virtual void WriteComplete(GMPErr aStatus) override {
-    if (GMP_FAILED(aStatus)) {
-      Done(mOnFailure, mOnSuccess);
-    } else {
-      Done(mOnSuccess, mOnFailure);
-    }
+  void OnWriteComplete(Status aStatus) override
+  {
+    Done(aStatus);
   }
 
 private:
-  WriteRecordClient(const std::vector<uint8_t>& aData,
-                    GMPTask* aOnSuccess,
-                    GMPTask* aOnFailure)
-    : mRecord(nullptr)
-    , mOnSuccess(aOnSuccess)
-    , mOnFailure(aOnFailure)
+  explicit WriteRecordClient(const vector<uint8_t>& aData,
+                             function<void()>&& aOnSuccess,
+                             function<void()>&& aOnFailure)
+    : mFileIO(nullptr)
+    , mOnSuccess(move(aOnSuccess))
+    , mOnFailure(move(aOnFailure))
     , mData(aData) {}
 
-  void Do(const std::string& aName) {
-    auto err = OpenRecord(aName.c_str(), aName.size(), &mRecord, this);
-    if (GMP_FAILED(err) ||
-        GMP_FAILED(mRecord->Open())) {
-      Done(mOnFailure, mOnSuccess);
-    }
+  void Do(const string& aName, Host_8* aHost)
+  {
+    // Initialize the FileIO.
+    mFileIO = aHost->CreateFileIO(this);
+    mFileIO->Open(aName.c_str(), aName.size());
   }
 
-  void Done(GMPTask* aToRun, GMPTask* aToDestroy) {
+  void Done(cdm::FileIOClient::Status aStatus)
+  {
     // Note: Call Close() before running continuation, in case the
     // continuation tries to open the same record; if we call Close()
     // after running the continuation, the Close() call will arrive
     // just after the Open() call succeeds, immediately closing the
     // record we just opened.
-    if (mRecord) {
-      mRecord->Close();
+    if (mFileIO) {
+      mFileIO->Close();
     }
-    aToDestroy->Destroy();
-    RunOnMainThread(aToRun);
+
+    if (IO_SUCCEEDED(aStatus)) {
+      mOnSuccess();
+    } else {
+      mOnFailure();
+    }
+
     delete this;
   }
 
-  GMPRecord* mRecord;
-  GMPTask* mOnSuccess;
-  GMPTask* mOnFailure;
-  const std::vector<uint8_t> mData;
+  FileIO* mFileIO = nullptr;
+
+  function<void()> mOnSuccess;
+  function<void()> mOnFailure;
+
+  const vector<uint8_t> mData;
 };
 
 void
-StoreData(const std::string& aRecordName,
-          const std::vector<uint8_t>& aData,
-          GMPTask* aOnSuccess,
-          GMPTask* aOnFailure)
+WriteData(Host_8* aHost,
+          string& aRecordName,
+          const vector<uint8_t>& aData,
+          function<void()>&& aOnSuccess,
+          function<void()>&& aOnFailure)
 {
-  WriteRecordClient::Write(aRecordName, aData, aOnSuccess, aOnFailure);
+  WriteRecordClient::Write(aHost,
+                           aRecordName,
+                           aData,
+                           move(aOnSuccess),
+                           move(aOnFailure));
 }
 
-class ReadRecordClient : public GMPRecordClient {
+class ReadRecordClient : public FileIOClient
+{
 public:
   /*
    * This function will take the memory ownership of the parameters and
    * delete them when done.
    */
-  static void Read(const std::string& aRecordName,
-                   ReadContinuation* aContinuation) {
-    assert(aContinuation);
-    (new ReadRecordClient(aContinuation))->Do(aRecordName);
+  static void Read(Host_8* aHost,
+                   string& aRecordName,
+                   function<void(const uint8_t*, uint32_t)>&& aOnSuccess,
+                   function<void()>&& aOnFailure)
+  {
+
+    (new ReadRecordClient(move(aOnSuccess), move(aOnFailure)))->
+      Do(aRecordName, aHost);
   }
 
-  virtual void OpenComplete(GMPErr aStatus) override {
+  void OnOpenComplete(Status aStatus) override
+  {
     auto err = aStatus;
-    if (GMP_FAILED(err) ||
-        GMP_FAILED(err = mRecord->Read())) {
+    if (aStatus != Status::kSuccess) {
       Done(err, nullptr, 0);
+    } else {
+      mFileIO->Read();
     }
   }
 
-  virtual void ReadComplete(GMPErr aStatus,
-                            const uint8_t* aData,
-                            uint32_t aDataSize) override {
+  void OnReadComplete(Status aStatus,
+                      const uint8_t* aData,
+                      uint32_t aDataSize) override
+  {
     Done(aStatus, aData, aDataSize);
   }
 
-  virtual void WriteComplete(GMPErr aStatus) override {
-    assert(false); // Should not reach here.
+  void OnWriteComplete(Status aStatus) override
+  {
+    // We should never reach here, this client only ever reads data.
+    assert(false);
   }
 
 private:
-  explicit ReadRecordClient(ReadContinuation* aContinuation)
-    : mRecord(nullptr)
-    , mContinuation(aContinuation) {}
+  explicit ReadRecordClient(function<void(const uint8_t*, uint32_t)>&& aOnSuccess,
+                            function<void()>&& aOnFailure)
+    : mFileIO(nullptr)
+    , mOnSuccess(move(aOnSuccess))
+    , mOnFailure(move(aOnFailure))
+  {}
 
-  void Do(const std::string& aName) {
-    auto err = OpenRecord(aName.c_str(), aName.size(), &mRecord, this);
-    if (GMP_FAILED(err) ||
-        GMP_FAILED(err = mRecord->Open())) {
-      Done(err, nullptr, 0);
-    }
+  void Do(const string& aName, Host_8* aHost)
+  {
+    mFileIO = aHost->CreateFileIO(this);
+    mFileIO->Open(aName.c_str(), aName.size());
   }
 
-  void Done(GMPErr err, const uint8_t* aData, uint32_t aDataSize) {
+  void Done(cdm::FileIOClient::Status aStatus,
+            const uint8_t* aData,
+            uint32_t aDataSize)
+  {
     // Note: Call Close() before running continuation, in case the
     // continuation tries to open the same record; if we call Close()
     // after running the continuation, the Close() call will arrive
     // just after the Open() call succeeds, immediately closing the
     // record we just opened.
-    if (mRecord) {
-      mRecord->Close();
+    if (mFileIO) {
+      mFileIO->Close();
     }
-    mContinuation->ReadComplete(err, aData, aDataSize);
-    delete mContinuation;
+
+    if (IO_SUCCEEDED(aStatus)) {
+      mOnSuccess(aData, aDataSize);
+    } else {
+      mOnFailure();
+    }
+
     delete this;
   }
 
-  GMPRecord* mRecord;
-  ReadContinuation* mContinuation;
+  FileIO* mFileIO = nullptr;
+
+  function<void(const uint8_t*, uint32_t)> mOnSuccess;
+  function<void()> mOnFailure;
 };
 
 void
-ReadData(const std::string& aRecordName,
-         ReadContinuation* aContinuation)
+ReadData(Host_8* mHost,
+         string& aRecordName,
+         function<void(const uint8_t*, uint32_t)>&& aOnSuccess,
+         function<void()>&& aOnFailure)
 {
-  ReadRecordClient::Read(aRecordName, aContinuation);
+  ReadRecordClient::Read(mHost,
+                         aRecordName,
+                         move(aOnSuccess),
+                         move(aOnFailure));
 }
-
-GMPErr
-EnumRecordNames(RecvGMPRecordIteratorPtr aRecvIteratorFunc)
-{
-  return GetPlatform()->getrecordenumerator(aRecvIteratorFunc, nullptr);
-}
--- a/media/gmp-clearkey/0.1/ClearKeyStorage.h
+++ b/media/gmp-clearkey/0.1/ClearKeyStorage.h
@@ -12,37 +12,32 @@
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 #ifndef __ClearKeyStorage_h__
 #define __ClearKeyStorage_h__
 
-#include "gmp-api/gmp-errors.h"
-#include "gmp-api/gmp-platform.h"
+#include <functional>
+#include <stdint.h>
 #include <string>
 #include <vector>
-#include <stdint.h>
 
-class GMPTask;
+#include "ClearKeySessionManager.h"
 
-// Responsible for ensuring that both aOnSuccess and aOnFailure are destroyed.
-void StoreData(const std::string& aRecordName,
-               const std::vector<uint8_t>& aData,
-               GMPTask* aOnSuccess,
-               GMPTask* aOnFailure);
+#define IO_SUCCEEDED(x) ((x) == cdm::FileIOClient::Status::kSuccess)
+#define IO_FAILED(x) ((x) != cdm::FileIOClient::Status::kSuccess)
 
-class ReadContinuation {
-public:
-  virtual void ReadComplete(GMPErr aStatus,
-                            const uint8_t* aData,
-                            uint32_t aLength) = 0;
-  virtual ~ReadContinuation() {}
-};
+// Writes data to a file and fires the appropriate callback when complete.
+void WriteData(cdm::Host_8* aHost,
+               std::string& aRecordName,
+               const std::vector<uint8_t>& aData,
+               std::function<void()>&& aOnSuccess,
+               std::function<void()>&& aOnFailure);
 
-// Deletes aContinuation after running it to report the result.
-void ReadData(const std::string& aSessionId,
-              ReadContinuation* aContinuation);
-
-GMPErr EnumRecordNames(RecvGMPRecordIteratorPtr aRecvIteratorFunc);
+// Reads data from a file and fires the appropriate callback when complete.
+void ReadData(cdm::Host_8* aHost,
+              std::string& aRecordName,
+              std::function<void(const uint8_t*, uint32_t)>&& aOnSuccess,
+              std::function<void()>&& aOnFailure);
 
 #endif // __ClearKeyStorage_h__
--- a/media/gmp-clearkey/0.1/ClearKeyUtils.cpp
+++ b/media/gmp-clearkey/0.1/ClearKeyUtils.cpp
@@ -9,43 +9,87 @@
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
+#include "ClearKeyUtils.h"
+
 #include <algorithm>
+#include <assert.h>
+#include <stdlib.h>
+#include <cctype>
 #include <ctype.h>
+#include <memory.h>
+#include <sstream>
 #include <stdarg.h>
 #include <stdint.h>
+#include <stdio.h>
 #include <vector>
 
-#include "ClearKeyUtils.h"
+#include "ArrayUtils.h"
+#include "BigEndian.h"
 #include "ClearKeyBase64.h"
-#include "ArrayUtils.h"
-#include <assert.h>
-#include <memory.h>
-#include "BigEndian.h"
+// This include is required in order for content_decryption_module to work
+// on Unix systems.
+#include "stddef.h"
+#include "content_decryption_module.h"
 #include "openaes/oaes_lib.h"
+#include "psshparser/PsshParser.h"
 
+using namespace cdm;
 using namespace std;
 
 void
 CK_Log(const char* aFmt, ...)
 {
+  FILE* out = stdout;
+
+  if (getenv("CLEARKEY_LOG_FILE")) {
+    out = fopen(getenv("CLEARKEY_LOG_FILE"), "a");
+  }
+
   va_list ap;
 
   va_start(ap, aFmt);
-  vprintf(aFmt, ap);
+  const size_t len = 1024;
+  char buf[len];
+  vsnprintf(buf, len, aFmt, ap);
   va_end(ap);
 
-  printf("\n");
-  fflush(stdout);
+  fprintf(out, "%s\n", buf);
+  fflush(out);
+
+  if (out != stdout) {
+    fclose(out);
+  }
+}
+
+static bool
+PrintableAsString(const uint8_t* aBytes, uint32_t aLength)
+{
+  return all_of(aBytes, aBytes + aLength, [] (uint8_t c) {
+    return isprint(c) == 1;
+  });
+}
+
+void
+CK_LogArray(const char* prepend,
+            const uint8_t* aData,
+            const uint32_t aDataSize)
+{
+  // If the data is valid ascii, use that. Otherwise print the hex
+  string data = PrintableAsString(aData, aDataSize) ?
+                string(aData, aData + aDataSize) :
+                ClearKeyUtils::ToHexString(aData, aDataSize);
+
+  CK_LOGD("%s%s", prepend, data.c_str());
 }
 
 static void
 IncrementIV(vector<uint8_t>& aIV) {
   using mozilla::BigEndian;
 
   assert(aIV.size() == 16);
   BigEndian::writeUint64(&aIV[8], BigEndian::readUint64(&aIV[8]) + 1);
@@ -110,27 +154,29 @@ EncodeBase64Web(vector<uint8_t> aBinary,
     }
 
     out[i] += (*data >> (shift + 2)) & sMask;
     shift = (shift + 2) % 8;
 
     // Cast idx to size_t before using it as an array-index,
     // to pacify clang 'Wchar-subscripts' warning:
     size_t idx = static_cast<size_t>(out[i]);
-    assert(idx < MOZ_ARRAY_LENGTH(sAlphabet)); // out of bounds index for 'sAlphabet'
+
+    // out of bounds index for 'sAlphabet'
+    assert(idx < MOZ_ARRAY_LENGTH(sAlphabet));
     out[i] = sAlphabet[idx];
   }
 
   return true;
 }
 
 /* static */ void
 ClearKeyUtils::MakeKeyRequest(const vector<KeyId>& aKeyIDs,
                               string& aOutRequest,
-                              GMPSessionType aSessionType)
+                              SessionType aSessionType)
 {
   assert(aKeyIDs.size() && aOutRequest.empty());
 
   aOutRequest.append("{\"kids\":[");
   for (size_t i = 0; i < aKeyIDs.size(); i++) {
     if (i) {
       aOutRequest.append(",");
     }
@@ -384,17 +430,17 @@ ParseKeys(ParserContext& aCtx, vector<Ke
   }
 
   return GetNextSymbol(aCtx) == ']';
 }
 
 /* static */ bool
 ClearKeyUtils::ParseJWK(const uint8_t* aKeyData, uint32_t aKeyDataSize,
                         vector<KeyIdPair>& aOutKeys,
-                        GMPSessionType aSessionType)
+                        SessionType aSessionType)
 {
   ParserContext ctx;
   ctx.mIter = aKeyData;
   ctx.mEnd = aKeyData + aKeyDataSize;
 
   // Consume '{' from start of object.
   EXPECT_SYMBOL(ctx, '{');
 
@@ -500,25 +546,26 @@ ClearKeyUtils::ParseKeyIdsInitData(const
 
   // Consume '}' from end of object.
   EXPECT_SYMBOL(ctx, '}');
 
   return true;
 }
 
 /* static */ const char*
-ClearKeyUtils::SessionTypeToString(GMPSessionType aSessionType)
+ClearKeyUtils::SessionTypeToString(SessionType aSessionType)
 {
   switch (aSessionType) {
-    case kGMPTemporySession: return "temporary";
-    case kGMPPersistentSession: return "persistent-license";
-    default: {
-      assert(false); // Should not reach here.
-      return "invalid";
-    }
+  case SessionType::kTemporary: return "temporary";
+  case SessionType::kPersistentLicense: return "persistent-license";
+  default: {
+    // We don't support any other license types.
+    assert(false);
+    return "invalid";
+  }
   }
 }
 
 /* static */ bool
 ClearKeyUtils::IsValidSessionId(const char* aBuff, uint32_t aLength)
 {
   if (aLength > 10) {
     // 10 is the max number of characters in UINT32_MAX when
@@ -528,14 +575,20 @@ ClearKeyUtils::IsValidSessionId(const ch
   for (uint32_t i = 0; i < aLength; i++) {
     if (!isdigit(aBuff[i])) {
       return false;
     }
   }
   return true;
 }
 
-GMPMutex* GMPCreateMutex() {
-  GMPMutex* mutex;
-  auto err = GetPlatform()->createmutex(&mutex);
-  assert(mutex);
-  return GMP_FAILED(err) ? nullptr : mutex;
+string
+ClearKeyUtils::ToHexString(const uint8_t * aBytes, uint32_t aLength)
+{
+  stringstream ss;
+  ss << std::showbase << std::uppercase << std::hex;
+  for (uint32_t i = 0; i < aLength; ++i) {
+    ss << std::hex << static_cast<uint32_t>(aBytes[i]);
+    ss << " ";
+  }
+
+  return ss.str();
 }
--- a/media/gmp-clearkey/0.1/ClearKeyUtils.h
+++ b/media/gmp-clearkey/0.1/ClearKeyUtils.h
@@ -16,43 +16,54 @@
 
 #ifndef __ClearKeyUtils_h__
 #define __ClearKeyUtils_h__
 
 #include <stdint.h>
 #include <string>
 #include <vector>
 #include <assert.h>
-#include "gmp-api/gmp-decryption.h"
+
+// This include is required in order for content_decryption_module to work
+// on Unix systems.
+#include "stddef.h"
+#include "content_decryption_module.h"
 
 #if 0
 void CK_Log(const char* aFmt, ...);
 #define CK_LOGE(...) CK_Log(__VA_ARGS__)
 #define CK_LOGD(...) CK_Log(__VA_ARGS__)
 #define CK_LOGW(...) CK_Log(__VA_ARGS__)
+#define CK_LOGARRAY(APREPEND, ADATA, ADATA_SIZE) CK_LogArray(APREPEND, \
+  ADATA, \
+  ADATA_SIZE)
 #else
+// Note: Enabling logging slows things down a LOT, especially when logging to
+// a file.
 #define CK_LOGE(...)
 #define CK_LOGD(...)
 #define CK_LOGW(...)
+#define CK_LOGARRAY(APREPEND, ADATA, ADATA_SIZE)
 #endif
 
-struct GMPPlatformAPI;
-extern GMPPlatformAPI* GetPlatform();
-
 typedef std::vector<uint8_t> KeyId;
 typedef std::vector<uint8_t> Key;
 
 // The session response size should be within a reasonable limit.
 // The size 64 KB is referenced from web-platform-test.
 static const uint32_t kMaxSessionResponseLength = 65536;
 
 // Provide limitation for KeyIds length and webm initData size.
 static const uint32_t kMaxWebmInitDataSize = 65536;
 static const uint32_t kMaxKeyIdsLength = 512;
 
+void CK_LogArray(const char* aPrepend,
+                 const uint8_t* aData,
+                 const uint32_t aDataSize);
+
 struct KeyIdPair
 {
   KeyId mKeyId;
   Key mKey;
 };
 
 class ClearKeyUtils
 {
@@ -61,54 +72,35 @@ public:
                          std::vector<uint8_t>& aData, std::vector<uint8_t>& aIV);
 
   static bool ParseKeyIdsInitData(const uint8_t* aInitData,
                                   uint32_t aInitDataSize,
                                   std::vector<KeyId>& aOutKeyIds);
 
   static void MakeKeyRequest(const std::vector<KeyId>& aKeyIds,
                              std::string& aOutRequest,
-                             GMPSessionType aSessionType);
+                             cdm::SessionType aSessionType);
 
   static bool ParseJWK(const uint8_t* aKeyData, uint32_t aKeyDataSize,
                        std::vector<KeyIdPair>& aOutKeys,
-                       GMPSessionType aSessionType);
-  static const char* SessionTypeToString(GMPSessionType aSessionType);
+                       cdm::SessionType aSessionType);
+  static const char* SessionTypeToString(cdm::SessionType aSessionType);
 
   static bool IsValidSessionId(const char* aBuff, uint32_t aLength);
+
+  static std::string ToHexString(const uint8_t * aBytes, uint32_t aLength);
 };
 
 template<class Container, class Element>
 inline bool
 Contains(const Container& aContainer, const Element& aElement)
 {
   return aContainer.find(aElement) != aContainer.end();
 }
 
-class AutoLock {
-public:
-  explicit AutoLock(GMPMutex* aMutex)
-    : mMutex(aMutex)
-  {
-    assert(aMutex);
-    if (mMutex) {
-      mMutex->Acquire();
-    }
-  }
-  ~AutoLock() {
-    if (mMutex) {
-      mMutex->Release();
-    }
-  }
-private:
-  GMPMutex* mMutex;
-};
-
-GMPMutex* GMPCreateMutex();
-
 template<typename T>
 inline void
 Assign(std::vector<T>& aVec, const T* aData, size_t aLength)
 {
   aVec.assign(aData, aData + aLength);
 }
 
 #endif // __ClearKeyUtils_h__
--- a/media/gmp-clearkey/0.1/RefCounted.h
+++ b/media/gmp-clearkey/0.1/RefCounted.h
@@ -82,35 +82,51 @@ protected:
     assert(!mRefCount);
   }
   AtomicRefCount mRefCount;
 };
 
 template<class T>
 class RefPtr {
 public:
-  explicit RefPtr(T* aPtr) : mPtr(nullptr) {
-    Assign(aPtr);
+  RefPtr(const RefPtr& src) {
+    Set(src.mPtr);
   }
+
+  explicit RefPtr(T* aPtr) {
+    Set(aPtr);
+  }
+  RefPtr() { Set(nullptr); }
+
   ~RefPtr() {
-    Assign(nullptr);
+    Set(nullptr);
   }
   T* operator->() const { return mPtr; }
+  T** operator&() { return &mPtr; }
+  T* operator->() { return mPtr; }
+  operator T*() { return mPtr; }
+
+  T* Get() const { return mPtr; }
 
   RefPtr& operator=(T* aVal) {
-    Assign(aVal);
+    Set(aVal);
     return *this;
   }
 
 private:
-  void Assign(T* aPtr) {
+  T* Set(T* aPtr) {
+    if (mPtr == aPtr) {
+      return aPtr;
+    }
     if (mPtr) {
       mPtr->Release();
     }
     mPtr = aPtr;
     if (mPtr) {
       aPtr->AddRef();
     }
+    return mPtr;
   }
-  T* mPtr;
+
+  T* mPtr = nullptr;
 };
 
 #endif // __RefCount_h__
--- a/media/gmp-clearkey/0.1/VideoDecoder.cpp
+++ b/media/gmp-clearkey/0.1/VideoDecoder.cpp
@@ -9,447 +9,310 @@
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
+#include <algorithm>
 #include <cstdint>
 #include <limits>
 
-#include "AnnexB.h"
 #include "BigEndian.h"
 #include "ClearKeyDecryptionManager.h"
 #include "ClearKeyUtils.h"
-#include "gmp-task-utils.h"
 #include "VideoDecoder.h"
 
 using namespace wmf;
+using namespace cdm;
 
-VideoDecoder::VideoDecoder(GMPVideoHost *aHostAPI)
-  : mHostAPI(aHostAPI)
-  , mCallback(nullptr)
-  , mWorkerThread(nullptr)
-  , mMutex(nullptr)
-  , mNumInputTasks(0)
-  , mSentExtraData(false)
-  , mIsFlushing(false)
+VideoDecoder::VideoDecoder(Host_8 *aHost)
+  : mHost(aHost)
   , mHasShutdown(false)
 {
   // We drop the ref in DecodingComplete().
   AddRef();
+
+  mDecoder = new WMFH264Decoder();
+
+  uint32_t cores = std::max(1u, std::thread::hardware_concurrency());
+  HRESULT hr = mDecoder->Init(cores);
 }
 
 VideoDecoder::~VideoDecoder()
 {
-  if (mMutex) {
-    mMutex->Destroy();
-  }
+
 }
 
-void
-VideoDecoder::InitDecode(const GMPVideoCodec& aCodecSettings,
-                         const uint8_t* aCodecSpecific,
-                         uint32_t aCodecSpecificLength,
-                         GMPVideoDecoderCallback* aCallback,
-                         int32_t aCoreCount)
+Status
+VideoDecoder::InitDecode(const VideoDecoderConfig& aConfig)
 {
-  mCallback = aCallback;
-  assert(mCallback);
-  mDecoder = new WMFH264Decoder();
-  HRESULT hr = mDecoder->Init(aCoreCount);
-  if (FAILED(hr)) {
+  if (!mDecoder) {
     CK_LOGD("VideoDecoder::InitDecode failed to init WMFH264Decoder");
-    mCallback->Error(GMPGenericErr);
-    return;
-  }
 
-  auto err = GetPlatform()->createmutex(&mMutex);
-  if (GMP_FAILED(err)) {
-    CK_LOGD("VideoDecoder::InitDecode failed to create GMPMutex");
-    mCallback->Error(GMPGenericErr);
-    return;
+    return Status::kDecodeError;
   }
 
-  // The first byte is mPacketizationMode, which is only relevant for
-  // WebRTC/OpenH264 usecase.
-  const uint8_t* avcc = aCodecSpecific + 1;
-  const uint8_t* avccEnd = aCodecSpecific + aCodecSpecificLength;
-  mExtraData.insert(mExtraData.end(), avcc, avccEnd);
-
-  AnnexB::ConvertConfig(mExtraData, mAnnexB);
+  return Status::kSuccess;
 }
 
-void
-VideoDecoder::EnsureWorker()
+Status
+VideoDecoder::Decode(const InputBuffer& aInputBuffer, VideoFrame* aVideoFrame)
 {
-  if (!mWorkerThread) {
-    GetPlatform()->createthread(&mWorkerThread);
-    if (!mWorkerThread) {
-      mCallback->Error(GMPAllocErr);
-      return;
-    }
-  }
-}
-
-void
-VideoDecoder::Decode(GMPVideoEncodedFrame* aInputFrame,
-                     bool aMissingFrames,
-                     const uint8_t* aCodecSpecificInfo,
-                     uint32_t aCodecSpecificInfoLength,
-                     int64_t aRenderTimeMs)
-{
-  if (aInputFrame->BufferType() != GMP_BufferLength32) {
-    // Gecko should only send frames with 4 byte NAL sizes to GMPs.
-    mCallback->Error(GMPGenericErr);
-    return;
+  // If the input buffer we have been passed has a null buffer, it means we
+  // should drain.
+  if (!aInputBuffer.data) {
+    // This will drain the decoder until there are no frames left to drain,
+    // whereupon it will return 'NeedsMoreData'.
+    CK_LOGD("Input buffer null: Draining");
+    return Drain(aVideoFrame);
   }
 
-  EnsureWorker();
+  DecodeData* data = new DecodeData();
+  Assign(data->mBuffer, aInputBuffer.data, aInputBuffer.data_size);
+  data->mTimestamp = aInputBuffer.timestamp;
+  data->mCrypto = CryptoMetaData(&aInputBuffer);
 
-  {
-    AutoLock lock(mMutex);
-    mNumInputTasks++;
+  CK_LOGD("VideoDecoder::DecodeTask");
+  AutoPtr<DecodeData> d(data);
+  HRESULT hr;
+
+  if (!data || !mDecoder) {
+    CK_LOGE("Decode job not set up correctly!");
+    return Status::kDecodeError;
   }
 
-  // Note: we don't need the codec specific info on a per-frame basis.
-  // It's mostly useful for WebRTC use cases.
+  std::vector<uint8_t>& buffer = data->mBuffer;
 
-  // Make a copy of the data, so we can release aInputFrame ASAP,
-  // to avoid too many shmem handles being held by the GMP process.
-  // If the GMP process holds on to too many shmem handles, the Gecko
-  // side can fail to allocate a shmem to send more input. This is
-  // particularly a problem in Gecko mochitests, which can open multiple
-  // actors at once which share the same pool of shmems.
-  DecodeData* data = new DecodeData();
-  Assign(data->mBuffer, aInputFrame->Buffer(), aInputFrame->Size());
-  data->mTimestamp = aInputFrame->TimeStamp();
-  data->mDuration = aInputFrame->Duration();
-  data->mIsKeyframe = (aInputFrame->FrameType() == kGMPKeyFrame);
-  const GMPEncryptedBufferMetadata* crypto = aInputFrame->GetDecryptionData();
-  if (crypto) {
-    data->mCrypto.Init(crypto);
-  }
-  aInputFrame->Destroy();
-  mWorkerThread->Post(WrapTaskRefCounted(this,
-                                         &VideoDecoder::DecodeTask,
-                                         data));
-}
-
-void
-VideoDecoder::DecodeTask(DecodeData* aData)
-{
-  CK_LOGD("VideoDecoder::DecodeTask");
-  AutoPtr<DecodeData> d(aData);
-  HRESULT hr;
+  if (data->mCrypto.IsValid()) {
+    Status rv =
+      ClearKeyDecryptionManager::Get()->Decrypt(buffer, data->mCrypto);
 
-  {
-    AutoLock lock(mMutex);
-    mNumInputTasks--;
-    assert(mNumInputTasks >= 0);
-  }
-
-  if (mIsFlushing) {
-    CK_LOGD("VideoDecoder::DecodeTask rejecting frame: flushing.");
-    return;
-  }
-
-  if (!aData || !mHostAPI || !mDecoder) {
-    CK_LOGE("Decode job not set up correctly!");
-    return;
-  }
-
-  std::vector<uint8_t>& buffer = aData->mBuffer;
-  if (aData->mCrypto.IsValid()) {
-    // Plugin host should have set up its decryptor/key sessions
-    // before trying to decode!
-    GMPErr rv =
-      ClearKeyDecryptionManager::Get()->Decrypt(buffer, aData->mCrypto);
-
-    if (GMP_FAILED(rv)) {
-      MaybeRunOnMainThread(WrapTask(mCallback, &GMPVideoDecoderCallback::Error, rv));
-      return;
+    if (STATUS_FAILED(rv)) {
+      CK_LOGARRAY("Failed to decrypt video using key ",
+                  aInputBuffer.key_id,
+                  aInputBuffer.key_id_size);
+      return rv;
     }
   }
 
-  AnnexB::ConvertFrameInPlace(buffer);
-
-  if (aData->mIsKeyframe) {
-    // We must send the SPS and PPS to Windows Media Foundation's decoder.
-    // Note: We do this *after* decryption, otherwise the subsample info
-    // would be incorrect.
-    buffer.insert(buffer.begin(), mAnnexB.begin(), mAnnexB.end());
-  }
-
   hr = mDecoder->Input(buffer.data(),
                        buffer.size(),
-                       aData->mTimestamp,
-                       aData->mDuration);
+                       data->mTimestamp);
 
   CK_LOGD("VideoDecoder::DecodeTask() Input ret hr=0x%x\n", hr);
+
+
   if (FAILED(hr)) {
+    assert(hr != MF_E_TRANSFORM_NEED_MORE_INPUT);
+
     CK_LOGE("VideoDecoder::DecodeTask() decode failed ret=0x%x%s\n",
-        hr,
-        ((hr == MF_E_NOTACCEPTING) ? " (MF_E_NOTACCEPTING)" : ""));
-    return;
+      hr,
+      ((hr == MF_E_NOTACCEPTING) ? " (MF_E_NOTACCEPTING)" : ""));
+    CK_LOGD("Decode failed. The decoder is not accepting input");
+    return Status::kDecodeError;
   }
 
-  while (hr == S_OK) {
+  return OutputFrame(aVideoFrame);
+}
+
+Status VideoDecoder::OutputFrame(VideoFrame* aVideoFrame) {
+  HRESULT hr = S_OK;
+
+  // Read all the output from the decoder. Ideally, this would be a while loop
+  // where we read the output and check the result as the condition. However,
+  // this produces a memory leak connected to assigning a new CComPtr to the
+  // address of the old one, which avoids the CComPtr cleaning up.
+  while (true) {
     CComPtr<IMFSample> output;
     hr = mDecoder->Output(&output);
-    CK_LOGD("VideoDecoder::DecodeTask() output ret=0x%x\n", hr);
-    if (hr == S_OK) {
-      MaybeRunOnMainThread(
-        WrapTaskRefCounted(this,
-                           &VideoDecoder::ReturnOutput,
-                           CComPtr<IMFSample>(output),
-                           mDecoder->GetFrameWidth(),
-                           mDecoder->GetFrameHeight(),
-                           mDecoder->GetStride()));
+
+    if (hr != S_OK) {
+      break;
     }
-    if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) {
-      AutoLock lock(mMutex);
-      if (mNumInputTasks == 0) {
-        // We have run all input tasks. We *must* notify Gecko so that it will
-        // send us more data.
-        MaybeRunOnMainThread(
-          WrapTask(mCallback,
-                   &GMPVideoDecoderCallback::InputDataExhausted));
-      }
-    }
-    if (FAILED(hr)) {
-      CK_LOGE("VideoDecoder::DecodeTask() output failed hr=0x%x\n", hr);
-    }
+
+    CK_LOGD("VideoDecoder::DecodeTask() output ret=0x%x\n", hr);
+
+    mOutputQueue.push(output);
+    CK_LOGD("Queue size: %u", mOutputQueue.size());
   }
-}
 
-void
-VideoDecoder::ReturnOutput(IMFSample* aSample,
-                           int32_t aWidth,
-                           int32_t aHeight,
-                           int32_t aStride)
-{
-  CK_LOGD("[%p] VideoDecoder::ReturnOutput()\n", this);
-  assert(aSample);
-
-  HRESULT hr;
-
-  GMPVideoFrame* f = nullptr;
-  auto err = mHostAPI->CreateFrame(kGMPI420VideoFrame, &f);
-  if (GMP_FAILED(err) || !f) {
-    CK_LOGE("Failed to create i420 frame!\n");
-    return;
-  }
-  if (HasShutdown()) {
-    // Note: GMPVideoHost::CreateFrame() can process messages before returning,
-    // including a message that calls VideoDecoder::DecodingComplete(), i.e.
-    // we can shutdown during the call!
-    CK_LOGD("Shutdown while waiting on GMPVideoHost::CreateFrame()!\n");
-    f->Destroy();
-    return;
+  // If we don't have any inputs, we need more data.
+  if (mOutputQueue.empty()) {
+    CK_LOGD("Decode failed. Not enought data; Requesting more input");
+    return Status::kNeedMoreData;
   }
 
-  auto vf = static_cast<GMPVideoi420Frame*>(f);
+  // We will get a MF_E_TRANSFORM_NEED_MORE_INPUT every time, as we always
+  // consume everything in the buffer.
+  if (hr != MF_E_TRANSFORM_NEED_MORE_INPUT && FAILED(hr)) {
+    CK_LOGD("Decode failed output ret=0x%x\n", hr);
+    return Status::kDecodeError;
+  }
+
+  CComPtr<IMFSample> result = mOutputQueue.front();
+  mOutputQueue.pop();
 
-  hr = SampleToVideoFrame(aSample, aWidth, aHeight, aStride, vf);
-  ENSURE(SUCCEEDED(hr), /*void*/);
+  // The Chromium CDM API doesn't have support for negative strides, though
+  // they are theoretically possible in real world data.
+  if (mDecoder->GetStride() <= 0) {
+    return Status::kDecodeError;
+  }
 
-  mCallback->Decoded(vf);
+  hr = SampleToVideoFrame(result,
+                          mDecoder->GetFrameWidth(),
+                          mDecoder->GetFrameHeight(),
+                          mDecoder->GetStride(),
+                          aVideoFrame);
+  if (FAILED(hr)) {
+    return Status::kDecodeError;
+  }
+
+  CK_LOGD("Decode succeeded.");
+  return Status::kSuccess;
 }
 
 HRESULT
 VideoDecoder::SampleToVideoFrame(IMFSample* aSample,
                                  int32_t aWidth,
                                  int32_t aHeight,
                                  int32_t aStride,
-                                 GMPVideoi420Frame* aVideoFrame)
+                                 VideoFrame* aVideoFrame)
 {
+  CK_LOGD("[%p] VideoDecoder::SampleToVideoFrame()\n", this);
+  assert(aSample);
+
   ENSURE(aSample != nullptr, E_POINTER);
   ENSURE(aVideoFrame != nullptr, E_POINTER);
 
   HRESULT hr;
   CComPtr<IMFMediaBuffer> mediaBuffer;
 
+  aVideoFrame->SetFormat(kI420);
+
   // Must convert to contiguous mediaBuffer to use IMD2DBuffer interface.
   hr = aSample->ConvertToContiguousBuffer(&mediaBuffer);
   ENSURE(SUCCEEDED(hr), hr);
 
   // Try and use the IMF2DBuffer interface if available, otherwise fallback
   // to the IMFMediaBuffer interface. Apparently IMF2DBuffer is more efficient,
   // but only some systems (Windows 8?) support it.
   BYTE* data = nullptr;
   LONG stride = 0;
   CComPtr<IMF2DBuffer> twoDBuffer;
   hr = mediaBuffer->QueryInterface(static_cast<IMF2DBuffer**>(&twoDBuffer));
   if (SUCCEEDED(hr)) {
     hr = twoDBuffer->Lock2D(&data, &stride);
     ENSURE(SUCCEEDED(hr), hr);
   } else {
-    hr = mediaBuffer->Lock(&data, NULL, NULL);
+    hr = mediaBuffer->Lock(&data, nullptr, nullptr);
     ENSURE(SUCCEEDED(hr), hr);
     stride = aStride;
   }
 
-  // The V and U planes are stored 16-row-aligned, so we need to add padding
+  // The U and V planes are stored 16-row-aligned, so we need to add padding
   // to the row heights to ensure the Y'CbCr planes are referenced properly.
-  // YV12, planar format: [YYYY....][VVVV....][UUUU....]
-  // i.e., Y, then V, then U.
+  // YV12, planar format: [YYYY....][UUUU....][VVVV....]
+  // i.e., Y, then U, then V.
   uint32_t padding = 0;
   if (aHeight % 16 != 0) {
     padding = 16 - (aHeight % 16);
   }
-  int32_t y_size = stride * (aHeight + padding);
-  int32_t v_size = stride * (aHeight + padding) / 4;
-  int32_t halfStride = (stride + 1) / 2;
-  int32_t halfHeight = (aHeight + 1) / 2;
+  uint32_t ySize = stride * (aHeight + padding);
+  uint32_t uSize = stride * (aHeight + padding) / 4;
+  uint32_t halfStride = (stride + 1) / 2;
+  uint32_t halfHeight = (aHeight + 1) / 2;
+
+  aVideoFrame->SetStride(VideoFrame::kYPlane, stride);
+  aVideoFrame->SetStride(VideoFrame::kUPlane, halfStride);
+  aVideoFrame->SetStride(VideoFrame::kVPlane, halfStride);
 
-  auto err = aVideoFrame->CreateEmptyFrame(stride, aHeight, stride, halfStride, halfStride);
-  ENSURE(GMP_SUCCEEDED(err), E_FAIL);
+  aVideoFrame->SetSize(Size(aWidth, aHeight));
+
+  uint64_t bufferSize = ySize + 2 * uSize;
 
-  err = aVideoFrame->SetWidth(aWidth);
-  ENSURE(GMP_SUCCEEDED(err), E_FAIL);
-  err = aVideoFrame->SetHeight(aHeight);
-  ENSURE(GMP_SUCCEEDED(err), E_FAIL);
+  // If the buffer is bigger than the max for a 32 bit, fail to avoid buffer
+  // overflows.
+  if (bufferSize > UINT32_MAX) {
+    return Status::kDecodeError;
+  }
 
-  uint8_t* outBuffer = aVideoFrame->Buffer(kGMPYPlane);
-  ENSURE(outBuffer != nullptr, E_FAIL);
-  assert(aVideoFrame->AllocatedSize(kGMPYPlane) >= stride*aHeight);
-  memcpy(outBuffer, data, stride*aHeight);
+  // Get the buffer from the host.
+  Buffer* buffer = mHost->Allocate(bufferSize);
+  aVideoFrame->SetFrameBuffer(buffer);
+
+  // Make sure the buffer is non-null (allocate guarantees it will be of
+  // sufficient size).
+  if (!buffer) {
+    return E_OUTOFMEMORY;
+  }
 
-  outBuffer = aVideoFrame->Buffer(kGMPUPlane);
-  ENSURE(outBuffer != nullptr, E_FAIL);
-  assert(aVideoFrame->AllocatedSize(kGMPUPlane) >= halfStride*halfHeight);
-  memcpy(outBuffer, data+y_size, halfStride*halfHeight);
+  uint8_t* outBuffer = buffer->Data();
+
+  aVideoFrame->SetPlaneOffset(VideoFrame::kYPlane, 0);
 
-  outBuffer = aVideoFrame->Buffer(kGMPVPlane);
-  ENSURE(outBuffer != nullptr, E_FAIL);
-  assert(aVideoFrame->AllocatedSize(kGMPVPlane) >= halfStride*halfHeight);
-  memcpy(outBuffer, data + y_size + v_size, halfStride*halfHeight);
+  // Offset is the size of the copied y data.
+  aVideoFrame->SetPlaneOffset(VideoFrame::kUPlane, ySize);
+
+  // Offset is the size of the copied y data + the size of the copied u data.
+  aVideoFrame->SetPlaneOffset(VideoFrame::kVPlane, ySize + uSize);
+
+  // Copy the data.
+  memcpy(outBuffer, data, ySize + uSize * 2);
 
   if (twoDBuffer) {
     twoDBuffer->Unlock2D();
   } else {
     mediaBuffer->Unlock();
   }
 
   LONGLONG hns = 0;
   hr = aSample->GetSampleTime(&hns);
   ENSURE(SUCCEEDED(hr), hr);
+
   aVideoFrame->SetTimestamp(HNsToUsecs(hns));
 
-  hr = aSample->GetSampleDuration(&hns);
-  ENSURE(SUCCEEDED(hr), hr);
-  aVideoFrame->SetDuration(HNsToUsecs(hns));
-
   return S_OK;
 }
 
 void
-VideoDecoder::ResetCompleteTask()
-{
-  mIsFlushing = false;
-  if (mCallback) {
-    MaybeRunOnMainThread(WrapTask(mCallback,
-                                  &GMPVideoDecoderCallback::ResetComplete));
-  }
-}
-
-void
 VideoDecoder::Reset()
 {
-  mIsFlushing = true;
+  CK_LOGD("VideoDecoder::Reset");
+
   if (mDecoder) {
     mDecoder->Reset();
   }
 
-  // Schedule ResetComplete callback to run after existing frames have been
-  // flushed out of the task queue.
-  EnsureWorker();
-  mWorkerThread->Post(WrapTaskRefCounted(this,
-                                         &VideoDecoder::ResetCompleteTask));
+  // Remove all the frames from the output queue.
+  while (!mOutputQueue.empty()) {
+    mOutputQueue.pop();
+  }
 }
 
-void
-VideoDecoder::DrainTask()
+Status
+VideoDecoder::Drain(VideoFrame* aVideoFrame)
 {
+  CK_LOGD("VideoDecoder::Drain()");
+
+  if (!mDecoder) {
+    CK_LOGD("Drain failed! Decoder was not initialized");
+    return Status::kDecodeError;
+  }
+
   mDecoder->Drain();
 
   // Return any pending output.
-  HRESULT hr = S_OK;
-  while (hr == S_OK) {
-    CComPtr<IMFSample> output;
-    hr = mDecoder->Output(&output);
-    CK_LOGD("VideoDecoder::DrainTask() output ret=0x%x\n", hr);
-    if (hr == S_OK) {
-      MaybeRunOnMainThread(
-        WrapTaskRefCounted(this,
-                           &VideoDecoder::ReturnOutput,
-                           CComPtr<IMFSample>(output),
-                           mDecoder->GetFrameWidth(),
-                           mDecoder->GetFrameHeight(),
-                           mDecoder->GetStride()));
-    }
-  }
-  MaybeRunOnMainThread(WrapTask(mCallback, &GMPVideoDecoderCallback::DrainComplete));
-}
-
-void
-VideoDecoder::Drain()
-{
-  if (!mDecoder) {
-    if (mCallback) {
-      mCallback->DrainComplete();
-    }
-    return;
-  }
-  EnsureWorker();
-  mWorkerThread->Post(WrapTaskRefCounted(this,
-                                         &VideoDecoder::DrainTask));
+  return OutputFrame(aVideoFrame);
 }
 
 void
 VideoDecoder::DecodingComplete()
 {
-  if (mWorkerThread) {
-    mWorkerThread->Join();
-  }
   mHasShutdown = true;
 
   // Release the reference we added in the constructor. There may be
   // WrapRefCounted tasks that also hold references to us, and keep
   // us alive a little longer.
   Release();
 }
-
-void
-VideoDecoder::MaybeRunOnMainThread(GMPTask* aTask)
-{
-  class MaybeRunTask : public GMPTask
-  {
-  public:
-    MaybeRunTask(VideoDecoder* aDecoder, GMPTask* aTask)
-      : mDecoder(aDecoder), mTask(aTask)
-    { }
-
-    virtual void Run(void) {
-      if (mDecoder->HasShutdown()) {
-        CK_LOGD("Trying to dispatch to main thread after VideoDecoder has shut down");
-        return;
-      }
-
-      mTask->Run();
-    }
-
-    virtual void Destroy()
-    {
-      mTask->Destroy();
-      delete this;
-    }
-
-  private:
-    RefPtr<VideoDecoder> mDecoder;
-    GMPTask* mTask;
-  };
-
-  GetPlatform()->runonmainthread(new MaybeRunTask(this, aTask));
-}
--- a/media/gmp-clearkey/0.1/VideoDecoder.h
+++ b/media/gmp-clearkey/0.1/VideoDecoder.h
@@ -13,98 +13,62 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 #ifndef __VideoDecoder_h__
 #define __VideoDecoder_h__
 
 #include <atomic>
+#include <queue>
+#include <thread>
 
-#include "gmp-task-utils.h"
-#include "gmp-video-decode.h"
-#include "gmp-video-host.h"
+// This include is required in order for content_decryption_module to work
+// on Unix systems.
+#include "stddef.h"
+#include "content_decryption_module.h"
 #include "WMFH264Decoder.h"
 
-#include "mfobjects.h"
-
-class VideoDecoder : public GMPVideoDecoder
-                   , public RefCounted
+class VideoDecoder : public RefCounted
 {
 public:
-  explicit VideoDecoder(GMPVideoHost *aHostAPI);
+  explicit VideoDecoder(cdm::Host_8 *aHost);
 
-  virtual void InitDecode(const GMPVideoCodec& aCodecSettings,
-                          const uint8_t* aCodecSpecific,
-                          uint32_t aCodecSpecificLength,
-                          GMPVideoDecoderCallback* aCallback,
-                          int32_t aCoreCount) override;
+  cdm::Status InitDecode(const cdm::VideoDecoderConfig& aConfig);
 
-  virtual void Decode(GMPVideoEncodedFrame* aInputFrame,
-                      bool aMissingFrames,
-                      const uint8_t* aCodecSpecific,
-                      uint32_t aCodecSpecificLength,
-                      int64_t aRenderTimeMs = -1);
+  cdm::Status Decode(const cdm::InputBuffer& aEncryptedBuffer,
+                     cdm::VideoFrame* aVideoFrame);
 
-  virtual void Reset() override;
+  void Reset();
 
-  virtual void Drain() override;
-
-  virtual void DecodingComplete() override;
+  void DecodingComplete();
 
   bool HasShutdown() { return mHasShutdown; }
 
 private:
 
   virtual ~VideoDecoder();
 
-  void EnsureWorker();
-
-  void DrainTask();
+  cdm::Status Drain(cdm::VideoFrame* aVideoFrame);
 
   struct DecodeData {
-    DecodeData()
-      : mTimestamp(0)
-      , mDuration(0)
-      , mIsKeyframe(false)
-    {}
     std::vector<uint8_t> mBuffer;
-    uint64_t mTimestamp;
-    uint64_t mDuration;
-    bool mIsKeyframe;
+    uint64_t mTimestamp = 0;
     CryptoMetaData mCrypto;
   };
 
-  void DecodeTask(DecodeData* aData);
-
-  void ResetCompleteTask();
-
-  void ReturnOutput(IMFSample* aSample,
-                    int32_t aWidth,
-                    int32_t aHeight,
-                    int32_t aStride);
+  cdm::Status OutputFrame(cdm::VideoFrame* aVideoFrame);
 
   HRESULT SampleToVideoFrame(IMFSample* aSample,
                              int32_t aWidth,
                              int32_t aHeight,
                              int32_t aStride,
-                             GMPVideoi420Frame* aVideoFrame);
-
-  void MaybeRunOnMainThread(GMPTask* aTask);
+                             cdm::VideoFrame* aVideoFrame);
 
-  GMPVideoHost *mHostAPI; // host-owned, invalid at DecodingComplete
-  GMPVideoDecoderCallback* mCallback; // host-owned, invalid at DecodingComplete
-  GMPThread* mWorkerThread;
-  GMPMutex* mMutex;
+  cdm::Host_8* mHost;
   wmf::AutoPtr<wmf::WMFH264Decoder> mDecoder;
 
-  std::vector<uint8_t> mExtraData;
-  std::vector<uint8_t> mAnnexB;
-
-  int32_t mNumInputTasks;
-  bool mSentExtraData;
-
-  std::atomic<bool> mIsFlushing;
+  std::queue<wmf::CComPtr<IMFSample>> mOutputQueue;
 
   bool mHasShutdown;
 };
 
 #endif // __VideoDecoder_h__
--- a/media/gmp-clearkey/0.1/WMFH264Decoder.cpp
+++ b/media/gmp-clearkey/0.1/WMFH264Decoder.cpp
@@ -191,17 +191,16 @@ WMFH264Decoder::SendMFTMessage(MFT_MESSA
   ENSURE(SUCCEEDED(hr), hr);
   return S_OK;
 }
 
 HRESULT
 WMFH264Decoder::CreateInputSample(const uint8_t* aData,
                                   uint32_t aDataSize,
                                   Microseconds aTimestamp,
-                                  Microseconds aDuration,
                                   IMFSample** aOutSample)
 {
   HRESULT hr;
   CComPtr<IMFSample> sample;
   hr = MFCreateSample(&sample);
   ENSURE(SUCCEEDED(hr), hr);
 
   CComPtr<IMFMediaBuffer> buffer;
@@ -226,18 +225,16 @@ WMFH264Decoder::CreateInputSample(const 
   ENSURE(SUCCEEDED(hr), hr);
 
   hr = sample->AddBuffer(buffer);
   ENSURE(SUCCEEDED(hr), hr);
 
   hr = sample->SetSampleTime(UsecsToHNs(aTimestamp));
   ENSURE(SUCCEEDED(hr), hr);
 
-  sample->SetSampleDuration(UsecsToHNs(aDuration));
-
   *aOutSample = sample.Detach();
 
   return S_OK;
 }
 
 HRESULT
 WMFH264Decoder::CreateOutputSample(IMFSample** aOutSample)
 {
@@ -296,22 +293,21 @@ WMFH264Decoder::GetOutputSample(IMFSampl
   // output.pSample
   *aOutSample = sample.Detach(); // AddRefs
   return S_OK;
 }
 
 HRESULT
 WMFH264Decoder::Input(const uint8_t* aData,
                       uint32_t aDataSize,
-                      Microseconds aTimestamp,
-                      Microseconds aDuration)
+                      Microseconds aTimestamp)
 {
   HRESULT hr;
   CComPtr<IMFSample> input = nullptr;
-  hr = CreateInputSample(aData, aDataSize, aTimestamp, aDuration, &input);
+  hr = CreateInputSample(aData, aDataSize, aTimestamp, &input);
   ENSURE(SUCCEEDED(hr) && input!=nullptr, hr);
 
   hr = mDecoder->ProcessInput(0, input, 0);
   if (hr == MF_E_NOTACCEPTING) {
     // MFT *already* has enough data to produce a sample. Retrieve it.
     LOG("ProcessInput returned MF_E_NOTACCEPTING\n");
     return MF_E_NOTACCEPTING;
   }
--- a/media/gmp-clearkey/0.1/WMFH264Decoder.h
+++ b/media/gmp-clearkey/0.1/WMFH264Decoder.h
@@ -25,18 +25,17 @@ class WMFH264Decoder {
 public:
   WMFH264Decoder();
   ~WMFH264Decoder();
 
   HRESULT Init(int32_t aCoreCount);
 
   HRESULT Input(const uint8_t* aData,
                 uint32_t aDataSize,
-                Microseconds aTimestamp,
-                Microseconds aDuration);
+                Microseconds aTimestamp);
 
   HRESULT Output(IMFSample** aOutput);
 
   HRESULT Reset();
 
   int32_t GetFrameWidth() const;
   int32_t GetFrameHeight() const;
   const IntRect& GetPictureRegion() const;
@@ -48,17 +47,16 @@ private:
 
   HRESULT SetDecoderInputType();
   HRESULT SetDecoderOutputType();
   HRESULT SendMFTMessage(MFT_MESSAGE_TYPE aMsg, UINT32 aData);
 
   HRESULT CreateInputSample(const uint8_t* aData,
                             uint32_t aDataSize,
                             Microseconds aTimestamp,
-                            Microseconds aDuration,
                             IMFSample** aOutSample);
 
   HRESULT CreateOutputSample(IMFSample** aOutSample);
 
   HRESULT GetOutputSample(IMFSample** aOutSample);
   HRESULT ConfigureVideoFrameGeometry(IMFMediaType* aMediaType);
 
   MFT_INPUT_STREAM_INFO mInputStreamInfo;
--- a/media/gmp-clearkey/0.1/WMFUtils.h
+++ b/media/gmp-clearkey/0.1/WMFUtils.h
@@ -114,18 +114,18 @@ typedef int64_t Microseconds;
 
 #ifdef ENSURE
 #undef ENSURE
 #endif
 
 #define ENSURE(condition, ret) \
 { if (!(condition)) { LOG("##condition## FAILED %S:%d\n", __FILE__, __LINE__); return ret; } }
 
-#define GMP_SUCCEEDED(x) ((x) == GMPNoErr)
-#define GMP_FAILED(x) ((x) != GMPNoErr)
+#define STATUS_SUCCEEDED(x) ((x) == Status::kSuccess)
+#define STATUS_FAILED(x) ((x) != Status::kSuccess)
 
 #define MFPLAT_FUNC(_func, _dllname) \
   extern decltype(::_func)* _func;
 #include "WMFSymbols.h"
 #undef MFPLAT_FUNC
 
 bool
 EnsureLibs();
--- a/media/gmp-clearkey/0.1/gmp-clearkey.cpp
+++ b/media/gmp-clearkey/0.1/gmp-clearkey.cpp
@@ -13,73 +13,52 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 #include <assert.h>
 #include <stdio.h>
 #include <string.h>
 
-#include "ClearKeyAsyncShutdown.h"
+#include "ClearKeyCDM.h"
 #include "ClearKeySessionManager.h"
-#include "gmp-api/gmp-async-shutdown.h"
-#include "gmp-api/gmp-decryption.h"
-#include "gmp-api/gmp-platform.h"
-
-#if defined(ENABLE_WMF)
-#include "WMFUtils.h"
-#include "VideoDecoder.h"
-#endif
+// This include is required in order for content_decryption_module to work
+// on Unix systems.
+#include "stddef.h"
+#include "content_decryption_module.h"
 
-#if defined(WIN32)
-#define GMP_EXPORT __declspec(dllexport)
-#else
-#define GMP_EXPORT __attribute__((visibility("default")))
-#endif
-
-static GMPPlatformAPI* sPlatform = nullptr;
-GMPPlatformAPI*
-GetPlatform()
-{
-  return sPlatform;
-}
+#ifdef ENABLE_WMF
+#include "WMFUtils.h"
+#endif // ENABLE_WMF
 
 extern "C" {
 
-GMP_EXPORT GMPErr
-GMPInit(GMPPlatformAPI* aPlatformAPI)
-{
-  sPlatform = aPlatformAPI;
-  return GMPNoErr;
+CDM_EXPORT
+void INITIALIZE_CDM_MODULE() {
+
 }
 
-GMP_EXPORT GMPErr
-GMPGetAPI(const char* aApiName, void* aHostAPI, void** aPluginAPI)
+CDM_EXPORT
+void* CreateCdmInstance(int cdm_interface_version,
+                        const char* key_system,
+                        uint32_t key_system_size,
+                        GetCdmHostFunc get_cdm_host_func,
+                        void* user_data)
 {
-  CK_LOGD("ClearKey GMPGetAPI |%s|", aApiName);
-  assert(!*aPluginAPI);
 
-  if (!strcmp(aApiName, GMP_API_DECRYPTOR)) {
-    *aPluginAPI = new ClearKeySessionManager();
-  }
-#if defined(ENABLE_WMF)
- else if (!strcmp(aApiName, GMP_API_VIDEO_DECODER) &&
-             wmf::EnsureLibs()) {
-    *aPluginAPI = new VideoDecoder(static_cast<GMPVideoHost*>(aHostAPI));
+  CK_LOGE("ClearKey CreateCDMInstance");
+
+#ifdef ENABLE_WMF
+  if (!wmf::EnsureLibs()) {
+    CK_LOGE("Required libraries were not found");
+    return nullptr;
   }
 #endif
-  else if (!strcmp(aApiName, GMP_API_ASYNC_SHUTDOWN)) {
-    *aPluginAPI = new ClearKeyAsyncShutdown(static_cast<GMPAsyncShutdownHost*> (aHostAPI));
-  } else {
-    CK_LOGE("GMPGetAPI couldn't resolve API name |%s|\n", aApiName);
-  }
 
-  return *aPluginAPI ? GMPNoErr : GMPNotImplementedErr;
-}
+  cdm::Host_8* host = static_cast<cdm::Host_8*>(
+    get_cdm_host_func(cdm_interface_version, user_data));
+  ClearKeyCDM* clearKey = new ClearKeyCDM(host);
 
-GMP_EXPORT GMPErr
-GMPShutdown(void)
-{
-  CK_LOGD("ClearKey GMPShutdown");
-  return GMPNoErr;
+  CK_LOGE("Created ClearKeyCDM instance!");
+
+  return clearKey;
 }
-
 }
deleted file mode 100644
--- a/media/gmp-clearkey/0.1/gmp-task-utils-generated.h
+++ /dev/null
@@ -1,1938 +0,0 @@
-/*
- * Copyright 2015, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "RefCounted.h"
-
-// 0 arguments --
-template<typename M> class gmp_task_args_nm_0 : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_nm_0(M m) :
-    m_(m)  {}
-
-  void Run() {
-    m_();
-  }
-
- private:
-  M m_;
-};
-
-
-
-// 0 arguments --
-template<typename M, typename R> class gmp_task_args_nm_0_ret : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_nm_0_ret(M m, R *r) :
-    m_(m), r_(r)  {}
-  virtual bool returns_value() const { return true; }
-
-  void Run() {
-    *r_ = m_();
-  }
-
- private:
-  M m_;
-  R* r_;
-};
-
-
-
-// 0 arguments --
-template<typename C, typename M> class gmp_task_args_m_0 : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_m_0(C o, M m) :
-    o_(o), m_(m)  {}
-
-  void Run() {
-    ((*o_).*m_)();
-  }
-
- private:
-  C o_;
-  M m_;
-};
-
-
-
-// 0 arguments --
-template<typename C, typename M, typename R> class gmp_task_args_m_0_ret : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_m_0_ret(C o, M m, R *r) :
-    o_(o), m_(m), r_(r)  {}
-  virtual bool returns_value() const { return true; }
-
-  void Run() {
-    *r_ = ((*o_).*m_)();
-  }
-
- private:
-  C o_;
-  M m_;
-  R* r_;
-};
-
-
-
-// 1 arguments --
-template<typename M, typename A0> class gmp_task_args_nm_1 : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_nm_1(M m, A0 a0) :
-    m_(m), a0_(a0)  {}
-
-  void Run() {
-    m_(a0_);
-  }
-
- private:
-  M m_;
-  A0 a0_;
-};
-
-
-
-// 1 arguments --
-template<typename M, typename A0, typename R> class gmp_task_args_nm_1_ret : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_nm_1_ret(M m, A0 a0, R *r) :
-    m_(m), r_(r), a0_(a0)  {}
-  virtual bool returns_value() const { return true; }
-
-  void Run() {
-    *r_ = m_(a0_);
-  }
-
- private:
-  M m_;
-  R* r_;
-  A0 a0_;
-};
-
-
-
-// 1 arguments --
-template<typename C, typename M, typename A0> class gmp_task_args_m_1 : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_m_1(C o, M m, A0 a0) :
-    o_(o), m_(m), a0_(a0)  {}
-
-  void Run() {
-    ((*o_).*m_)(a0_);
-  }
-
- private:
-  C o_;
-  M m_;
-  A0 a0_;
-};
-
-
-
-// 1 arguments --
-template<typename C, typename M, typename A0, typename R> class gmp_task_args_m_1_ret : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_m_1_ret(C o, M m, A0 a0, R *r) :
-    o_(o), m_(m), r_(r), a0_(a0)  {}
-  virtual bool returns_value() const { return true; }
-
-  void Run() {
-    *r_ = ((*o_).*m_)(a0_);
-  }
-
- private:
-  C o_;
-  M m_;
-  R* r_;
-  A0 a0_;
-};
-
-
-
-// 2 arguments --
-template<typename M, typename A0, typename A1> class gmp_task_args_nm_2 : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_nm_2(M m, A0 a0, A1 a1) :
-    m_(m), a0_(a0), a1_(a1)  {}
-
-  void Run() {
-    m_(a0_, a1_);
-  }
-
- private:
-  M m_;
-  A0 a0_;
-  A1 a1_;
-};
-
-
-
-// 2 arguments --
-template<typename M, typename A0, typename A1, typename R> class gmp_task_args_nm_2_ret : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_nm_2_ret(M m, A0 a0, A1 a1, R *r) :
-    m_(m), r_(r), a0_(a0), a1_(a1)  {}
-  virtual bool returns_value() const { return true; }
-
-  void Run() {
-    *r_ = m_(a0_, a1_);
-  }
-
- private:
-  M m_;
-  R* r_;
-  A0 a0_;
-  A1 a1_;
-};
-
-
-
-// 2 arguments --
-template<typename C, typename M, typename A0, typename A1> class gmp_task_args_m_2 : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_m_2(C o, M m, A0 a0, A1 a1) :
-    o_(o), m_(m), a0_(a0), a1_(a1)  {}
-
-  void Run() {
-    ((*o_).*m_)(a0_, a1_);
-  }
-
- private:
-  C o_;
-  M m_;
-  A0 a0_;
-  A1 a1_;
-};
-
-
-
-// 2 arguments --
-template<typename C, typename M, typename A0, typename A1, typename R> class gmp_task_args_m_2_ret : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_m_2_ret(C o, M m, A0 a0, A1 a1, R *r) :
-    o_(o), m_(m), r_(r), a0_(a0), a1_(a1)  {}
-  virtual bool returns_value() const { return true; }
-
-  void Run() {
-    *r_ = ((*o_).*m_)(a0_, a1_);
-  }
-
- private:
-  C o_;
-  M m_;
-  R* r_;
-  A0 a0_;
-  A1 a1_;
-};
-
-
-
-// 3 arguments --
-template<typename M, typename A0, typename A1, typename A2> class gmp_task_args_nm_3 : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_nm_3(M m, A0 a0, A1 a1, A2 a2) :
-    m_(m), a0_(a0), a1_(a1), a2_(a2)  {}
-
-  void Run() {
-    m_(a0_, a1_, a2_);
-  }
-
- private:
-  M m_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-};
-
-
-
-// 3 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename R> class gmp_task_args_nm_3_ret : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_nm_3_ret(M m, A0 a0, A1 a1, A2 a2, R *r) :
-    m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2)  {}
-  virtual bool returns_value() const { return true; }
-
-  void Run() {
-    *r_ = m_(a0_, a1_, a2_);
-  }
-
- private:
-  M m_;
-  R* r_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-};
-
-
-
-// 3 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2> class gmp_task_args_m_3 : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_m_3(C o, M m, A0 a0, A1 a1, A2 a2) :
-    o_(o), m_(m), a0_(a0), a1_(a1), a2_(a2)  {}
-
-  void Run() {
-    ((*o_).*m_)(a0_, a1_, a2_);
-  }
-
- private:
-  C o_;
-  M m_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-};
-
-
-
-// 3 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename R> class gmp_task_args_m_3_ret : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_m_3_ret(C o, M m, A0 a0, A1 a1, A2 a2, R *r) :
-    o_(o), m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2)  {}
-  virtual bool returns_value() const { return true; }
-
-  void Run() {
-    *r_ = ((*o_).*m_)(a0_, a1_, a2_);
-  }
-
- private:
-  C o_;
-  M m_;
-  R* r_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-};
-
-
-
-// 4 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3> class gmp_task_args_nm_4 : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_nm_4(M m, A0 a0, A1 a1, A2 a2, A3 a3) :
-    m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3)  {}
-
-  void Run() {
-    m_(a0_, a1_, a2_, a3_);
-  }
-
- private:
-  M m_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-};
-
-
-
-// 4 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename R> class gmp_task_args_nm_4_ret : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_nm_4_ret(M m, A0 a0, A1 a1, A2 a2, A3 a3, R *r) :
-    m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3)  {}
-  virtual bool returns_value() const { return true; }
-
-  void Run() {
-    *r_ = m_(a0_, a1_, a2_, a3_);
-  }
-
- private:
-  M m_;
-  R* r_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-};
-
-
-
-// 4 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3> class gmp_task_args_m_4 : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_m_4(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3) :
-    o_(o), m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3)  {}
-
-  void Run() {
-    ((*o_).*m_)(a0_, a1_, a2_, a3_);
-  }
-
- private:
-  C o_;
-  M m_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-};
-
-
-
-// 4 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename R> class gmp_task_args_m_4_ret : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_m_4_ret(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, R *r) :
-    o_(o), m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3)  {}
-  virtual bool returns_value() const { return true; }
-
-  void Run() {
-    *r_ = ((*o_).*m_)(a0_, a1_, a2_, a3_);
-  }
-
- private:
-  C o_;
-  M m_;
-  R* r_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-};
-
-
-
-// 5 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4> class gmp_task_args_nm_5 : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_nm_5(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) :
-    m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4)  {}
-
-  void Run() {
-    m_(a0_, a1_, a2_, a3_, a4_);
-  }
-
- private:
-  M m_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-  A4 a4_;
-};
-
-
-
-// 5 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename R> class gmp_task_args_nm_5_ret : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_nm_5_ret(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, R *r) :
-    m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4)  {}
-  virtual bool returns_value() const { return true; }
-
-  void Run() {
-    *r_ = m_(a0_, a1_, a2_, a3_, a4_);
-  }
-
- private:
-  M m_;
-  R* r_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-  A4 a4_;
-};
-
-
-
-// 5 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4> class gmp_task_args_m_5 : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_m_5(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) :
-    o_(o), m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4)  {}
-
-  void Run() {
-    ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_);
-  }
-
- private:
-  C o_;
-  M m_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-  A4 a4_;
-};
-
-
-
-// 5 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename R> class gmp_task_args_m_5_ret : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_m_5_ret(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, R *r) :
-    o_(o), m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4)  {}
-  virtual bool returns_value() const { return true; }
-
-  void Run() {
-    *r_ = ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_);
-  }
-
- private:
-  C o_;
-  M m_;
-  R* r_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-  A4 a4_;
-};
-
-
-
-// 6 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5> class gmp_task_args_nm_6 : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_nm_6(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) :
-    m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5)  {}
-
-  void Run() {
-    m_(a0_, a1_, a2_, a3_, a4_, a5_);
-  }
-
- private:
-  M m_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-  A4 a4_;
-  A5 a5_;
-};
-
-
-
-// 6 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename R> class gmp_task_args_nm_6_ret : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_nm_6_ret(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, R *r) :
-    m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5)  {}
-  virtual bool returns_value() const { return true; }
-
-  void Run() {
-    *r_ = m_(a0_, a1_, a2_, a3_, a4_, a5_);
-  }
-
- private:
-  M m_;
-  R* r_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-  A4 a4_;
-  A5 a5_;
-};
-
-
-
-// 6 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5> class gmp_task_args_m_6 : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_m_6(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) :
-    o_(o), m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5)  {}
-
-  void Run() {
-    ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_);
-  }
-
- private:
-  C o_;
-  M m_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-  A4 a4_;
-  A5 a5_;
-};
-
-
-
-// 6 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename R> class gmp_task_args_m_6_ret : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_m_6_ret(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, R *r) :
-    o_(o), m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5)  {}
-  virtual bool returns_value() const { return true; }
-
-  void Run() {
-    *r_ = ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_);
-  }
-
- private:
-  C o_;
-  M m_;
-  R* r_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-  A4 a4_;
-  A5 a5_;
-};
-
-
-
-// 7 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6> class gmp_task_args_nm_7 : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_nm_7(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) :
-    m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6)  {}
-
-  void Run() {
-    m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_);
-  }
-
- private:
-  M m_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-  A4 a4_;
-  A5 a5_;
-  A6 a6_;
-};
-
-
-
-// 7 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename R> class gmp_task_args_nm_7_ret : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_nm_7_ret(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, R *r) :
-    m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6)  {}
-  virtual bool returns_value() const { return true; }
-
-  void Run() {
-    *r_ = m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_);
-  }
-
- private:
-  M m_;
-  R* r_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-  A4 a4_;
-  A5 a5_;
-  A6 a6_;
-};
-
-
-
-// 7 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6> class gmp_task_args_m_7 : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_m_7(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) :
-    o_(o), m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6)  {}
-
-  void Run() {
-    ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_);
-  }
-
- private:
-  C o_;
-  M m_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-  A4 a4_;
-  A5 a5_;
-  A6 a6_;
-};
-
-
-
-// 7 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename R> class gmp_task_args_m_7_ret : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_m_7_ret(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, R *r) :
-    o_(o), m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6)  {}
-  virtual bool returns_value() const { return true; }
-
-  void Run() {
-    *r_ = ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_);
-  }
-
- private:
-  C o_;
-  M m_;
-  R* r_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-  A4 a4_;
-  A5 a5_;
-  A6 a6_;
-};
-
-
-
-// 8 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7> class gmp_task_args_nm_8 : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_nm_8(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) :
-    m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7)  {}
-
-  void Run() {
-    m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_);
-  }
-
- private:
-  M m_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-  A4 a4_;
-  A5 a5_;
-  A6 a6_;
-  A7 a7_;
-};
-
-
-
-// 8 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename R> class gmp_task_args_nm_8_ret : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_nm_8_ret(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, R *r) :
-    m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7)  {}
-  virtual bool returns_value() const { return true; }
-
-  void Run() {
-    *r_ = m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_);
-  }
-
- private:
-  M m_;
-  R* r_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-  A4 a4_;
-  A5 a5_;
-  A6 a6_;
-  A7 a7_;
-};
-
-
-
-// 8 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7> class gmp_task_args_m_8 : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_m_8(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) :
-    o_(o), m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7)  {}
-
-  void Run() {
-    ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_);
-  }
-
- private:
-  C o_;
-  M m_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-  A4 a4_;
-  A5 a5_;
-  A6 a6_;
-  A7 a7_;
-};
-
-
-
-// 8 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename R> class gmp_task_args_m_8_ret : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_m_8_ret(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, R *r) :
-    o_(o), m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7)  {}
-  virtual bool returns_value() const { return true; }
-
-  void Run() {
-    *r_ = ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_);
-  }
-
- private:
-  C o_;
-  M m_;
-  R* r_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-  A4 a4_;
-  A5 a5_;
-  A6 a6_;
-  A7 a7_;
-};
-
-
-
-// 9 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8> class gmp_task_args_nm_9 : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_nm_9(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) :
-    m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8)  {}
-
-  void Run() {
-    m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_);
-  }
-
- private:
-  M m_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-  A4 a4_;
-  A5 a5_;
-  A6 a6_;
-  A7 a7_;
-  A8 a8_;
-};
-
-
-
-// 9 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename R> class gmp_task_args_nm_9_ret : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_nm_9_ret(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, R *r) :
-    m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8)  {}
-  virtual bool returns_value() const { return true; }
-
-  void Run() {
-    *r_ = m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_);
-  }
-
- private:
-  M m_;
-  R* r_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-  A4 a4_;
-  A5 a5_;
-  A6 a6_;
-  A7 a7_;
-  A8 a8_;
-};
-
-
-
-// 9 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8> class gmp_task_args_m_9 : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_m_9(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) :
-    o_(o), m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8)  {}
-
-  void Run() {
-    ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_);
-  }
-
- private:
-  C o_;
-  M m_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-  A4 a4_;
-  A5 a5_;
-  A6 a6_;
-  A7 a7_;
-  A8 a8_;
-};
-
-
-
-// 9 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename R> class gmp_task_args_m_9_ret : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_m_9_ret(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, R *r) :
-    o_(o), m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8)  {}
-  virtual bool returns_value() const { return true; }
-
-  void Run() {
-    *r_ = ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_);
-  }
-
- private:
-  C o_;
-  M m_;
-  R* r_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-  A4 a4_;
-  A5 a5_;
-  A6 a6_;
-  A7 a7_;
-  A8 a8_;
-};
-
-
-
-// 10 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9> class gmp_task_args_nm_10 : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_nm_10(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) :
-    m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9)  {}
-
-  void Run() {
-    m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_);
-  }
-
- private:
-  M m_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-  A4 a4_;
-  A5 a5_;
-  A6 a6_;
-  A7 a7_;
-  A8 a8_;
-  A9 a9_;
-};
-
-
-
-// 10 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename R> class gmp_task_args_nm_10_ret : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_nm_10_ret(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, R *r) :
-    m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9)  {}
-  virtual bool returns_value() const { return true; }
-
-  void Run() {
-    *r_ = m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_);
-  }
-
- private:
-  M m_;
-  R* r_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-  A4 a4_;
-  A5 a5_;
-  A6 a6_;
-  A7 a7_;
-  A8 a8_;
-  A9 a9_;
-};
-
-
-
-// 10 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9> class gmp_task_args_m_10 : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_m_10(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) :
-    o_(o), m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9)  {}
-
-  void Run() {
-    ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_);
-  }
-
- private:
-  C o_;
-  M m_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-  A4 a4_;
-  A5 a5_;
-  A6 a6_;
-  A7 a7_;
-  A8 a8_;
-  A9 a9_;
-};
-
-
-
-// 10 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename R> class gmp_task_args_m_10_ret : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_m_10_ret(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, R *r) :
-    o_(o), m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9)  {}
-  virtual bool returns_value() const { return true; }
-
-  void Run() {
-    *r_ = ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_);
-  }
-
- private:
-  C o_;
-  M m_;
-  R* r_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-  A4 a4_;
-  A5 a5_;
-  A6 a6_;
-  A7 a7_;
-  A8 a8_;
-  A9 a9_;
-};
-
-
-
-// 11 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10> class gmp_task_args_nm_11 : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_nm_11(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) :
-    m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10)  {}
-
-  void Run() {
-    m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_);
-  }
-
- private:
-  M m_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-  A4 a4_;
-  A5 a5_;
-  A6 a6_;
-  A7 a7_;
-  A8 a8_;
-  A9 a9_;
-  A10 a10_;
-};
-
-
-
-// 11 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename R> class gmp_task_args_nm_11_ret : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_nm_11_ret(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, R *r) :
-    m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10)  {}
-  virtual bool returns_value() const { return true; }
-
-  void Run() {
-    *r_ = m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_);
-  }
-
- private:
-  M m_;
-  R* r_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-  A4 a4_;
-  A5 a5_;
-  A6 a6_;
-  A7 a7_;
-  A8 a8_;
-  A9 a9_;
-  A10 a10_;
-};
-
-
-
-// 11 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10> class gmp_task_args_m_11 : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_m_11(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) :
-    o_(o), m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10)  {}
-
-  void Run() {
-    ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_);
-  }
-
- private:
-  C o_;
-  M m_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-  A4 a4_;
-  A5 a5_;
-  A6 a6_;
-  A7 a7_;
-  A8 a8_;
-  A9 a9_;
-  A10 a10_;
-};
-
-
-
-// 11 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename R> class gmp_task_args_m_11_ret : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_m_11_ret(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, R *r) :
-    o_(o), m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10)  {}
-  virtual bool returns_value() const { return true; }
-
-  void Run() {
-    *r_ = ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_);
-  }
-
- private:
-  C o_;
-  M m_;
-  R* r_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-  A4 a4_;
-  A5 a5_;
-  A6 a6_;
-  A7 a7_;
-  A8 a8_;
-  A9 a9_;
-  A10 a10_;
-};
-
-
-
-// 12 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11> class gmp_task_args_nm_12 : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_nm_12(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11) :
-    m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11)  {}
-
-  void Run() {
-    m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_);
-  }
-
- private:
-  M m_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-  A4 a4_;
-  A5 a5_;
-  A6 a6_;
-  A7 a7_;
-  A8 a8_;
-  A9 a9_;
-  A10 a10_;
-  A11 a11_;
-};
-
-
-
-// 12 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename R> class gmp_task_args_nm_12_ret : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_nm_12_ret(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, R *r) :
-    m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11)  {}
-  virtual bool returns_value() const { return true; }
-
-  void Run() {
-    *r_ = m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_);
-  }
-
- private:
-  M m_;
-  R* r_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-  A4 a4_;
-  A5 a5_;
-  A6 a6_;
-  A7 a7_;
-  A8 a8_;
-  A9 a9_;
-  A10 a10_;
-  A11 a11_;
-};
-
-
-
-// 12 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11> class gmp_task_args_m_12 : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_m_12(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11) :
-    o_(o), m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11)  {}
-
-  void Run() {
-    ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_);
-  }
-
- private:
-  C o_;
-  M m_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-  A4 a4_;
-  A5 a5_;
-  A6 a6_;
-  A7 a7_;
-  A8 a8_;
-  A9 a9_;
-  A10 a10_;
-  A11 a11_;
-};
-
-
-
-// 12 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename R> class gmp_task_args_m_12_ret : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_m_12_ret(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, R *r) :
-    o_(o), m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11)  {}
-  virtual bool returns_value() const { return true; }
-
-  void Run() {
-    *r_ = ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_);
-  }
-
- private:
-  C o_;
-  M m_;
-  R* r_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-  A4 a4_;
-  A5 a5_;
-  A6 a6_;
-  A7 a7_;
-  A8 a8_;
-  A9 a9_;
-  A10 a10_;
-  A11 a11_;
-};
-
-
-
-// 13 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12> class gmp_task_args_nm_13 : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_nm_13(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12) :
-    m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11), a12_(a12)  {}
-
-  void Run() {
-    m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_, a12_);
-  }
-
- private:
-  M m_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-  A4 a4_;
-  A5 a5_;
-  A6 a6_;
-  A7 a7_;
-  A8 a8_;
-  A9 a9_;
-  A10 a10_;
-  A11 a11_;
-  A12 a12_;
-};
-
-
-
-// 13 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename R> class gmp_task_args_nm_13_ret : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_nm_13_ret(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, R *r) :
-    m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11), a12_(a12)  {}
-  virtual bool returns_value() const { return true; }
-
-  void Run() {
-    *r_ = m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_, a12_);
-  }
-
- private:
-  M m_;
-  R* r_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-  A4 a4_;
-  A5 a5_;
-  A6 a6_;
-  A7 a7_;
-  A8 a8_;
-  A9 a9_;
-  A10 a10_;
-  A11 a11_;
-  A12 a12_;
-};
-
-
-
-// 13 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12> class gmp_task_args_m_13 : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_m_13(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12) :
-    o_(o), m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11), a12_(a12)  {}
-
-  void Run() {
-    ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_, a12_);
-  }
-
- private:
-  C o_;
-  M m_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-  A4 a4_;
-  A5 a5_;
-  A6 a6_;
-  A7 a7_;
-  A8 a8_;
-  A9 a9_;
-  A10 a10_;
-  A11 a11_;
-  A12 a12_;
-};
-
-
-
-// 13 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename R> class gmp_task_args_m_13_ret : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_m_13_ret(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, R *r) :
-    o_(o), m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11), a12_(a12)  {}
-  virtual bool returns_value() const { return true; }
-
-  void Run() {
-    *r_ = ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_, a12_);
-  }
-
- private:
-  C o_;
-  M m_;
-  R* r_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-  A4 a4_;
-  A5 a5_;
-  A6 a6_;
-  A7 a7_;
-  A8 a8_;
-  A9 a9_;
-  A10 a10_;
-  A11 a11_;
-  A12 a12_;
-};
-
-
-
-// 14 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13> class gmp_task_args_nm_14 : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_nm_14(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13) :
-    m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11), a12_(a12), a13_(a13)  {}
-
-  void Run() {
-    m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_, a12_, a13_);
-  }
-
- private:
-  M m_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-  A4 a4_;
-  A5 a5_;
-  A6 a6_;
-  A7 a7_;
-  A8 a8_;
-  A9 a9_;
-  A10 a10_;
-  A11 a11_;
-  A12 a12_;
-  A13 a13_;
-};
-
-
-
-// 14 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13, typename R> class gmp_task_args_nm_14_ret : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_nm_14_ret(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13, R *r) :
-    m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11), a12_(a12), a13_(a13)  {}
-  virtual bool returns_value() const { return true; }
-
-  void Run() {
-    *r_ = m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_, a12_, a13_);
-  }
-
- private:
-  M m_;
-  R* r_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-  A4 a4_;
-  A5 a5_;
-  A6 a6_;
-  A7 a7_;
-  A8 a8_;
-  A9 a9_;
-  A10 a10_;
-  A11 a11_;
-  A12 a12_;
-  A13 a13_;
-};
-
-
-
-// 14 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13> class gmp_task_args_m_14 : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_m_14(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13) :
-    o_(o), m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11), a12_(a12), a13_(a13)  {}
-
-  void Run() {
-    ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_, a12_, a13_);
-  }
-
- private:
-  C o_;
-  M m_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-  A4 a4_;
-  A5 a5_;
-  A6 a6_;
-  A7 a7_;
-  A8 a8_;
-  A9 a9_;
-  A10 a10_;
-  A11 a11_;
-  A12 a12_;
-  A13 a13_;
-};
-
-
-
-// 14 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13, typename R> class gmp_task_args_m_14_ret : public gmp_task_args_base {
- public:
-  explicit gmp_task_args_m_14_ret(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13, R *r) :
-    o_(o), m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11), a12_(a12), a13_(a13)  {}
-  virtual bool returns_value() const { return true; }
-
-  void Run() {
-    *r_ = ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_, a12_, a13_);
-  }
-
- private:
-  C o_;
-  M m_;
-  R* r_;
-  A0 a0_;
-  A1 a1_;
-  A2 a2_;
-  A3 a3_;
-  A4 a4_;
-  A5 a5_;
-  A6 a6_;
-  A7 a7_;
-  A8 a8_;
-  A9 a9_;
-  A10 a10_;
-  A11 a11_;
-  A12 a12_;
-  A13 a13_;
-};
-
-
-
-
-
-
-// 0 arguments --
-template<typename M>
-gmp_task_args_nm_0<M>* WrapTaskNM(M m) {
-  return new gmp_task_args_nm_0<M>
-    (m);
-}
-
-// 0 arguments --
-template<typename M, typename R>
-gmp_task_args_nm_0_ret<M, R>* WrapTaskNMRet(M m, R* r) {
-  return new gmp_task_args_nm_0_ret<M, R>
-    (m, r);
-}
-
-// 0 arguments --
-template<typename C, typename M>
-gmp_task_args_m_0<C, M>* WrapTask(C o, M m) {
-  return new gmp_task_args_m_0<C, M>
-    (o, m);
-}
-
-// 0 arguments --
-template<typename C, typename M, typename R>
-gmp_task_args_m_0_ret<C, M, R>* WrapTaskRet(C o, M m, R* r) {
-  return new gmp_task_args_m_0_ret<C, M, R>
-    (o, m, r);
-}
-
-// 1 arguments --
-template<typename M, typename A0>
-gmp_task_args_nm_1<M, A0>* WrapTaskNM(M m, A0 a0) {
-  return new gmp_task_args_nm_1<M, A0>
-    (m, a0);
-}
-
-// 1 arguments --
-template<typename M, typename A0, typename R>
-gmp_task_args_nm_1_ret<M, A0, R>* WrapTaskNMRet(M m, A0 a0, R* r) {
-  return new gmp_task_args_nm_1_ret<M, A0, R>
-    (m, a0, r);
-}
-
-// 1 arguments --
-template<typename C, typename M, typename A0>
-gmp_task_args_m_1<C, M, A0>* WrapTask(C o, M m, A0 a0) {
-  return new gmp_task_args_m_1<C, M, A0>
-    (o, m, a0);
-}
-
-// 1 arguments --
-template<typename C, typename M, typename A0, typename R>
-gmp_task_args_m_1_ret<C, M, A0, R>* WrapTaskRet(C o, M m, A0 a0, R* r) {
-  return new gmp_task_args_m_1_ret<C, M, A0, R>
-    (o, m, a0, r);
-}
-
-// 2 arguments --
-template<typename M, typename A0, typename A1>
-gmp_task_args_nm_2<M, A0, A1>* WrapTaskNM(M m, A0 a0, A1 a1) {
-  return new gmp_task_args_nm_2<M, A0, A1>
-    (m, a0, a1);
-}
-
-// 2 arguments --
-template<typename M, typename A0, typename A1, typename R>
-gmp_task_args_nm_2_ret<M, A0, A1, R>* WrapTaskNMRet(M m, A0 a0, A1 a1, R* r) {
-  return new gmp_task_args_nm_2_ret<M, A0, A1, R>
-    (m, a0, a1, r);
-}
-
-// 2 arguments --
-template<typename C, typename M, typename A0, typename A1>
-gmp_task_args_m_2<C, M, A0, A1>* WrapTask(C o, M m, A0 a0, A1 a1) {
-  return new gmp_task_args_m_2<C, M, A0, A1>
-    (o, m, a0, a1);
-}
-
-// 2 arguments --
-template<typename C, typename M, typename A0, typename A1, typename R>
-gmp_task_args_m_2_ret<C, M, A0, A1, R>* WrapTaskRet(C o, M m, A0 a0, A1 a1, R* r) {
-  return new gmp_task_args_m_2_ret<C, M, A0, A1, R>
-    (o, m, a0, a1, r);
-}
-
-// 3 arguments --
-template<typename M, typename A0, typename A1, typename A2>
-gmp_task_args_nm_3<M, A0, A1, A2>* WrapTaskNM(M m, A0 a0, A1 a1, A2 a2) {
-  return new gmp_task_args_nm_3<M, A0, A1, A2>
-    (m, a0, a1, a2);
-}
-
-// 3 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename R>
-gmp_task_args_nm_3_ret<M, A0, A1, A2, R>* WrapTaskNMRet(M m, A0 a0, A1 a1, A2 a2, R* r) {
-  return new gmp_task_args_nm_3_ret<M, A0, A1, A2, R>
-    (m, a0, a1, a2, r);
-}
-
-// 3 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2>
-gmp_task_args_m_3<C, M, A0, A1, A2>* WrapTask(C o, M m, A0 a0, A1 a1, A2 a2) {
-  return new gmp_task_args_m_3<C, M, A0, A1, A2>
-    (o, m, a0, a1, a2);
-}
-
-// 3 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename R>
-gmp_task_args_m_3_ret<C, M, A0, A1, A2, R>* WrapTaskRet(C o, M m, A0 a0, A1 a1, A2 a2, R* r) {
-  return new gmp_task_args_m_3_ret<C, M, A0, A1, A2, R>
-    (o, m, a0, a1, a2, r);
-}
-
-// 4 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3>
-gmp_task_args_nm_4<M, A0, A1, A2, A3>* WrapTaskNM(M m, A0 a0, A1 a1, A2 a2, A3 a3) {
-  return new gmp_task_args_nm_4<M, A0, A1, A2, A3>
-    (m, a0, a1, a2, a3);
-}
-
-// 4 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename R>
-gmp_task_args_nm_4_ret<M, A0, A1, A2, A3, R>* WrapTaskNMRet(M m, A0 a0, A1 a1, A2 a2, A3 a3, R* r) {
-  return new gmp_task_args_nm_4_ret<M, A0, A1, A2, A3, R>
-    (m, a0, a1, a2, a3, r);
-}
-
-// 4 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3>
-gmp_task_args_m_4<C, M, A0, A1, A2, A3>* WrapTask(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3) {
-  return new gmp_task_args_m_4<C, M, A0, A1, A2, A3>
-    (o, m, a0, a1, a2, a3);
-}
-
-// 4 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename R>
-gmp_task_args_m_4_ret<C, M, A0, A1, A2, A3, R>* WrapTaskRet(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, R* r) {
-  return new gmp_task_args_m_4_ret<C, M, A0, A1, A2, A3, R>
-    (o, m, a0, a1, a2, a3, r);
-}
-
-// 5 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4>
-gmp_task_args_nm_5<M, A0, A1, A2, A3, A4>* WrapTaskNM(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) {
-  return new gmp_task_args_nm_5<M, A0, A1, A2, A3, A4>
-    (m, a0, a1, a2, a3, a4);
-}
-
-// 5 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename R>
-gmp_task_args_nm_5_ret<M, A0, A1, A2, A3, A4, R>* WrapTaskNMRet(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, R* r) {
-  return new gmp_task_args_nm_5_ret<M, A0, A1, A2, A3, A4, R>
-    (m, a0, a1, a2, a3, a4, r);
-}
-
-// 5 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4>
-gmp_task_args_m_5<C, M, A0, A1, A2, A3, A4>* WrapTask(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) {
-  return new gmp_task_args_m_5<C, M, A0, A1, A2, A3, A4>
-    (o, m, a0, a1, a2, a3, a4);
-}
-
-// 5 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename R>
-gmp_task_args_m_5_ret<C, M, A0, A1, A2, A3, A4, R>* WrapTaskRet(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, R* r) {
-  return new gmp_task_args_m_5_ret<C, M, A0, A1, A2, A3, A4, R>
-    (o, m, a0, a1, a2, a3, a4, r);
-}
-
-// 6 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5>
-gmp_task_args_nm_6<M, A0, A1, A2, A3, A4, A5>* WrapTaskNM(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) {
-  return new gmp_task_args_nm_6<M, A0, A1, A2, A3, A4, A5>
-    (m, a0, a1, a2, a3, a4, a5);
-}
-
-// 6 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename R>
-gmp_task_args_nm_6_ret<M, A0, A1, A2, A3, A4, A5, R>* WrapTaskNMRet(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, R* r) {
-  return new gmp_task_args_nm_6_ret<M, A0, A1, A2, A3, A4, A5, R>
-    (m, a0, a1, a2, a3, a4, a5, r);
-}
-
-// 6 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5>
-gmp_task_args_m_6<C, M, A0, A1, A2, A3, A4, A5>* WrapTask(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) {
-  return new gmp_task_args_m_6<C, M, A0, A1, A2, A3, A4, A5>
-    (o, m, a0, a1, a2, a3, a4, a5);
-}
-
-// 6 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename R>
-gmp_task_args_m_6_ret<C, M, A0, A1, A2, A3, A4, A5, R>* WrapTaskRet(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, R* r) {
-  return new gmp_task_args_m_6_ret<C, M, A0, A1, A2, A3, A4, A5, R>
-    (o, m, a0, a1, a2, a3, a4, a5, r);
-}
-
-// 7 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
-gmp_task_args_nm_7<M, A0, A1, A2, A3, A4, A5, A6>* WrapTaskNM(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) {
-  return new gmp_task_args_nm_7<M, A0, A1, A2, A3, A4, A5, A6>
-    (m, a0, a1, a2, a3, a4, a5, a6);
-}
-
-// 7 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename R>
-gmp_task_args_nm_7_ret<M, A0, A1, A2, A3, A4, A5, A6, R>* WrapTaskNMRet(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, R* r) {
-  return new gmp_task_args_nm_7_ret<M, A0, A1, A2, A3, A4, A5, A6, R>
-    (m, a0, a1, a2, a3, a4, a5, a6, r);
-}
-
-// 7 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
-gmp_task_args_m_7<C, M, A0, A1, A2, A3, A4, A5, A6>* WrapTask(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) {
-  return new gmp_task_args_m_7<C, M, A0, A1, A2, A3, A4, A5, A6>
-    (o, m, a0, a1, a2, a3, a4, a5, a6);
-}
-
-// 7 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename R>
-gmp_task_args_m_7_ret<C, M, A0, A1, A2, A3, A4, A5, A6, R>* WrapTaskRet(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, R* r) {
-  return new gmp_task_args_m_7_ret<C, M, A0, A1, A2, A3, A4, A5, A6, R>
-    (o, m, a0, a1, a2, a3, a4, a5, a6, r);
-}
-
-// 8 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
-gmp_task_args_nm_8<M, A0, A1, A2, A3, A4, A5, A6, A7>* WrapTaskNM(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) {
-  return new gmp_task_args_nm_8<M, A0, A1, A2, A3, A4, A5, A6, A7>
-    (m, a0, a1, a2, a3, a4, a5, a6, a7);
-}
-
-// 8 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename R>
-gmp_task_args_nm_8_ret<M, A0, A1, A2, A3, A4, A5, A6, A7, R>* WrapTaskNMRet(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, R* r) {
-  return new gmp_task_args_nm_8_ret<M, A0, A1, A2, A3, A4, A5, A6, A7, R>
-    (m, a0, a1, a2, a3, a4, a5, a6, a7, r);
-}
-
-// 8 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
-gmp_task_args_m_8<C, M, A0, A1, A2, A3, A4, A5, A6, A7>* WrapTask(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) {
-  return new gmp_task_args_m_8<C, M, A0, A1, A2, A3, A4, A5, A6, A7>
-    (o, m, a0, a1, a2, a3, a4, a5, a6, a7);
-}
-
-// 8 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename R>
-gmp_task_args_m_8_ret<C, M, A0, A1, A2, A3, A4, A5, A6, A7, R>* WrapTaskRet(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, R* r) {
-  return new gmp_task_args_m_8_ret<C, M, A0, A1, A2, A3, A4, A5, A6, A7, R>
-    (o, m, a0, a1, a2, a3, a4, a5, a6, a7, r);
-}
-
-// 9 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8>
-gmp_task_args_nm_9<M, A0, A1, A2, A3, A4, A5, A6, A7, A8>* WrapTaskNM(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) {
-  return new gmp_task_args_nm_9<M, A0, A1, A2, A3, A4, A5, A6, A7, A8>
-    (m, a0, a1, a2, a3, a4, a5, a6, a7, a8);
-}
-
-// 9 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename R>
-gmp_task_args_nm_9_ret<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, R>* WrapTaskNMRet(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, R* r) {
-  return new gmp_task_args_nm_9_ret<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, R>
-    (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, r);
-}
-
-// 9 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8>
-gmp_task_args_m_9<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8>* WrapTask(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) {
-  return new gmp_task_args_m_9<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8>
-    (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8);
-}
-
-// 9 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename R>
-gmp_task_args_m_9_ret<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, R>* WrapTaskRet(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, R* r) {
-  return new gmp_task_args_m_9_ret<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, R>
-    (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, r);
-}
-
-// 10 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9>
-gmp_task_args_nm_10<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9>* WrapTaskNM(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) {
-  return new gmp_task_args_nm_10<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9>
-    (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
-}
-
-// 10 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename R>
-gmp_task_args_nm_10_ret<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, R>* WrapTaskNMRet(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, R* r) {
-  return new gmp_task_args_nm_10_ret<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, R>
-    (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, r);
-}
-
-// 10 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9>
-gmp_task_args_m_10<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9>* WrapTask(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) {
-  return new gmp_task_args_m_10<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9>
-    (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
-}
-
-// 10 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename R>
-gmp_task_args_m_10_ret<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, R>* WrapTaskRet(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, R* r) {
-  return new gmp_task_args_m_10_ret<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, R>
-    (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, r);
-}
-
-// 11 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10>
-gmp_task_args_nm_11<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>* WrapTaskNM(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) {
-  return new gmp_task_args_nm_11<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>
-    (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
-}
-
-// 11 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename R>
-gmp_task_args_nm_11_ret<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, R>* WrapTaskNMRet(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, R* r) {
-  return new gmp_task_args_nm_11_ret<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, R>
-    (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, r);
-}
-
-// 11 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10>
-gmp_task_args_m_11<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>* WrapTask(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) {
-  return new gmp_task_args_m_11<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>
-    (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
-}
-
-// 11 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename R>
-gmp_task_args_m_11_ret<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, R>* WrapTaskRet(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, R* r) {
-  return new gmp_task_args_m_11_ret<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, R>
-    (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, r);
-}
-
-// 12 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11>
-gmp_task_args_nm_12<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11>* WrapTaskNM(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11) {
-  return new gmp_task_args_nm_12<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11>
-    (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11);
-}
-
-// 12 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename R>
-gmp_task_args_nm_12_ret<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, R>* WrapTaskNMRet(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, R* r) {
-  return new gmp_task_args_nm_12_ret<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, R>
-    (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, r);
-}
-
-// 12 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11>
-gmp_task_args_m_12<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11>* WrapTask(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11) {
-  return new gmp_task_args_m_12<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11>
-    (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11);
-}
-
-// 12 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename R>
-gmp_task_args_m_12_ret<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, R>* WrapTaskRet(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, R* r) {
-  return new gmp_task_args_m_12_ret<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, R>
-    (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, r);
-}
-
-// 13 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12>
-gmp_task_args_nm_13<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12>* WrapTaskNM(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12) {
-  return new gmp_task_args_nm_13<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12>
-    (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12);
-}
-
-// 13 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename R>
-gmp_task_args_nm_13_ret<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, R>* WrapTaskNMRet(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, R* r) {
-  return new gmp_task_args_nm_13_ret<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, R>
-    (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, r);
-}
-
-// 13 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12>
-gmp_task_args_m_13<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12>* WrapTask(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12) {
-  return new gmp_task_args_m_13<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12>
-    (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12);
-}
-
-// 13 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename R>
-gmp_task_args_m_13_ret<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, R>* WrapTaskRet(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, R* r) {
-  return new gmp_task_args_m_13_ret<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, R>
-    (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, r);
-}
-
-// 14 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13>
-gmp_task_args_nm_14<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13>* WrapTaskNM(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13) {
-  return new gmp_task_args_nm_14<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13>
-    (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13);
-}
-
-// 14 arguments --
-template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13, typename R>
-gmp_task_args_nm_14_ret<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, R>* WrapTaskNMRet(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13, R* r) {
-  return new gmp_task_args_nm_14_ret<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, R>
-    (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, r);
-}
-
-// 14 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13>
-gmp_task_args_m_14<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13>* WrapTask(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13) {
-  return new gmp_task_args_m_14<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13>
-    (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13);
-}
-
-// 14 arguments --
-template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13, typename R>
-gmp_task_args_m_14_ret<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, R>* WrapTaskRet(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13, R* r) {
-  return new gmp_task_args_m_14_ret<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, R>
-    (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, r);
-}
-
-class RefCountTaskWrapper : public gmp_task_args_base {
-public:
-  RefCountTaskWrapper(GMPTask* aTask, RefCounted* aRefCounted)
-    : mTask(aTask)
-    , mRefCounted(aRefCounted)
-  {}
-  virtual void Run() override {
-    mTask->Run();
-  }
-  virtual void Destroy() override {
-    mTask->Destroy();
-    gmp_task_args_base::Destroy();
-  }
-private:
-  ~RefCountTaskWrapper() {}
-
-  GMPTask* mTask;
-  RefPtr<RefCounted> mRefCounted;
-};
-
-template<typename Type, typename Method, typename... Args>
-GMPTask*
-WrapTaskRefCounted(Type* aType, Method aMethod, Args&&... args)
-{
-  GMPTask* t = WrapTask(aType, aMethod, std::forward<Args>(args)...);
-  return new RefCountTaskWrapper(t, aType);
-}
deleted file mode 100644
--- a/media/gmp-clearkey/0.1/gmp-task-utils.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2015, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// Original author: ekr@rtfm.com
-
-#ifndef gmp_task_utils_h_
-#define gmp_task_utils_h_
-
-#include "gmp-api/gmp-platform.h"
-
-class gmp_task_args_base : public GMPTask {
-public:
-  virtual void Destroy() { delete this; }
-  virtual void Run() = 0;
-};
-
-// The generated file contains four major function templates
-// (in variants for arbitrary numbers of arguments up to 10,
-// which is why it is machine generated). The four templates
-// are:
-//
-// WrapTask(o, m, ...) -- wraps a member function m of an object ptr o
-// WrapTaskRet(o, m, ..., r) -- wraps a member function m of an object ptr o
-//                                  the function returns something that can
-//                                  be assigned to *r
-// WrapTaskNM(f, ...) -- wraps a function f
-// WrapTaskNMRet(f, ..., r) -- wraps a function f that returns something
-//                                 that can be assigned to *r
-//
-// All of these template functions return a GMPTask* which can be passed
-// to DispatchXX().
-#include "gmp-task-utils-generated.h"
-
-#endif // gmp_task_utils_h_
--- a/media/gmp-clearkey/0.1/moz.build
+++ b/media/gmp-clearkey/0.1/moz.build
@@ -6,57 +6,54 @@
 
 SharedLibrary('clearkey')
 
 FINAL_TARGET = 'dist/bin/gmp-clearkey/0.1'
 
 FINAL_TARGET_PP_FILES += ['manifest.json.in']
 
 UNIFIED_SOURCES += [
-    'ClearKeyAsyncShutdown.cpp',
     'ClearKeyBase64.cpp',
+    'ClearKeyCDM.cpp',
     'ClearKeyDecryptionManager.cpp',
     'ClearKeyPersistence.cpp',
     'ClearKeySession.cpp',
     'ClearKeySessionManager.cpp',
     'ClearKeyStorage.cpp',
     'ClearKeyUtils.cpp',
     'gmp-clearkey.cpp',
 ]
 
 SOURCES += [
     'openaes/oaes_lib.c',
 ]
 
 if CONFIG['OS_ARCH'] == 'WINNT':
     UNIFIED_SOURCES += [
-        'AnnexB.cpp',
         'VideoDecoder.cpp',
         'WMFH264Decoder.cpp',
     ]
 
     SOURCES += [
         'WMFUtils.cpp',
     ]
 
     OS_LIBS += [
         'mfuuid',
     ]
 
     DEFINES['ENABLE_WMF'] = True
 
+
+DEFINES['CDM_IMPLEMENTATION'] = True
+
 TEST_DIRS += [
     'gtest',
 ]
 
-
-LOCAL_INCLUDES += [
-    '/dom/media/gmp',
-]
-
 DISABLE_STL_WRAPPING = True
 DEFINES['MOZ_NO_MOZALLOC'] = True
 
 USE_LIBS += ['psshparser']
 
 # Suppress warnings in third-party code.
 if CONFIG['GNU_CXX']:
     CFLAGS += [