diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /media/gmp-clearkey/0.1/ClearKeyPersistence.cpp | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | uxp-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz |
Add m-esr52 at 52.6.0
Diffstat (limited to 'media/gmp-clearkey/0.1/ClearKeyPersistence.cpp')
-rw-r--r-- | media/gmp-clearkey/0.1/ClearKeyPersistence.cpp | 260 |
1 files changed, 260 insertions, 0 deletions
diff --git a/media/gmp-clearkey/0.1/ClearKeyPersistence.cpp b/media/gmp-clearkey/0.1/ClearKeyPersistence.cpp new file mode 100644 index 0000000000..2e14d822ee --- /dev/null +++ b/media/gmp-clearkey/0.1/ClearKeyPersistence.cpp @@ -0,0 +1,260 @@ +/* + * 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 "ClearKeyPersistence.h" +#include "ClearKeyUtils.h" +#include "ClearKeyStorage.h" +#include "ClearKeySessionManager.h" +#include "RefCounted.h" + +#include <stdint.h> +#include <string.h> +#include <set> +#include <vector> +#include <sstream> +#include <assert.h> + +using namespace std; + +// Whether we've loaded the persistent session ids from GMPStorage yet. +enum PersistentKeyState { + UNINITIALIZED, + LOADING, + LOADED +}; +static PersistentKeyState sPersistentKeyState = UNINITIALIZED; + +// Set of session Ids of the persistent sessions created or residing in +// storage. +static set<uint32_t> sPersistentSessionIds; + +static vector<GMPTask*> sTasksBlockedOnSessionIdLoad; + +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)); + } + aRecordIterator->NextRecord(); + } + } + sPersistentKeyState = LOADED; + aRecordIterator->Close(); + + for (size_t i = 0; i < sTasksBlockedOnSessionIdLoad.size(); i++) { + sTasksBlockedOnSessionIdLoad[i]->Run(); + sTasksBlockedOnSessionIdLoad[i]->Destroy(); + } + sTasksBlockedOnSessionIdLoad.clear(); +} + +/* static */ void +ClearKeyPersistence::EnsureInitialized() +{ + if (sPersistentKeyState == UNINITIALIZED) { + sPersistentKeyState = LOADING; + if (GMP_FAILED(EnumRecordNames(&ReadAllRecordsFromIterator))) { + sPersistentKeyState = LOADED; + } + } +} + +/* static */ string +ClearKeyPersistence::GetNewSessionId(GMPSessionType aSessionType) +{ + static uint32_t sNextSessionId = 1; + + // Ensure we don't re-use a session id that was persisted. + while (Contains(sPersistentSessionIds, sNextSessionId)) { + sNextSessionId++; + } + + string sessionId; + stringstream ss; + ss << sNextSessionId; + ss >> sessionId; + + if (aSessionType == kGMPPersistentSession) { + sPersistentSessionIds.insert(sNextSessionId); + } + + 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) +{ + if (sPersistentKeyState >= LOADED) { + return false; + } + GMPTask* t = new CreateSessionTask(aInstance, + aCreateSessionToken, + aPromiseId, + aInitDataType, + aInitData, + aInitDataSize, + aSessionType); + sTasksBlockedOnSessionIdLoad.push_back(t); + return true; +} + +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) +{ + if (sPersistentKeyState >= LOADED) { + return false; + } + GMPTask* t = new LoadSessionTask(aInstance, + aPromiseId, + aSessionId, + aSessionIdLength); + sTasksBlockedOnSessionIdLoad.push_back(t); + return true; +} + +/* static */ bool +ClearKeyPersistence::IsPersistentSessionId(const string& aSessionId) +{ + return Contains(sPersistentSessionIds, atoi(aSessionId.c_str())); +} + +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())); +} |