1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 #include "cdm-test-storage.h"
7 #include <vector>
8 
9 #include "mozilla/Assertions.h"
10 #include "mozilla/Attributes.h"
11 
12 using namespace cdm;
13 
14 class WriteRecordClient : public FileIOClient {
15  public:
WriteRecordClient(std::function<void ()> && aOnSuccess,std::function<void ()> && aOnFailure,const uint8_t * aData,uint32_t aDataSize)16   WriteRecordClient(std::function<void()>&& aOnSuccess,
17                     std::function<void()>&& aOnFailure, const uint8_t* aData,
18                     uint32_t aDataSize)
19       : mOnSuccess(move(aOnSuccess)), mOnFailure(move(aOnFailure)) {
20     mData.insert(mData.end(), aData, aData + aDataSize);
21   }
22 
OnOpenComplete(Status aStatus)23   void OnOpenComplete(Status aStatus) override {
24     // If we hit an error, fail.
25     if (aStatus != Status::kSuccess) {
26       Done(aStatus);
27     } else if (mFileIO) {  // Otherwise, write our data to the file.
28       mFileIO->Write(mData.empty() ? nullptr : &mData.front(), mData.size());
29     }
30   }
31 
OnReadComplete(Status aStatus,const uint8_t * aData,uint32_t aDataSize)32   void OnReadComplete(Status aStatus, const uint8_t* aData,
33                       uint32_t aDataSize) override {}
34 
OnWriteComplete(Status aStatus)35   void OnWriteComplete(Status aStatus) override { Done(aStatus); }
36 
Do(const std::string & aName,Host_10 * aHost)37   void Do(const std::string& aName, Host_10* aHost) {
38     // Initialize the FileIO.
39     mFileIO = aHost->CreateFileIO(this);
40     mFileIO->Open(aName.c_str(), aName.size());
41   }
42 
43  private:
Done(cdm::FileIOClient::Status aStatus)44   void Done(cdm::FileIOClient::Status aStatus) {
45     // Note: Call Close() before running continuation, in case the
46     // continuation tries to open the same record; if we call Close()
47     // after running the continuation, the Close() call will arrive
48     // just after the Open() call succeeds, immediately closing the
49     // record we just opened.
50     if (mFileIO) {
51       // will delete mFileIO inside Close.
52       mFileIO->Close();
53     }
54 
55     if (IO_SUCCEEDED(aStatus)) {
56       mOnSuccess();
57     } else {
58       mOnFailure();
59     }
60 
61     delete this;
62   }
63 
64   FileIO* mFileIO = nullptr;
65   std::function<void()> mOnSuccess;
66   std::function<void()> mOnFailure;
67   std::vector<uint8_t> mData;
68 };
69 
WriteRecord(Host_10 * aHost,const std::string & aRecordName,const uint8_t * aData,uint32_t aNumBytes,std::function<void ()> && aOnSuccess,std::function<void ()> && aOnFailure)70 void WriteRecord(Host_10* aHost, const std::string& aRecordName,
71                  const uint8_t* aData, uint32_t aNumBytes,
72                  std::function<void()>&& aOnSuccess,
73                  std::function<void()>&& aOnFailure) {
74   // client will be delete in WriteRecordClient::Done
75   WriteRecordClient* client = new WriteRecordClient(
76       move(aOnSuccess), move(aOnFailure), aData, aNumBytes);
77   client->Do(aRecordName, aHost);
78 }
79 
WriteRecord(Host_10 * aHost,const std::string & aRecordName,const std::string & aData,std::function<void ()> && aOnSuccess,std::function<void ()> && aOnFailure)80 void WriteRecord(Host_10* aHost, const std::string& aRecordName,
81                  const std::string& aData, std::function<void()>&& aOnSuccess,
82                  std::function<void()>&& aOnFailure) {
83   return WriteRecord(aHost, aRecordName, (const uint8_t*)aData.c_str(),
84                      aData.size(), move(aOnSuccess), move(aOnFailure));
85 }
86 
87 class ReadRecordClient : public FileIOClient {
88  public:
ReadRecordClient(std::function<void (bool,const uint8_t *,uint32_t)> && aOnReadComplete)89   explicit ReadRecordClient(
90       std::function<void(bool, const uint8_t*, uint32_t)>&& aOnReadComplete)
91       : mOnReadComplete(move(aOnReadComplete)) {}
92 
OnOpenComplete(Status aStatus)93   void OnOpenComplete(Status aStatus) override {
94     auto err = aStatus;
95     if (aStatus != Status::kSuccess) {
96       Done(err, reinterpret_cast<const uint8_t*>(""), 0);
97     } else {
98       mFileIO->Read();
99     }
100   }
101 
OnReadComplete(Status aStatus,const uint8_t * aData,uint32_t aDataSize)102   void OnReadComplete(Status aStatus, const uint8_t* aData,
103                       uint32_t aDataSize) override {
104     Done(aStatus, aData, aDataSize);
105   }
106 
OnWriteComplete(Status aStatus)107   void OnWriteComplete(Status aStatus) override {}
108 
Do(const std::string & aName,Host_10 * aHost)109   void Do(const std::string& aName, Host_10* aHost) {
110     mFileIO = aHost->CreateFileIO(this);
111     mFileIO->Open(aName.c_str(), aName.size());
112   }
113 
114  private:
Done(cdm::FileIOClient::Status aStatus,const uint8_t * aData,uint32_t aDataSize)115   void Done(cdm::FileIOClient::Status aStatus, const uint8_t* aData,
116             uint32_t aDataSize) {
117     // Note: Call Close() before running continuation, in case the
118     // continuation tries to open the same record; if we call Close()
119     // after running the continuation, the Close() call will arrive
120     // just after the Open() call succeeds, immediately closing the
121     // record we just opened.
122     if (mFileIO) {
123       // will delete mFileIO inside Close.
124       mFileIO->Close();
125     }
126 
127     if (IO_SUCCEEDED(aStatus)) {
128       mOnReadComplete(true, aData, aDataSize);
129     } else {
130       mOnReadComplete(false, reinterpret_cast<const uint8_t*>(""), 0);
131     }
132 
133     delete this;
134   }
135 
136   FileIO* mFileIO = nullptr;
137   std::function<void(bool, const uint8_t*, uint32_t)> mOnReadComplete;
138 };
139 
ReadRecord(Host_10 * aHost,const std::string & aRecordName,std::function<void (bool,const uint8_t *,uint32_t)> && aOnReadComplete)140 void ReadRecord(
141     Host_10* aHost, const std::string& aRecordName,
142     std::function<void(bool, const uint8_t*, uint32_t)>&& aOnReadComplete) {
143   // client will be delete in ReadRecordClient::Done
144   ReadRecordClient* client = new ReadRecordClient(move(aOnReadComplete));
145   client->Do(aRecordName, aHost);
146 }
147 
148 class OpenRecordClient : public FileIOClient {
149  public:
OpenRecordClient(std::function<void (bool)> && aOpenComplete)150   explicit OpenRecordClient(std::function<void(bool)>&& aOpenComplete)
151       : mOpenComplete(move(aOpenComplete)) {}
152 
OnOpenComplete(Status aStatus)153   void OnOpenComplete(Status aStatus) override { Done(aStatus); }
154 
OnReadComplete(Status aStatus,const uint8_t * aData,uint32_t aDataSize)155   void OnReadComplete(Status aStatus, const uint8_t* aData,
156                       uint32_t aDataSize) override {}
157 
OnWriteComplete(Status aStatus)158   void OnWriteComplete(Status aStatus) override {}
159 
Do(const std::string & aName,Host_10 * aHost)160   void Do(const std::string& aName, Host_10* aHost) {
161     // Initialize the FileIO.
162     mFileIO = aHost->CreateFileIO(this);
163     mFileIO->Open(aName.c_str(), aName.size());
164   }
165 
166  private:
Done(cdm::FileIOClient::Status aStatus)167   void Done(cdm::FileIOClient::Status aStatus) {
168     // Note: Call Close() before running continuation, in case the
169     // continuation tries to open the same record; if we call Close()
170     // after running the continuation, the Close() call will arrive
171     // just after the Open() call succeeds, immediately closing the
172     // record we just opened.
173     if (mFileIO) {
174       // will delete mFileIO inside Close.
175       mFileIO->Close();
176     }
177 
178     if (IO_SUCCEEDED(aStatus)) {
179       mOpenComplete(true);
180     } else {
181       mOpenComplete(false);
182     }
183 
184     delete this;
185   }
186 
187   FileIO* mFileIO = nullptr;
188   std::function<void(bool)> mOpenComplete;
189   ;
190 };
191 
OpenRecord(Host_10 * aHost,const std::string & aRecordName,std::function<void (bool)> && aOpenComplete)192 void OpenRecord(Host_10* aHost, const std::string& aRecordName,
193                 std::function<void(bool)>&& aOpenComplete) {
194   // client will be delete in OpenRecordClient::Done
195   OpenRecordClient* client = new OpenRecordClient(move(aOpenComplete));
196   client->Do(aRecordName, aHost);
197 }
198