// 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/ppapi/cdm_adapter.h"

#include "media/cdm/ppapi/cdm_file_io_impl.h"
#include "media/cdm/ppapi/cdm_helpers.h"
#include "media/cdm/ppapi/cdm_logging.h"
#include "media/cdm/ppapi/supported_cdm_versions.h"
#include "ppapi/c/ppb_console.h"
#include "ppapi/cpp/private/uma_private.h"

#if defined(CHECK_DOCUMENT_URL)
#include "ppapi/cpp/dev/url_util_dev.h"
#include "ppapi/cpp/instance_handle.h"
#endif  // defined(CHECK_DOCUMENT_URL)

namespace {

#if !defined(NDEBUG)
  #define DLOG_TO_CONSOLE(message) LogToConsole(message);
#else
  #define DLOG_TO_CONSOLE(message) (void)(message);
#endif

bool IsMainThread() {
  return pp::Module::Get()->core()->IsMainThread();
}

// Posts a task to run |cb| on the main thread. The task is posted even if the
// current thread is the main thread.
void PostOnMain(pp::CompletionCallback cb) {
  pp::Module::Get()->core()->CallOnMainThread(0, cb, PP_OK);
}

// Ensures |cb| is called on the main thread, either because the current thread
// is the main thread or by posting it to the main thread.
void CallOnMain(pp::CompletionCallback cb) {
  // TODO(tomfinegan): This is only necessary because PPAPI doesn't allow calls
  // off the main thread yet. Remove this once the change lands.
  if (IsMainThread())
    cb.Run(PP_OK);
  else
    PostOnMain(cb);
}

// Configures a cdm::InputBuffer. |subsamples| must exist as long as
// |input_buffer| is in use.
void ConfigureInputBuffer(
    const pp::Buffer_Dev& encrypted_buffer,
    const PP_EncryptedBlockInfo& encrypted_block_info,
    std::vector<cdm::SubsampleEntry>* subsamples,
    cdm::InputBuffer* input_buffer) {
  PP_DCHECK(subsamples);
  PP_DCHECK(!encrypted_buffer.is_null());

  input_buffer->data = static_cast<uint8_t*>(encrypted_buffer.data());
  input_buffer->data_size = encrypted_block_info.data_size;
  PP_DCHECK(encrypted_buffer.size() >= input_buffer->data_size);

  PP_DCHECK(encrypted_block_info.key_id_size <=
            arraysize(encrypted_block_info.key_id));
  input_buffer->key_id_size = encrypted_block_info.key_id_size;
  input_buffer->key_id = input_buffer->key_id_size > 0 ?
      encrypted_block_info.key_id : NULL;

  PP_DCHECK(encrypted_block_info.iv_size <= arraysize(encrypted_block_info.iv));
  input_buffer->iv_size = encrypted_block_info.iv_size;
  input_buffer->iv = encrypted_block_info.iv_size > 0 ?
      encrypted_block_info.iv : NULL;

  input_buffer->num_subsamples = encrypted_block_info.num_subsamples;
  if (encrypted_block_info.num_subsamples > 0) {
    subsamples->reserve(encrypted_block_info.num_subsamples);

    for (uint32_t i = 0; i < encrypted_block_info.num_subsamples; ++i) {
      subsamples->push_back(cdm::SubsampleEntry(
          encrypted_block_info.subsamples[i].clear_bytes,
          encrypted_block_info.subsamples[i].cipher_bytes));
    }

    input_buffer->subsamples = &(*subsamples)[0];
  }

  input_buffer->timestamp = encrypted_block_info.tracking_info.timestamp;
}

PP_DecryptResult CdmStatusToPpDecryptResult(cdm::Status status) {
  switch (status) {
    case cdm::kSuccess:
      return PP_DECRYPTRESULT_SUCCESS;
    case cdm::kNoKey:
      return PP_DECRYPTRESULT_DECRYPT_NOKEY;
    case cdm::kNeedMoreData:
      return PP_DECRYPTRESULT_NEEDMOREDATA;
    case cdm::kDecryptError:
      return PP_DECRYPTRESULT_DECRYPT_ERROR;
    case cdm::kDecodeError:
      return PP_DECRYPTRESULT_DECODE_ERROR;
    default:
      PP_NOTREACHED();
      return PP_DECRYPTRESULT_DECODE_ERROR;
  }
}

PP_DecryptedFrameFormat CdmVideoFormatToPpDecryptedFrameFormat(
    cdm::VideoFormat format) {
  switch (format) {
    case cdm::kYv12:
      return PP_DECRYPTEDFRAMEFORMAT_YV12;
    case cdm::kI420:
      return PP_DECRYPTEDFRAMEFORMAT_I420;
    default:
      return PP_DECRYPTEDFRAMEFORMAT_UNKNOWN;
  }
}

PP_DecryptedSampleFormat CdmAudioFormatToPpDecryptedSampleFormat(
    cdm::AudioFormat format) {
  switch (format) {
    case cdm::kAudioFormatU8:
      return PP_DECRYPTEDSAMPLEFORMAT_U8;
    case cdm::kAudioFormatS16:
      return PP_DECRYPTEDSAMPLEFORMAT_S16;
    case cdm::kAudioFormatS32:
      return PP_DECRYPTEDSAMPLEFORMAT_S32;
    case cdm::kAudioFormatF32:
      return PP_DECRYPTEDSAMPLEFORMAT_F32;
    case cdm::kAudioFormatPlanarS16:
      return PP_DECRYPTEDSAMPLEFORMAT_PLANAR_S16;
    case cdm::kAudioFormatPlanarF32:
      return PP_DECRYPTEDSAMPLEFORMAT_PLANAR_F32;
    default:
      return PP_DECRYPTEDSAMPLEFORMAT_UNKNOWN;
  }
}

cdm::AudioDecoderConfig::AudioCodec PpAudioCodecToCdmAudioCodec(
    PP_AudioCodec codec) {
  switch (codec) {
    case PP_AUDIOCODEC_VORBIS:
      return cdm::AudioDecoderConfig::kCodecVorbis;
    case PP_AUDIOCODEC_AAC:
      return cdm::AudioDecoderConfig::kCodecAac;
    default:
      return cdm::AudioDecoderConfig::kUnknownAudioCodec;
  }
}

cdm::VideoDecoderConfig::VideoCodec PpVideoCodecToCdmVideoCodec(
    PP_VideoCodec codec) {
  switch (codec) {
    case PP_VIDEOCODEC_VP8:
      return cdm::VideoDecoderConfig::kCodecVp8;
    case PP_VIDEOCODEC_H264:
      return cdm::VideoDecoderConfig::kCodecH264;
    case PP_VIDEOCODEC_VP9:
      return cdm::VideoDecoderConfig::kCodecVp9;
    default:
      return cdm::VideoDecoderConfig::kUnknownVideoCodec;
  }
}

cdm::VideoDecoderConfig::VideoCodecProfile PpVCProfileToCdmVCProfile(
    PP_VideoCodecProfile profile) {
  switch (profile) {
    case PP_VIDEOCODECPROFILE_NOT_NEEDED:
      return cdm::VideoDecoderConfig::kProfileNotNeeded;
    case PP_VIDEOCODECPROFILE_H264_BASELINE:
      return cdm::VideoDecoderConfig::kH264ProfileBaseline;
    case PP_VIDEOCODECPROFILE_H264_MAIN:
      return cdm::VideoDecoderConfig::kH264ProfileMain;
    case PP_VIDEOCODECPROFILE_H264_EXTENDED:
      return cdm::VideoDecoderConfig::kH264ProfileExtended;
    case PP_VIDEOCODECPROFILE_H264_HIGH:
      return cdm::VideoDecoderConfig::kH264ProfileHigh;
    case PP_VIDEOCODECPROFILE_H264_HIGH_10:
      return cdm::VideoDecoderConfig::kH264ProfileHigh10;
    case PP_VIDEOCODECPROFILE_H264_HIGH_422:
      return cdm::VideoDecoderConfig::kH264ProfileHigh422;
    case PP_VIDEOCODECPROFILE_H264_HIGH_444_PREDICTIVE:
      return cdm::VideoDecoderConfig::kH264ProfileHigh444Predictive;
    default:
      return cdm::VideoDecoderConfig::kUnknownVideoCodecProfile;
  }
}

cdm::VideoFormat PpDecryptedFrameFormatToCdmVideoFormat(
    PP_DecryptedFrameFormat format) {
  switch (format) {
    case PP_DECRYPTEDFRAMEFORMAT_YV12:
      return cdm::kYv12;
    case PP_DECRYPTEDFRAMEFORMAT_I420:
      return cdm::kI420;
    default:
      return cdm::kUnknownVideoFormat;
  }
}

cdm::StreamType PpDecryptorStreamTypeToCdmStreamType(
    PP_DecryptorStreamType stream_type) {
  switch (stream_type) {
    case PP_DECRYPTORSTREAMTYPE_AUDIO:
      return cdm::kStreamTypeAudio;
    case PP_DECRYPTORSTREAMTYPE_VIDEO:
      return cdm::kStreamTypeVideo;
  }

  PP_NOTREACHED();
  return cdm::kStreamTypeVideo;
}

cdm::SessionType PpSessionTypeToCdmSessionType(PP_SessionType session_type) {
  switch (session_type) {
    case PP_SESSIONTYPE_TEMPORARY:
      return cdm::kTemporary;
    case PP_SESSIONTYPE_PERSISTENT:
      return cdm::kPersistent;
    default:
      PP_NOTREACHED();
      return cdm::kTemporary;
  }
}

PP_CdmExceptionCode CdmExceptionTypeToPpCdmExceptionType(cdm::Error error) {
  switch (error) {
    case cdm::kNotSupportedError:
      return PP_CDMEXCEPTIONCODE_NOTSUPPORTEDERROR;
    case cdm::kInvalidStateError:
      return PP_CDMEXCEPTIONCODE_INVALIDSTATEERROR;
    case cdm::kInvalidAccessError:
      return PP_CDMEXCEPTIONCODE_INVALIDACCESSERROR;
    case cdm::kQuotaExceededError:
      return PP_CDMEXCEPTIONCODE_QUOTAEXCEEDEDERROR;
    case cdm::kUnknownError:
      return PP_CDMEXCEPTIONCODE_UNKNOWNERROR;
    case cdm::kClientError:
      return PP_CDMEXCEPTIONCODE_CLIENTERROR;
    case cdm::kOutputError:
      return PP_CDMEXCEPTIONCODE_OUTPUTERROR;
    default:
      PP_NOTREACHED();
      return PP_CDMEXCEPTIONCODE_UNKNOWNERROR;
  }
}

}  // namespace

namespace media {

CdmAdapter::CdmAdapter(PP_Instance instance, pp::Module* module)
    : pp::Instance(instance),
      pp::ContentDecryptor_Private(this),
#if defined(OS_CHROMEOS)
      output_protection_(this),
      platform_verification_(this),
      output_link_mask_(0),
      output_protection_mask_(0),
      query_output_protection_in_progress_(false),
      uma_for_output_protection_query_reported_(false),
      uma_for_output_protection_positive_result_reported_(false),
#endif
      allocator_(this),
      cdm_(NULL),
      deferred_initialize_audio_decoder_(false),
      deferred_audio_decoder_config_id_(0),
      deferred_initialize_video_decoder_(false),
      deferred_video_decoder_config_id_(0) {
  callback_factory_.Initialize(this);
}

CdmAdapter::~CdmAdapter() {}

bool CdmAdapter::CreateCdmInstance(const std::string& key_system) {
  PP_DCHECK(!cdm_);
  cdm_ = make_linked_ptr(CdmWrapper::Create(
      key_system.data(), key_system.size(), GetCdmHost, this));
  bool success = cdm_ != NULL;

  const std::string message = "CDM instance for " + key_system +
                              (success ? "" : " could not be") + " created.";
  DLOG_TO_CONSOLE(message);
  CDM_DLOG() << message;

  return success;
}

// No errors should be reported in this function because the spec says:
// "Store this new error object internally with the MediaKeys instance being
// created. This will be used to fire an error against any session created for
// this instance." These errors will be reported during session creation
// (CreateSession()) or session loading (LoadSession()).
// TODO(xhwang): If necessary, we need to store the error here if we want to
// support more specific error reporting (other than "Unknown").
void CdmAdapter::Initialize(const std::string& key_system) {
  PP_DCHECK(!key_system.empty());
  PP_DCHECK(key_system_.empty() || (key_system_ == key_system && cdm_));

#if defined(CHECK_DOCUMENT_URL)
  PP_URLComponents_Dev url_components = {};
  const pp::URLUtil_Dev* url_util = pp::URLUtil_Dev::Get();
  if (!url_util)
    return;
  pp::Var href = url_util->GetDocumentURL(pp::InstanceHandle(pp_instance()),
                                          &url_components);
  PP_DCHECK(href.is_string());
  std::string url = href.AsString();
  PP_DCHECK(!url.empty());
  std::string url_scheme =
      url.substr(url_components.scheme.begin, url_components.scheme.len);
  if (url_scheme != "file") {
    // Skip this check for file:// URLs as they don't have a host component.
    PP_DCHECK(url_components.host.begin);
    PP_DCHECK(0 < url_components.host.len);
  }
#endif  // defined(CHECK_DOCUMENT_URL)

  if (!cdm_ && !CreateCdmInstance(key_system))
    return;

  PP_DCHECK(cdm_);
  key_system_ = key_system;
}

void CdmAdapter::CreateSession(uint32_t promise_id,
                               const std::string& init_data_type,
                               pp::VarArrayBuffer init_data,
                               PP_SessionType session_type) {
  // Initialize() doesn't report an error, so CreateSession() can be called
  // even if Initialize() failed.
  // TODO(jrummell): Remove this code when prefixed EME gets removed.
  // TODO(jrummell): Verify that Initialize() failing does not resolve the
  // MediaKeys.create() promise.
  if (!cdm_) {
    RejectPromise(promise_id,
                  cdm::kInvalidStateError,
                  0,
                  "CDM has not been initialized.");
    return;
  }

  cdm_->CreateSession(promise_id,
                      init_data_type.data(),
                      init_data_type.size(),
                      static_cast<const uint8_t*>(init_data.Map()),
                      init_data.ByteLength(),
                      PpSessionTypeToCdmSessionType(session_type));
}

void CdmAdapter::LoadSession(uint32_t promise_id,
                             const std::string& web_session_id) {
  // Initialize() doesn't report an error, so LoadSession() can be called
  // even if Initialize() failed.
  // TODO(jrummell): Remove this code when prefixed EME gets removed.
  // TODO(jrummell): Verify that Initialize() failing does not resolve the
  // MediaKeys.create() promise.
  if (!cdm_) {
    RejectPromise(promise_id,
                  cdm::kInvalidStateError,
                  0,
                  "CDM has not been initialized.");
    return;
  }

  cdm_->LoadSession(promise_id, web_session_id.data(), web_session_id.size());
}

void CdmAdapter::UpdateSession(uint32_t promise_id,
                               const std::string& web_session_id,
                               pp::VarArrayBuffer response) {
  const uint8_t* response_ptr = static_cast<const uint8_t*>(response.Map());
  const uint32_t response_size = response.ByteLength();

  PP_DCHECK(!web_session_id.empty());
  PP_DCHECK(response_ptr);
  PP_DCHECK(response_size > 0);

  cdm_->UpdateSession(promise_id,
                      web_session_id.data(),
                      web_session_id.length(),
                      response_ptr,
                      response_size);
}

void CdmAdapter::CloseSession(uint32_t promise_id,
                              const std::string& web_session_id) {
  if (!cdm_->CloseSession(
          promise_id, web_session_id.data(), web_session_id.length())) {
    // CDM_4 and CDM_5 don't support this method, so reject the promise.
    RejectPromise(promise_id, cdm::kNotSupportedError, 0, "Not implemented.");
  }
}

void CdmAdapter::ReleaseSession(uint32_t promise_id,
                                const std::string& web_session_id) {
  cdm_->RemoveSession(
      promise_id, web_session_id.data(), web_session_id.length());
}

void CdmAdapter::GetUsableKeyIds(uint32_t promise_id,
                                 const std::string& web_session_id) {
  if (!cdm_->GetUsableKeyIds(
          promise_id, web_session_id.data(), web_session_id.length())) {
    // CDM_4 and CDM_5 don't support this method, so reject the promise.
    RejectPromise(promise_id, cdm::kNotSupportedError, 0, "Not implemented.");
  }
}

// Note: In the following decryption/decoding related functions, errors are NOT
// reported via KeyError, but are reported via corresponding PPB calls.

void CdmAdapter::Decrypt(pp::Buffer_Dev encrypted_buffer,
                         const PP_EncryptedBlockInfo& encrypted_block_info) {
  PP_DCHECK(!encrypted_buffer.is_null());

  // Release a buffer that the caller indicated it is finished with.
  allocator_.Release(encrypted_block_info.tracking_info.buffer_id);

  cdm::Status status = cdm::kDecryptError;
  LinkedDecryptedBlock decrypted_block(new DecryptedBlockImpl());

  if (cdm_) {
    cdm::InputBuffer input_buffer;
    std::vector<cdm::SubsampleEntry> subsamples;
    ConfigureInputBuffer(encrypted_buffer, encrypted_block_info, &subsamples,
                         &input_buffer);
    status = cdm_->Decrypt(input_buffer, decrypted_block.get());
    PP_DCHECK(status != cdm::kSuccess ||
              (decrypted_block->DecryptedBuffer() &&
               decrypted_block->DecryptedBuffer()->Size()));
  }

  CallOnMain(callback_factory_.NewCallback(
      &CdmAdapter::DeliverBlock,
      status,
      decrypted_block,
      encrypted_block_info.tracking_info));
}

void CdmAdapter::InitializeAudioDecoder(
    const PP_AudioDecoderConfig& decoder_config,
    pp::Buffer_Dev extra_data_buffer) {
  PP_DCHECK(!deferred_initialize_audio_decoder_);
  PP_DCHECK(deferred_audio_decoder_config_id_ == 0);
  cdm::Status status = cdm::kSessionError;
  if (cdm_) {
    cdm::AudioDecoderConfig cdm_decoder_config;
    cdm_decoder_config.codec =
        PpAudioCodecToCdmAudioCodec(decoder_config.codec);
    cdm_decoder_config.channel_count = decoder_config.channel_count;
    cdm_decoder_config.bits_per_channel = decoder_config.bits_per_channel;
    cdm_decoder_config.samples_per_second = decoder_config.samples_per_second;
    cdm_decoder_config.extra_data =
        static_cast<uint8_t*>(extra_data_buffer.data());
    cdm_decoder_config.extra_data_size = extra_data_buffer.size();
    status = cdm_->InitializeAudioDecoder(cdm_decoder_config);
  }

  if (status == cdm::kDeferredInitialization) {
    deferred_initialize_audio_decoder_ = true;
    deferred_audio_decoder_config_id_ = decoder_config.request_id;
    return;
  }

  CallOnMain(callback_factory_.NewCallback(
      &CdmAdapter::DecoderInitializeDone,
      PP_DECRYPTORSTREAMTYPE_AUDIO,
      decoder_config.request_id,
      status == cdm::kSuccess));
}

void CdmAdapter::InitializeVideoDecoder(
    const PP_VideoDecoderConfig& decoder_config,
    pp::Buffer_Dev extra_data_buffer) {
  PP_DCHECK(!deferred_initialize_video_decoder_);
  PP_DCHECK(deferred_video_decoder_config_id_ == 0);
  cdm::Status status = cdm::kSessionError;
  if (cdm_) {
    cdm::VideoDecoderConfig cdm_decoder_config;
    cdm_decoder_config.codec =
        PpVideoCodecToCdmVideoCodec(decoder_config.codec);
    cdm_decoder_config.profile =
        PpVCProfileToCdmVCProfile(decoder_config.profile);
    cdm_decoder_config.format =
        PpDecryptedFrameFormatToCdmVideoFormat(decoder_config.format);
    cdm_decoder_config.coded_size.width = decoder_config.width;
    cdm_decoder_config.coded_size.height = decoder_config.height;
    cdm_decoder_config.extra_data =
        static_cast<uint8_t*>(extra_data_buffer.data());
    cdm_decoder_config.extra_data_size = extra_data_buffer.size();
    status = cdm_->InitializeVideoDecoder(cdm_decoder_config);
  }

  if (status == cdm::kDeferredInitialization) {
    deferred_initialize_video_decoder_ = true;
    deferred_video_decoder_config_id_ = decoder_config.request_id;
    return;
  }

  CallOnMain(callback_factory_.NewCallback(
      &CdmAdapter::DecoderInitializeDone,
      PP_DECRYPTORSTREAMTYPE_VIDEO,
      decoder_config.request_id,
      status == cdm::kSuccess));
}

void CdmAdapter::DeinitializeDecoder(PP_DecryptorStreamType decoder_type,
                                     uint32_t request_id) {
  PP_DCHECK(cdm_);  // InitializeXxxxxDecoder should have succeeded.
  if (cdm_) {
    cdm_->DeinitializeDecoder(
        PpDecryptorStreamTypeToCdmStreamType(decoder_type));
  }

  CallOnMain(callback_factory_.NewCallback(
      &CdmAdapter::DecoderDeinitializeDone,
      decoder_type,
      request_id));
}

void CdmAdapter::ResetDecoder(PP_DecryptorStreamType decoder_type,
                              uint32_t request_id) {
  PP_DCHECK(cdm_);  // InitializeXxxxxDecoder should have succeeded.
  if (cdm_)
    cdm_->ResetDecoder(PpDecryptorStreamTypeToCdmStreamType(decoder_type));

  CallOnMain(callback_factory_.NewCallback(&CdmAdapter::DecoderResetDone,
                                           decoder_type,
                                           request_id));
}

void CdmAdapter::DecryptAndDecode(
    PP_DecryptorStreamType decoder_type,
    pp::Buffer_Dev encrypted_buffer,
    const PP_EncryptedBlockInfo& encrypted_block_info) {
  PP_DCHECK(cdm_);  // InitializeXxxxxDecoder should have succeeded.
  // Release a buffer that the caller indicated it is finished with.
  allocator_.Release(encrypted_block_info.tracking_info.buffer_id);

  cdm::InputBuffer input_buffer;
  std::vector<cdm::SubsampleEntry> subsamples;
  if (cdm_ && !encrypted_buffer.is_null()) {
    ConfigureInputBuffer(encrypted_buffer,
                         encrypted_block_info,
                         &subsamples,
                         &input_buffer);
  }

  cdm::Status status = cdm::kDecodeError;

  switch (decoder_type) {
    case PP_DECRYPTORSTREAMTYPE_VIDEO: {
      LinkedVideoFrame video_frame(new VideoFrameImpl());
      if (cdm_)
        status = cdm_->DecryptAndDecodeFrame(input_buffer, video_frame.get());
      CallOnMain(callback_factory_.NewCallback(
          &CdmAdapter::DeliverFrame,
          status,
          video_frame,
          encrypted_block_info.tracking_info));
      return;
    }

    case PP_DECRYPTORSTREAMTYPE_AUDIO: {
      LinkedAudioFrames audio_frames(new AudioFramesImpl());
      if (cdm_) {
        status = cdm_->DecryptAndDecodeSamples(input_buffer,
                                               audio_frames.get());
      }
      CallOnMain(callback_factory_.NewCallback(
          &CdmAdapter::DeliverSamples,
          status,
          audio_frames,
          encrypted_block_info.tracking_info));
      return;
    }

    default:
      PP_NOTREACHED();
      return;
  }
}

cdm::Buffer* CdmAdapter::Allocate(uint32_t capacity) {
  return allocator_.Allocate(capacity);
}

void CdmAdapter::SetTimer(int64_t delay_ms, void* context) {
  // NOTE: doesn't really need to run on the main thread; could just as well run
  // on a helper thread if |cdm_| were thread-friendly and care was taken.  We
  // only use CallOnMainThread() here to get delayed-execution behavior.
  pp::Module::Get()->core()->CallOnMainThread(
      delay_ms,
      callback_factory_.NewCallback(&CdmAdapter::TimerExpired, context),
      PP_OK);
}

void CdmAdapter::TimerExpired(int32_t result, void* context) {
  PP_DCHECK(result == PP_OK);
  cdm_->TimerExpired(context);
}

// cdm::Host_4 methods

double CdmAdapter::GetCurrentWallTimeInSeconds() {
  return GetCurrentTime();
}

void CdmAdapter::OnSessionCreated(uint32_t session_id,
                                  const char* web_session_id,
                                  uint32_t web_session_id_length) {
  uint32_t promise_id = cdm_->LookupPromiseId(session_id);
  cdm_->AssignWebSessionId(session_id, web_session_id, web_session_id_length);
  OnResolveNewSessionPromise(promise_id, web_session_id, web_session_id_length);
}

void CdmAdapter::OnSessionMessage(uint32_t session_id,
                                  const char* message,
                                  uint32_t message_length,
                                  const char* destination_url,
                                  uint32_t destination_url_length) {
  std::string web_session_id = cdm_->LookupWebSessionId(session_id);
  OnSessionMessage(web_session_id.data(),
                   web_session_id.length(),
                   message,
                   message_length,
                   destination_url,
                   destination_url_length);
}

void CdmAdapter::OnSessionReady(uint32_t session_id) {
  uint32_t promise_id = cdm_->LookupPromiseId(session_id);
  if (promise_id) {
    OnResolvePromise(promise_id);
  } else {
    std::string web_session_id = cdm_->LookupWebSessionId(session_id);
    OnSessionReady(web_session_id.data(), web_session_id.length());
  }
}

void CdmAdapter::OnSessionClosed(uint32_t session_id) {
  uint32_t promise_id = cdm_->LookupPromiseId(session_id);
  std::string web_session_id = cdm_->LookupWebSessionId(session_id);
  cdm_->DropWebSessionId(web_session_id);
  if (promise_id) {
    OnResolvePromise(promise_id);
  } else {
    OnSessionClosed(web_session_id.data(), web_session_id.length());
  }
}

void CdmAdapter::OnSessionError(uint32_t session_id,
                                cdm::MediaKeyError error_code,
                                uint32_t system_code) {
  uint32_t promise_id = cdm_->LookupPromiseId(session_id);

  // Existing cdm::MediaKeyError don't map to DOM error names. Convert them
  // into non-standard names so that the prefixed API can extract them.
  // TODO(jrummell): Remove this conversion and the inverse when CDM4 is gone.
  cdm::Error error;
  switch (error_code) {
    case cdm::kPrefixedClientError:
      error = cdm::kClientError;
      break;
    case cdm::kPrefixedOutputError:
      error = cdm::kOutputError;
      break;
    case cdm::kPrefixedUnknownError:
    default:
      error = cdm::kUnknownError;
      break;
  }

  if (promise_id) {
    RejectPromise(promise_id, error, system_code, std::string());
  } else {
    std::string web_session_id = cdm_->LookupWebSessionId(session_id);
    OnSessionError(web_session_id.data(),
                   web_session_id.length(),
                   error,
                   system_code,
                   NULL,
                   0);
  }
}

// cdm::Host_5 and cdm::Host_6 methods

cdm::Time CdmAdapter::GetCurrentTime() {
  return GetCurrentWallTime();
}

cdm::Time CdmAdapter::GetCurrentWallTime() {
  return pp::Module::Get()->core()->GetTime();
}

void CdmAdapter::OnResolvePromise(uint32_t promise_id) {
  PostOnMain(callback_factory_.NewCallback(
      &CdmAdapter::SendPromiseResolvedInternal, promise_id));

  // CDM_5 doesn't support OnSessionKeysChange(), so simulate one if requested.
  // Passing "true" which may result in false positives for retrying.
  std::string session_id;
  if (cdm_->SessionUsableKeysEventNeeded(promise_id, &session_id))
    OnSessionKeysChange(session_id.data(), session_id.length(), true);
}

void CdmAdapter::OnResolveNewSessionPromise(uint32_t promise_id,
                                            const char* web_session_id,
                                            uint32_t web_session_id_length) {
  PostOnMain(callback_factory_.NewCallback(
      &CdmAdapter::SendPromiseResolvedWithSessionInternal,
      promise_id,
      std::string(web_session_id, web_session_id_length)));

  // CDM_5 doesn't support OnSessionKeysChange(), so simulate one if requested.
  // Passing "true" which may result in false positives for retrying.
  std::string session_id;
  if (cdm_->SessionUsableKeysEventNeeded(promise_id, &session_id))
    OnSessionKeysChange(web_session_id, web_session_id_length, true);
}

void CdmAdapter::OnResolveKeyIdsPromise(uint32_t promise_id,
                                        const cdm::BinaryData* usable_key_ids,
                                        uint32_t usable_key_ids_length) {
  std::vector<std::vector<uint8> > key_ids;
  for (uint32_t i = 0; i < usable_key_ids_length; ++i) {
    key_ids.push_back(
        std::vector<uint8>(usable_key_ids[i].data,
                           usable_key_ids[i].data + usable_key_ids[i].length));
  }
  PostOnMain(callback_factory_.NewCallback(
      &CdmAdapter::SendPromiseResolvedWithUsableKeyIdsInternal,
      promise_id,
      key_ids));
}

void CdmAdapter::OnRejectPromise(uint32_t promise_id,
                                 cdm::Error error,
                                 uint32_t system_code,
                                 const char* error_message,
                                 uint32_t error_message_length) {
  RejectPromise(promise_id,
                error,
                system_code,
                std::string(error_message, error_message_length));
}

void CdmAdapter::RejectPromise(uint32_t promise_id,
                               cdm::Error error,
                               uint32_t system_code,
                               const std::string& error_message) {
  PostOnMain(callback_factory_.NewCallback(
      &CdmAdapter::SendPromiseRejectedInternal,
      promise_id,
      SessionError(error, system_code, error_message)));
}

void CdmAdapter::OnSessionMessage(const char* web_session_id,
                                  uint32_t web_session_id_length,
                                  const char* message,
                                  uint32_t message_length,
                                  const char* destination_url,
                                  uint32_t destination_url_length) {
  PostOnMain(callback_factory_.NewCallback(
      &CdmAdapter::SendSessionMessageInternal,
      std::string(web_session_id, web_session_id_length),
      std::vector<uint8>(message, message + message_length),
      std::string(destination_url, destination_url_length)));
}

void CdmAdapter::OnSessionKeysChange(const char* web_session_id,
                                     uint32_t web_session_id_length,
                                     bool has_additional_usable_key) {
  OnSessionUsableKeysChange(
      web_session_id, web_session_id_length, has_additional_usable_key);
}

void CdmAdapter::OnSessionUsableKeysChange(const char* web_session_id,
                                           uint32_t web_session_id_length,
                                           bool has_additional_usable_key) {
  PostOnMain(callback_factory_.NewCallback(
      &CdmAdapter::SendSessionUsableKeysChangeInternal,
      std::string(web_session_id, web_session_id_length),
      has_additional_usable_key));
}

void CdmAdapter::OnExpirationChange(const char* web_session_id,
                                    uint32_t web_session_id_length,
                                    cdm::Time new_expiry_time) {
  PostOnMain(callback_factory_.NewCallback(
      &CdmAdapter::SendExpirationChangeInternal,
      std::string(web_session_id, web_session_id_length),
      new_expiry_time));
}

void CdmAdapter::OnSessionReady(const char* web_session_id,
                                uint32_t web_session_id_length) {
  PostOnMain(callback_factory_.NewCallback(
      &CdmAdapter::SendSessionReadyInternal,
      std::string(web_session_id, web_session_id_length)));
}

void CdmAdapter::OnSessionClosed(const char* web_session_id,
                                 uint32_t web_session_id_length) {
  PostOnMain(callback_factory_.NewCallback(
      &CdmAdapter::SendSessionClosedInternal,
      std::string(web_session_id, web_session_id_length)));
}

void CdmAdapter::OnSessionError(const char* web_session_id,
                                uint32_t web_session_id_length,
                                cdm::Error error,
                                uint32_t system_code,
                                const char* error_message,
                                uint32_t error_message_length) {
  PostOnMain(callback_factory_.NewCallback(
      &CdmAdapter::SendSessionErrorInternal,
      std::string(web_session_id, web_session_id_length),
      SessionError(error,
                   system_code,
                   std::string(error_message, error_message_length))));
}

// Helpers to pass the event to Pepper.

void CdmAdapter::SendPromiseResolvedInternal(int32_t result,
                                             uint32_t promise_id) {
  PP_DCHECK(result == PP_OK);
  pp::ContentDecryptor_Private::PromiseResolved(promise_id);
}

void CdmAdapter::SendPromiseResolvedWithSessionInternal(
    int32_t result,
    uint32_t promise_id,
    const std::string& web_session_id) {
  PP_DCHECK(result == PP_OK);
  pp::ContentDecryptor_Private::PromiseResolvedWithSession(promise_id,
                                                           web_session_id);
}

void CdmAdapter::SendPromiseResolvedWithUsableKeyIdsInternal(
    int32_t result,
    uint32_t promise_id,
    std::vector<std::vector<uint8> > key_ids) {
  PP_DCHECK(result == PP_OK);
  // TODO(jrummell): Implement this event in subsequent CL.
  // (http://crbug.com/358271).
}

void CdmAdapter::SendPromiseRejectedInternal(int32_t result,
                                             uint32_t promise_id,
                                             const SessionError& error) {
  PP_DCHECK(result == PP_OK);
  pp::ContentDecryptor_Private::PromiseRejected(
      promise_id,
      CdmExceptionTypeToPpCdmExceptionType(error.error),
      error.system_code,
      error.error_description);
}

void CdmAdapter::SendSessionMessageInternal(
    int32_t result,
    const std::string& web_session_id,
    const std::vector<uint8>& message,
    const std::string& destination_url) {
  PP_DCHECK(result == PP_OK);

  pp::VarArrayBuffer message_array_buffer(message.size());
  if (message.size() > 0) {
    memcpy(message_array_buffer.Map(), message.data(), message.size());
  }

  pp::ContentDecryptor_Private::SessionMessage(
      web_session_id, message_array_buffer, destination_url);
}

void CdmAdapter::SendSessionReadyInternal(int32_t result,
                                          const std::string& web_session_id) {
  PP_DCHECK(result == PP_OK);
  pp::ContentDecryptor_Private::SessionReady(web_session_id);
}

void CdmAdapter::SendSessionClosedInternal(int32_t result,
                                           const std::string& web_session_id) {
  PP_DCHECK(result == PP_OK);
  pp::ContentDecryptor_Private::SessionClosed(web_session_id);
}

void CdmAdapter::SendSessionErrorInternal(int32_t result,
                                          const std::string& web_session_id,
                                          const SessionError& error) {
  PP_DCHECK(result == PP_OK);
  pp::ContentDecryptor_Private::SessionError(
      web_session_id,
      CdmExceptionTypeToPpCdmExceptionType(error.error),
      error.system_code,
      error.error_description);
}

void CdmAdapter::SendSessionUsableKeysChangeInternal(
    int32_t result,
    const std::string& web_session_id,
    bool has_additional_usable_key) {
  PP_DCHECK(result == PP_OK);
  // TODO(jrummell): Implement this event in subsequent CL.
  // (http://crbug.com/358271).
}

void CdmAdapter::SendExpirationChangeInternal(int32_t result,
                                              const std::string& web_session_id,
                                              cdm::Time new_expiry_time) {
  PP_DCHECK(result == PP_OK);
  // TODO(jrummell): Implement this event in subsequent CL.
  // (http://crbug.com/358271).
}

void CdmAdapter::DeliverBlock(int32_t result,
                              const cdm::Status& status,
                              const LinkedDecryptedBlock& decrypted_block,
                              const PP_DecryptTrackingInfo& tracking_info) {
  PP_DCHECK(result == PP_OK);
  PP_DecryptedBlockInfo decrypted_block_info = {};
  decrypted_block_info.tracking_info = tracking_info;
  decrypted_block_info.tracking_info.timestamp = decrypted_block->Timestamp();
  decrypted_block_info.tracking_info.buffer_id = 0;
  decrypted_block_info.data_size = 0;
  decrypted_block_info.result = CdmStatusToPpDecryptResult(status);

  pp::Buffer_Dev buffer;

  if (decrypted_block_info.result == PP_DECRYPTRESULT_SUCCESS) {
    PP_DCHECK(decrypted_block.get() && decrypted_block->DecryptedBuffer());
    if (!decrypted_block.get() || !decrypted_block->DecryptedBuffer()) {
      PP_NOTREACHED();
      decrypted_block_info.result = PP_DECRYPTRESULT_DECRYPT_ERROR;
    } else {
      PpbBuffer* ppb_buffer =
          static_cast<PpbBuffer*>(decrypted_block->DecryptedBuffer());
      decrypted_block_info.tracking_info.buffer_id = ppb_buffer->buffer_id();
      decrypted_block_info.data_size = ppb_buffer->Size();

      buffer = ppb_buffer->TakeBuffer();
    }
  }

  pp::ContentDecryptor_Private::DeliverBlock(buffer, decrypted_block_info);
}

void CdmAdapter::DecoderInitializeDone(int32_t result,
                                       PP_DecryptorStreamType decoder_type,
                                       uint32_t request_id,
                                       bool success) {
  PP_DCHECK(result == PP_OK);
  pp::ContentDecryptor_Private::DecoderInitializeDone(decoder_type,
                                                      request_id,
                                                      success);
}

void CdmAdapter::DecoderDeinitializeDone(int32_t result,
                                         PP_DecryptorStreamType decoder_type,
                                         uint32_t request_id) {
  pp::ContentDecryptor_Private::DecoderDeinitializeDone(decoder_type,
                                                        request_id);
}

void CdmAdapter::DecoderResetDone(int32_t result,
                                  PP_DecryptorStreamType decoder_type,
                                  uint32_t request_id) {
  pp::ContentDecryptor_Private::DecoderResetDone(decoder_type, request_id);
}

void CdmAdapter::DeliverFrame(
    int32_t result,
    const cdm::Status& status,
    const LinkedVideoFrame& video_frame,
    const PP_DecryptTrackingInfo& tracking_info) {
  PP_DCHECK(result == PP_OK);
  PP_DecryptedFrameInfo decrypted_frame_info = {};
  decrypted_frame_info.tracking_info.request_id = tracking_info.request_id;
  decrypted_frame_info.tracking_info.buffer_id = 0;
  decrypted_frame_info.result = CdmStatusToPpDecryptResult(status);

  pp::Buffer_Dev buffer;

  if (decrypted_frame_info.result == PP_DECRYPTRESULT_SUCCESS) {
    if (!IsValidVideoFrame(video_frame)) {
      PP_NOTREACHED();
      decrypted_frame_info.result = PP_DECRYPTRESULT_DECODE_ERROR;
    } else {
      PpbBuffer* ppb_buffer =
          static_cast<PpbBuffer*>(video_frame->FrameBuffer());

      decrypted_frame_info.tracking_info.timestamp = video_frame->Timestamp();
      decrypted_frame_info.tracking_info.buffer_id = ppb_buffer->buffer_id();
      decrypted_frame_info.format =
          CdmVideoFormatToPpDecryptedFrameFormat(video_frame->Format());
      decrypted_frame_info.width = video_frame->Size().width;
      decrypted_frame_info.height = video_frame->Size().height;
      decrypted_frame_info.plane_offsets[PP_DECRYPTEDFRAMEPLANES_Y] =
          video_frame->PlaneOffset(cdm::VideoFrame::kYPlane);
      decrypted_frame_info.plane_offsets[PP_DECRYPTEDFRAMEPLANES_U] =
          video_frame->PlaneOffset(cdm::VideoFrame::kUPlane);
      decrypted_frame_info.plane_offsets[PP_DECRYPTEDFRAMEPLANES_V] =
          video_frame->PlaneOffset(cdm::VideoFrame::kVPlane);
      decrypted_frame_info.strides[PP_DECRYPTEDFRAMEPLANES_Y] =
          video_frame->Stride(cdm::VideoFrame::kYPlane);
      decrypted_frame_info.strides[PP_DECRYPTEDFRAMEPLANES_U] =
          video_frame->Stride(cdm::VideoFrame::kUPlane);
      decrypted_frame_info.strides[PP_DECRYPTEDFRAMEPLANES_V] =
          video_frame->Stride(cdm::VideoFrame::kVPlane);

      buffer = ppb_buffer->TakeBuffer();
    }
  }

  pp::ContentDecryptor_Private::DeliverFrame(buffer, decrypted_frame_info);
}

void CdmAdapter::DeliverSamples(int32_t result,
                                const cdm::Status& status,
                                const LinkedAudioFrames& audio_frames,
                                const PP_DecryptTrackingInfo& tracking_info) {
  PP_DCHECK(result == PP_OK);

  PP_DecryptedSampleInfo decrypted_sample_info = {};
  decrypted_sample_info.tracking_info = tracking_info;
  decrypted_sample_info.tracking_info.timestamp = 0;
  decrypted_sample_info.tracking_info.buffer_id = 0;
  decrypted_sample_info.data_size = 0;
  decrypted_sample_info.result = CdmStatusToPpDecryptResult(status);

  pp::Buffer_Dev buffer;

  if (decrypted_sample_info.result == PP_DECRYPTRESULT_SUCCESS) {
    PP_DCHECK(audio_frames.get() && audio_frames->FrameBuffer());
    if (!audio_frames.get() || !audio_frames->FrameBuffer()) {
      PP_NOTREACHED();
      decrypted_sample_info.result = PP_DECRYPTRESULT_DECRYPT_ERROR;
    } else {
      PpbBuffer* ppb_buffer =
          static_cast<PpbBuffer*>(audio_frames->FrameBuffer());

      decrypted_sample_info.tracking_info.buffer_id = ppb_buffer->buffer_id();
      decrypted_sample_info.data_size = ppb_buffer->Size();
      decrypted_sample_info.format =
          CdmAudioFormatToPpDecryptedSampleFormat(audio_frames->Format());

      buffer = ppb_buffer->TakeBuffer();
    }
  }

  pp::ContentDecryptor_Private::DeliverSamples(buffer, decrypted_sample_info);
}

bool CdmAdapter::IsValidVideoFrame(const LinkedVideoFrame& video_frame) {
  if (!video_frame.get() ||
      !video_frame->FrameBuffer() ||
      (video_frame->Format() != cdm::kI420 &&
       video_frame->Format() != cdm::kYv12)) {
    CDM_DLOG() << "Invalid video frame!";
    return false;
  }

  PpbBuffer* ppb_buffer = static_cast<PpbBuffer*>(video_frame->FrameBuffer());

  for (uint32_t i = 0; i < cdm::VideoFrame::kMaxPlanes; ++i) {
    int plane_height = (i == cdm::VideoFrame::kYPlane) ?
        video_frame->Size().height : (video_frame->Size().height + 1) / 2;
    cdm::VideoFrame::VideoPlane plane =
        static_cast<cdm::VideoFrame::VideoPlane>(i);
    if (ppb_buffer->Size() < video_frame->PlaneOffset(plane) +
                             plane_height * video_frame->Stride(plane)) {
      return false;
    }
  }

  return true;
}

#if !defined(NDEBUG)
void CdmAdapter::LogToConsole(const pp::Var& value) {
  PP_DCHECK(IsMainThread());
  const PPB_Console* console = reinterpret_cast<const PPB_Console*>(
      pp::Module::Get()->GetBrowserInterface(PPB_CONSOLE_INTERFACE));
  console->Log(pp_instance(), PP_LOGLEVEL_LOG, value.pp_var());
}
#endif  // !defined(NDEBUG)

void CdmAdapter::SendPlatformChallenge(
    const char* service_id, uint32_t service_id_length,
    const char* challenge, uint32_t challenge_length) {
#if defined(OS_CHROMEOS)
  pp::VarArrayBuffer challenge_var(challenge_length);
  uint8_t* var_data = static_cast<uint8_t*>(challenge_var.Map());
  memcpy(var_data, challenge, challenge_length);

  std::string service_id_str(service_id, service_id_length);

  linked_ptr<PepperPlatformChallengeResponse> response(
      new PepperPlatformChallengeResponse());

  int32_t result = platform_verification_.ChallengePlatform(
      pp::Var(service_id_str),
      challenge_var,
      &response->signed_data,
      &response->signed_data_signature,
      &response->platform_key_certificate,
      callback_factory_.NewCallback(&CdmAdapter::SendPlatformChallengeDone,
                                    response));
  challenge_var.Unmap();
  if (result == PP_OK_COMPLETIONPENDING)
    return;

  // Fall through on error and issue an empty OnPlatformChallengeResponse().
  PP_DCHECK(result != PP_OK);
#endif

  cdm::PlatformChallengeResponse platform_challenge_response = {};
  cdm_->OnPlatformChallengeResponse(platform_challenge_response);
}

void CdmAdapter::EnableOutputProtection(uint32_t desired_protection_mask) {
#if defined(OS_CHROMEOS)
  int32_t result = output_protection_.EnableProtection(
      desired_protection_mask, callback_factory_.NewCallback(
          &CdmAdapter::EnableProtectionDone));

  // Errors are ignored since clients must call QueryOutputProtectionStatus() to
  // inspect the protection status on a regular basis.

  if (result != PP_OK && result != PP_OK_COMPLETIONPENDING)
    CDM_DLOG() << __FUNCTION__ << " failed!";
#endif
}

void CdmAdapter::QueryOutputProtectionStatus() {
#if defined(OS_CHROMEOS)
  PP_DCHECK(!query_output_protection_in_progress_);

  output_link_mask_ = output_protection_mask_ = 0;
  const int32_t result = output_protection_.QueryStatus(
      &output_link_mask_,
      &output_protection_mask_,
      callback_factory_.NewCallback(
          &CdmAdapter::QueryOutputProtectionStatusDone));
  if (result == PP_OK_COMPLETIONPENDING) {
    query_output_protection_in_progress_ = true;
    ReportOutputProtectionQuery();
    return;
  }

  // Fall through on error and issue an empty OnQueryOutputProtectionStatus().
  PP_DCHECK(result != PP_OK);
#endif

  cdm_->OnQueryOutputProtectionStatus(0, 0);
}

void CdmAdapter::OnDeferredInitializationDone(cdm::StreamType stream_type,
                                              cdm::Status decoder_status) {
  switch (stream_type) {
    case cdm::kStreamTypeAudio:
      PP_DCHECK(deferred_initialize_audio_decoder_);
      CallOnMain(
          callback_factory_.NewCallback(&CdmAdapter::DecoderInitializeDone,
                                        PP_DECRYPTORSTREAMTYPE_AUDIO,
                                        deferred_audio_decoder_config_id_,
                                        decoder_status == cdm::kSuccess));
      deferred_initialize_audio_decoder_ = false;
      deferred_audio_decoder_config_id_ = 0;
      break;
    case cdm::kStreamTypeVideo:
      PP_DCHECK(deferred_initialize_video_decoder_);
      CallOnMain(
          callback_factory_.NewCallback(&CdmAdapter::DecoderInitializeDone,
                                        PP_DECRYPTORSTREAMTYPE_VIDEO,
                                        deferred_video_decoder_config_id_,
                                        decoder_status == cdm::kSuccess));
      deferred_initialize_video_decoder_ = false;
      deferred_video_decoder_config_id_ = 0;
      break;
  }
}

// The CDM owns the returned object and must call FileIO::Close() to release it.
cdm::FileIO* CdmAdapter::CreateFileIO(cdm::FileIOClient* client) {
  return new CdmFileIOImpl(client, pp_instance());
}

#if defined(OS_CHROMEOS)
void CdmAdapter::ReportOutputProtectionUMA(OutputProtectionStatus status) {
  pp::UMAPrivate uma_interface_(this);
  uma_interface_.HistogramEnumeration(
      "Media.EME.OutputProtection", status, OUTPUT_PROTECTION_MAX);
}

void CdmAdapter::ReportOutputProtectionQuery() {
  if (uma_for_output_protection_query_reported_)
    return;

  ReportOutputProtectionUMA(OUTPUT_PROTECTION_QUERIED);
  uma_for_output_protection_query_reported_ = true;
}

void CdmAdapter::ReportOutputProtectionQueryResult() {
  if (uma_for_output_protection_positive_result_reported_)
    return;

  // Report UMAs for output protection query result.
  uint32_t external_links = (output_link_mask_ & ~cdm::kLinkTypeInternal);

  if (!external_links) {
    ReportOutputProtectionUMA(OUTPUT_PROTECTION_NO_EXTERNAL_LINK);
    uma_for_output_protection_positive_result_reported_ = true;
    return;
  }

  const uint32_t kProtectableLinks =
      cdm::kLinkTypeHDMI | cdm::kLinkTypeDVI | cdm::kLinkTypeDisplayPort;
  bool is_unprotectable_link_connected = external_links & ~kProtectableLinks;
  bool is_hdcp_enabled_on_all_protectable_links =
      output_protection_mask_ & cdm::kProtectionHDCP;

  if (!is_unprotectable_link_connected &&
      is_hdcp_enabled_on_all_protectable_links) {
    ReportOutputProtectionUMA(
        OUTPUT_PROTECTION_ALL_EXTERNAL_LINKS_PROTECTED);
    uma_for_output_protection_positive_result_reported_ = true;
    return;
  }

  // Do not report a negative result because it could be a false negative.
  // Instead, we will calculate number of negatives using the total number of
  // queries and success results.
}

void CdmAdapter::SendPlatformChallengeDone(
    int32_t result,
    const linked_ptr<PepperPlatformChallengeResponse>& response) {
  if (result != PP_OK) {
    CDM_DLOG() << __FUNCTION__ << ": Platform challenge failed!";
    cdm::PlatformChallengeResponse platform_challenge_response = {};
    cdm_->OnPlatformChallengeResponse(platform_challenge_response);
    return;
  }

  pp::VarArrayBuffer signed_data_var(response->signed_data);
  pp::VarArrayBuffer signed_data_signature_var(response->signed_data_signature);
  std::string platform_key_certificate_string =
      response->platform_key_certificate.AsString();

  cdm::PlatformChallengeResponse platform_challenge_response = {
      static_cast<uint8_t*>(signed_data_var.Map()),
      signed_data_var.ByteLength(),
      static_cast<uint8_t*>(signed_data_signature_var.Map()),
      signed_data_signature_var.ByteLength(),
      reinterpret_cast<const uint8_t*>(platform_key_certificate_string.data()),
      static_cast<uint32_t>(platform_key_certificate_string.length())};
  cdm_->OnPlatformChallengeResponse(platform_challenge_response);

  signed_data_var.Unmap();
  signed_data_signature_var.Unmap();
}

void CdmAdapter::EnableProtectionDone(int32_t result) {
  // Does nothing since clients must call QueryOutputProtectionStatus() to
  // inspect the protection status on a regular basis.
  CDM_DLOG() << __FUNCTION__ << " : " << result;
}

void CdmAdapter::QueryOutputProtectionStatusDone(int32_t result) {
  PP_DCHECK(query_output_protection_in_progress_);
  query_output_protection_in_progress_ = false;

  // Return a protection status of none on error.
  if (result != PP_OK)
    output_link_mask_ = output_protection_mask_ = 0;
  else
    ReportOutputProtectionQueryResult();

  cdm_->OnQueryOutputProtectionStatus(output_link_mask_,
                                      output_protection_mask_);
}
#endif

CdmAdapter::SessionError::SessionError(cdm::Error error,
                                       uint32_t system_code,
                                       std::string error_description)
    : error(error),
      system_code(system_code),
      error_description(error_description) {
}

void* GetCdmHost(int host_interface_version, void* user_data) {
  if (!host_interface_version || !user_data)
    return NULL;

  COMPILE_ASSERT(
      cdm::ContentDecryptionModule::Host::kVersion == cdm::Host_6::kVersion,
      update_code_below);

  // Ensure IsSupportedCdmHostVersion matches implementation of this function.
  // Always update this DCHECK when updating this function.
  // If this check fails, update this function and DCHECK or update
  // IsSupportedCdmHostVersion.

  PP_DCHECK(
      // Future version is not supported.
      !IsSupportedCdmHostVersion(cdm::Host_6::kVersion + 1) &&
      // Current version is supported.
      IsSupportedCdmHostVersion(cdm::Host_6::kVersion) &&
      // Include all previous supported versions (if any) here.
      IsSupportedCdmHostVersion(cdm::Host_5::kVersion) &&
      IsSupportedCdmHostVersion(cdm::Host_4::kVersion) &&
      // One older than the oldest supported version is not supported.
      !IsSupportedCdmHostVersion(cdm::Host_4::kVersion - 1));
  PP_DCHECK(IsSupportedCdmHostVersion(host_interface_version));

  CdmAdapter* cdm_adapter = static_cast<CdmAdapter*>(user_data);
  CDM_DLOG() << "Create CDM Host with version " << host_interface_version;
  switch (host_interface_version) {
    case cdm::Host_4::kVersion:
      return static_cast<cdm::Host_4*>(cdm_adapter);
    case cdm::Host_5::kVersion:
      return static_cast<cdm::Host_5*>(cdm_adapter);
    case cdm::Host_6::kVersion:
      return static_cast<cdm::Host_6*>(cdm_adapter);
    default:
      PP_NOTREACHED();
      return NULL;
  }
}

// This object is the global object representing this plugin library as long
// as it is loaded.
class CdmAdapterModule : public pp::Module {
 public:
  CdmAdapterModule() : pp::Module() {
    // This function blocks the renderer thread (PluginInstance::Initialize()).
    // Move this call to other places if this may be a concern in the future.
    INITIALIZE_CDM_MODULE();
  }
  virtual ~CdmAdapterModule() {
    DeinitializeCdmModule();
  }

  virtual pp::Instance* CreateInstance(PP_Instance instance) {
    return new CdmAdapter(instance, this);
  }

 private:
  CdmFileIOImpl::ResourceTracker cdm_file_io_impl_resource_tracker;
};

}  // namespace media

namespace pp {

// Factory function for your specialization of the Module object.
Module* CreateModule() {
  return new media::CdmAdapterModule();
}

}  // namespace pp
