// Copyright 2018 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "starboard/shared/widevine/drm_system_widevine.h"

#include <algorithm>
#include <vector>

#include "starboard/character.h"
#include "starboard/common/log.h"
#include "starboard/common/mutex.h"
#include "starboard/common/string.h"
#include "starboard/memory.h"
#include "starboard/once.h"
#include "starboard/shared/starboard/application.h"
#include "starboard/shared/widevine/widevine_storage.h"
#include "starboard/shared/widevine/widevine_timer.h"
#include "starboard/time.h"
#include "third_party/ce_cdm/core/include/log.h"  // for wvcdm::InitLogging();
#include "third_party/ce_cdm/core/include/string_conversions.h"

using wv3cdm = ::widevine::Cdm;

namespace starboard {
namespace shared {
namespace widevine {
namespace {

const int kInitializationVectorSize = 16;
const char* kWidevineKeySystem[] = {"com.widevine", "com.widevine.alpha"};
const char kWidevineStorageFileName[] = "wvcdm.dat";

class WidevineClock : public wv3cdm::IClock {
 public:
  int64_t now() override {
    return SbTimeToPosix(SbTimeGetNow()) / kSbTimeMillisecond;
  }
};

class Registry {
 public:
  void Register(SbDrmSystem drm_system) {
    SB_DCHECK(SbDrmSystemIsValid(drm_system));
    ScopedLock scoped_lock(mutex_);
    auto iter = std::find(drm_systems_.begin(), drm_systems_.end(), drm_system);
    SB_DCHECK(iter == drm_systems_.end());
    drm_systems_.push_back(drm_system);
  }

  void Unregister(SbDrmSystem drm_system) {
    ScopedLock scoped_lock(mutex_);
    auto iter = std::find(drm_systems_.begin(), drm_systems_.end(), drm_system);
    SB_DCHECK(iter != drm_systems_.end());
    drm_systems_.erase(iter);
  }

  bool Contains(SbDrmSystem drm_system) const {
    ScopedLock scoped_lock(mutex_);
    auto iter = std::find(drm_systems_.begin(), drm_systems_.end(), drm_system);
    return iter != drm_systems_.end();
  }

 private:
  Mutex mutex_;
  // Use std::vector<> as usually there is only one active instance of widevine
  // drm system.
  std::vector<SbDrmSystem> drm_systems_;
};

SB_ONCE_INITIALIZE_FUNCTION(Registry, GetRegistry);

std::string GetWidevineStoragePath() {
  char path[SB_FILE_MAX_PATH + 1] = {0};
  auto path_size = SB_ARRAY_SIZE_INT(path);
  SB_CHECK(SbSystemGetPath(kSbSystemPathCacheDirectory, path, path_size) &&
           SbStringConcat(path, SB_FILE_SEP_STRING, path_size) &&
           SbStringConcat(path, kWidevineStorageFileName, path_size));
  return path;
}

// Converts |::widevine::Cdm::KeyStatus| to starboard's |SbDrmKeyStatus|
// Note: there is no mapping from any Widevine's Cdm::KeyStatus to
// starboard's kSbDrmKeyStatusDownscaled.
SbDrmKeyStatus CdmKeyStatusToSbDrmKeyStatus(
    const wv3cdm::KeyStatus key_status) {
  switch (key_status) {
    case wv3cdm::kUsable:
      return kSbDrmKeyStatusUsable;
    case wv3cdm::kExpired:
      return kSbDrmKeyStatusExpired;
    case wv3cdm::kOutputRestricted:
      return kSbDrmKeyStatusRestricted;
    case wv3cdm::kStatusPending:
      return kSbDrmKeyStatusPending;
    case wv3cdm::kInternalError:
      return kSbDrmKeyStatusError;
    case wv3cdm::kReleased:
      return kSbDrmKeyStatusReleased;
    default:
      SB_NOTREACHED();
  }
  return kSbDrmKeyStatusError;
}

// Converts |::widevine::Cdm::Status| to starboard's |SbDrmStatus|
// Note: there is no mapping for few Widevine's Cdm::Status-es that
// just converted here to starboard's kSbDrmStatusUnknownError.
SbDrmStatus CdmStatusToSbDrmStatus(const wv3cdm::Status status) {
  switch (status) {
    case wv3cdm::kSuccess:
      return kSbDrmStatusSuccess;
    case wv3cdm::kTypeError:
      return kSbDrmStatusTypeError;
    case wv3cdm::kNotSupported:
      return kSbDrmStatusNotSupportedError;
    case wv3cdm::kInvalidState:
      return kSbDrmStatusInvalidStateError;
    case wv3cdm::kQuotaExceeded:
      return kSbDrmStatusQuotaExceededError;
    case wv3cdm::kNeedsDeviceCertificate:
    case wv3cdm::kSessionNotFound:
    case wv3cdm::kDecryptError:
    case wv3cdm::kNoKey:
    case wv3cdm::kKeyUsageBlockedByPolicy:
    case wv3cdm::kRangeError:
    case wv3cdm::kDeferred:
    case wv3cdm::kUnexpectedError:
      return kSbDrmStatusUnknownError;
    default:
      SB_NOTREACHED();
  }
  return kSbDrmStatusUnknownError;
}

SB_ONCE_INITIALIZE_FUNCTION(Mutex, GetInitializationMutex);

void EnsureWidevineCdmIsInitialized(const std::string& company_name,
                                    const std::string& model_name) {
  static WidevineClock s_clock;
  static WidevineStorage s_storage(GetWidevineStoragePath());
  static WidevineTimer s_timer;
  static bool s_initialized = false;

  ScopedLock scoped_lock(*GetInitializationMutex());

  if (s_initialized) {
    return;
  }

  wvcdm::InitLogging();

  wv3cdm::ClientInfo client_info;

  client_info.product_name = "Cobalt";
  client_info.company_name = company_name;
  client_info.device_name = "";
  client_info.model_name = model_name;
  client_info.arch_name = "";
  client_info.build_info = wv3cdm::version();

  SB_LOG(INFO) << "Initialize wvcdm using product_name: \""
               << client_info.product_name << "\", company_name: \""
               << client_info.company_name << "\", and model_name: \""
               << client_info.model_name << "\".";

  auto log_level = wv3cdm::kInfo;
#if COBALT_BUILD_TYPE_GOLD
  log_level = wv3cdm::kSilent;
#endif  // COBALT_BUILD_TYPE_GOLD
  wv3cdm::Status status =
      wv3cdm::initialize(wv3cdm::kNoSecureOutput, client_info, &s_storage,
                         &s_clock, &s_timer, log_level);
  SB_DCHECK(status == wv3cdm::kSuccess);
  s_initialized = true;
}

}  // namespace

// static
const char DrmSystemWidevine::kFirstSbDrmSessionId[] = "initialdrmsessionid";

DrmSystemWidevine::DrmSystemWidevine(
    void* context,
    SbDrmSessionUpdateRequestFunc session_update_request_callback,
    SbDrmSessionUpdatedFunc session_updated_callback
#if SB_HAS(DRM_KEY_STATUSES)
    ,
    SbDrmSessionKeyStatusesChangedFunc key_statuses_changed_callback
#endif  // SB_HAS(DRM_KEY_STATUSES)
#if SB_API_VERSION >= 10
    ,
    SbDrmServerCertificateUpdatedFunc server_certificate_updated_callback
#endif  // SB_API_VERSION >= 10
#if SB_HAS(DRM_SESSION_CLOSED)
    ,
    SbDrmSessionClosedFunc session_closed_callback
#endif  // SB_HAS(DRM_SESSION_CLOSED)
    ,
    const std::string& company_name,
    const std::string& model_name)
    : context_(context),
      session_update_request_callback_(session_update_request_callback),
      session_updated_callback_(session_updated_callback),
#if SB_HAS(DRM_KEY_STATUSES)
      key_statuses_changed_callback_(key_statuses_changed_callback),
#endif  // SB_HAS(DRM_KEY_STATUSES)
#if SB_API_VERSION >= 10
      server_certificate_updated_callback_(server_certificate_updated_callback),
#endif  // SB_API_VERSION >= 10
#if SB_HAS(DRM_SESSION_CLOSED)
      session_closed_callback_(session_closed_callback),
#endif  // SB_HAS(DRM_SESSION_CLOSED)
      ticket_thread_id_(SbThreadGetId()) {
  SB_DCHECK(!company_name.empty());
  SB_DCHECK(!model_name.empty());

#if !defined(COBALT_BUILD_TYPE_GOLD)
  using shared::starboard::Application;

  auto command_line = Application::Get()->GetCommandLine();
  auto value = command_line->GetSwitchValue("maximum_drm_session_updates");
  if (!value.empty()) {
    maximum_number_of_session_updates_ = SbStringAToI(value.c_str());
    SB_LOG(INFO) << "Limit drm session updates to "
                 << maximum_number_of_session_updates_;
  }
#endif  // !defined(COBALT_BUILD_TYPE_GOLD)

  EnsureWidevineCdmIsInitialized(company_name, model_name);
#if SB_API_VERSION >= 10
  const bool kEnablePrivacyMode = true;
#else   // SB_API_VERSION >= 10
  const bool kEnablePrivacyMode = false;
#endif  // SB_API_VERSION >= 10
  cdm_.reset(wv3cdm::create(this, NULL, kEnablePrivacyMode));
  SB_DCHECK(cdm_);

  GetRegistry()->Register(this);
}

DrmSystemWidevine::~DrmSystemWidevine() {
  GetRegistry()->Unregister(this);
}

// static
bool DrmSystemWidevine::IsKeySystemSupported(const char* key_system) {
  for (auto wv_key_system : kWidevineKeySystem) {
    if (SbStringCompareAll(key_system, wv_key_system) == 0) {
      return true;
    }
  }
  return false;
}

// static
bool DrmSystemWidevine::IsDrmSystemWidevine(SbDrmSystem drm_system) {
  return GetRegistry()->Contains(drm_system);
}

void DrmSystemWidevine::GenerateSessionUpdateRequest(
    int ticket,
    const char* type,
    const void* initialization_data,
    int initialization_data_size) {
  SB_DCHECK(thread_checker_.CalledOnValidThread());

  const std::string init_str(static_cast<const char*>(initialization_data),
                             initialization_data_size);
  wv3cdm::InitDataType init_type = wv3cdm::kWebM;
  if (SbStringCompareAll("cenc", type) == 0) {
    init_type = wv3cdm::kCenc;
  } else if (SbStringCompareAll("webm", type) == 0) {
    init_type = wv3cdm::kWebM;
  } else {
    SB_NOTREACHED();
  }

  if (!is_server_certificate_set_) {
    // When privacy mode is on and server certificate hasn't been set yet for
    // the current playback, save the requests and send a server certificate
    // request instead.
    bool first_request = pending_generate_session_update_requests_.empty();
    GenerateSessionUpdateRequestData request_data = {
        first_request ? kSbDrmTicketInvalid : ticket, init_type, init_str};
    pending_generate_session_update_requests_.push_back(request_data);
    if (first_request) {
      SendServerCertificateRequest(ticket);
    }
    return;
  }

  GenerateSessionUpdateRequestInternal(ticket, init_type, init_str, false);
}

void DrmSystemWidevine::UpdateSession(int ticket,
                                      const void* key,
                                      int key_size,
                                      const void* sb_drm_session_id,
                                      int sb_drm_session_id_size) {
  SB_DCHECK(thread_checker_.CalledOnValidThread());
  const std::string str_key(static_cast<const char*>(key), key_size);

  wv3cdm::Status status;
  if (!pending_generate_session_update_requests_.empty()) {
    status = ProcessServerCertificateResponse(str_key);
  } else {
    std::string wvcdm_session_id;
    bool succeeded = SbDrmSessionIdToWvdmSessionId(
        sb_drm_session_id, sb_drm_session_id_size, &wvcdm_session_id);
    SB_DCHECK(succeeded);
    status = cdm_->update(wvcdm_session_id, str_key);
  }
  SB_DLOG(INFO) << "Update keys status " << status;
#if SB_API_VERSION >= 10
  session_updated_callback_(this, context_, ticket,
                            CdmStatusToSbDrmStatus(status), "",
                            sb_drm_session_id, sb_drm_session_id_size);
#else   // SB_API_VERSION >= 10
  session_updated_callback_(this, context_, ticket, sb_drm_session_id,
                            sb_drm_session_id_size, status == wv3cdm::kSuccess);
#endif  // SB_API_VERSION >= 10

  // It is possible that |key| actually contains a server certificate, in such
  // case try to process the pending GenerateSessionUpdateRequest() calls.
  TrySendPendingGenerateSessionUpdateRequests();
}

void DrmSystemWidevine::CloseSession(const void* sb_drm_session_id,
                                     int sb_drm_session_id_size) {
  SB_DCHECK(thread_checker_.CalledOnValidThread());
  std::string wvcdm_session_id;
  bool succeeded = SbDrmSessionIdToWvdmSessionId(
      sb_drm_session_id, sb_drm_session_id_size, &wvcdm_session_id);
  if (succeeded) {
    cdm_->close(wvcdm_session_id);
  }
#if SB_HAS(DRM_SESSION_CLOSED)
  session_closed_callback_(this, context_, sb_drm_session_id,
                           sb_drm_session_id_size);
#endif  // SB_HAS(DRM_SESSION_CLOSED)
}

#if SB_API_VERSION >= 10
void DrmSystemWidevine::UpdateServerCertificate(int ticket,
                                                const void* certificate,
                                                int certificate_size) {
  SB_DCHECK(thread_checker_.CalledOnValidThread());
  const std::string str_certificate(static_cast<const char*>(certificate),
                                    certificate_size);
  wv3cdm::Status status = cdm_->setServiceCertificate(str_certificate);

  is_server_certificate_set_ = (status == wv3cdm::kSuccess);

  server_certificate_updated_callback_(this, context_, ticket,
                                       CdmStatusToSbDrmStatus(status), "");
}
#endif  // SB_API_VERSION >= 10

void IncrementIv(uint8_t* iv, size_t block_count) {
  if (0 == block_count)
    return;
  uint8_t carry = 0;
  uint8_t n = static_cast<uint8_t>(kInitializationVectorSize - 1);

  while (n >= 8) {
    uint32_t temp = block_count & 0xff;
    temp += iv[n];
    temp += carry;
    iv[n] = temp & 0xff;
    carry = (temp & 0x100) ? 1 : 0;
    block_count = block_count >> 8;
    n--;
    if (0 == block_count && !carry) {
      break;
    }
  }
}

SbDrmSystemPrivate::DecryptStatus DrmSystemWidevine::Decrypt(
    InputBuffer* buffer) {
  const SbDrmSampleInfo* drm_info = buffer->drm_info();

  if (drm_info == NULL || drm_info->initialization_vector_size == 0) {
    return kSuccess;
  }

  // Adapt |buffer| and |drm_info| to a |cdm::InputBuffer|.
  SB_DCHECK(drm_info->initialization_vector_size == kInitializationVectorSize);
  std::vector<uint8_t> initialization_vector(
      drm_info->initialization_vector,
      drm_info->initialization_vector + drm_info->initialization_vector_size);

  wv3cdm::InputBuffer input;
  input.data = buffer->data();
  input.data_length = buffer->size();
  input.block_offset = 0;
  input.key_id = drm_info->identifier;
  input.key_id_length = drm_info->identifier_size;
  input.iv = initialization_vector.data();
  input.iv_length = static_cast<uint32_t>(initialization_vector.size());
  input.is_video = (buffer->sample_type() == kSbMediaTypeVideo);

  std::vector<uint8_t> output_data(buffer->size());
  wv3cdm::OutputBuffer output;
  output.data = output_data.data();
  output.data_length = output_data.size();

  size_t block_counter = 0;
  size_t encrypted_offset = 0;

  for (size_t i = 0; i < buffer->drm_info()->subsample_count; i++) {
    const SbDrmSubSampleMapping& subsample =
        buffer->drm_info()->subsample_mapping[i];
    if (subsample.clear_byte_count) {
      input.last_subsample = i + 1 == buffer->drm_info()->subsample_count &&
                             subsample.encrypted_byte_count == 0;
      input.encryption_scheme = wv3cdm::EncryptionScheme::kClear;
      input.data_length = subsample.clear_byte_count;

      wv3cdm::Status status = cdm_->decrypt(input, output);
      if (status != wv3cdm::kSuccess) {
        if (status == wv3cdm::kNoKey) {
          return kRetry;
        }
        SB_DLOG(ERROR) << "Decrypt status " << status;
        SB_DLOG(ERROR) << "Key ID "
                       << wvcdm::b2a_hex(
                              std::string(reinterpret_cast<const char*>(
                                              &drm_info->identifier[0]),
                                          drm_info->identifier_size));
        return kFailure;
      }

      input.data += subsample.clear_byte_count;
      output.data += subsample.clear_byte_count;
      output.data_length -= subsample.clear_byte_count;
      input.first_subsample = false;
    }

    if (subsample.encrypted_byte_count) {
      input.last_subsample = i + 1 == buffer->drm_info()->subsample_count;
      input.encryption_scheme = wv3cdm::EncryptionScheme::kAesCtr;
      input.data_length = subsample.encrypted_byte_count;

      wv3cdm::Status status = cdm_->decrypt(input, output);
      if (status != wv3cdm::kSuccess) {
        if (status == wv3cdm::kNoKey) {
          SB_DLOG(ERROR) << "Decrypt status: kNoKey";
          return kRetry;
        }
        SB_DLOG(ERROR) << "Decrypt status " << status;
        SB_DLOG(ERROR) << "Key ID "
                       << wvcdm::b2a_hex(
                              std::string(reinterpret_cast<const char*>(
                                              &drm_info->identifier[0]),
                                          drm_info->identifier_size));
        return kFailure;
      }

      input.data += subsample.encrypted_byte_count;
      output.data += subsample.encrypted_byte_count;
      output.data_length -= subsample.encrypted_byte_count;

      input.block_offset += subsample.encrypted_byte_count;
      input.block_offset %= 16;

      encrypted_offset += subsample.encrypted_byte_count;

      // Increase initialization vector for CTR mode.
      if (input.encryption_scheme == wv3cdm::kAesCtr) {
        size_t new_block_counter = encrypted_offset / 16;
        IncrementIv(initialization_vector.data(),
                    new_block_counter - block_counter);
        block_counter = new_block_counter;
      }
      input.first_subsample = false;
    }
  }

  buffer->SetDecryptedContent(output_data.data(), output_data.size());
  return kSuccess;
}

void DrmSystemWidevine::GenerateSessionUpdateRequestInternal(
    int ticket,
    wv3cdm::InitDataType init_data_type,
    const std::string& initialization_data,
    bool is_first_session) {
  SB_DCHECK(thread_checker_.CalledOnValidThread());

  wv3cdm::SessionType session_type = wv3cdm::kTemporary;

  std::string wvcdm_session_id;
  // createSession() may return |kDeferred| if individualization is pending.
  wv3cdm::Status status = cdm_->createSession(session_type, &wvcdm_session_id);

  if (status == wv3cdm::kSuccess) {
    // Ensure that the session id generated by the cdm is never the same as the
    // fake id (kFirstSbDrmSessionId).
    SB_DCHECK(wvcdm_session_id != kFirstSbDrmSessionId);
    if (is_first_session) {
      first_wvcdm_session_id_ = wvcdm_session_id;
    }
    SetTicket(WvdmSessionIdToSbDrmSessionId(wvcdm_session_id), ticket);
    SB_DLOG(INFO) << "Calling generateRequest()";
    status = cdm_->generateRequest(wvcdm_session_id, init_data_type,
                                   initialization_data);
    SB_DLOG(INFO) << "generateRequest() returns " << status;
  } else {
    // createSession() shouldn't return |kDeferred|, and if it does, the
    // following if statement will incorrectly assume that there is a follow-up
    // license request automatically generated after the individualization is
    // finished, which won't happen.
    SB_DCHECK(status != wv3cdm::kDeferred);
  }

  if (status != wv3cdm::kSuccess && status != wv3cdm::kDeferred) {
    // Reset ticket before invoking user-provided callback to indicate that
    // no session update request is pending.
    SetTicket(WvdmSessionIdToSbDrmSessionId(wvcdm_session_id),
              kSbDrmTicketInvalid);

    SB_DLOG(ERROR) << "GenerateKeyRequest status " << status;
// Send an empty request to signal an error.
#if SB_API_VERSION >= 10
    session_update_request_callback_(
        this, context_, ticket, CdmStatusToSbDrmStatus(status),
        kSbDrmSessionRequestTypeLicenseRequest, "", NULL, 0, NULL, 0, NULL);
#else   // SB_API_VERSION >= 10
    session_update_request_callback_(this, context_, ticket, NULL, 0, NULL, 0,
                                     NULL);
#endif  // SB_API_VERSION >= 10
  }

  // When |status| is |kDeferred|, it indicates that the cdm requires
  // individualization.  In such case an individualization request may be sent
  // if this is the first GenerateSessionUpdateRequest().  We won't send a
  // generated key request now. Once the individualization response is received
  // by the cdm, it will call |onMessage| for all pending sessions on the same
  // thread.
}

void DrmSystemWidevine::onMessage(const std::string& wvcdm_session_id,
                                  wv3cdm::MessageType message_type,
                                  const std::string& message) {
  const std::string sb_drm_session_id =
      WvdmSessionIdToSbDrmSessionId(wvcdm_session_id);
  switch (message_type) {
    case wv3cdm::kLicenseRequest:
      SendSessionUpdateRequest(kSbDrmSessionRequestTypeLicenseRequest,
                               sb_drm_session_id, message);
      break;
    case wv3cdm::kLicenseRenewal:
      SendSessionUpdateRequest(kSbDrmSessionRequestTypeLicenseRenewal,
                               sb_drm_session_id, message);
      break;
    case wv3cdm::kLicenseRelease:
      SendSessionUpdateRequest(kSbDrmSessionRequestTypeLicenseRelease,
                               sb_drm_session_id, message);
      break;
    case wv3cdm::kIndividualizationRequest:
      // Not used, onDirectIndividualizationRequest() will be called instead.
      SB_NOTREACHED();
      break;
    case wv3cdm::kLicenseSub:
      // For loading sub licenses from embedded key data, not used.
      SB_NOTREACHED();
      break;
  }
}

void DrmSystemWidevine::onKeyStatusesChange(
    const std::string& wvcdm_session_id) {
#if SB_HAS(DRM_KEY_STATUSES)
  wv3cdm::KeyStatusMap key_statuses;
  wv3cdm::Status status = cdm_->getKeyStatuses(wvcdm_session_id, &key_statuses);

  if (status != wv3cdm::kSuccess) {
    return;
  }

  std::vector<SbDrmKeyId> sb_key_ids;
  std::vector<SbDrmKeyStatus> sb_key_statuses;

  for (auto& key_status : key_statuses) {
    SbDrmKeyId sb_key_id;
    SB_DCHECK(key_status.first.size() <= sizeof(sb_key_id.identifier));
    SbMemoryCopy(sb_key_id.identifier, key_status.first.c_str(),
                 key_status.first.size());
    sb_key_id.identifier_size = static_cast<int>(key_status.first.size());
    sb_key_ids.push_back(sb_key_id);
    sb_key_statuses.push_back(CdmKeyStatusToSbDrmKeyStatus(key_status.second));
  }

  const std::string sb_drm_session_id =
      WvdmSessionIdToSbDrmSessionId(wvcdm_session_id);
  key_statuses_changed_callback_(this, context_, sb_drm_session_id.c_str(),
                                 sb_drm_session_id.size(), sb_key_ids.size(),
                                 sb_key_ids.data(), sb_key_statuses.data());
#else   // SB_HAS(DRM_KEY_STATUSES)
  SB_UNREFERENCED_PARAMETER(wvcdm_session_id);
#endif  // SB_HAS(DRM_KEY_STATUSES)
}

void DrmSystemWidevine::onRemoveComplete(const std::string& wvcdm_session_id) {
  SB_UNREFERENCED_PARAMETER(wvcdm_session_id);
  SB_NOTIMPLEMENTED();
}

void DrmSystemWidevine::onDeferredComplete(const std::string& wvcdm_session_id,
                                           wv3cdm::Status result) {
  SB_UNREFERENCED_PARAMETER(wvcdm_session_id);
  SB_UNREFERENCED_PARAMETER(result);
  SB_NOTIMPLEMENTED();
}

void DrmSystemWidevine::onDirectIndividualizationRequest(
    const std::string& wvcdm_session_id,
    const std::string& request) {
  SendSessionUpdateRequest(kSbDrmSessionRequestTypeIndividualizationRequest,
                           WvdmSessionIdToSbDrmSessionId(wvcdm_session_id),
                           request);
}

void DrmSystemWidevine::SetTicket(const std::string& sb_drm_session_id,
                                  int ticket) {
  SB_DCHECK(SbThreadGetId() == ticket_thread_id_)
      << "Ticket should only be set from the constructor thread.";
  sb_drm_session_id_to_ticket_map_[sb_drm_session_id] = ticket;
}

int DrmSystemWidevine::GetAndResetTicket(const std::string& sb_drm_session_id) {
  // Returning no ticket is a valid way to indicate that a host's method was
  // called spontaneously by CDM, potentially from the timer thread.
  if (SbThreadGetId() != ticket_thread_id_) {
    return kSbDrmTicketInvalid;
  }
  auto iter = sb_drm_session_id_to_ticket_map_.find(sb_drm_session_id);
  if (iter == sb_drm_session_id_to_ticket_map_.end()) {
    return kSbDrmTicketInvalid;
  }
  auto ticket = iter->second;
  sb_drm_session_id_to_ticket_map_.erase(iter);
  return ticket;
}

std::string DrmSystemWidevine::WvdmSessionIdToSbDrmSessionId(
    const std::string& wvcdm_session_id) {
#if SB_API_VERSION >= 10
  SB_DCHECK(wvcdm_session_id != kFirstSbDrmSessionId);
  if (wvcdm_session_id == first_wvcdm_session_id_) {
    return kFirstSbDrmSessionId;
  }
#endif  // SB_API_VERSION >= 10
  return wvcdm_session_id;
}

bool DrmSystemWidevine::SbDrmSessionIdToWvdmSessionId(
    const void* sb_drm_session_id,
    int sb_drm_session_id_size,
    std::string* wvcdm_session_id) {
  SB_DCHECK(wvcdm_session_id);
  const std::string str_sb_drm_session_id(
      static_cast<const char*>(sb_drm_session_id), sb_drm_session_id_size);
#if SB_API_VERSION >= 10
  if (str_sb_drm_session_id == kFirstSbDrmSessionId) {
    *wvcdm_session_id = first_wvcdm_session_id_;
    return !first_wvcdm_session_id_.empty();
  }
#endif  // SB_API_VERSION >= 10
  *wvcdm_session_id = str_sb_drm_session_id;
  return true;
}

void DrmSystemWidevine::SendServerCertificateRequest(int ticket) {
  std::string message;
  auto status = cdm_->getServiceCertificateRequest(&message);
  if (status == wv3cdm::kSuccess) {
    SetTicket(kFirstSbDrmSessionId, ticket);
    // Note that calling createSession() without a server certificate may fail.
    // So use |kFirstSbDrmSessionId| as the session id.  Once we have a real
    // session id, we will map it from/to the fake session id.
    SendSessionUpdateRequest(kSbDrmSessionRequestTypeLicenseRequest,
                             kFirstSbDrmSessionId, message);
  } else {
// Signals failure by sending NULL as the session id.
#if SB_API_VERSION >= 10
    session_update_request_callback_(
        this, context_, ticket, CdmStatusToSbDrmStatus(status),
        kSbDrmSessionRequestTypeLicenseRequest, "", NULL, 0, NULL, 0, NULL);
#else   // SB_API_VERSION >= 10
    session_update_request_callback_(this, context_, ticket, NULL, 0, NULL, 0,
                                     NULL);
#endif  // SB_API_VERSION >= 10
  }
}

wv3cdm::Status DrmSystemWidevine::ProcessServerCertificateResponse(
    const std::string& response) {
  SB_DCHECK(thread_checker_.CalledOnValidThread());
  is_server_certificate_set_ = false;
  std::string certificate;
  auto status = cdm_->parseServiceCertificateResponse(response, &certificate);
  if (status != wv3cdm::kSuccess) {
    return status;
  }
  status = cdm_->setServiceCertificate(certificate);
  is_server_certificate_set_ = (status == wv3cdm::kSuccess);
  return status;
}

void DrmSystemWidevine::TrySendPendingGenerateSessionUpdateRequests() {
  SB_DCHECK(thread_checker_.CalledOnValidThread());
  if (!is_server_certificate_set_) {
    return;
  }
  decltype(pending_generate_session_update_requests_) pending_requests;
  pending_requests.swap(pending_generate_session_update_requests_);
  for (auto iter = pending_requests.begin(); iter != pending_requests.end();
       ++iter) {
    GenerateSessionUpdateRequestInternal(iter->ticket, iter->init_data_type,
                                         iter->initialization_data,
                                         iter == pending_requests.begin());
  }
}

void DrmSystemWidevine::SendSessionUpdateRequest(
    SbDrmSessionRequestType type,
    const std::string& sb_drm_session_id,
    const std::string& message) {
  int ticket = GetAndResetTicket(sb_drm_session_id);

#if SB_API_VERSION >= 10

#if !defined(COBALT_BUILD_TYPE_GOLD)
  if (number_of_session_updates_sent_ > maximum_number_of_session_updates_) {
    SB_LOG(INFO) << "Number of drm sessions exceeds maximum allowed session"
                 << " (" << maximum_number_of_session_updates_ << "), fail the"
                 << " current update request with quota exceeded error";
    session_update_request_callback_(
        this, context_, ticket, kSbDrmStatusQuotaExceededError, type, "", NULL,
        0, message.c_str(), static_cast<int>(message.size()), NULL);
    return;
  }
  ++number_of_session_updates_sent_;
#endif  // !defined(COBALT_BUILD_TYPE_GOLD)

  session_update_request_callback_(
      this, context_, ticket, kSbDrmStatusSuccess, type, "",
      sb_drm_session_id.c_str(), static_cast<int>(sb_drm_session_id.size()),
      message.c_str(), static_cast<int>(message.size()), NULL);
#else   // SB_API_VERSION >= 10
  session_update_request_callback_(
      this, context_, ticket, sb_drm_session_id.c_str(),
      static_cast<int>(sb_drm_session_id.size()), message.c_str(),
      static_cast<int>(message.size()), NULL);
#endif  // SB_API_VERSION >= 10
}

}  // namespace widevine
}  // namespace shared
}  // namespace starboard
