1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #ifndef DOM_MEDIA_PLATFORM_WMF_CLEARKEY_WMFCLEARKEYCDM_H
6 #define DOM_MEDIA_PLATFORM_WMF_CLEARKEY_WMFCLEARKEYCDM_H
9 #include <unordered_map>
12 #include <windows.media.protection.h>
14 #include <wrl/client.h>
16 #include "ClearKeySessionManager.h"
17 #include "MFCDMExtra.h"
18 #include "WMFClearKeyUtils.h"
19 #include "content_decryption_module.h"
23 class SessionManagerWrapper
;
24 class WMFClearKeySession
;
26 // This our customized MFCDM for supporting clearkey in our testing. It would
27 // use ClearKeySessionManager via SessionManagerWrapper to perform decryption.
28 class WMFClearKeyCDM final
29 : public Microsoft::WRL::RuntimeClass
<
30 Microsoft::WRL::RuntimeClassFlags
<Microsoft::WRL::ClassicCom
>,
31 IMFContentDecryptionModule
, IMFGetService
, IMFShutdown
,
32 Microsoft::WRL::FtmBase
> {
34 WMFClearKeyCDM() = default;
36 WMFClearKeyCDM(const WMFClearKeyCDM
&) = delete;
37 WMFClearKeyCDM
& operator=(const WMFClearKeyCDM
&) = delete;
39 HRESULT
RuntimeClassInitialize(IPropertyStore
* aProperties
);
41 // IMFContentDecryptionModule
42 STDMETHODIMP
SetContentEnabler(IMFContentEnabler
* aContentEnabler
,
43 IMFAsyncResult
* aResult
) override
;
44 STDMETHODIMP
GetSuspendNotify(IMFCdmSuspendNotify
** aNotify
) override
;
45 STDMETHODIMP
SetPMPHostApp(IMFPMPHostApp
* aPmpHostApp
) override
;
46 STDMETHODIMP
CreateSession(
47 MF_MEDIAKEYSESSION_TYPE aSessionType
,
48 IMFContentDecryptionModuleSessionCallbacks
* aCallbacks
,
49 IMFContentDecryptionModuleSession
** aSession
) override
;
50 STDMETHODIMP
SetServerCertificate(const BYTE
* aCertificate
,
51 DWORD aCertificateSize
) override
;
52 STDMETHODIMP
CreateTrustedInput(const BYTE
* aContentInitData
,
53 DWORD aContentInitDataSize
,
54 IMFTrustedInput
** aTrustedInput
) override
;
55 STDMETHODIMP
GetProtectionSystemIds(GUID
** aSystemIds
,
56 DWORD
* aCount
) override
;
58 STDMETHODIMP
GetService(REFGUID aGuidService
, REFIID aRiid
,
59 LPVOID
* aPpvObject
) override
;
62 STDMETHODIMP
Shutdown() override
;
63 STDMETHODIMP
GetShutdownStatus(MFSHUTDOWN_STATUS
* aStatus
) override
;
66 RefPtr
<SessionManagerWrapper
> mSessionManager
;
67 Microsoft::WRL::ComPtr
<
68 ABI::Windows::Media::Protection::IMediaProtectionPMPServer
>
72 // In order to reuse existing Gecko clearkey implementation, we need to
73 // inherit the class `cdm::Host_10`.
74 // TODO : add a way to assert thread usage. It would be used on MF thread pool
75 // and the media supervisor thread pool.
76 class SessionManagerWrapper final
: public RefCounted
, private cdm::Host_10
{
78 explicit SessionManagerWrapper(WMFClearKeyCDM
* aCDM
);
80 HRESULT
GenerateRequest(cdm::InitDataType aInitDataType
,
81 const BYTE
* aInitData
, DWORD aInitDataSize
,
82 cdm::SessionType aSessionType
,
83 WMFClearKeySession
* aSession
,
84 std::string
& aSessionIdOut
);
85 HRESULT
UpdateSession(const std::string
& aSessionId
, const BYTE
* aResponse
,
87 HRESULT
CloseSession(const std::string
& aSessionId
);
88 HRESULT
RemoveSession(const std::string
& aSessionId
);
89 HRESULT
Decrypt(const cdm::InputBuffer_2
& aBuffer
,
90 cdm::DecryptedBlock
* aDecryptedBlock
);
96 ~SessionManagerWrapper();
98 void OnInitialized(bool aSuccess
) override
{}
99 void OnResolveKeyStatusPromise(uint32_t aPromiseId
,
100 cdm::KeyStatus aKeyStatus
) override
{}
101 void OnResolveNewSessionPromise(uint32_t aPromiseId
, const char* aSessionId
,
102 uint32_t aSessionIdSize
) override
;
103 void OnResolvePromise(uint32_t aPromiseId
) override
;
104 void OnRejectPromise(uint32_t aPromiseId
, cdm::Exception aException
,
105 uint32_t aSystemCode
, const char* aErrorMessage
,
106 uint32_t aErrorMessageSize
) override
;
107 void OnSessionMessage(const char* aSessionId
, uint32_t aSessionIdSize
,
108 cdm::MessageType aMessageType
, const char* aMessage
,
109 uint32_t aMessageSize
) override
;
110 void OnSessionKeysChange(const char* aSessionId
, uint32_t aSessionIdSize
,
111 bool aHasAdditionalUsableKey
,
112 const cdm::KeyInformation
* aKeysInfo
,
113 uint32_t aKeysInfoCount
) override
;
114 void OnExpirationChange(const char* aSessionId
, uint32_t aSessionIdSize
,
115 cdm::Time aNewExpiryTime
) override
{
116 // No need to implement this because the session would never expire in
119 void OnSessionClosed(const char* aSessionId
,
120 uint32_t aSessionIdSize
) override
{
121 // No need to implement this because session doesn't have close callback
124 cdm::FileIO
* CreateFileIO(cdm::FileIOClient
* aClient
) override
{
125 // We don't support this because we only support temporary session.
128 void SendPlatformChallenge(const char* aServiceId
, uint32_t aServiceIdSize
,
129 const char* aChallenge
,
130 uint32_t aChallengeSize
) override
{}
131 void EnableOutputProtection(uint32_t aDesiredProtectionMask
) override
{}
132 void QueryOutputProtectionStatus() override
{};
133 void OnDeferredInitializationDone(cdm::StreamType aStreamType
,
134 cdm::Status aDecoderStatus
) override
{}
135 void RequestStorageId(uint32_t aVersion
) override
{}
136 cdm::Buffer
* Allocate(uint32_t aCapacity
) override
;
137 void SetTimer(int64_t aDelayMs
, void* aContext
) override
{}
138 cdm::Time
GetCurrentWallTime() override
{ return 0.0; }
139 friend class SessionManager
;
141 Microsoft::WRL::ComPtr
<WMFClearKeyCDM
> mOwnerCDM
;
142 RefPtr
<ClearKeySessionManager
> mSessionManager
;
143 std::unordered_map
<std::string
, Microsoft::WRL::ComPtr
<WMFClearKeySession
>>
146 // This is a RAII helper class to use ClearKeySessionManager::XXXSession
147 // methods in a sync style, which is what MFCDM is required.
148 // ClearKeySessionManager uses cdm::Host_10's OnResolve/RejectXXX as callback
149 // to report whether those function calls relatd with specific promise id
150 // succeed or not. As we only do temporary session for ClearKey testing, we
151 // don't need to wait to setup the storage so calling those XXXsession
152 // functions are actully a sync process. We guarantee that
153 // ClearKeySessionManager will use OnResolve/Reject methods to notify us
154 // result, right after we calling the session related method.
155 // [How to to use this class, not thread-safe]
156 // 1. create it on the stack
157 // 2. use GetPromiseId() to generate a fake promise id for tracking
158 // 3. in cdm::Host_10's callback function, check promise id to know what
159 // result needs to be set
160 // 4. check result to see if the session method succeed or not
161 class SyncResultChecker final
{
163 using ResultType
= std::variant
<const char*, bool>;
164 explicit SyncResultChecker(SessionManagerWrapper
& aOwner
)
165 : mOwner(aOwner
), mIdx(sIdx
++), mKeySession(nullptr) {
166 mOwner
.mActiveSyncResultChecker
.insert({mIdx
, this});
168 SyncResultChecker(SessionManagerWrapper
& aOwner
,
169 WMFClearKeySession
* aKeySession
)
170 : mOwner(aOwner
), mIdx(sIdx
++), mKeySession(aKeySession
) {
171 mOwner
.mActiveSyncResultChecker
.insert({mIdx
, this});
173 ~SyncResultChecker() { mOwner
.mActiveSyncResultChecker
.erase(mIdx
); }
174 uint32_t GetPromiseId() const { return mIdx
; }
175 const ResultType
& GetResult() const { return mResult
; }
176 WMFClearKeySession
* GetKeySession() const { return mKeySession
; }
179 // Only allow setting result from these callbacks.
180 friend void SessionManagerWrapper::OnResolveNewSessionPromise(uint32_t,
183 friend void SessionManagerWrapper::OnResolvePromise(uint32_t);
184 friend void SessionManagerWrapper::OnRejectPromise(uint32_t, cdm::Exception
,
185 uint32_t, const char*,
187 void SetResultConstChar(const char* aResult
) {
188 mResult
.emplace
<const char*>(aResult
);
190 void SetResultBool(bool aResult
) { mResult
.emplace
<bool>(aResult
); }
192 static inline uint32_t sIdx
= 0;
193 SessionManagerWrapper
& mOwner
;
196 WMFClearKeySession
* const mKeySession
;
198 std::unordered_map
<uint32_t, SyncResultChecker
*> mActiveSyncResultChecker
;
200 // Protect following members.
202 bool mIsShutdown
= false;
205 } // namespace mozilla
207 #endif // DOM_MEDIA_PLATFORM_WMF_CLEARKEY_WMFCLEARKEYCDM_H