// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/fuchsia/cdm/fuchsia_cdm.h"

#include "base/fuchsia/fuchsia_logging.h"
#include "base/fuchsia/mem_buffer_util.h"
#include "base/logging.h"
#include "media/base/callback_registry.h"
#include "media/base/cdm_promise.h"
#include "third_party/abseil-cpp/absl/types/optional.h"

#define REJECT_PROMISE_AND_RETURN_IF_BAD_CDM(promise, cdm)         \
  if (!cdm) {                                                      \
    promise->reject(CdmPromise::Exception::INVALID_STATE_ERROR, 0, \
                    "CDM channel is disconnected.");               \
    return;                                                        \
  }

namespace media {

namespace {

std::string GetInitDataTypeName(EmeInitDataType type) {
  switch (type) {
    case EmeInitDataType::WEBM:
      return "webm";
    case EmeInitDataType::CENC:
      return "cenc";
    case EmeInitDataType::KEYIDS:
      return "keyids";
    case EmeInitDataType::UNKNOWN:
      return "unknown";
  }
}

fuchsia::media::drm::LicenseInitData CreateLicenseInitData(
    EmeInitDataType type,
    const std::vector<uint8_t>& data) {
  fuchsia::media::drm::LicenseInitData init_data;
  init_data.type = GetInitDataTypeName(type);
  init_data.data = data;
  return init_data;
}

fuchsia::media::drm::LicenseServerMessage CreateLicenseServerMessage(
    const std::vector<uint8_t>& response) {
  fuchsia::media::drm::LicenseServerMessage message;
  message.message = base::MemBufferFromString(
      base::StringPiece(reinterpret_cast<const char*>(response.data()),
                        response.size()),
      "cr-drm-license-server-message");
  return message;
}

fuchsia::media::drm::LicenseSessionType ToFuchsiaLicenseSessionType(
    CdmSessionType session_type) {
  switch (session_type) {
    case CdmSessionType::kTemporary:
      return fuchsia::media::drm::LicenseSessionType::TEMPORARY;
    case CdmSessionType::kPersistentLicense:
      return fuchsia::media::drm::LicenseSessionType::PERSISTENT_LICENSE;
  }
}

CdmMessageType ToCdmMessageType(fuchsia::media::drm::LicenseMessageType type) {
  switch (type) {
    case fuchsia::media::drm::LicenseMessageType::REQUEST:
      return CdmMessageType::LICENSE_REQUEST;
    case fuchsia::media::drm::LicenseMessageType::RENEWAL:
      return CdmMessageType::LICENSE_RENEWAL;
    case fuchsia::media::drm::LicenseMessageType::RELEASE:
      return CdmMessageType::LICENSE_RELEASE;
  }
}

CdmKeyInformation::KeyStatus ToCdmKeyStatus(
    fuchsia::media::drm::KeyStatus status) {
  switch (status) {
    case fuchsia::media::drm::KeyStatus::USABLE:
      return CdmKeyInformation::USABLE;
    case fuchsia::media::drm::KeyStatus::EXPIRED:
      return CdmKeyInformation::EXPIRED;
    case fuchsia::media::drm::KeyStatus::RELEASED:
      return CdmKeyInformation::RELEASED;
    case fuchsia::media::drm::KeyStatus::OUTPUT_RESTRICTED:
      return CdmKeyInformation::OUTPUT_RESTRICTED;
    case fuchsia::media::drm::KeyStatus::OUTPUT_DOWNSCALED:
      return CdmKeyInformation::OUTPUT_DOWNSCALED;
    case fuchsia::media::drm::KeyStatus::STATUS_PENDING:
      return CdmKeyInformation::KEY_STATUS_PENDING;
    case fuchsia::media::drm::KeyStatus::INTERNAL_ERROR:
      return CdmKeyInformation::INTERNAL_ERROR;
  }
}

CdmPromise::Exception ToCdmPromiseException(fuchsia::media::drm::Error error) {
  switch (error) {
    case fuchsia::media::drm::Error::TYPE:
      return CdmPromise::Exception::TYPE_ERROR;
    case fuchsia::media::drm::Error::NOT_SUPPORTED:
      return CdmPromise::Exception::NOT_SUPPORTED_ERROR;
    case fuchsia::media::drm::Error::INVALID_STATE:
      return CdmPromise::Exception::INVALID_STATE_ERROR;
    case fuchsia::media::drm::Error::QUOTA_EXCEEDED:
      return CdmPromise::Exception::QUOTA_EXCEEDED_ERROR;

    case fuchsia::media::drm::Error::NOT_PROVISIONED:
      // FuchsiaCdmManager is supposed to provision CDM.
      NOTREACHED();
      return CdmPromise::Exception::INVALID_STATE_ERROR;

    case fuchsia::media::drm::Error::INTERNAL:
      DLOG(ERROR) << "CDM failed due to an internal error.";
      return CdmPromise::Exception::INVALID_STATE_ERROR;
  }
}

}  // namespace

class FuchsiaCdm::CdmSession {
 public:
  using ResultCB =
      base::OnceCallback<void(absl::optional<CdmPromise::Exception>)>;
  using SessionReadyCB = base::OnceCallback<void(bool success)>;

  CdmSession(const FuchsiaCdm::SessionCallbacks* callbacks,
             base::RepeatingClosure on_new_key)
      : session_callbacks_(callbacks), on_new_key_(on_new_key) {
    // License session events, e.g. license request message, key status change.
    // Fuchsia CDM service guarantees callback of functions (e.g.
    // GenerateLicenseRequest) are called before event callbacks. So it's safe
    // to rely on this to resolve the EME promises and send session events to
    // JS. EME requires promises are resolved before session message.
    session_.events().OnLicenseMessageGenerated =
        fit::bind_member(this, &CdmSession::OnLicenseMessageGenerated);
    session_.events().OnKeyStatesChanged =
        fit::bind_member(this, &CdmSession::OnKeyStatesChanged);

    session_.set_error_handler(
        fit::bind_member(this, &CdmSession::OnSessionError));
  }

  CdmSession(const CdmSession&) = delete;
  CdmSession& operator=(const CdmSession&) = delete;

  ~CdmSession() {
    if (!session_id_.empty()) {
      session_callbacks_->closed_cb.Run(session_id_,
                                        CdmSessionClosedReason::kInternalError);
    }
  }

  fidl::InterfaceRequest<fuchsia::media::drm::LicenseSession> NewRequest() {
    return session_.NewRequest();
  }

  void GenerateLicenseRequest(EmeInitDataType init_data_type,
                              const std::vector<uint8_t>& init_data,
                              ResultCB generate_license_request_cb) {
    DCHECK(!result_cb_);
    result_cb_ = std::move(generate_license_request_cb);
    session_->GenerateLicenseRequest(
        CreateLicenseInitData(init_data_type, init_data),
        [this](fuchsia::media::drm::LicenseSession_GenerateLicenseRequest_Result
                   result) { ProcessResult(result); });
  }

  void GenerateLicenseRelease(ResultCB generate_license_release_cb) {
    DCHECK(!result_cb_);
    result_cb_ = std::move(generate_license_release_cb);
    pending_release_ = true;
    session_->GenerateLicenseRelease(
        [this](fuchsia::media::drm::LicenseSession_GenerateLicenseRelease_Result
                   result) { ProcessResult(result); });
  }

  void ProcessLicenseResponse(const std::vector<uint8_t>& response,
                              ResultCB process_license_response_cb) {
    DCHECK(!result_cb_);
    result_cb_ = std::move(process_license_response_cb);
    session_->ProcessLicenseResponse(
        CreateLicenseServerMessage(response),
        [this](fuchsia::media::drm::LicenseSession_ProcessLicenseResponse_Result
                   result) { ProcessResult(result); });
  }

  void set_session_id(const std::string& session_id) {
    session_id_ = session_id;
  }
  const std::string& session_id() const { return session_id_; }

  void set_session_ready_cb(SessionReadyCB session_ready_cb) {
    session_ready_cb_ = std::move(session_ready_cb);
    session_.events().OnReady =
        fit::bind_member(this, &CdmSession::OnSessionReady);
  }

  bool pending_release() const { return pending_release_; }

 private:
  void OnSessionReady() {
    DCHECK(session_ready_cb_);
    std::move(session_ready_cb_).Run(true);
  }

  void OnLicenseMessageGenerated(fuchsia::media::drm::LicenseMessage message) {
    DCHECK(!session_id_.empty());
    absl::optional<std::string> session_msg =
        base::StringFromMemBuffer(message.message);

    if (!session_msg) {
      LOG(ERROR) << "Failed to generate message for session " << session_id_;
      return;
    }

    session_callbacks_->message_cb.Run(
        session_id_, ToCdmMessageType(message.type),
        std::vector<uint8_t>(session_msg->begin(), session_msg->end()));
  }

  void OnKeyStatesChanged(
      std::vector<fuchsia::media::drm::KeyState> key_states) {
    bool has_additional_usable_key = false;
    CdmKeysInfo keys_info;
    for (const auto& key_state : key_states) {
      if (!key_state.has_key_id() || !key_state.has_status()) {
        continue;
      }
      CdmKeyInformation::KeyStatus status = ToCdmKeyStatus(key_state.status());
      has_additional_usable_key |= (status == CdmKeyInformation::USABLE);
      keys_info.emplace_back(
          new CdmKeyInformation(key_state.key_id(), status, 0));
    }

    session_callbacks_->keys_change_cb.Run(
        session_id_, has_additional_usable_key, std::move(keys_info));

    if (has_additional_usable_key)
      on_new_key_.Run();
  }

  void OnSessionError(zx_status_t status) {
    ZX_LOG(ERROR, status) << "Session error.";

    if (session_ready_cb_)
      std::move(session_ready_cb_).Run(false);

    if (result_cb_)
      std::move(result_cb_).Run(CdmPromise::Exception::TYPE_ERROR);
  }

  template <typename T>
  void ProcessResult(const T& result) {
    DCHECK(result_cb_);
    std::move(result_cb_)
        .Run(result.is_err()
                 ? absl::make_optional(ToCdmPromiseException(result.err()))
                 : absl::nullopt);
  }

  const SessionCallbacks* const session_callbacks_;
  base::RepeatingClosure on_new_key_;

  fuchsia::media::drm::LicenseSessionPtr session_;
  std::string session_id_;

  // Callback for OnReady.
  SessionReadyCB session_ready_cb_;

  // Callback for license operation.
  ResultCB result_cb_;

  // `GenerateLicenseRelease` has been called and the session is waiting for
  // license release response from server.
  bool pending_release_ = false;
};

FuchsiaCdm::SessionCallbacks::SessionCallbacks() = default;
FuchsiaCdm::SessionCallbacks::SessionCallbacks(SessionCallbacks&&) = default;
FuchsiaCdm::SessionCallbacks::~SessionCallbacks() = default;
FuchsiaCdm::SessionCallbacks& FuchsiaCdm::SessionCallbacks::operator=(
    SessionCallbacks&&) = default;

FuchsiaCdm::FuchsiaCdm(fuchsia::media::drm::ContentDecryptionModulePtr cdm,
                       ReadyCB ready_cb,
                       SessionCallbacks callbacks)
    : cdm_(std::move(cdm)),
      ready_cb_(std::move(ready_cb)),
      session_callbacks_(std::move(callbacks)),
      decryptor_(this) {
  DCHECK(cdm_);
  cdm_.events().OnProvisioned =
      fit::bind_member(this, &FuchsiaCdm::OnProvisioned);
  cdm_.set_error_handler([this](zx_status_t status) {
    ZX_LOG(ERROR, status) << "The fuchsia.media.drm.ContentDecryptionModule"
                          << " channel was terminated.";

    // Reject all the pending promises.
    promises_.Clear(CdmPromiseAdapter::ClearReason::kConnectionError);

    // If the channel closed prior to invoking the ready_cb_, we should invoke
    // it here with failure.
    if (ready_cb_) {
      std::move(ready_cb_).Run(
          false, "ContentDecryptionModule closed prior to being ready");
    }
  });
}

FuchsiaCdm::~FuchsiaCdm() = default;

std::unique_ptr<SysmemBufferStream> FuchsiaCdm::CreateStreamDecryptor(
    bool secure_mode) {
  fuchsia::media::drm::DecryptorParams params;
  params.set_require_secure_mode(secure_mode);
  params.mutable_input_details()->set_format_details_version_ordinal(0);

  fuchsia::media::StreamProcessorPtr stream_processor;
  cdm_->CreateDecryptor(std::move(params), stream_processor.NewRequest());

  auto decryptor =
      std::make_unique<FuchsiaStreamDecryptor>(std::move(stream_processor));

  // Save callback to use to notify the decryptor about a new key.
  auto new_key_cb = decryptor->GetOnNewKeyClosure();
  {
    base::AutoLock auto_lock(new_key_callbacks_lock_);
    new_key_callbacks_.push_back(std::move(new_key_cb));
  }

  return decryptor;
}

void FuchsiaCdm::SetServerCertificate(
    const std::vector<uint8_t>& certificate,
    std::unique_ptr<SimpleCdmPromise> promise) {
  REJECT_PROMISE_AND_RETURN_IF_BAD_CDM(promise, cdm_);

  uint32_t promise_id = promises_.SavePromise(std::move(promise));
  cdm_->SetServerCertificate(
      certificate,
      [this, promise_id](
          fuchsia::media::drm::
              ContentDecryptionModule_SetServerCertificate_Result result) {
        if (result.is_err()) {
          promises_.RejectPromise(promise_id,
                                  ToCdmPromiseException(result.err()), 0,
                                  "Fail to set server cert.");
          return;
        }

        promises_.ResolvePromise(promise_id);
      });
}

void FuchsiaCdm::CreateSessionAndGenerateRequest(
    CdmSessionType session_type,
    EmeInitDataType init_data_type,
    const std::vector<uint8_t>& init_data,
    std::unique_ptr<NewSessionCdmPromise> promise) {
  if (init_data_type == EmeInitDataType::UNKNOWN) {
    promise->reject(CdmPromise::Exception::NOT_SUPPORTED_ERROR, 0,
                    "init data type is not supported.");
    return;
  }

  REJECT_PROMISE_AND_RETURN_IF_BAD_CDM(promise, cdm_);

  uint32_t promise_id = promises_.SavePromise(std::move(promise));

  auto session = std::make_unique<CdmSession>(
      &session_callbacks_,
      base::BindRepeating(&FuchsiaCdm::OnNewKey, base::Unretained(this)));
  CdmSession* session_ptr = session.get();

  cdm_->CreateLicenseSession(
      ToFuchsiaLicenseSessionType(session_type), session_ptr->NewRequest(),
      [this, promise_id,
       session = std::move(session)](std::string session_id) mutable {
        OnCreateSession(std::move(session), promise_id, session_id);
      });

  // It's safe to pass raw pointer |session_ptr| because |session| owns the
  // callback so it's guaranteed to outlive the callback.
  session_ptr->GenerateLicenseRequest(
      init_data_type, init_data,
      base::BindOnce(&FuchsiaCdm::OnGenerateLicenseRequestStatus,
                     base::Unretained(this), session_ptr, promise_id));
}

void FuchsiaCdm::OnProvisioned() {
  if (ready_cb_) {
    std::move(ready_cb_).Run(true, "");
  }
}

void FuchsiaCdm::OnCreateSession(std::unique_ptr<CdmSession> session,
                                 uint32_t promise_id,
                                 const std::string& session_id) {
  if (session_id.empty()) {
    promises_.RejectPromise(promise_id,
                            CdmPromise::Exception::NOT_SUPPORTED_ERROR, 0,
                            "fail to create license session.");
    return;
  }

  session->set_session_id(session_id);
  DCHECK(session_map_.find(session_id) == session_map_.end())
      << "Duplicated session id " << session_id;
  session_map_[session_id] = std::move(session);
}

void FuchsiaCdm::OnGenerateLicenseRequestStatus(
    CdmSession* session,
    uint32_t promise_id,
    absl::optional<CdmPromise::Exception> exception) {
  DCHECK(session);
  std::string session_id = session->session_id();

  if (exception.has_value()) {
    promises_.RejectPromise(promise_id, exception.value(), 0,
                            "fail to generate license.");
    session_map_.erase(session_id);
    return;
  }

  DCHECK(!session_id.empty());
  promises_.ResolvePromise(promise_id, session_id);
}

void FuchsiaCdm::LoadSession(CdmSessionType session_type,
                             const std::string& session_id,
                             std::unique_ptr<NewSessionCdmPromise> promise) {
  DCHECK_NE(session_type, CdmSessionType::kTemporary);
  DCHECK(!session_id.empty());
  REJECT_PROMISE_AND_RETURN_IF_BAD_CDM(promise, cdm_);

  if (session_map_.contains(session_id)) {
    promise->reject(CdmPromise::Exception::QUOTA_EXCEEDED_ERROR, 0,
                    "session already exists.");
    return;
  }

  uint32_t promise_id = promises_.SavePromise(std::move(promise));

  auto session = std::make_unique<CdmSession>(
      &session_callbacks_,
      base::BindRepeating(&FuchsiaCdm::OnNewKey, base::Unretained(this)));
  CdmSession* session_ptr = session.get();

  session_ptr->set_session_id(session_id);
  session_ptr->set_session_ready_cb(
      base::BindOnce(&FuchsiaCdm::OnSessionLoaded, base::Unretained(this),
                     std::move(session), promise_id));

  cdm_->LoadLicenseSession(session_id, session_ptr->NewRequest());
}

void FuchsiaCdm::OnSessionLoaded(std::unique_ptr<CdmSession> session,
                                 uint32_t promise_id,
                                 bool loaded) {
  if (!loaded) {
    promises_.ResolvePromise(promise_id, std::string());
    return;
  }

  std::string session_id = session->session_id();
  DCHECK(session_map_.find(session_id) == session_map_.end())
      << "Duplicated session id " << session_id;

  session_map_.emplace(session_id, std::move(session));

  promises_.ResolvePromise(promise_id, session_id);
}

void FuchsiaCdm::UpdateSession(const std::string& session_id,
                               const std::vector<uint8_t>& response,
                               std::unique_ptr<SimpleCdmPromise> promise) {
  auto it = session_map_.find(session_id);
  if (it == session_map_.end()) {
    promise->reject(CdmPromise::Exception::INVALID_STATE_ERROR, 0,
                    "session doesn't exist.");
    return;
  }

  REJECT_PROMISE_AND_RETURN_IF_BAD_CDM(promise, cdm_);

  // Caller should NOT pass in an empty response.
  DCHECK(!response.empty());

  uint32_t promise_id = promises_.SavePromise(std::move(promise));

  CdmSession* session = it->second.get();
  DCHECK(session);

  session->ProcessLicenseResponse(
      response, base::BindOnce(&FuchsiaCdm::OnProcessLicenseServerMessageStatus,
                               base::Unretained(this), session_id, promise_id));
}

void FuchsiaCdm::OnProcessLicenseServerMessageStatus(
    const std::string& session_id,
    uint32_t promise_id,
    absl::optional<CdmPromise::Exception> exception) {
  if (exception.has_value()) {
    promises_.RejectPromise(promise_id, exception.value(), 0,
                            "fail to process license.");
    return;
  }

  promises_.ResolvePromise(promise_id);

  auto it = session_map_.find(session_id);
  if (it == session_map_.end())
    return;

  // Close the session if the session is waiting for license release ack.
  CdmSession* session = it->second.get();
  DCHECK(session);

  if (!session->pending_release())
    return;

  session_map_.erase(it);
}

void FuchsiaCdm::CloseSession(const std::string& session_id,
                              std::unique_ptr<SimpleCdmPromise> promise) {
  // There's a small window app can call close twice before receiving the closed
  // event, in which case we want to resolve the promise. Read
  // AesDecryptor::CloseSession for more details.
  //
  // Resolve the promise before deleting CdmSession. CdmSession will call
  // SessionClosedCB in its destructor.
  promise->resolve();
  session_map_.erase(session_id);
}

void FuchsiaCdm::RemoveSession(const std::string& session_id,
                               std::unique_ptr<SimpleCdmPromise> promise) {
  auto it = session_map_.find(session_id);
  if (it == session_map_.end()) {
    promise->reject(CdmPromise::Exception::INVALID_STATE_ERROR, 0,
                    "session doesn't exist.");
    return;
  }

  REJECT_PROMISE_AND_RETURN_IF_BAD_CDM(promise, cdm_);

  uint32_t promise_id = promises_.SavePromise(std::move(promise));

  CdmSession* session = it->second.get();
  DCHECK(session);

  // For a temporary session, the API will remove the keys and close the
  // session. For a persistent license session, the API will invalidate the keys
  // and generates a license release message.
  session->GenerateLicenseRelease(
      base::BindOnce(&FuchsiaCdm::OnGenerateLicenseReleaseStatus,
                     base::Unretained(this), session_id, promise_id));
}

void FuchsiaCdm::OnGenerateLicenseReleaseStatus(
    const std::string& session_id,
    uint32_t promise_id,
    absl::optional<CdmPromise::Exception> exception) {
  if (exception.has_value()) {
    promises_.RejectPromise(promise_id, exception.value(), 0,
                            "Failed to release license.");
    session_map_.erase(session_id);
    return;
  }

  DCHECK(!session_id.empty());
  promises_.ResolvePromise(promise_id);
}

CdmContext* FuchsiaCdm::GetCdmContext() {
  return this;
}

std::unique_ptr<CallbackRegistration> FuchsiaCdm::RegisterEventCB(
    EventCB event_cb) {
  return event_callbacks_.Register(std::move(event_cb));
}

Decryptor* FuchsiaCdm::GetDecryptor() {
  return &decryptor_;
}

FuchsiaCdmContext* FuchsiaCdm::GetFuchsiaCdmContext() {
  return this;
}

void FuchsiaCdm::OnNewKey() {
  event_callbacks_.Notify(Event::kHasAdditionalUsableKey);
  {
    base::AutoLock auto_lock(new_key_callbacks_lock_);

    // Remove cancelled callbacks.
    new_key_callbacks_.erase(
        std::remove_if(
            new_key_callbacks_.begin(), new_key_callbacks_.end(),
            [](const base::RepeatingClosure& cb) { return cb.IsCancelled(); }),
        new_key_callbacks_.end());

    for (auto& cb : new_key_callbacks_) {
      cb.Run();
    }
  }
}

}  // namespace media
