Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/dom/media/eme/mediadrm/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 14 kB image not shown  

Quelle  MediaDrmCDMProxy.cpp   Sprache: C

 
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "mozilla/dom/MediaKeySession.h"
#include "mozilla/MediaDrmCDMProxy.h"
#include "MediaDrmCDMCallbackProxy.h"

namespace mozilla {

MediaDrmSessionType ToMediaDrmSessionType(
    dom::MediaKeySessionType aSessionType) {
  switch (aSessionType) {
    case dom::MediaKeySessionType::Temporary:
      return kKeyStreaming;
    case dom::MediaKeySessionType::Persistent_license:
      return kKeyOffline;
    default:
      return kKeyStreaming;
  };
}

MediaDrmCDMProxy::MediaDrmCDMProxy(dom::MediaKeys* aKeys,
                                   const nsAString& aKeySystem,
                                   bool aDistinctiveIdentifierRequired,
                                   bool aPersistentStateRequired)
    : CDMProxy(aKeys, aKeySystem, aDistinctiveIdentifierRequired,
               aPersistentStateRequired),
      mCDM(nullptr),
      mShutdownCalled(false) {
  MOZ_ASSERT(NS_IsMainThread());
  MOZ_COUNT_CTOR(MediaDrmCDMProxy);
}

MediaDrmCDMProxy::~MediaDrmCDMProxy() { MOZ_COUNT_DTOR(MediaDrmCDMProxy); }

void MediaDrmCDMProxy::Init(PromiseId aPromiseId, const nsAString& aOrigin,
                            const nsAString& aTopLevelOrigin,
                            const nsAString& aName) {
  MOZ_ASSERT(NS_IsMainThread());
  NS_ENSURE_TRUE_VOID(!mKeys.IsNull());

  EME_LOG("MediaDrmCDMProxy::Init (%s, %s) %s",
          NS_ConvertUTF16toUTF8(aOrigin).get(),
          NS_ConvertUTF16toUTF8(aTopLevelOrigin).get(),
          NS_ConvertUTF16toUTF8(aName).get());

  // Create a thread to work with cdm.
  if (!mOwnerThread) {
    nsresult rv =
        NS_NewNamedThread("MDCDMThread", getter_AddRefs(mOwnerThread));
    if (NS_FAILED(rv)) {
      RejectPromiseWithStateError(
          aPromiseId, nsLiteralCString(
                          "Couldn't create CDM thread MediaDrmCDMProxy::Init"));
      return;
    }
  }

  mCDM = mozilla::MakeUnique<MediaDrmProxySupport>(mKeySystem);
  nsCOMPtr<nsIRunnable> task(
      NewRunnableMethod<uint32_t>("MediaDrmCDMProxy::md_Init"this,
                                  &MediaDrmCDMProxy::md_Init, aPromiseId));
  mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
}

void MediaDrmCDMProxy::CreateSession(uint32_t aCreateSessionToken,
                                     MediaKeySessionType aSessionType,
                                     PromiseId aPromiseId,
                                     const nsAString& aInitDataType,
                                     nsTArray<uint8_t>& aInitData) {
  MOZ_ASSERT(NS_IsMainThread());
  MOZ_ASSERT(mOwnerThread);

  UniquePtr<CreateSessionData> data(new CreateSessionData());
  data->mSessionType = aSessionType;
  data->mCreateSessionToken = aCreateSessionToken;
  data->mPromiseId = aPromiseId;
  data->mInitDataType = NS_ConvertUTF16toUTF8(aInitDataType);
  data->mInitData = std::move(aInitData);

  nsCOMPtr<nsIRunnable> task(NewRunnableMethod<UniquePtr<CreateSessionData>&&>(
      "MediaDrmCDMProxy::md_CreateSession"this,
      &MediaDrmCDMProxy::md_CreateSession, std::move(data)));
  mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
}

void MediaDrmCDMProxy::LoadSession(PromiseId aPromiseId,
                                   dom::MediaKeySessionType aSessionType,
                                   const nsAString& aSessionId) {
  // TODO: Implement LoadSession.
  RejectPromiseWithStateError(
      aPromiseId, "Currently Fennec does not support LoadSession"_ns);
}

void MediaDrmCDMProxy::SetServerCertificate(PromiseId aPromiseId,
                                            nsTArray<uint8_t>& aCert) {
  MOZ_ASSERT(NS_IsMainThread());
  MOZ_ASSERT(mOwnerThread);

  mOwnerThread->Dispatch(NewRunnableMethod<PromiseId, const nsTArray<uint8_t>>(
                             "MediaDrmCDMProxy::md_SetServerCertificate"this,
                             &MediaDrmCDMProxy::md_SetServerCertificate,
                             aPromiseId, std::move(aCert)),
                         NS_DISPATCH_NORMAL);
}

void MediaDrmCDMProxy::UpdateSession(const nsAString& aSessionId,
                                     PromiseId aPromiseId,
                                     nsTArray<uint8_t>& aResponse) {
  MOZ_ASSERT(NS_IsMainThread());
  MOZ_ASSERT(mOwnerThread);
  NS_ENSURE_TRUE_VOID(!mKeys.IsNull());

  UniquePtr<UpdateSessionData> data(new UpdateSessionData());
  data->mPromiseId = aPromiseId;
  data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId);
  data->mResponse = std::move(aResponse);

  nsCOMPtr<nsIRunnable> task(NewRunnableMethod<UniquePtr<UpdateSessionData>&&>(
      "MediaDrmCDMProxy::md_UpdateSession"this,
      &MediaDrmCDMProxy::md_UpdateSession, std::move(data)));
  mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
}

void MediaDrmCDMProxy::CloseSession(const nsAString& aSessionId,
                                    PromiseId aPromiseId) {
  MOZ_ASSERT(NS_IsMainThread());
  MOZ_ASSERT(mOwnerThread);
  NS_ENSURE_TRUE_VOID(!mKeys.IsNull());

  UniquePtr<SessionOpData> data(new SessionOpData());
  data->mPromiseId = aPromiseId;
  data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId);

  nsCOMPtr<nsIRunnable> task(NewRunnableMethod<UniquePtr<SessionOpData>&&>(
      "MediaDrmCDMProxy::md_CloseSession"this,
      &MediaDrmCDMProxy::md_CloseSession, std::move(data)));
  mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
}

void MediaDrmCDMProxy::RemoveSession(const nsAString& aSessionId,
                                     PromiseId aPromiseId) {
  // TODO: Implement RemoveSession.
  RejectPromiseWithStateError(
      aPromiseId, "Currently Fennec does not support RemoveSession"_ns);
}

void MediaDrmCDMProxy::QueryOutputProtectionStatus() {
  // TODO(bryce): determine if this is needed for Android and implement as
  // needed. See also `NotifyOutputProtectionStatus`.
}

void MediaDrmCDMProxy::NotifyOutputProtectionStatus(
    OutputProtectionCheckStatus aCheckStatus,
    OutputProtectionCaptureStatus aCaptureStatus) {
  // TODO(bryce): determine if this is needed for Android and implement as
  // needed. See also `QueryOutputProtectionStatus`.
}

void MediaDrmCDMProxy::Shutdown() {
  MOZ_ASSERT(NS_IsMainThread());
  MOZ_ASSERT(mOwnerThread);
  nsCOMPtr<nsIRunnable> task(NewRunnableMethod(
      "MediaDrmCDMProxy::md_Shutdown"this, &MediaDrmCDMProxy::md_Shutdown));

  mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
  mOwnerThread->Shutdown();
  mOwnerThread = nullptr;
  mKeys.Clear();
}

void MediaDrmCDMProxy::Terminated() {
  // TODO: Implement Terminated.
  // Should find a way to handle the case when remote side MediaDrm crashed.
}

void MediaDrmCDMProxy::OnSetSessionId(uint32_t aCreateSessionToken,
                                      const nsAString& aSessionId) {
  MOZ_ASSERT(NS_IsMainThread());
  if (mKeys.IsNull()) {
    return;
  }

  RefPtr<dom::MediaKeySession> session(
      mKeys->GetPendingSession(aCreateSessionToken));
  if (session) {
    session->SetSessionId(aSessionId);
  }
}

void MediaDrmCDMProxy::OnResolveLoadSessionPromise(uint32_t aPromiseId,
                                                   bool aSuccess) {
  MOZ_ASSERT(NS_IsMainThread());
  if (mKeys.IsNull()) {
    return;
  }
  mKeys->OnSessionLoaded(aPromiseId, aSuccess);
}

void MediaDrmCDMProxy::OnSessionMessage(const nsAString& aSessionId,
                                        dom::MediaKeyMessageType aMessageType,
                                        const nsTArray<uint8_t>& aMessage) {
  MOZ_ASSERT(NS_IsMainThread());
  if (mKeys.IsNull()) {
    return;
  }
  RefPtr<dom::MediaKeySession> session(mKeys->GetSession(aSessionId));
  if (session) {
    session->DispatchKeyMessage(aMessageType, aMessage);
  }
}

void MediaDrmCDMProxy::OnExpirationChange(const nsAString& aSessionId,
                                          UnixTime aExpiryTime) {
  MOZ_ASSERT(NS_IsMainThread());
  if (mKeys.IsNull()) {
    return;
  }
  RefPtr<dom::MediaKeySession> session(mKeys->GetSession(aSessionId));
  if (session) {
    session->SetExpiration(static_cast<double>(aExpiryTime));
  }
}

void MediaDrmCDMProxy::OnSessionClosed(const nsAString& aSessionId) {
  MOZ_ASSERT(NS_IsMainThread());
  if (mKeys.IsNull()) {
    return;
  }
  RefPtr<dom::MediaKeySession> session(mKeys->GetSession(aSessionId));
  if (session) {
    session->OnClosed();
  }
}

void MediaDrmCDMProxy::OnSessionError(const nsAString& aSessionId,
                                      nsresult aException, uint32_t aSystemCode,
                                      const nsAString& aMsg) {
  MOZ_ASSERT(NS_IsMainThread());
  if (mKeys.IsNull()) {
    return;
  }
  RefPtr<dom::MediaKeySession> session(mKeys->GetSession(aSessionId));
  if (session) {
    session->DispatchKeyError(aSystemCode);
  }
}

void MediaDrmCDMProxy::OnRejectPromise(uint32_t aPromiseId,
                                       ErrorResult&& aException,
                                       const nsCString& aMsg) {
  MOZ_ASSERT(NS_IsMainThread());
  RejectPromise(aPromiseId, std::move(aException), aMsg);
}

RefPtr<DecryptPromise> MediaDrmCDMProxy::Decrypt(MediaRawData* aSample) {
  MOZ_ASSERT_UNREACHABLE("Fennec could not handle decrypting individually");
  return nullptr;
}

void MediaDrmCDMProxy::OnDecrypted(uint32_t aId, DecryptStatus aResult,
                                   const nsTArray<uint8_t>& aDecryptedData) {
  MOZ_ASSERT_UNREACHABLE("Fennec could not handle decrypted event");
}

void MediaDrmCDMProxy::RejectPromise(PromiseId aId, ErrorResult&& aException,
                                     const nsCString& aReason) {
  if (NS_IsMainThread()) {
    if (!mKeys.IsNull()) {
      mKeys->RejectPromise(aId, std::move(aException), aReason);
    }
  } else {
    nsCOMPtr<nsIRunnable> task(
        new RejectPromiseTask(this, aId, std::move(aException), aReason));
    mMainThread->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
  }
}

void MediaDrmCDMProxy::RejectPromiseWithStateError(PromiseId aId,
                                                   const nsCString& aReason) {
  ErrorResult rv;
  rv.ThrowInvalidStateError(aReason);
  RejectPromise(aId, std::move(rv), aReason);
}

void MediaDrmCDMProxy::ResolvePromise(PromiseId aId) {
  if (NS_IsMainThread()) {
    if (!mKeys.IsNull()) {
      mKeys->ResolvePromise(aId);
    } else {
      NS_WARNING("MediaDrmCDMProxy unable to resolve promise!");
    }
  } else {
    nsCOMPtr<nsIRunnable> task;
    task =
        NewRunnableMethod<PromiseId>("MediaDrmCDMProxy::ResolvePromise"this,
                                     &MediaDrmCDMProxy::ResolvePromise, aId);
    mMainThread->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
  }
}

template <typename T>
void MediaDrmCDMProxy::ResolvePromiseWithResult(PromiseId aId,
                                                const T& aResult) {
  if (NS_IsMainThread()) {
    if (!mKeys.IsNull()) {
      mKeys->ResolvePromiseWithResult(aId, aResult);
    } else {
      NS_WARNING("MediaDrmCDMProxy unable to resolve promise!");
    }
    return;
  }

  nsCOMPtr<nsIRunnable> task;
  task = NewRunnableMethod<PromiseId, T>(
      "MediaDrmCDMProxy::ResolvePromiseWithResult"this,
      &MediaDrmCDMProxy::ResolvePromiseWithResult<T>, aId, aResult);
  mMainThread->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
}

void MediaDrmCDMProxy::OnKeyStatusesChange(const nsAString& aSessionId) {
  MOZ_ASSERT(NS_IsMainThread());
  if (mKeys.IsNull()) {
    return;
  }
  RefPtr<dom::MediaKeySession> session(mKeys->GetSession(aSessionId));
  if (session) {
    session->DispatchKeyStatusesChange();
  }
}

void MediaDrmCDMProxy::GetStatusForPolicy(
    PromiseId aPromiseId, const dom::HDCPVersion& aMinHdcpVersion) {
  // TODO: Implement GetStatusForPolicy.
  constexpr auto err =
      "Currently Fennec does not support GetStatusForPolicy"_ns;

  ErrorResult rv;
  rv.ThrowNotSupportedError(err);
  RejectPromise(aPromiseId, std::move(rv), err);
}

#ifdef DEBUG
bool MediaDrmCDMProxy::IsOnOwnerThread() {
  return NS_GetCurrentThread() == mOwnerThread;
}
#endif

const nsString& MediaDrmCDMProxy::GetMediaDrmStubId() const {
  MOZ_ASSERT(mCDM);
  return mCDM->GetMediaDrmStubId();
}

void MediaDrmCDMProxy::OnCDMCreated(uint32_t aPromiseId) {
  MOZ_ASSERT(NS_IsMainThread());
  if (mKeys.IsNull()) {
    return;
  }

  if (mCDM) {
    mKeys->OnCDMCreated(aPromiseId, 0);
    return;
  }

  // No CDM? Just reject the promise.
  constexpr auto err = "Null CDM in OnCDMCreated()"_ns;
  ErrorResult rv;
  rv.ThrowInvalidStateError(err);
  mKeys->RejectPromise(aPromiseId, std::move(rv), err);
}

void MediaDrmCDMProxy::md_Init(uint32_t aPromiseId) {
  MOZ_ASSERT(IsOnOwnerThread());
  MOZ_ASSERT(mCDM);

  UniquePtr<MediaDrmCDMCallbackProxy> callback(
      new MediaDrmCDMCallbackProxy(this));
  mCDM->Init(std::move(callback));
  nsCOMPtr<nsIRunnable> task(
      NewRunnableMethod<uint32_t>("MediaDrmCDMProxy::OnCDMCreated"this,
                                  &MediaDrmCDMProxy::OnCDMCreated, aPromiseId));
  mMainThread->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
}

void MediaDrmCDMProxy::md_CreateSession(UniquePtr<CreateSessionData>&& aData) {
  MOZ_ASSERT(IsOnOwnerThread());

  if (!mCDM) {
    RejectPromiseWithStateError(aData->mPromiseId,
                                "Null CDM in md_CreateSession"_ns);
    return;
  }

  mCDM->CreateSession(aData->mCreateSessionToken, aData->mPromiseId,
                      aData->mInitDataType, aData->mInitData,
                      ToMediaDrmSessionType(aData->mSessionType));
}

void MediaDrmCDMProxy::md_SetServerCertificate(PromiseId aPromiseId,
                                               const nsTArray<uint8_t>& aCert) {
  MOZ_ASSERT(IsOnOwnerThread());

  if (!mCDM) {
    RejectPromiseWithStateError(aPromiseId,
                                "Null CDM in md_SetServerCertificate"_ns);
    return;
  }

  if (mCDM->SetServerCertificate(aCert)) {
    ResolvePromiseWithResult(aPromiseId, true);
  } else {
    RejectPromiseWithStateError(
        aPromiseId, "MediaDrmCDMProxy unable to set server certificate"_ns);
  }
}

void MediaDrmCDMProxy::md_UpdateSession(UniquePtr<UpdateSessionData>&& aData) {
  MOZ_ASSERT(IsOnOwnerThread());

  if (!mCDM) {
    RejectPromiseWithStateError(aData->mPromiseId,
                                "Null CDM in md_UpdateSession"_ns);
    return;
  }
  mCDM->UpdateSession(aData->mPromiseId, aData->mSessionId, aData->mResponse);
}

void MediaDrmCDMProxy::md_CloseSession(UniquePtr<SessionOpData>&& aData) {
  MOZ_ASSERT(IsOnOwnerThread());

  if (!mCDM) {
    RejectPromiseWithStateError(aData->mPromiseId,
                                "Null CDM in md_CloseSession"_ns);
    return;
  }
  mCDM->CloseSession(aData->mPromiseId, aData->mSessionId);
}

void MediaDrmCDMProxy::md_Shutdown() {
  MOZ_ASSERT(IsOnOwnerThread());
  MOZ_ASSERT(mCDM);
  if (mShutdownCalled) {
    return;
  }
  mShutdownCalled = true;
  mCDM->Shutdown();
  mCDM = nullptr;
}

}  // namespace mozilla

Messung V0.5
C=78 H=96 G=87

¤ Dauer der Verarbeitung: 0.5 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.