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/. */
7 #include "mozilla/CDMCaps.h"
8 #include "mozilla/EMEUtils.h"
9 #include "nsThreadUtils.h"
10 #include "SamplesWaitingForKey.h"
14 CDMCaps::CDMCaps() = default;
16 CDMCaps::~CDMCaps() = default;
18 // Keys with MediaKeyStatus::Usable, MediaKeyStatus::Output_downscaled,
19 // or MediaKeyStatus::Output_restricted status can be used by the CDM
20 // to decrypt or decrypt-and-decode samples.
21 static bool IsUsableStatus(dom::MediaKeyStatus aStatus
) {
22 return aStatus
== dom::MediaKeyStatus::Usable
||
23 aStatus
== dom::MediaKeyStatus::Output_restricted
||
24 aStatus
== dom::MediaKeyStatus::Output_downscaled
;
27 bool CDMCaps::IsKeyUsable(const CencKeyId
& aKeyId
) {
28 for (const KeyStatus
& keyStatus
: mKeyStatuses
) {
29 if (keyStatus
.mId
== aKeyId
) {
30 return IsUsableStatus(keyStatus
.mStatus
);
36 bool CDMCaps::SetKeyStatus(const CencKeyId
& aKeyId
, const nsString
& aSessionId
,
37 const dom::Optional
<dom::MediaKeyStatus
>& aStatus
) {
38 if (!aStatus
.WasPassed()) {
39 // Called from ForgetKeyStatus.
40 // Return true if the element is found to notify key changes.
41 return mKeyStatuses
.RemoveElement(
42 KeyStatus(aKeyId
, aSessionId
, dom::MediaKeyStatus::Internal_error
));
45 KeyStatus
key(aKeyId
, aSessionId
, aStatus
.Value());
46 auto index
= mKeyStatuses
.IndexOf(key
);
47 if (index
!= mKeyStatuses
.NoIndex
) {
48 if (mKeyStatuses
[index
].mStatus
== aStatus
.Value()) {
52 auto oldStatus
= mKeyStatuses
[index
].mStatus
;
53 mKeyStatuses
[index
].mStatus
= aStatus
.Value();
54 // The old key status was one for which we can decrypt media. We don't
55 // need to do the "notify usable" step below, as it should be impossible
56 // for us to have anything waiting on this key to become usable, since it
57 // was already usable.
58 if (IsUsableStatus(oldStatus
)) {
62 mKeyStatuses
.AppendElement(key
);
65 // Only call NotifyUsable() for a key when we are going from non-usable
67 if (!IsUsableStatus(aStatus
.Value())) {
71 auto& waiters
= mWaitForKeys
;
73 while (i
< waiters
.Length()) {
75 if (w
.mKeyId
== aKeyId
) {
76 w
.mListener
->NotifyUsable(aKeyId
);
77 waiters
.RemoveElementAt(i
);
85 void CDMCaps::NotifyWhenKeyIdUsable(const CencKeyId
& aKey
,
86 SamplesWaitingForKey
* aListener
) {
87 MOZ_ASSERT(!IsKeyUsable(aKey
));
88 MOZ_ASSERT(aListener
);
89 mWaitForKeys
.AppendElement(WaitForKeys(aKey
, aListener
));
92 void CDMCaps::GetKeyStatusesForSession(const nsAString
& aSessionId
,
93 nsTArray
<KeyStatus
>& aOutKeyStatuses
) {
94 for (const KeyStatus
& keyStatus
: mKeyStatuses
) {
95 if (keyStatus
.mSessionId
.Equals(aSessionId
)) {
96 aOutKeyStatuses
.AppendElement(keyStatus
);
101 bool CDMCaps::RemoveKeysForSession(const nsString
& aSessionId
) {
102 bool changed
= false;
103 nsTArray
<KeyStatus
> statuses
;
104 GetKeyStatusesForSession(aSessionId
, statuses
);
105 for (const KeyStatus
& status
: statuses
) {
106 changed
|= SetKeyStatus(status
.mId
, aSessionId
,
107 dom::Optional
<dom::MediaKeyStatus
>());
112 } // namespace mozilla