summaryrefslogtreecommitdiff
path: root/media/gmp-clearkey/0.1/ClearKeySessionManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'media/gmp-clearkey/0.1/ClearKeySessionManager.cpp')
-rw-r--r--media/gmp-clearkey/0.1/ClearKeySessionManager.cpp418
1 files changed, 0 insertions, 418 deletions
diff --git a/media/gmp-clearkey/0.1/ClearKeySessionManager.cpp b/media/gmp-clearkey/0.1/ClearKeySessionManager.cpp
deleted file mode 100644
index 4dbb062992..0000000000
--- a/media/gmp-clearkey/0.1/ClearKeySessionManager.cpp
+++ /dev/null
@@ -1,418 +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 <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"
-#include <assert.h>
-
-using namespace std;
-
-ClearKeySessionManager::ClearKeySessionManager()
- : 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;
- }
-}
-
-ClearKeySessionManager::~ClearKeySessionManager()
-{
- CK_LOGD("ClearKeySessionManager dtor %p", this);
-}
-
-void
-ClearKeySessionManager::Init(GMPDecryptorCallback* aCallback,
- bool aDistinctiveIdentifierAllowed,
- bool aPersistentStateAllowed)
-{
- CK_LOGD("ClearKeySessionManager::Init");
- mCallback = aCallback;
- ClearKeyPersistence::EnsureInitialized();
-}
-
-void
-ClearKeySessionManager::CreateSession(uint32_t aCreateSessionToken,
- uint32_t aPromiseId,
- const char* aInitDataType,
- uint32_t aInitDataTypeSize,
- const uint8_t* aInitData,
- uint32_t aInitDataSize,
- GMPSessionType aSessionType)
-{
- CK_LOGD("ClearKeySessionManager::CreateSession type:%s", aInitDataType);
-
- 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());
- return;
- }
-
- if (ClearKeyPersistence::DeferCreateSessionIfNotReady(this,
- aCreateSessionToken,
- aPromiseId,
- initDataType,
- aInitData,
- aInitDataSize,
- aSessionType)) {
- return;
- }
-
- string sessionId = ClearKeyPersistence::GetNewSessionId(aSessionType);
- assert(mSessions.find(sessionId) == mSessions.end());
-
- ClearKeySession* session = new ClearKeySession(sessionId, mCallback, aSessionType);
- session->Init(aCreateSessionToken, aPromiseId, initDataType, aInitData, aInitDataSize);
- 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);
- }
-
- 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());
-}
-
-void
-ClearKeySessionManager::LoadSession(uint32_t aPromiseId,
- const char* aSessionId,
- uint32_t aSessionIdLength)
-{
- CK_LOGD("ClearKeySessionManager::LoadSession");
-
- if (!ClearKeyUtils::IsValidSessionId(aSessionId, aSessionIdLength)) {
- mCallback->ResolveLoadSessionPromise(aPromiseId, false);
- return;
- }
-
- if (ClearKeyPersistence::DeferLoadSessionIfNotReady(this,
- aPromiseId,
- aSessionId,
- aSessionIdLength)) {
- return;
- }
-
- string sid(aSessionId, aSessionId + aSessionIdLength);
- if (!ClearKeyPersistence::IsPersistentSessionId(sid)) {
- mCallback->ResolveLoadSessionPromise(aPromiseId, false);
- return;
- }
-
- // Callsback PersistentSessionDataLoaded with results...
- ClearKeyPersistence::LoadSessionData(this, sid, aPromiseId);
-}
-
-void
-ClearKeySessionManager::PersistentSessionDataLoaded(GMPErr aStatus,
- uint32_t aPromiseId,
- const string& aSessionId,
- const uint8_t* aKeyData,
- uint32_t aKeyDataSize)
-{
- CK_LOGD("ClearKeySessionManager::PersistentSessionDataLoaded");
- if (GMP_FAILED(aStatus) ||
- Contains(mSessions, aSessionId) ||
- (aKeyDataSize % (2 * CENC_KEY_LEN)) != 0) {
- mCallback->ResolveLoadSessionPromise(aPromiseId, false);
- return;
- }
-
- ClearKeySession* session = new ClearKeySession(aSessionId,
- mCallback,
- kGMPPersistentSession);
- mSessions[aSessionId] = session;
-
- uint32_t numKeys = aKeyDataSize / (2 * CENC_KEY_LEN);
-
- vector<GMPMediaKeyInfo> key_infos;
- 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);
-
- 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);
- key_infos.push_back(GMPMediaKeyInfo(&keyPairs[i].mKeyId[0],
- keyPairs[i].mKeyId.size(),
- kGMPUsable));
- }
- mCallback->BatchedKeyStatusChanged(&aSessionId[0], aSessionId.size(),
- key_infos.data(), key_infos.size());
-
- mCallback->ResolveLoadSessionPromise(aPromiseId, true);
-}
-
-void
-ClearKeySessionManager::UpdateSession(uint32_t aPromiseId,
- const char* aSessionId,
- uint32_t aSessionIdLength,
- const uint8_t* aResponse,
- uint32_t aResponseSize)
-{
- CK_LOGD("ClearKeySessionManager::UpdateSession");
- string sessionId(aSessionId, aSessionId + aSessionIdLength);
-
- 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);
- 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);
- return;
- }
-
- // Parse the response for any (key ID, key) pairs.
- vector<KeyIdPair> keyPairs;
- if (!ClearKeyUtils::ParseJWK(aResponse, aResponseSize, keyPairs, session->Type())) {
- CK_LOGW("ClearKey CDM failed to parse JSON Web Key.");
- mCallback->RejectPromise(aPromiseId, kGMPTypeError, nullptr, 0);
- return;
- }
-
- vector<GMPMediaKeyInfo> key_infos;
- 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));
- }
- mCallback->BatchedKeyStatusChanged(aSessionId, aSessionIdLength,
- key_infos.data(), key_infos.size());
-
- if (session->Type() != kGMPPersistentSession) {
- mCallback->ResolvePromise(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);
-}
-
-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++) {
- const KeyId& keyId = keyIds[i];
- if (!mDecryptionManager->HasKeyForKeyId(keyId)) {
- continue;
- }
- assert(keyId.size() == CENC_KEY_LEN);
- aOutKeyData.insert(aOutKeyData.end(), keyId.begin(), keyId.end());
- const Key& key = mDecryptionManager->GetDecryptionKey(keyId);
- assert(key.size() == CENC_KEY_LEN);
- aOutKeyData.insert(aOutKeyData.end(), key.begin(), key.end());
- }
-}
-
-void
-ClearKeySessionManager::CloseSession(uint32_t aPromiseId,
- const char* aSessionId,
- uint32_t aSessionIdLength)
-{
- CK_LOGD("ClearKeySessionManager::CloseSession");
-
- string sessionId(aSessionId, aSessionId + aSessionIdLength);
- 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);
- return;
- }
-
- ClearKeySession* session = itr->second;
- assert(session);
-
- ClearInMemorySessionData(session);
- mCallback->SessionClosed(aSessionId, aSessionIdLength);
- mCallback->ResolvePromise(aPromiseId);
-}
-
-void
-ClearKeySessionManager::ClearInMemorySessionData(ClearKeySession* aSession)
-{
- mSessions.erase(aSession->Id());
- delete aSession;
-}
-
-void
-ClearKeySessionManager::RemoveSession(uint32_t aPromiseId,
- const char* aSessionId,
- uint32_t aSessionIdLength)
-{
- 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);
- return;
- }
-
- ClearKeySession* session = itr->second;
- assert(session);
- string sid = session->Id();
- bool isPersistent = session->Type() == kGMPPersistentSession;
- ClearInMemorySessionData(session);
-
- if (!isPersistent) {
- mCallback->ResolvePromise(aPromiseId);
- return;
- }
-
- ClearKeyPersistence::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);
-}
-
-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 */);
-}
-
-void
-ClearKeySessionManager::Decrypt(GMPBuffer* aBuffer,
- GMPEncryptedBufferMetadata* aMetadata)
-{
- CK_LOGD("ClearKeySessionManager::Decrypt");
-
- if (!mThread) {
- CK_LOGW("No decrypt thread");
- mCallback->Decrypted(aBuffer, GMPGenericErr);
- return;
- }
-
- mThread->Post(WrapTaskRefCounted(this,
- &ClearKeySessionManager::DoDecrypt,
- aBuffer, aMetadata));
-}
-
-void
-ClearKeySessionManager::DoDecrypt(GMPBuffer* aBuffer,
- GMPEncryptedBufferMetadata* aMetadata)
-{
- CK_LOGD("ClearKeySessionManager::DoDecrypt");
-
- GMPErr rv = mDecryptionManager->Decrypt(aBuffer->Data(), aBuffer->Size(),
- CryptoMetaData(aMetadata));
- CK_LOGD("DeDecrypt finished with code %x\n", rv);
- mCallback->Decrypted(aBuffer, rv);
-}
-
-void
-ClearKeySessionManager::Shutdown()
-{
- CK_LOGD("ClearKeySessionManager::Shutdown %p", this);
-
- for (auto it = mSessions.begin(); it != mSessions.end(); it++) {
- delete it->second;
- }
- mSessions.clear();
-}
-
-void
-ClearKeySessionManager::DecryptingComplete()
-{
- CK_LOGD("ClearKeySessionManager::DecryptingComplete %p", this);
-
- GMPThread* thread = mThread;
- thread->Join();
-
- Shutdown();
- mDecryptionManager = nullptr;
- Release();
-}