/* * 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 "ClearKeyStorage.h" #include // This include is required in order for content_decryption_module to work // on Unix systems. #include #include #include "content_decryption_module.h" #include "ArrayUtils.h" #include "ClearKeyUtils.h" using namespace cdm; using std::function; using std::string; using std::vector; class WriteRecordClient : public FileIOClient { public: /* * This function will take the memory ownership of the parameters and * delete them when done. */ static void Write(Host_10* aHost, string& aRecordName, const vector& aData, function&& aOnSuccess, function&& aOnFailure) { WriteRecordClient* client = new WriteRecordClient( aData, std::move(aOnSuccess), std::move(aOnFailure)); client->Do(aRecordName, aHost); } 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()); } } 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); } void OnWriteComplete(Status aStatus) override { Done(aStatus); } private: explicit WriteRecordClient(const vector& aData, function&& aOnSuccess, function&& aOnFailure) : mFileIO(nullptr), mOnSuccess(std::move(aOnSuccess)), mOnFailure(std::move(aOnFailure)), mData(aData) {} void Do(const string& aName, Host_10* aHost) { // Initialize the FileIO. mFileIO = aHost->CreateFileIO(this); mFileIO->Open(aName.c_str(), aName.size()); } 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 (mFileIO) { mFileIO->Close(); } if (IO_SUCCEEDED(aStatus)) { mOnSuccess(); } else { mOnFailure(); } delete this; } FileIO* mFileIO = nullptr; function mOnSuccess; function mOnFailure; const vector mData; }; void WriteData(Host_10* aHost, string& aRecordName, const vector& aData, function&& aOnSuccess, function&& aOnFailure) { WriteRecordClient::Write(aHost, aRecordName, aData, std::move(aOnSuccess), std::move(aOnFailure)); } class ReadRecordClient : public FileIOClient { public: /* * This function will take the memory ownership of the parameters and * delete them when done. */ static void Read(Host_10* aHost, string& aRecordName, function&& aOnSuccess, function&& aOnFailure) { (new ReadRecordClient(std::move(aOnSuccess), std::move(aOnFailure))) ->Do(aRecordName, aHost); } void OnOpenComplete(Status aStatus) override { auto err = aStatus; if (aStatus != Status::kSuccess) { Done(err, nullptr, 0); } else { mFileIO->Read(); } } void OnReadComplete(Status aStatus, const uint8_t* aData, uint32_t aDataSize) override { Done(aStatus, aData, aDataSize); } void OnWriteComplete(Status aStatus) override { // We should never reach here, this client only ever reads data. assert(false); } private: explicit ReadRecordClient( function&& aOnSuccess, function&& aOnFailure) : mFileIO(nullptr), mOnSuccess(std::move(aOnSuccess)), mOnFailure(std::move(aOnFailure)) {} void Do(const string& aName, Host_10* aHost) { mFileIO = aHost->CreateFileIO(this); mFileIO->Open(aName.c_str(), aName.size()); } 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 (mFileIO) { mFileIO->Close(); } if (IO_SUCCEEDED(aStatus)) { mOnSuccess(aData, aDataSize); } else { mOnFailure(); } delete this; } FileIO* mFileIO = nullptr; function mOnSuccess; function mOnFailure; }; void ReadData(Host_10* aHost, string& aRecordName, function&& aOnSuccess, function&& aOnFailure) { ReadRecordClient::Read(aHost, aRecordName, std::move(aOnSuccess), std::move(aOnFailure)); }