// Copyright 2013 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/cdm/library_cdm/clear_key_cdm/clear_key_cdm.h"

#include <algorithm>
#include <cstring>
#include <memory>
#include <sstream>
#include <utility>

#include "base/bind.h"
#include "base/cxx17_backports.h"
#include "base/files/file.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "media/base/cdm_callback_promise.h"
#include "media/base/cdm_key_information.h"
#include "media/base/decoder_buffer.h"
#include "media/base/decrypt_config.h"
#include "media/base/encryption_pattern.h"
#include "media/cdm/api/content_decryption_module_ext.h"
#include "media/cdm/cdm_type_conversion.h"
#include "media/cdm/json_web_key.h"
#include "media/cdm/library_cdm/cdm_host_proxy.h"
#include "media/cdm/library_cdm/cdm_host_proxy_impl.h"
#include "media/cdm/library_cdm/clear_key_cdm/cdm_file_io_test.h"
#include "media/cdm/library_cdm/clear_key_cdm/cdm_video_decoder.h"
#include "media/media_buildflags.h"

#if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER)
#include "base/at_exit.h"
#include "base/files/file_path.h"
#include "base/path_service.h"
#include "media/base/media.h"
#include "media/cdm/library_cdm/clear_key_cdm/ffmpeg_cdm_audio_decoder.h"

#if !defined COMPONENT_BUILD
static base::AtExitManager g_at_exit_manager;
#endif
#endif  // CLEAR_KEY_CDM_USE_FFMPEG_DECODER

const char kClearKeyCdmVersion[] = "0.1.0.1";
const char kExternalClearKeyKeySystem[] = "org.chromium.externalclearkey";

// Variants of External Clear Key key system to test different scenarios.
const char kExternalClearKeyDecryptOnlyKeySystem[] =
    "org.chromium.externalclearkey.decryptonly";
const char kExternalClearKeyMessageTypeTestKeySystem[] =
    "org.chromium.externalclearkey.messagetypetest";
const char kExternalClearKeyFileIOTestKeySystem[] =
    "org.chromium.externalclearkey.fileiotest";
const char kExternalClearKeyOutputProtectionTestKeySystem[] =
    "org.chromium.externalclearkey.outputprotectiontest";
const char kExternalClearKeyPlatformVerificationTestKeySystem[] =
    "org.chromium.externalclearkey.platformverificationtest";
const char kExternalClearKeyCrashKeySystem[] =
    "org.chromium.externalclearkey.crash";
const char kExternalClearKeyVerifyCdmHostTestKeySystem[] =
    "org.chromium.externalclearkey.verifycdmhosttest";
const char kExternalClearKeyStorageIdTestKeySystem[] =
    "org.chromium.externalclearkey.storageidtest";
const char kExternalClearKeyDifferentGuidTestKeySystem[] =
    "org.chromium.externalclearkey.differentguid";

const int64_t kMsPerSecond = 1000;
const int64_t kMaxTimerDelayMs = 5 * kMsPerSecond;

// CDM unit test result header. Must be in sync with UNIT_TEST_RESULT_HEADER in
// media/test/data/eme_player_js/globals.js.
const char kUnitTestResultHeader[] = "UNIT_TEST_RESULT";

const char kDummyIndividualizationRequest[] = "dummy individualization request";

static bool g_is_cdm_module_initialized = false;

// Copies |input_buffer| into a DecoderBuffer. If the |input_buffer| is
// empty, an empty (end-of-stream) DecoderBuffer is returned.
static scoped_refptr<media::DecoderBuffer> CopyDecoderBufferFrom(
    const cdm::InputBuffer_2& input_buffer) {
  if (!input_buffer.data) {
    DCHECK(!input_buffer.data_size);
    return media::DecoderBuffer::CreateEOSBuffer();
  }

  // TODO(xhwang): Get rid of this copy.
  scoped_refptr<media::DecoderBuffer> output_buffer =
      media::DecoderBuffer::CopyFrom(input_buffer.data, input_buffer.data_size);
  output_buffer->set_timestamp(base::Microseconds(input_buffer.timestamp));

  if (input_buffer.encryption_scheme == cdm::EncryptionScheme::kUnencrypted)
    return output_buffer;

  DCHECK_GT(input_buffer.iv_size, 0u);
  DCHECK_GT(input_buffer.key_id_size, 0u);
  std::vector<media::SubsampleEntry> subsamples;
  for (uint32_t i = 0; i < input_buffer.num_subsamples; ++i) {
    subsamples.push_back(
        media::SubsampleEntry(input_buffer.subsamples[i].clear_bytes,
                              input_buffer.subsamples[i].cipher_bytes));
  }

  const std::string key_id_string(
      reinterpret_cast<const char*>(input_buffer.key_id),
      input_buffer.key_id_size);
  const std::string iv_string(reinterpret_cast<const char*>(input_buffer.iv),
                              input_buffer.iv_size);
  if (input_buffer.encryption_scheme == cdm::EncryptionScheme::kCenc) {
    output_buffer->set_decrypt_config(media::DecryptConfig::CreateCencConfig(
        key_id_string, iv_string, subsamples));
  } else {
    DCHECK_EQ(input_buffer.encryption_scheme, cdm::EncryptionScheme::kCbcs);
    output_buffer->set_decrypt_config(media::DecryptConfig::CreateCbcsConfig(
        key_id_string, iv_string, subsamples,
        media::EncryptionPattern(input_buffer.pattern.crypt_byte_block,
                                 input_buffer.pattern.skip_byte_block)));
  }

  return output_buffer;
}

static std::string GetUnitTestResultMessage(bool success) {
  std::string message(kUnitTestResultHeader);
  message += success ? '1' : '0';
  return message;
}

// Shallow copy all the key information from |keys_info| into |keys_vector|.
// |keys_vector| is only valid for the lifetime of |keys_info| because it
// contains pointers into the latter.
void ConvertCdmKeysInfo(const media::CdmKeysInfo& keys_info,
                        std::vector<cdm::KeyInformation>* keys_vector) {
  keys_vector->reserve(keys_info.size());
  for (const auto& key_info : keys_info) {
    cdm::KeyInformation key = {};
    key.key_id = key_info->key_id.data();
    key.key_id_size = key_info->key_id.size();
    key.status = ToCdmKeyStatus(key_info->status);
    key.system_code = key_info->system_code;
    keys_vector->push_back(key);
  }
}

void INITIALIZE_CDM_MODULE() {
  DVLOG(1) << __func__;
  media::InitializeMediaLibrary();
  g_is_cdm_module_initialized = true;
}

void DeinitializeCdmModule() {
  DVLOG(1) << __func__;
}

void* CreateCdmInstance(int cdm_interface_version,
                        const char* key_system,
                        uint32_t key_system_size,
                        GetCdmHostFunc get_cdm_host_func,
                        void* user_data) {
  DVLOG(1) << "CreateCdmInstance()";

  if (!g_is_cdm_module_initialized) {
    DVLOG(1) << "CDM module not initialized.";
    return nullptr;
  }

  std::string key_system_string(key_system, key_system_size);
  if (key_system_string != kExternalClearKeyKeySystem &&
      key_system_string != kExternalClearKeyDecryptOnlyKeySystem &&
      key_system_string != kExternalClearKeyMessageTypeTestKeySystem &&
      key_system_string != kExternalClearKeyFileIOTestKeySystem &&
      key_system_string != kExternalClearKeyOutputProtectionTestKeySystem &&
      key_system_string != kExternalClearKeyPlatformVerificationTestKeySystem &&
      key_system_string != kExternalClearKeyCrashKeySystem &&
      key_system_string != kExternalClearKeyVerifyCdmHostTestKeySystem &&
      key_system_string != kExternalClearKeyStorageIdTestKeySystem &&
      key_system_string != kExternalClearKeyDifferentGuidTestKeySystem) {
    DVLOG(1) << "Unsupported key system:" << key_system_string;
    return nullptr;
  }

  // We support CDM_10 and CDM_11.
  using CDM_10 = cdm::ContentDecryptionModule_10;
  using CDM_11 = cdm::ContentDecryptionModule_11;

  if (cdm_interface_version == CDM_10::kVersion) {
    CDM_10::Host* host = static_cast<CDM_10::Host*>(
        get_cdm_host_func(CDM_10::Host::kVersion, user_data));
    if (!host)
      return nullptr;

    DVLOG(1) << __func__ << ": Create ClearKeyCdm with CDM_10::Host.";
    return static_cast<CDM_10*>(
        new media::ClearKeyCdm(host, key_system_string));
  }

  if (cdm_interface_version == CDM_11::kVersion) {
    CDM_11::Host* host = static_cast<CDM_11::Host*>(
        get_cdm_host_func(CDM_11::Host::kVersion, user_data));
    if (!host)
      return nullptr;

    DVLOG(1) << __func__ << ": Create ClearKeyCdm with CDM_11::Host.";
    return static_cast<CDM_11*>(
        new media::ClearKeyCdm(host, key_system_string));
  }

  return nullptr;
}

const char* GetCdmVersion() {
  return kClearKeyCdmVersion;
}

static bool g_verify_host_files_result = false;

// Makes sure files and corresponding signature files are readable but not
// writable.
bool VerifyCdmHost_0(const cdm::HostFile* host_files, uint32_t num_files) {
  DVLOG(1) << __func__ << ": " << num_files;

  // We should always have the CDM and at least one common file.
  // The common CDM host file (e.g. chrome) might not exist since we are running
  // in browser_tests.
  const uint32_t kMinNumHostFiles = 2;

  // We should always have the CDM.
  const int kNumCdmFiles = 1;

  if (num_files < kMinNumHostFiles) {
    LOG(ERROR) << "Too few host files: " << num_files;
    g_verify_host_files_result = false;
    return true;
  }

  int num_opened_files = 0;
  for (uint32_t i = 0; i < num_files; ++i) {
    const int kBytesToRead = 10;
    std::vector<char> buffer(kBytesToRead);

    base::File file(static_cast<base::PlatformFile>(host_files[i].file));
    if (!file.IsValid())
      continue;

    num_opened_files++;

    int bytes_read = file.Read(0, buffer.data(), buffer.size());
    if (bytes_read != kBytesToRead) {
      LOG(ERROR) << "File bytes read: " << bytes_read;
      g_verify_host_files_result = false;
      return true;
    }

    // TODO(xhwang): Check that the files are not writable.
    // TODO(xhwang): Also verify the signature file when it's available.
  }

  // We should always have CDM files opened.
  if (num_opened_files < kNumCdmFiles) {
    LOG(ERROR) << "Too few opened files: " << num_opened_files;
    g_verify_host_files_result = false;
    return true;
  }

  g_verify_host_files_result = true;
  return true;
}

namespace media {

namespace {

// See ISO 23001-8:2016, section 7. Value 2 means "Unspecified".
constexpr cdm::ColorSpace kUnspecifiedColorSpace = {2, 2, 2,
                                                    cdm::ColorRange::kInvalid};

cdm::VideoDecoderConfig_3 ToVideoDecoderConfig_3(
    cdm::VideoDecoderConfig_2 config) {
  cdm::VideoDecoderConfig_3 result = {
      config.codec,           config.profile,          config.format,
      kUnspecifiedColorSpace, config.coded_size,       config.extra_data,
      config.extra_data_size, config.encryption_scheme};
  return result;
}

// Adapting a cdm::VideoFrame to a cdm::VideoFrame_2 interface. Simply pass all
// calls through except for SetColorSpace() and ColorSpace().
class CdmVideoFrameAdapter : public cdm::VideoFrame_2 {
 public:
  explicit CdmVideoFrameAdapter(cdm::VideoFrame* video_frame)
      : video_frame_(video_frame) {}

  // cdm::VideoFrame_2 implementation.
  void SetFormat(cdm::VideoFormat format) final {
    video_frame_->SetFormat(format);
  }
  void SetSize(cdm::Size size) final { video_frame_->SetSize(size); }
  void SetFrameBuffer(cdm::Buffer* frame_buffer) final {
    video_frame_->SetFrameBuffer(frame_buffer);
  }
  void SetPlaneOffset(cdm::VideoPlane plane, uint32_t offset) final {
    video_frame_->SetPlaneOffset(plane, offset);
  }
  void SetStride(cdm::VideoPlane plane, uint32_t stride) final {
    video_frame_->SetStride(plane, stride);
  }
  void SetTimestamp(int64_t timestamp) final {
    video_frame_->SetTimestamp(timestamp);
  }
  void SetColorSpace(cdm::ColorSpace color_space) final {
    // Do nothing since cdm::VideoFrame does not support colorspace.
  }

 private:
  cdm::VideoFrame* const video_frame_ = nullptr;
};

}  // namespace

template <typename HostInterface>
ClearKeyCdm::ClearKeyCdm(HostInterface* host, const std::string& key_system)
    : host_interface_version_(HostInterface::kVersion),
      cdm_host_proxy_(new CdmHostProxyImpl<HostInterface>(host)),
      cdm_(new ClearKeyPersistentSessionCdm(
          cdm_host_proxy_.get(),
          base::BindRepeating(&ClearKeyCdm::OnSessionMessage,
                              base::Unretained(this)),
          base::BindRepeating(&ClearKeyCdm::OnSessionClosed,
                              base::Unretained(this)),
          base::BindRepeating(&ClearKeyCdm::OnSessionKeysChange,
                              base::Unretained(this)),
          base::BindRepeating(&ClearKeyCdm::OnSessionExpirationUpdate,
                              base::Unretained(this)))),
      key_system_(key_system) {
  DCHECK(g_is_cdm_module_initialized);
}

ClearKeyCdm::~ClearKeyCdm() = default;

void ClearKeyCdm::Initialize(bool allow_distinctive_identifier,
                             bool allow_persistent_state,
                             bool /* use_hw_secure_codecs */) {
  // Implementation doesn't use distinctive identifier and will only need
  // to check persistent state permission.
  allow_persistent_state_ = allow_persistent_state;

  cdm_host_proxy_->OnInitialized(true);
}

void ClearKeyCdm::GetStatusForPolicy(uint32_t promise_id,
                                     const cdm::Policy& policy) {
  // Pretend the device is HDCP 2.0 compliant.
  const cdm::HdcpVersion kDeviceHdcpVersion = cdm::kHdcpVersion2_0;

  if (policy.min_hdcp_version <= kDeviceHdcpVersion) {
    cdm_host_proxy_->OnResolveKeyStatusPromise(promise_id, cdm::kUsable);
    return;
  }

  cdm_host_proxy_->OnResolveKeyStatusPromise(promise_id,
                                             cdm::kOutputRestricted);
}

void ClearKeyCdm::CreateSessionAndGenerateRequest(
    uint32_t promise_id,
    cdm::SessionType session_type,
    cdm::InitDataType init_data_type,
    const uint8_t* init_data,
    uint32_t init_data_size) {
  DVLOG(1) << __func__;

  if (session_type != cdm::kTemporary && !allow_persistent_state_) {
    OnPromiseFailed(promise_id, CdmPromise::Exception::INVALID_STATE_ERROR, 0,
                    "Persistent state not allowed.");
    return;
  }

  std::unique_ptr<media::NewSessionCdmPromise> promise(
      new media::CdmCallbackPromise<std::string>(
          base::BindOnce(&ClearKeyCdm::OnSessionCreated, base::Unretained(this),
                         promise_id),
          base::BindOnce(&ClearKeyCdm::OnPromiseFailed, base::Unretained(this),
                         promise_id)));
  cdm_->CreateSessionAndGenerateRequest(
      ToMediaSessionType(session_type), ToEmeInitDataType(init_data_type),
      std::vector<uint8_t>(init_data, init_data + init_data_size),
      std::move(promise));

  // Run unit tests if applicable. Unit test results are reported in the form of
  // a session message. Therefore it can only be called after session creation.
  if (key_system_ == kExternalClearKeyFileIOTestKeySystem) {
    StartFileIOTest();
  } else if (key_system_ == kExternalClearKeyOutputProtectionTestKeySystem) {
    StartOutputProtectionTest();
  } else if (key_system_ ==
             kExternalClearKeyPlatformVerificationTestKeySystem) {
    StartPlatformVerificationTest();
  } else if (key_system_ == kExternalClearKeyVerifyCdmHostTestKeySystem) {
    ReportVerifyCdmHostTestResult();
  } else if (key_system_ == kExternalClearKeyStorageIdTestKeySystem) {
    StartStorageIdTest();
  }
}

void ClearKeyCdm::LoadSession(uint32_t promise_id,
                              cdm::SessionType session_type,
                              const char* session_id,
                              uint32_t session_id_length) {
  DVLOG(1) << __func__;
  DCHECK_EQ(session_type, cdm::kPersistentLicense);
  DCHECK(allow_persistent_state_);
  std::string web_session_str(session_id, session_id_length);

  std::unique_ptr<media::NewSessionCdmPromise> promise(
      new media::CdmCallbackPromise<std::string>(
          base::BindOnce(&ClearKeyCdm::OnSessionCreated, base::Unretained(this),
                         promise_id),
          base::BindOnce(&ClearKeyCdm::OnPromiseFailed, base::Unretained(this),
                         promise_id)));
  cdm_->LoadSession(ToMediaSessionType(session_type),
                    std::move(web_session_str), std::move(promise));
}

void ClearKeyCdm::UpdateSession(uint32_t promise_id,
                                const char* session_id,
                                uint32_t session_id_length,
                                const uint8_t* response,
                                uint32_t response_size) {
  DVLOG(1) << __func__;
  std::string web_session_str(session_id, session_id_length);
  std::vector<uint8_t> response_vector(response, response + response_size);

  std::unique_ptr<media::SimpleCdmPromise> promise(
      new media::CdmCallbackPromise<>(
          base::BindOnce(&ClearKeyCdm::OnUpdateSuccess, base::Unretained(this),
                         promise_id, web_session_str),
          base::BindOnce(&ClearKeyCdm::OnPromiseFailed, base::Unretained(this),
                         promise_id)));

  cdm_->UpdateSession(session_id, response_vector, std::move(promise));
}

void ClearKeyCdm::OnUpdateSuccess(uint32_t promise_id,
                                  const std::string& session_id) {
  // Now create the expiration changed event.
  cdm::Time expiration = 0.0;  // Never expires.

  if (key_system_ == kExternalClearKeyMessageTypeTestKeySystem) {
    // For renewal key system, set a non-zero expiration that is approximately
    // 100 years after 01 January 1970 UTC.
    expiration = 3153600000.0;  // 100 * 365 * 24 * 60 * 60;

    if (!has_set_timer_) {
      // Make sure the CDM can get time and sleep if necessary.
      constexpr auto kSleepDuration = base::Seconds(1);
      auto start_time = base::Time::Now();
      base::PlatformThread::Sleep(kSleepDuration);
      auto time_elapsed = base::Time::Now() - start_time;
      CHECK_GE(time_elapsed, kSleepDuration);

      ScheduleNextTimer();
    }

    // Also send an individualization request if never sent before. Only
    // supported on Host_10 and later.
    if (host_interface_version_ >= cdm::Host_10::kVersion &&
        !has_sent_individualization_request_) {
      has_sent_individualization_request_ = true;
      const std::string request = kDummyIndividualizationRequest;
      cdm_host_proxy_->OnSessionMessage(session_id.data(), session_id.length(),
                                        cdm::kIndividualizationRequest,
                                        request.data(), request.size());
    }
  }

  cdm_host_proxy_->OnExpirationChange(session_id.data(), session_id.length(),
                                      expiration);

  // Resolve the promise.
  OnPromiseResolved(promise_id);
}

void ClearKeyCdm::CloseSession(uint32_t promise_id,
                               const char* session_id,
                               uint32_t session_id_length) {
  DVLOG(1) << __func__;
  std::string web_session_str(session_id, session_id_length);

  std::unique_ptr<media::SimpleCdmPromise> promise(
      new media::CdmCallbackPromise<>(
          base::BindOnce(&ClearKeyCdm::OnPromiseResolved,
                         base::Unretained(this), promise_id),
          base::BindOnce(&ClearKeyCdm::OnPromiseFailed, base::Unretained(this),
                         promise_id)));
  cdm_->CloseSession(std::move(web_session_str), std::move(promise));
}

void ClearKeyCdm::RemoveSession(uint32_t promise_id,
                                const char* session_id,
                                uint32_t session_id_length) {
  DVLOG(1) << __func__;
  std::string web_session_str(session_id, session_id_length);

  std::unique_ptr<media::SimpleCdmPromise> promise(
      new media::CdmCallbackPromise<>(
          base::BindOnce(&ClearKeyCdm::OnPromiseResolved,
                         base::Unretained(this), promise_id),
          base::BindOnce(&ClearKeyCdm::OnPromiseFailed, base::Unretained(this),
                         promise_id)));
  cdm_->RemoveSession(std::move(web_session_str), std::move(promise));
}

void ClearKeyCdm::SetServerCertificate(uint32_t promise_id,
                                       const uint8_t* server_certificate_data,
                                       uint32_t server_certificate_data_size) {
  DVLOG(1) << __func__;
  std::unique_ptr<media::SimpleCdmPromise> promise(
      new media::CdmCallbackPromise<>(
          base::BindOnce(&ClearKeyCdm::OnPromiseResolved,
                         base::Unretained(this), promise_id),
          base::BindOnce(&ClearKeyCdm::OnPromiseFailed, base::Unretained(this),
                         promise_id)));
  cdm_->SetServerCertificate(
      std::vector<uint8_t>(
          server_certificate_data,
          server_certificate_data + server_certificate_data_size),
      std::move(promise));
}

void ClearKeyCdm::TimerExpired(void* context) {
  DVLOG(1) << __func__;
  DCHECK(has_set_timer_);
  std::string renewal_message;

  if (key_system_ == kExternalClearKeyMessageTypeTestKeySystem) {
    if (!next_renewal_message_.empty() &&
        context == &next_renewal_message_[0]) {
      renewal_message = next_renewal_message_;
    } else {
      renewal_message = "ERROR: Invalid timer context found!";
    }

    cdm_host_proxy_->OnSessionMessage(
        last_session_id_.data(), last_session_id_.length(),
        cdm::kLicenseRenewal, renewal_message.data(), renewal_message.length());
  } else if (key_system_ == kExternalClearKeyOutputProtectionTestKeySystem) {
    // Check output protection again.
    cdm_host_proxy_->QueryOutputProtectionStatus();
  }

  // Start the timer to schedule another timeout.
  ScheduleNextTimer();
}

static void CopyDecryptResults(media::Decryptor::Status* status_copy,
                               scoped_refptr<DecoderBuffer>* buffer_copy,
                               media::Decryptor::Status status,
                               scoped_refptr<DecoderBuffer> buffer) {
  *status_copy = status;
  *buffer_copy = std::move(buffer);
}

cdm::Status ClearKeyCdm::Decrypt(const cdm::InputBuffer_2& encrypted_buffer,
                                 cdm::DecryptedBlock* decrypted_block) {
  DVLOG(1) << __func__;
  DCHECK(encrypted_buffer.data);

  scoped_refptr<DecoderBuffer> buffer;
  cdm::Status status = DecryptToMediaDecoderBuffer(encrypted_buffer, &buffer);

  if (status != cdm::kSuccess)
    return status;

  DCHECK(buffer->data());
  decrypted_block->SetDecryptedBuffer(
      cdm_host_proxy_->Allocate(buffer->data_size()));
  memcpy(reinterpret_cast<void*>(decrypted_block->DecryptedBuffer()->Data()),
         buffer->data(), buffer->data_size());
  decrypted_block->DecryptedBuffer()->SetSize(buffer->data_size());
  decrypted_block->SetTimestamp(buffer->timestamp().InMicroseconds());

  return cdm::kSuccess;
}

cdm::Status ClearKeyCdm::InitializeAudioDecoder(
    const cdm::AudioDecoderConfig_2& audio_decoder_config) {
  if (key_system_ == kExternalClearKeyDecryptOnlyKeySystem)
    return cdm::kInitializationError;

#if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER)
  if (!audio_decoder_) {
    audio_decoder_ =
        std::make_unique<media::FFmpegCdmAudioDecoder>(cdm_host_proxy_.get());
  }

  if (!audio_decoder_->Initialize(audio_decoder_config))
    return cdm::kInitializationError;

  return cdm::kSuccess;
#else
  return cdm::kInitializationError;
#endif  // CLEAR_KEY_CDM_USE_FFMPEG_DECODER
}

cdm::Status ClearKeyCdm::InitializeVideoDecoder(
    const cdm::VideoDecoderConfig_2& video_decoder_config) {
  return InitializeVideoDecoder(ToVideoDecoderConfig_3(video_decoder_config));
}

cdm::Status ClearKeyCdm::InitializeVideoDecoder(
    const cdm::VideoDecoderConfig_3& video_decoder_config) {
  if (key_system_ == kExternalClearKeyDecryptOnlyKeySystem)
    return cdm::kInitializationError;

  if (!video_decoder_) {
    video_decoder_ =
        CreateVideoDecoder(cdm_host_proxy_.get(), video_decoder_config);
    if (!video_decoder_)
      return cdm::kInitializationError;
  }

  if (!video_decoder_->Initialize(video_decoder_config).is_ok())
    return cdm::kInitializationError;

  return cdm::kSuccess;
}

void ClearKeyCdm::ResetDecoder(cdm::StreamType decoder_type) {
  DVLOG(1) << __func__;
#if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER)
  switch (decoder_type) {
    case cdm::kStreamTypeVideo:
      video_decoder_->Reset();
      break;
    case cdm::kStreamTypeAudio:
      audio_decoder_->Reset();
      break;
    default:
      NOTREACHED() << "ResetDecoder(): invalid cdm::StreamType";
  }
#endif  // CLEAR_KEY_CDM_USE_FFMPEG_DECODER
}

void ClearKeyCdm::DeinitializeDecoder(cdm::StreamType decoder_type) {
  DVLOG(1) << __func__;
  switch (decoder_type) {
    case cdm::kStreamTypeVideo:
      video_decoder_->Deinitialize();
      break;
    case cdm::kStreamTypeAudio:
#if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER)
      audio_decoder_->Deinitialize();
#endif
      break;
    default:
      NOTREACHED() << "DeinitializeDecoder(): invalid cdm::StreamType";
  }
}

cdm::Status ClearKeyCdm::DecryptAndDecodeFrame(
    const cdm::InputBuffer_2& encrypted_buffer,
    cdm::VideoFrame* decoded_frame) {
  CdmVideoFrameAdapter adapted_frame(decoded_frame);
  return DecryptAndDecodeFrame(encrypted_buffer, &adapted_frame);
}

cdm::Status ClearKeyCdm::DecryptAndDecodeFrame(
    const cdm::InputBuffer_2& encrypted_buffer,
    cdm::VideoFrame_2* decoded_frame) {
  DVLOG(1) << __func__;
  TRACE_EVENT0("media", "ClearKeyCdm::DecryptAndDecodeFrame");

  scoped_refptr<DecoderBuffer> buffer;
  cdm::Status status = DecryptToMediaDecoderBuffer(encrypted_buffer, &buffer);

  if (status != cdm::kSuccess)
    return status;

  return video_decoder_->Decode(buffer, decoded_frame);
}

cdm::Status ClearKeyCdm::DecryptAndDecodeSamples(
    const cdm::InputBuffer_2& encrypted_buffer,
    cdm::AudioFrames* audio_frames) {
  DVLOG(1) << __func__;

  // Trigger a crash on purpose for testing purpose.
  // Only do this after a session has been created since the test also checks
  // that the session is properly closed.
  if (!last_session_id_.empty() &&
      key_system_ == kExternalClearKeyCrashKeySystem) {
    CHECK(false) << "Crash in decrypt-and-decode with crash key system.";
  }

  scoped_refptr<DecoderBuffer> buffer;
  cdm::Status status = DecryptToMediaDecoderBuffer(encrypted_buffer, &buffer);

  if (status != cdm::kSuccess)
    return status;

#if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER)
  const uint8_t* data = NULL;
  int32_t size = 0;
  int64_t timestamp = 0;
  if (!buffer->end_of_stream()) {
    data = buffer->data();
    size = buffer->data_size();
    timestamp = encrypted_buffer.timestamp;
  }

  return audio_decoder_->DecodeBuffer(data, size, timestamp, audio_frames);
#else
  return cdm::kSuccess;
#endif  // CLEAR_KEY_CDM_USE_FFMPEG_DECODER
}

void ClearKeyCdm::Destroy() {
  DVLOG(1) << __func__;
  delete this;
}

void ClearKeyCdm::ScheduleNextTimer() {
  // Prepare the next renewal message and set timer. Renewal message is only
  // needed for the renewal test, and is ignored for other uses of the timer.
  std::ostringstream msg_stream;
  msg_stream << "Renewal from ClearKey CDM set at time "
             << base::Time::FromDoubleT(cdm_host_proxy_->GetCurrentWallTime())
             << ".";
  next_renewal_message_ = msg_stream.str();

  cdm_host_proxy_->SetTimer(timer_delay_ms_, &next_renewal_message_[0]);
  has_set_timer_ = true;

  // Use a smaller timer delay at start-up to facilitate testing. Increase the
  // timer delay up to a limit to avoid message spam.
  if (timer_delay_ms_ < kMaxTimerDelayMs)
    timer_delay_ms_ = std::min(2 * timer_delay_ms_, kMaxTimerDelayMs);
}

cdm::Status ClearKeyCdm::DecryptToMediaDecoderBuffer(
    const cdm::InputBuffer_2& encrypted_buffer,
    scoped_refptr<DecoderBuffer>* decrypted_buffer) {
  DCHECK(decrypted_buffer);

  scoped_refptr<DecoderBuffer> buffer = CopyDecoderBufferFrom(encrypted_buffer);

  // EOS and unencrypted streams can be returned as-is.
  if (buffer->end_of_stream() || !buffer->decrypt_config()) {
    *decrypted_buffer = std::move(buffer);
    return cdm::kSuccess;
  }

  // Callback is called synchronously, so we can use variables on the stack.
  media::Decryptor::Status status = media::Decryptor::kError;
  // The CDM does not care what the stream type is. Pass kVideo
  // for both audio and video decryption.
  cdm_->GetCdmContext()->GetDecryptor()->Decrypt(
      media::Decryptor::kVideo, std::move(buffer),
      base::BindOnce(&CopyDecryptResults, &status, decrypted_buffer));

  if (status == media::Decryptor::kError)
    return cdm::kDecryptError;

  if (status == media::Decryptor::kNoKey)
    return cdm::kNoKey;

  DCHECK_EQ(status, media::Decryptor::kSuccess);
  return cdm::kSuccess;
}

void ClearKeyCdm::OnPlatformChallengeResponse(
    const cdm::PlatformChallengeResponse& response) {
  DVLOG(1) << __func__;

  if (!is_running_platform_verification_test_) {
    NOTREACHED() << "OnPlatformChallengeResponse() called unexpectedly.";
    return;
  }

  is_running_platform_verification_test_ = false;

  // We are good as long as we get some response back. Ignore the challenge
  // response for now.
  // TODO(xhwang): Also test host challenge here.
  OnUnitTestComplete(true);
}

void ClearKeyCdm::OnQueryOutputProtectionStatus(
    cdm::QueryResult result,
    uint32_t link_mask,
    uint32_t output_protection_mask) {
  DVLOG(1) << __func__ << " result:" << result << ", link_mask:" << link_mask
           << ", output_protection_mask:" << output_protection_mask;

  if (!is_running_output_protection_test_) {
    NOTREACHED() << "OnQueryOutputProtectionStatus() called unexpectedly.";
    return;
  }

  // A session ID is needed, so use |last_session_id_|. However, if this is
  // called before a session has been created, we have no session to send this
  // to, so no event is generated. Note that this only works with a single
  // session, the same as renewal messages.
  if (last_session_id_.empty())
    return;

  // If the query succeeds and link mask contains kLinkTypeNetwork, send a
  // 'keystatuschange' event with a key marked as output-restricted. If the
  // query succeeds and link mask does not contain kLinkTypeNetwork, send a
  // 'keystatuschange' event with a key marked as usable. If the query failed,
  // send a 'keystatuschange' event with a key marked as internal-error. As
  // the JavaScript test doesn't check key IDs, use a dummy key ID.
  //
  // Note that QueryOutputProtectionStatus() is known to fail on Linux Chrome
  // OS builds, so the key status returned will be 'internal-error'.
  //
  // Note that this does not modify any keys, so if the caller does not check
  // the 'keystatuschange' event, nothing will happen as decoding will continue
  // to work.
  cdm::KeyStatus key_status = cdm::kInternalError;
  if (result == cdm::kQuerySucceeded) {
    key_status = (link_mask & cdm::kLinkTypeNetwork) ? cdm::kOutputRestricted
                                                     : cdm::kUsable;
  }
  const uint8_t kDummyKeyId[] = {'d', 'u', 'm', 'm', 'y'};
  std::vector<cdm::KeyInformation> keys_vector = {
      {kDummyKeyId, base::size(kDummyKeyId), key_status, 0}};
  cdm_host_proxy_->OnSessionKeysChange(last_session_id_.data(),
                                       last_session_id_.length(), false,
                                       keys_vector.data(), keys_vector.size());
}

void ClearKeyCdm::OnStorageId(uint32_t version,
                              const uint8_t* storage_id,
                              uint32_t storage_id_size) {
  if (!is_running_storage_id_test_) {
    NOTREACHED() << "OnStorageId() called unexpectedly.";
    return;
  }

  is_running_storage_id_test_ = false;
  DVLOG(1) << __func__ << ": storage_id (hex encoded) = "
           << (storage_id_size ? base::HexEncode(storage_id, storage_id_size)
                               : "<empty>");

#if BUILDFLAG(ENABLE_CDM_STORAGE_ID)
  // Storage Id is enabled, so something should be returned. It should be the
  // length of a SHA-256 hash (256 bits).
  constexpr uint32_t kExpectedStorageIdSizeInBytes = 256 / 8;
  OnUnitTestComplete(storage_id_size == kExpectedStorageIdSizeInBytes);
#else
  // Storage Id not available, so an empty vector should be returned.
  OnUnitTestComplete(storage_id_size == 0);
#endif
}

void ClearKeyCdm::OnSessionMessage(const std::string& session_id,
                                   CdmMessageType message_type,
                                   const std::vector<uint8_t>& message) {
  DVLOG(1) << __func__ << ": size = " << message.size();

  cdm_host_proxy_->OnSessionMessage(
      session_id.data(), session_id.length(), ToCdmMessageType(message_type),
      reinterpret_cast<const char*>(message.data()), message.size());
}

void ClearKeyCdm::OnSessionKeysChange(const std::string& session_id,
                                      bool has_additional_usable_key,
                                      CdmKeysInfo keys_info) {
  DVLOG(1) << __func__ << ": size = " << keys_info.size();

  // Crash if the special key ID "crash" is present.
  const std::vector<uint8_t> kCrashKeyId{'c', 'r', 'a', 's', 'h'};
  for (const auto& key_info : keys_info) {
    if (key_info->key_id == kCrashKeyId)
      CHECK(false) << "Crash on special crash key ID.";
  }

  std::vector<cdm::KeyInformation> keys_vector;
  ConvertCdmKeysInfo(keys_info, &keys_vector);
  cdm_host_proxy_->OnSessionKeysChange(session_id.data(), session_id.length(),
                                       has_additional_usable_key,
                                       keys_vector.data(), keys_vector.size());
}

void ClearKeyCdm::OnSessionClosed(const std::string& session_id,
                                  CdmSessionClosedReason /*reason*/) {
  cdm_host_proxy_->OnSessionClosed(session_id.data(), session_id.length());
}

void ClearKeyCdm::OnSessionExpirationUpdate(const std::string& session_id,
                                            base::Time new_expiry_time) {
  DVLOG(1) << __func__ << ": expiry_time = " << new_expiry_time;
  cdm_host_proxy_->OnExpirationChange(session_id.data(), session_id.length(),
                                      new_expiry_time.ToDoubleT());
}

void ClearKeyCdm::OnSessionCreated(uint32_t promise_id,
                                   const std::string& session_id) {
  // Save the latest session ID for renewal and file IO test messages.
  last_session_id_ = session_id;

  cdm_host_proxy_->OnResolveNewSessionPromise(promise_id, session_id.data(),
                                              session_id.length());
}

void ClearKeyCdm::OnPromiseResolved(uint32_t promise_id) {
  cdm_host_proxy_->OnResolvePromise(promise_id);
}

void ClearKeyCdm::OnPromiseFailed(uint32_t promise_id,
                                  CdmPromise::Exception exception_code,
                                  uint32_t system_code,
                                  const std::string& error_message) {
  DVLOG(1) << __func__ << ": error = " << error_message;
  cdm_host_proxy_->OnRejectPromise(promise_id, ToCdmException(exception_code),
                                   system_code, error_message.data(),
                                   error_message.length());
}

void ClearKeyCdm::OnUnitTestComplete(bool success) {
  std::string message = GetUnitTestResultMessage(success);
  cdm_host_proxy_->OnSessionMessage(
      last_session_id_.data(), last_session_id_.length(), cdm::kLicenseRequest,
      message.data(), message.length());
}

void ClearKeyCdm::StartFileIOTest() {
  file_io_test_runner_ = std::make_unique<FileIOTestRunner>(base::BindRepeating(
      &CdmHostProxy::CreateFileIO, base::Unretained(cdm_host_proxy_.get())));
  file_io_test_runner_->RunAllTests(base::BindOnce(
      &ClearKeyCdm::OnFileIOTestComplete, base::Unretained(this)));
}

void ClearKeyCdm::OnFileIOTestComplete(bool success) {
  DVLOG(1) << __func__ << ": " << success;
  OnUnitTestComplete(success);
  file_io_test_runner_.reset();
}

void ClearKeyCdm::StartOutputProtectionTest() {
  DVLOG(1) << __func__;
  is_running_output_protection_test_ = true;
  cdm_host_proxy_->QueryOutputProtectionStatus();

  // Also start the timer to run this periodically.
  ScheduleNextTimer();
}

void ClearKeyCdm::StartPlatformVerificationTest() {
  DVLOG(1) << __func__;
  is_running_platform_verification_test_ = true;

  std::string service_id = "test_service_id";
  std::string challenge = "test_challenge";

  cdm_host_proxy_->SendPlatformChallenge(service_id.data(), service_id.size(),
                                         challenge.data(), challenge.size());
}

void ClearKeyCdm::ReportVerifyCdmHostTestResult() {
  // VerifyCdmHost() should have already been called and test result stored
  // in |g_verify_host_files_result|.
  OnUnitTestComplete(g_verify_host_files_result);
}

void ClearKeyCdm::StartStorageIdTest() {
  DVLOG(1) << __func__;
  is_running_storage_id_test_ = true;

  // Request the latest available version.
  cdm_host_proxy_->RequestStorageId(0);
}

}  // namespace media
