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 #include "WMFClearKeySession.h"
12 #include "WMFClearKeyCDM.h"
13 #include "WMFClearKeyUtils.h"
17 using Microsoft::WRL::ComPtr
;
19 static cdm::SessionType
ToCdmSessionType(MF_MEDIAKEYSESSION_TYPE aSessionType
) {
20 switch (aSessionType
) {
21 case MF_MEDIAKEYSESSION_TYPE_TEMPORARY
:
22 return cdm::SessionType::kTemporary
;
24 MOZ_ASSERT_UNREACHABLE("Only support temporary type for testing");
25 return cdm::SessionType::kTemporary
;
29 static MF_MEDIAKEY_STATUS
ToMFKeyStatus(cdm::KeyStatus aStatus
) {
31 case cdm::KeyStatus::kUsable
:
32 return MF_MEDIAKEY_STATUS_USABLE
;
33 case cdm::KeyStatus::kExpired
:
34 return MF_MEDIAKEY_STATUS_EXPIRED
;
35 case cdm::KeyStatus::kOutputDownscaled
:
36 return MF_MEDIAKEY_STATUS_OUTPUT_DOWNSCALED
;
37 case cdm::KeyStatus::kStatusPending
:
38 return MF_MEDIAKEY_STATUS_STATUS_PENDING
;
39 case cdm::KeyStatus::kInternalError
:
40 return MF_MEDIAKEY_STATUS_INTERNAL_ERROR
;
41 case cdm::KeyStatus::kReleased
:
42 return MF_MEDIAKEY_STATUS_RELEASED
;
43 case cdm::KeyStatus::kOutputRestricted
:
44 return MF_MEDIAKEY_STATUS_OUTPUT_RESTRICTED
;
48 HRESULT
WMFClearKeySession::RuntimeClassInitialize(
49 MF_MEDIAKEYSESSION_TYPE aSessionType
,
50 IMFContentDecryptionModuleSessionCallbacks
* aCallbacks
,
51 SessionManagerWrapper
* aManager
) {
53 MOZ_ASSERT(aCallbacks
);
55 mSessionType
= ToCdmSessionType(aSessionType
);
56 mCallbacks
= aCallbacks
;
57 mSessionManager
= aManager
;
61 WMFClearKeySession::~WMFClearKeySession() { ENTRY_LOG(); }
63 STDMETHODIMP
WMFClearKeySession::GenerateRequest(LPCWSTR aInitDataType
,
64 const BYTE
* aInitData
,
65 DWORD aInitDataSize
) {
66 if (!mSessionManager
) {
69 ENTRY_LOG_ARGS("init-type=%ls", aInitDataType
);
70 cdm::InitDataType initType
;
71 if (wcscmp(aInitDataType
, L
"cenc") == 0) {
72 initType
= cdm::InitDataType::kCenc
;
73 } else if (wcscmp(aInitDataType
, L
"keyids") == 0) {
74 initType
= cdm::InitDataType::kKeyIds
;
75 } else if (wcscmp(aInitDataType
, L
"webm") == 0) {
76 initType
= cdm::InitDataType::kWebM
;
78 return MF_NOT_SUPPORTED_ERR
;
80 RETURN_IF_FAILED(mSessionManager
->GenerateRequest(
81 initType
, aInitData
, aInitDataSize
, mSessionType
, this, mSessionId
));
82 MOZ_ASSERT(!mSessionId
.empty());
83 ENTRY_LOG_ARGS("created session, sid=%s", mSessionId
.c_str());
87 STDMETHODIMP
WMFClearKeySession::Load(LPCWSTR session_id
, BOOL
* loaded
) {
89 // Per step 5, Load can only be called on persistent session, but we only
90 // support temporary session for MF clearkey due to testing reason.
91 // https://rawgit.com/w3c/encrypted-media/V1/index.html#dom-mediakeysession-load
92 return MF_E_NOT_AVAILABLE
;
95 STDMETHODIMP
WMFClearKeySession::Update(const BYTE
* aResponse
,
96 DWORD aResponseSize
) {
98 if (!mSessionManager
) {
102 mSessionManager
->UpdateSession(mSessionId
, aResponse
, aResponseSize
));
106 STDMETHODIMP
WMFClearKeySession::Close() {
108 // It has been shutdowned and sesssion has been closed.
109 if (!mSessionManager
) {
112 RETURN_IF_FAILED(mSessionManager
->CloseSession(mSessionId
));
116 STDMETHODIMP
WMFClearKeySession::Remove() {
118 // It has been shutdowned and sesssion has been removed.
119 if (!mSessionManager
) {
122 RETURN_IF_FAILED(mSessionManager
->RemoveSession(mSessionId
));
126 STDMETHODIMP
WMFClearKeySession::GetSessionId(LPWSTR
* aSessionId
) {
128 if (!mSessionManager
) {
131 if (mSessionId
.empty()) {
132 *aSessionId
= (LPWSTR
)CoTaskMemAlloc(sizeof(wchar_t));
133 if (*aSessionId
!= NULL
) {
134 **aSessionId
= L
'\0';
137 return E_OUTOFMEMORY
;
141 std::wstring_convert
<std::codecvt_utf8
<wchar_t>> converter
;
142 std::wstring wideStr
= converter
.from_bytes(mSessionId
);
144 (LPWSTR
)CoTaskMemAlloc((wideStr
.length() + 1) * sizeof(wchar_t));
145 if (*aSessionId
!= NULL
) {
146 wcscpy_s(*aSessionId
, wideStr
.length() + 1, wideStr
.c_str());
149 return E_OUTOFMEMORY
;
153 STDMETHODIMP
WMFClearKeySession::GetExpiration(double* expiration
) {
155 // This is used for testing, never expires.
156 *expiration
= std::nan("1");
160 STDMETHODIMP
WMFClearKeySession::GetKeyStatuses(MFMediaKeyStatus
** aKeyStatuses
,
161 UINT
* aKeyStatusesCount
) {
163 *aKeyStatuses
= nullptr;
164 *aKeyStatusesCount
= 0;
166 const auto keyStatusCount
= mKeyInfo
.size();
167 if (mSessionId
.empty() || keyStatusCount
== 0) {
168 ENTRY_LOG_ARGS("No session ID or no key info!");
172 MFMediaKeyStatus
* keyStatusArray
= nullptr;
173 keyStatusArray
= static_cast<MFMediaKeyStatus
*>(
174 CoTaskMemAlloc(keyStatusCount
* sizeof(MFMediaKeyStatus
)));
175 if (!keyStatusArray
) {
176 ENTRY_LOG_ARGS("OOM when alloacting keyStatusArray!");
177 return E_OUTOFMEMORY
;
179 ZeroMemory(keyStatusArray
, keyStatusCount
* sizeof(MFMediaKeyStatus
));
180 for (UINT idx
= 0; idx
< keyStatusCount
; idx
++) {
181 keyStatusArray
[idx
].cbKeyId
= mKeyInfo
[idx
].mKeyId
.size();
182 keyStatusArray
[idx
].pbKeyId
=
183 static_cast<BYTE
*>(CoTaskMemAlloc(sizeof(mKeyInfo
[idx
].mKeyId
.size())));
184 if (keyStatusArray
[idx
].pbKeyId
== nullptr) {
185 ENTRY_LOG_ARGS("OOM when alloacting keyStatusArray's pbKeyId!");
186 return E_OUTOFMEMORY
;
189 keyStatusArray
[idx
].eMediaKeyStatus
=
190 ToMFKeyStatus(mKeyInfo
[idx
].mKeyStatus
);
191 memcpy(keyStatusArray
[idx
].pbKeyId
, mKeyInfo
[idx
].mKeyId
.data(),
192 mKeyInfo
[idx
].mKeyId
.size());
195 *aKeyStatuses
= keyStatusArray
;
196 *aKeyStatusesCount
= keyStatusCount
;
197 ENTRY_LOG_ARGS("return key status!");
201 void WMFClearKeySession::OnKeyMessage(
202 MF_MEDIAKEYSESSION_MESSAGETYPE aMessageType
, const BYTE
* aMessage
,
203 DWORD aMessageSize
) {
204 ENTRY_LOG_ARGS("aMessageSize=%lu", aMessageSize
);
205 if (!mSessionManager
) {
208 mCallbacks
->KeyMessage(aMessageType
, aMessage
, aMessageSize
, nullptr);
211 void WMFClearKeySession::OnKeyStatusChanged(
212 const cdm::KeyInformation
* aKeysInfo
, uint32_t aKeysInfoCount
) {
213 ENTRY_LOG_ARGS("aKeysInfoCount=%u", aKeysInfoCount
);
214 if (!mSessionManager
) {
218 for (uint32_t idx
= 0; idx
< aKeysInfoCount
; idx
++) {
219 const cdm::KeyInformation
& key
= aKeysInfo
[idx
];
220 mKeyInfo
.push_back(KeyInformation
{key
.key_id
, key
.key_id_size
, key
.status
});
221 ENTRY_LOG_ARGS("idx=%u, keySize=%u, status=%u", idx
, key
.key_id_size
,
224 mCallbacks
->KeyStatusChanged();
227 void WMFClearKeySession::Shutdown() {
229 mCallbacks
= nullptr;
230 mSessionManager
= nullptr;
233 } // namespace mozilla