Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  RemoteCDMProxy.cpp   Sprache: C

 

/* 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 "RemoteCDMProxy.h"

#include "mozilla/EMEOriginID.h"
#include "mozilla/RemoteDecodeUtils.h"
#include "mozilla/dom/MediaKeySession.h"

#ifdef MOZ_WIDGET_ANDROID
#  include "mozilla/MediaDrmProvisioningHelper.h"
#endif

namespace mozilla {

#define LOGD(msg, ...) \
  MOZ_LOG_FMT(gRemoteDecodeLog, LogLevel::Debug, msg, ##__VA_ARGS__)

RemoteCDMProxy::RemoteCDMProxy(
    nsCOMPtr<nsISerialEventTarget>&& aThread,
    RefPtr<GenericNonExclusivePromise>&& aIPDLPromise, RemoteMediaIn aLocation,
    dom::MediaKeys* aKeys, const nsAString& aKeySystem,
    bool aDistinctiveIdentifierRequired, bool aPersistentStateRequired)
    : CDMProxy(aKeys, aKeySystem, aDistinctiveIdentifierRequired,
               aPersistentStateRequired),
      mChild(MakeRefPtr<RemoteCDMChild>()),
      mThread(std::move(aThread)),
      mIPDLPromise(std::move(aIPDLPromise)),
      mLocation(aLocation) {
  mChild->Initialize(this);
}

RemoteCDMProxy::~RemoteCDMProxy() { Destroy(); }

void RemoteCDMProxy::Destroy() {
  mThread->Dispatch(NS_NewRunnableFunction(
      __func__, [child = mChild]() { child->Destroy(); }));
}

void RemoteCDMProxy::OnProvision(
    const RemoteCDMProvisionRequestIPDL& aRequest,
    PRemoteCDMChild::ProvisionResolver&& aResolver) {
  LOGD("[{}] RemoteCDMProxy::OnProvision", fmt::ptr(this));
#ifdef MOZ_WIDGET_ANDROID
  auto helper =
      MakeRefPtr<MediaDrmProvisioningHelper>(aRequest, std::move(aResolver));
  helper->Provision();
#else
  aResolver(MediaResult(NS_ERROR_DOM_MEDIA_NOT_SUPPORTED_ERR));
#endif
}

void RemoteCDMProxy::OnSessionKeyStatus(const RemoteCDMKeyStatusIPDL& aMsg) {
  LOGD("[{}] RemoteCDMProxy::OnSessionKeyStatus", fmt::ptr(this));
  bool changed = false;
  {
    auto caps = mCapabilites.Lock();
    for (const auto& keyInfo : aMsg.keyInfo()) {
      changed |=
          caps->SetKeyStatus(keyInfo.mKeyId, aMsg.sessionId(), keyInfo.mStatus);
    }
  }

  if (!changed) {
    return;
  }

  NS_DispatchToMainThread(NS_NewRunnableFunction(
      __func__, [self = RefPtr{this}, sessionId = aMsg.sessionId()]() {
        if (self->mKeys.IsNull()) {
          return;
        }
        if (RefPtr<dom::MediaKeySession> session =
                self->mKeys->GetSession(sessionId)) {
          session->DispatchKeyStatusesChange();
        }
      }));
}

void RemoteCDMProxy::OnSessionKeyExpiration(RemoteCDMKeyExpirationIPDL&& aMsg) {
  LOGD("[{}] RemoteCDMProxy::OnSessionKeyExpiration", fmt::ptr(this));
  NS_DispatchToMainThread(NS_NewRunnableFunction(
      __func__, [self = RefPtr{this}, msg = std::move(aMsg)]() {
        if (self->mKeys.IsNull()) {
          return;
        }
        if (RefPtr<dom::MediaKeySession> session =
                self->mKeys->GetSession(msg.sessionId())) {
          session->SetExpiration(msg.expiredTimeMilliSecondsSinceEpoch());
        }
      }));
}

void RemoteCDMProxy::OnSessionKeyMessage(RemoteCDMKeyMessageIPDL&& aMsg) {
  LOGD("[{}] RemoteCDMProxy::OnSessionKeyMessage", fmt::ptr(this));
  NS_DispatchToMainThread(NS_NewRunnableFunction(
      __func__, [self = RefPtr{this}, msg = std::move(aMsg)]() {
        if (self->mKeys.IsNull()) {
          return;
        }
        if (RefPtr<dom::MediaKeySession> session =
                self->mKeys->GetSession(msg.sessionId())) {
          session->DispatchKeyMessage(msg.type(), msg.message());
        }
      }));
}

void RemoteCDMProxy::Init(PromiseId aPromiseId, const nsAString& aOrigin,
                          const nsAString& aTopLevelOrigin,
                          const nsAString& aName) {
  MOZ_ASSERT(NS_IsMainThread());

  if (mKeys.IsNull()) {
    return;
  }

  LOGD("[{}] RemoteCDMProxy::Init -- promise {}", fmt::ptr(this), aPromiseId);
  if (!mIPDLPromise) {
    RejectPromise(aPromiseId,
                  MediaResult(NS_ERROR_DOM_INVALID_STATE_ERR,
                              "PRemoteCDMChild already initialized"_ns));
    return;
  }

  RefPtr<GenericNonExclusivePromise> ipdlPromise = mIPDLPromise;
  mIPDLPromise = nullptr;

  GetEMEOriginID(mKeys->GetPrincipal())
      ->Then(
          GetMainThreadSerialEventTarget(), __func__,
          [self = RefPtr{this}, aPromiseId, ipdlPromise](
              const media::PrincipalKeyPromise::ResolveOrRejectValue& aValue) {
            if (self->mKeys.IsNull()) {
              return;
            }
            nsCString originID;
            if (aValue.IsResolve()) {
              originID = aValue.ResolveValue();
            }
            // On rejection, proceed without origin ID.
            ipdlPromise->Then(
                self->mThread, __func__,
                [self, aPromiseId, originID = std::move(originID)](
                    const GenericNonExclusivePromise::ResolveOrRejectValue&
                        aValue) {
                  LOGD("[{}] RemoteCDMChild::Init -- promise {} resolved {}",
                       fmt::ptr(self.get()), aPromiseId, aValue.IsResolve());

                  if (aValue.IsReject()) {
                    self->RejectPromise(
                        aPromiseId,
                        MediaResult(NS_ERROR_DOM_INVALID_STATE_ERR,
                                    "PRemoteCDMChild ensure process fail"_ns));
                    return;
                  }
                  self->InitInternal(aPromiseId, originID);
                });
          });
}

void RemoteCDMProxy::InitInternal(PromiseId aPromiseId,
                                  const nsCString& aOriginID) {
  LOGD("[{}] RemoteCDMProxy::InitInternal -- promise {}", fmt::ptr(this),
       aPromiseId);
  RefPtr<RemoteMediaManagerChild> manager =
      RemoteMediaManagerChild::GetSingleton(mLocation);
  if (!manager) {
    RejectPromise(aPromiseId,
                  MediaResult(NS_ERROR_DOM_INVALID_STATE_ERR,
                              "PRemoteCDMChild manager is not available"_ns));
    return;
  }

  LOGD("[{}] RemoteCDMProxy::InitInternal -- send constructor", fmt::ptr(this));
  if (!manager->SendPRemoteCDMConstructor(mChild, mKeySystem)) {
    RejectPromise(aPromiseId,
                  MediaResult(NS_ERROR_DOM_INVALID_STATE_ERR,
                              "PRemoteCDMChild manager is unable to send"_ns));
    return;
  }

  LOGD("[{}] RemoteCDMProxy::InitInternal -- send init", fmt::ptr(this));
  mChild
      ->SendInit(RemoteCDMInitRequestIPDL(mDistinctiveIdentifierRequired,
                                          mPersistentStateRequired, aOriginID))
      ->Then(
          GetMainThreadSerialEventTarget(), __func__,
          [self = RefPtr{this},
           aPromiseId](const PRemoteCDMChild::InitPromise::ResolveOrRejectValue&
                           aValue) {
            LOGD("[{}] RemoteCDMProxy::InitInternal -- promise {} resolved {}",
                 fmt::ptr(self.get()), aPromiseId, aValue.IsResolve());

            if (self->mKeys.IsNull()) {
              return;
            }

            if (aValue.IsReject()) {
              self->RejectPromise(
                  aPromiseId,
                  MediaResult(NS_ERROR_DOM_INVALID_STATE_ERR,
                              "PRemoteCDMProxy::SendInit IPC fail"_ns));
              return;
            }

            self->mKeys->OnCDMCreated(aPromiseId, 0);
          });
}

void RemoteCDMProxy::CreateSession(uint32_t aCreateSessionToken,
                                   dom::MediaKeySessionType aSessionType,
                                   PromiseId aPromiseId,
                                   const nsAString& aInitDataType,
                                   nsTArray<uint8_t>& aInitData) {
  MOZ_ALWAYS_SUCCEEDS(mThread->Dispatch(NS_NewRunnableFunction(
      __func__, [self = RefPtr{this}, aCreateSessionToken, aSessionType,
                 aPromiseId, initDataType = nsString(aInitDataType),
                 initData = std::move(aInitData)]() mutable {
        LOGD("[{}] RemoteCDMProxy::CreateSession -- promise {}",
             fmt::ptr(self.get()), aPromiseId);
        self->mChild
            ->SendCreateSession(RemoteCDMCreateSessionRequestIPDL(
                aSessionType, std::move(initDataType), std::move(initData)))
            ->Then(
                GetMainThreadSerialEventTarget(), __func__,
                [self, aCreateSessionToken,
                 aPromiseId](const PRemoteCDMChild::CreateSessionPromise::
                                 ResolveOrRejectValue& aValue) {
                  if (self->mKeys.IsNull()) {
                    return;
                  }

                  if (aValue.IsReject()) {
                    self->RejectPromise(
                        aPromiseId,
                        MediaResult(
                            NS_ERROR_DOM_INVALID_STATE_ERR,
                            "PRemoteCDMProxy::SendCreateSession IPC fail"_ns));
                    return;
                  }

                  const auto& response = aValue.ResolveValue();
                  if (response.type() ==
                      RemoteCDMSessionResponseIPDL::TMediaResult) {
                    self->RejectPromise(aPromiseId, response.get_MediaResult());
                    return;
                  }

                  const auto& msg = response.get_RemoteCDMKeyMessageIPDL();
                  const auto& sessionId = msg.sessionId();
                  if (RefPtr<dom::MediaKeySession> session =
                          self->mKeys->GetPendingSession(aCreateSessionToken)) {
                    session->SetSessionId(sessionId);
                    session->DispatchKeyMessage(msg.type(), msg.message());
                  }

                  self->ResolvePromise(aPromiseId);
                });
      })));
}

void RemoteCDMProxy::LoadSession(PromiseId aPromiseId,
                                 dom::MediaKeySessionType aSessionType,
                                 const nsAString& aSessionId) {
  MOZ_ALWAYS_SUCCEEDS(mThread->Dispatch(NS_NewRunnableFunction(
      __func__, [self = RefPtr{this}, aPromiseId, aSessionType,
                 sessionId = nsString(aSessionId)]() mutable {
        LOGD("[{}] RemoteCDMProxy::LoadSession -- promise {}",
             fmt::ptr(self.get()), aPromiseId);
        self->mChild
            ->SendLoadSession(RemoteCDMLoadSessionRequestIPDL(
                aSessionType, std::move(sessionId)))
            ->Then(
                GetMainThreadSerialEventTarget(), __func__,
                [self, aPromiseId](const PRemoteCDMChild::LoadSessionPromise::
                                       ResolveOrRejectValue& aValue) {
                  if (self->mKeys.IsNull()) {
                    return;
                  }

                  self->mKeys->OnSessionLoaded(
                      aPromiseId, aValue.IsResolve() &&
                                      NS_SUCCEEDED(aValue.ResolveValue()));
                });
      })));
}

void RemoteCDMProxy::SetServerCertificate(PromiseId aPromiseId,
                                          nsTArray<uint8_t>& aCert) {
  MOZ_ALWAYS_SUCCEEDS(mThread->Dispatch(NS_NewRunnableFunction(
      __func__,
      [self = RefPtr{this}, aPromiseId, cert = std::move(aCert)]() mutable {
        LOGD("[{}] RemoteCDMProxy::SetServerCertificate -- promise {}",
             fmt::ptr(self.get()), aPromiseId);
        self->mChild->SendSetServerCertificate(std::move(cert))
            ->Then(
                GetMainThreadSerialEventTarget(), __func__,
                [self, aPromiseId](
                    const PRemoteCDMChild::SetServerCertificatePromise::
                        ResolveOrRejectValue& aValue) {
                  if (self->mKeys.IsNull()) {
                    return;
                  }

                  if (aValue.IsReject()) {
                    self->RejectPromise(
                        aPromiseId,
                        MediaResult(
                            NS_ERROR_DOM_INVALID_STATE_ERR,
                            "PRemoteCDMProxy::SendSetServerCertificate IPC fail"_ns));
                    return;
                  }

                  self->ResolveOrRejectPromise(aPromiseId,
                                               aValue.ResolveValue());
                });
      })));
}

void RemoteCDMProxy::UpdateSession(const nsAString& aSessionId,
                                   PromiseId aPromiseId,
                                   nsTArray<uint8_t>& aResponse) {
  MOZ_ALWAYS_SUCCEEDS(mThread->Dispatch(NS_NewRunnableFunction(
      __func__, [self = RefPtr{this}, sessionId = nsString(aSessionId),
                 aPromiseId, response = std::move(aResponse)]() mutable {
        LOGD("[{}] RemoteCDMProxy::UpdateSession -- promise {}",
             fmt::ptr(self.get()), aPromiseId);
        self->mChild
            ->SendUpdateSession(RemoteCDMUpdateSessionRequestIPDL(
                std::move(sessionId), std::move(response)))
            ->Then(
                GetMainThreadSerialEventTarget(), __func__,
                [self, aPromiseId](const PRemoteCDMChild::UpdateSessionPromise::
                                       ResolveOrRejectValue& aValue) {
                  if (self->mKeys.IsNull()) {
                    return;
                  }

                  if (aValue.IsReject()) {
                    self->RejectPromise(
                        aPromiseId,
                        MediaResult(
                            NS_ERROR_DOM_INVALID_STATE_ERR,
                            "PRemoteCDMProxy::SendUpdateSession IPC fail"_ns));
                    return;
                  }

                  self->ResolveOrRejectPromise(aPromiseId,
                                               aValue.ResolveValue());
                });
      })));
}

void RemoteCDMProxy::CloseSession(const nsAString& aSessionId,
                                  PromiseId aPromiseId) {
  MOZ_ALWAYS_SUCCEEDS(mThread->Dispatch(NS_NewRunnableFunction(
      __func__, [self = RefPtr{this}, sessionId = nsString(aSessionId),
                 aPromiseId]() mutable {
        LOGD("[{}] RemoteCDMProxy::CloseSession -- promise {}",
             fmt::ptr(self.get()), aPromiseId);
        self->mChild->SendCloseSession(std::move(sessionId))
            ->Then(
                GetMainThreadSerialEventTarget(), __func__,
                [self, aPromiseId](const PRemoteCDMChild::CloseSessionPromise::
                                       ResolveOrRejectValue& aValue) {
                  if (self->mKeys.IsNull()) {
                    return;
                  }

                  if (aValue.IsReject()) {
                    self->RejectPromise(
                        aPromiseId,
                        MediaResult(
                            NS_ERROR_DOM_INVALID_STATE_ERR,
                            "PRemoteCDMProxy::SendCloseSession IPC fail"_ns));
                    return;
                  }

                  self->ResolveOrRejectPromise(aPromiseId,
                                               aValue.ResolveValue());
                });
      })));
}

void RemoteCDMProxy::RemoveSession(const nsAString& aSessionId,
                                   PromiseId aPromiseId) {
  MOZ_ALWAYS_SUCCEEDS(mThread->Dispatch(NS_NewRunnableFunction(
      __func__, [self = RefPtr{this}, sessionId = nsString(aSessionId),
                 aPromiseId]() mutable {
        LOGD("[{}] RemoteCDMProxy::RemoveSession -- promise {}",
             fmt::ptr(self.get()), aPromiseId);
        self->mChild->SendRemoveSession(std::move(sessionId))
            ->Then(
                GetMainThreadSerialEventTarget(), __func__,
                [self, aPromiseId](const PRemoteCDMChild::RemoveSessionPromise::
                                       ResolveOrRejectValue& aValue) {
                  if (self->mKeys.IsNull()) {
                    return;
                  }

                  if (aValue.IsReject()) {
                    self->RejectPromise(
                        aPromiseId,
                        MediaResult(
                            NS_ERROR_DOM_INVALID_STATE_ERR,
                            "PRemoteCDMProxy::SendRemoveSession IPC fail"_ns));
                    return;
                  }

                  self->ResolveOrRejectPromise(aPromiseId,
                                               aValue.ResolveValue());
                });
      })));
}

void RemoteCDMProxy::QueryOutputProtectionStatus() {}

void RemoteCDMProxy::NotifyOutputProtectionStatus(
    OutputProtectionCheckStatus aCheckStatus,
    OutputProtectionCaptureStatus aCaptureStatus) {}

void RemoteCDMProxy::Shutdown() {
  LOGD("[{}] RemoteCDMProxy::Shutdown", fmt::ptr(this));
  mKeys.Clear();
  Destroy();
}

void RemoteCDMProxy::Terminated() {
  MOZ_ASSERT_UNREACHABLE("Unexpected to be called!");
}

void RemoteCDMProxy::OnSetSessionId(uint32_t aCreateSessionToken,
                                    const nsAString& aSessionId) {
  MOZ_ASSERT_UNREACHABLE("Unexpected to be called!");
}

void RemoteCDMProxy::OnResolveLoadSessionPromise(uint32_t aPromiseId,
                                                 bool aSuccess) {
  MOZ_ASSERT_UNREACHABLE("Unexpected to be called!");
}

void RemoteCDMProxy::OnSessionMessage(const nsAString& aSessionId,
                                      dom::MediaKeyMessageType aMessageType,
                                      const nsTArray<uint8_t>& aMessage) {
  MOZ_ASSERT_UNREACHABLE("Unexpected to be called!");
}

void RemoteCDMProxy::OnExpirationChange(const nsAString& aSessionId,
                                        UnixTime aExpiryTime) {
  MOZ_ASSERT_UNREACHABLE("Unexpected to be called!");
}

void RemoteCDMProxy::OnSessionClosed(const nsAString& aSessionId,
                                     dom::MediaKeySessionClosedReason aReason) {
  MOZ_ASSERT_UNREACHABLE("Unexpected to be called!");
}

void RemoteCDMProxy::OnSessionError(const nsAString& aSessionId,
                                    nsresult aException, uint32_t aSystemCode,
                                    const nsAString& aMsg) {
  MOZ_ASSERT_UNREACHABLE("Unexpected to be called!");
}

void RemoteCDMProxy::OnRejectPromise(uint32_t aPromiseId,
                                     ErrorResult&& aException,
                                     const nsCString& aMsg) {
  MOZ_ASSERT_UNREACHABLE("Unexpected to be called!");
}

RefPtr<DecryptPromise> RemoteCDMProxy::Decrypt(MediaRawData* aSample) {
  MOZ_ASSERT_UNREACHABLE("Unexpected to be called!");
  return nullptr;
}

void RemoteCDMProxy::OnDecrypted(uint32_t aId, DecryptStatus aResult,
                                 const nsTArray<uint8_t>& aDecryptedData) {
  MOZ_ASSERT_UNREACHABLE("Unexpected to be called!");
}

void RemoteCDMProxy::RejectPromise(PromiseId aId, ErrorResult&& aException,
                                   const nsCString& aReason) {
  LOGD("[{}] RemoteCDMProxy::RejectPromise -- {}", fmt::ptr(this), aId);
  MOZ_ASSERT(NS_IsMainThread());
  MOZ_ASSERT(!mKeys.IsNull());
  mKeys->RejectPromise(aId, std::move(aException), aReason);
}

void RemoteCDMProxy::ResolvePromise(PromiseId aId) {
  LOGD("[{}] RemoteCDMProxy::ResolvePromise -- {}", fmt::ptr(this), aId);
  MOZ_ASSERT(NS_IsMainThread());
  MOZ_ASSERT(!mKeys.IsNull());
  mKeys->ResolvePromise(aId);
}

void RemoteCDMProxy::RejectPromise(PromiseId aId, const MediaResult& aResult) {
  MOZ_ASSERT(NS_FAILED(aResult.Code()));

  ErrorResult rv;
  aResult.ThrowTo(rv);
  RejectPromise(aId, std::move(rv), aResult.Message());
}

void RemoteCDMProxy::ResolveOrRejectPromise(PromiseId aId,
                                            const MediaResult& aResult) {
  if (aResult.Code() == NS_OK) {
    ResolvePromise(aId);
    return;
  }

  RejectPromise(aId, aResult);
}

void RemoteCDMProxy::OnKeyStatusesChange(const nsAString& aSessionId) {}

void RemoteCDMProxy::GetStatusForPolicy(
    PromiseId aPromiseId, const dom::HDCPVersion& aMinHdcpVersion) {
  RejectPromise(
      aPromiseId,
      MediaResult(NS_ERROR_DOM_MEDIA_NOT_SUPPORTED_ERR,
                  "Currently Fennec does not support GetStatusForPolicy"));
}

#ifdef DEBUG
bool RemoteCDMProxy::IsOnOwnerThread() { return mThread->IsOnCurrentThread(); }
#endif

#undef LOGD

}  // namespace mozilla

Messung V0.5 in Prozent
C=98 H=99 G=98

¤ Dauer der Verarbeitung: 0.13 Sekunden  (vorverarbeitet am  2026-09-28) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

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.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=1126864
#Domains=1897691