tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

CDMCaps.cpp (3667B)


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