1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5  * You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef CDMProxy_h_
8 #define CDMProxy_h_
9 
10 #include "mozilla/CDMCaps.h"
11 #include "mozilla/MozPromise.h"
12 
13 #include "mozilla/dom/MediaKeyMessageEvent.h"
14 #include "mozilla/dom/MediaKeys.h"
15 
16 #include "nsIThread.h"
17 
18 namespace mozilla {
19 class MediaRawData;
20 
21 enum DecryptStatus {
22   Ok = 0,
23   GenericErr = 1,
24   NoKeyErr = 2,
25   AbortedErr = 3,
26 };
27 
28 struct DecryptResult {
DecryptResultDecryptResult29   DecryptResult(DecryptStatus aStatus, MediaRawData* aSample)
30     : mStatus(aStatus)
31     , mSample(aSample)
32   {}
33   DecryptStatus mStatus;
34   RefPtr<MediaRawData> mSample;
35 };
36 
37 class CDMKeyInfo {
38 public:
CDMKeyInfo(const nsTArray<uint8_t> & aKeyId)39   explicit CDMKeyInfo(const nsTArray<uint8_t>& aKeyId)
40     : mKeyId(aKeyId)
41     , mStatus()
42   {}
43 
CDMKeyInfo(const nsTArray<uint8_t> & aKeyId,const dom::Optional<dom::MediaKeyStatus> & aStatus)44   CDMKeyInfo(const nsTArray<uint8_t>& aKeyId,
45              const dom::Optional<dom::MediaKeyStatus>& aStatus)
46     : mKeyId(aKeyId)
47     , mStatus(aStatus.Value())
48   {}
49 
50   // The copy-ctor and copy-assignment operator for Optional<T> are declared as
51   // delete, so override CDMKeyInfo copy-ctor for nsTArray operations.
CDMKeyInfo(const CDMKeyInfo & aKeyInfo)52   CDMKeyInfo(const CDMKeyInfo& aKeyInfo)
53   {
54     mKeyId = aKeyInfo.mKeyId;
55     if (aKeyInfo.mStatus.WasPassed()) {
56       mStatus.Construct(aKeyInfo.mStatus.Value());
57     }
58   }
59 
60   nsTArray<uint8_t> mKeyId;
61   dom::Optional<dom::MediaKeyStatus> mStatus;
62 };
63 
64 typedef int64_t UnixTime;
65 
66 // Proxies calls CDM, and proxies calls back.
67 // Note: Promises are passed in via a PromiseId, so that the ID can be
68 // passed via IPC to the CDM, which can then signal when to reject or
69 // resolve the promise using its PromiseId.
70 class CDMProxy {
71 protected:
72   typedef dom::PromiseId PromiseId;
73   typedef dom::MediaKeySessionType MediaKeySessionType;
74 public:
75 
76   NS_IMETHOD_(MozExternalRefCountType) AddRef(void) = 0;
77   NS_IMETHOD_(MozExternalRefCountType) Release(void) = 0;
78 
79   typedef MozPromise<DecryptResult, DecryptResult, /* IsExclusive = */ true> DecryptPromise;
80 
81   // Main thread only.
CDMProxy(dom::MediaKeys * aKeys,const nsAString & aKeySystem,bool aDistinctiveIdentifierRequired,bool aPersistentStateRequired)82   CDMProxy(dom::MediaKeys* aKeys,
83            const nsAString& aKeySystem,
84            bool aDistinctiveIdentifierRequired,
85            bool aPersistentStateRequired)
86     : mKeys(aKeys)
87     , mKeySystem(aKeySystem)
88     , mDistinctiveIdentifierRequired(aDistinctiveIdentifierRequired)
89     , mPersistentStateRequired(aPersistentStateRequired)
90   {}
91 
92   // Main thread only.
93   // Loads the CDM corresponding to mKeySystem.
94   // Calls MediaKeys::OnCDMCreated() when the CDM is created.
95   virtual void Init(PromiseId aPromiseId,
96                     const nsAString& aOrigin,
97                     const nsAString& aTopLevelOrigin,
98                     const nsAString& aName,
99                     bool aInPrivateBrowsing) = 0;
100 
OnSetDecryptorId(uint32_t aId)101   virtual void OnSetDecryptorId(uint32_t aId) {}
102 
103   // Main thread only.
104   // Uses the CDM to create a key session.
105   // Calls MediaKeys::OnSessionActivated() when session is created.
106   // Assumes ownership of (Move()s) aInitData's contents.
107   virtual void CreateSession(uint32_t aCreateSessionToken,
108                              MediaKeySessionType aSessionType,
109                              PromiseId aPromiseId,
110                              const nsAString& aInitDataType,
111                              nsTArray<uint8_t>& aInitData) = 0;
112 
113   // Main thread only.
114   // Uses the CDM to load a presistent session stored on disk.
115   // Calls MediaKeys::OnSessionActivated() when session is loaded.
116   virtual void LoadSession(PromiseId aPromiseId,
117                            const nsAString& aSessionId) = 0;
118 
119   // Main thread only.
120   // Sends a new certificate to the CDM.
121   // Calls MediaKeys->ResolvePromise(aPromiseId) after the CDM has
122   // processed the request.
123   // Assumes ownership of (Move()s) aCert's contents.
124   virtual void SetServerCertificate(PromiseId aPromiseId,
125                                     nsTArray<uint8_t>& aCert) = 0;
126 
127   // Main thread only.
128   // Sends an update to the CDM.
129   // Calls MediaKeys->ResolvePromise(aPromiseId) after the CDM has
130   // processed the request.
131   // Assumes ownership of (Move()s) aResponse's contents.
132   virtual void UpdateSession(const nsAString& aSessionId,
133                              PromiseId aPromiseId,
134                              nsTArray<uint8_t>& aResponse) = 0;
135 
136   // Main thread only.
137   // Calls MediaKeys->ResolvePromise(aPromiseId) after the CDM has
138   // processed the request.
139   // If processing this operation results in the session actually closing,
140   // we also call MediaKeySession::OnClosed(), which in turn calls
141   // MediaKeys::OnSessionClosed().
142   virtual void CloseSession(const nsAString& aSessionId,
143                             PromiseId aPromiseId) = 0;
144 
145   // Main thread only.
146   // Removes all data for a persisent session.
147   // Calls MediaKeys->ResolvePromise(aPromiseId) after the CDM has
148   // processed the request.
149   virtual void RemoveSession(const nsAString& aSessionId,
150                              PromiseId aPromiseId) = 0;
151 
152   // Main thread only.
153   virtual void Shutdown() = 0;
154 
155   // Main thread only.
156   virtual void Terminated() = 0;
157 
158   // Threadsafe.
159   virtual const nsCString& GetNodeId() const = 0;
160 
161   // Main thread only.
162   virtual void OnSetSessionId(uint32_t aCreateSessionToken,
163                               const nsAString& aSessionId) = 0;
164 
165   // Main thread only.
166   virtual void OnResolveLoadSessionPromise(uint32_t aPromiseId,
167                                            bool aSuccess) = 0;
168 
169   // Main thread only.
170   virtual void OnSessionMessage(const nsAString& aSessionId,
171                                 dom::MediaKeyMessageType aMessageType,
172                                 nsTArray<uint8_t>& aMessage) = 0;
173 
174   // Main thread only.
175   virtual void OnExpirationChange(const nsAString& aSessionId,
176                                   UnixTime aExpiryTime) = 0;
177 
178   // Main thread only.
179   virtual void OnSessionClosed(const nsAString& aSessionId) = 0;
180 
181   // Main thread only.
182   virtual void OnSessionError(const nsAString& aSessionId,
183                               nsresult aException,
184                               uint32_t aSystemCode,
185                               const nsAString& aMsg) = 0;
186 
187   // Main thread only.
188   virtual void OnRejectPromise(uint32_t aPromiseId,
189                                nsresult aDOMException,
190                                const nsCString& aMsg) = 0;
191 
192   virtual RefPtr<DecryptPromise> Decrypt(MediaRawData* aSample) = 0;
193 
194   // Owner thread only.
195   virtual void OnDecrypted(uint32_t aId,
196                            DecryptStatus aResult,
197                            const nsTArray<uint8_t>& aDecryptedData) = 0;
198 
199   // Reject promise with DOMException corresponding to aExceptionCode.
200   // Can be called from any thread.
201   virtual void RejectPromise(PromiseId aId,
202                              nsresult aExceptionCode,
203                              const nsCString& aReason) = 0;
204 
205   // Resolves promise with "undefined".
206   // Can be called from any thread.
207   virtual void ResolvePromise(PromiseId aId) = 0;
208 
209   // Threadsafe.
210   virtual const nsString& KeySystem() const = 0;
211 
212   virtual  CDMCaps& Capabilites() = 0;
213 
214   // Main thread only.
215   virtual void OnKeyStatusesChange(const nsAString& aSessionId) = 0;
216 
217   virtual void GetSessionIdsForKeyId(const nsTArray<uint8_t>& aKeyId,
218                                      nsTArray<nsCString>& aSessionIds) = 0;
219 
220 #ifdef DEBUG
221   virtual bool IsOnOwnerThread() = 0;
222 #endif
223 
GetDecryptorId()224   virtual uint32_t GetDecryptorId() { return 0; }
225 
226 protected:
~CDMProxy()227   virtual ~CDMProxy() {}
228 
229   // Helper to enforce that a raw pointer is only accessed on the main thread.
230   template<class Type>
231   class MainThreadOnlyRawPtr {
232   public:
MainThreadOnlyRawPtr(Type * aPtr)233     explicit MainThreadOnlyRawPtr(Type* aPtr)
234       : mPtr(aPtr)
235     {
236       MOZ_ASSERT(NS_IsMainThread());
237     }
238 
IsNull()239     bool IsNull() const {
240       MOZ_ASSERT(NS_IsMainThread());
241       return !mPtr;
242     }
243 
Clear()244     void Clear() {
245       MOZ_ASSERT(NS_IsMainThread());
246       mPtr = nullptr;
247     }
248 
249     Type* operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN {
250       MOZ_ASSERT(NS_IsMainThread());
251       return mPtr;
252     }
253   private:
254     Type* mPtr;
255   };
256 
257   // Our reference back to the MediaKeys object.
258   // WARNING: This is a non-owning reference that is cleared by MediaKeys
259   // destructor. only use on main thread, and always nullcheck before using!
260   MainThreadOnlyRawPtr<dom::MediaKeys> mKeys;
261 
262   const nsString mKeySystem;
263 
264   // Onwer specified thread. e.g. Gecko Media Plugin thread.
265   // All interactions with the out-of-process EME plugin must come from this thread.
266   RefPtr<nsIThread> mOwnerThread;
267 
268   nsCString mNodeId;
269 
270   CDMCaps mCapabilites;
271 
272   const bool mDistinctiveIdentifierRequired;
273   const bool mPersistentStateRequired;
274 };
275 
276 
277 } // namespace mozilla
278 
279 #endif // CDMProxy_h_
280