// 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 "content/renderer/media/webcontentdecryptionmodulesession_impl.h"

#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/logging.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "content/renderer/media/cdm_session_adapter.h"
#include "media/base/cdm_promise.h"
#include "third_party/WebKit/public/platform/WebURL.h"

namespace content {

const char kCreateSessionUMAName[] = "CreateSession";

// For backwards compatibility with blink not using
// WebContentDecryptionModuleResult, reserve an index for |outstanding_results_|
// that will not be used when adding a WebContentDecryptionModuleResult.
// TODO(jrummell): Remove once blink always uses
// WebContentDecryptionModuleResult.
const uint32 kReservedIndex = 0;

static blink::WebContentDecryptionModuleException ConvertException(
    media::MediaKeys::Exception exception_code) {
  switch (exception_code) {
    case media::MediaKeys::NOT_SUPPORTED_ERROR:
      return blink::WebContentDecryptionModuleExceptionNotSupportedError;
    case media::MediaKeys::INVALID_STATE_ERROR:
      return blink::WebContentDecryptionModuleExceptionInvalidStateError;
    case media::MediaKeys::INVALID_ACCESS_ERROR:
      return blink::WebContentDecryptionModuleExceptionInvalidAccessError;
    case media::MediaKeys::QUOTA_EXCEEDED_ERROR:
      return blink::WebContentDecryptionModuleExceptionQuotaExceededError;
    case media::MediaKeys::UNKNOWN_ERROR:
      return blink::WebContentDecryptionModuleExceptionUnknownError;
    case media::MediaKeys::CLIENT_ERROR:
      return blink::WebContentDecryptionModuleExceptionClientError;
    case media::MediaKeys::OUTPUT_ERROR:
      return blink::WebContentDecryptionModuleExceptionOutputError;
    default:
      NOTREACHED();
      return blink::WebContentDecryptionModuleExceptionUnknownError;
  }
}

WebContentDecryptionModuleSessionImpl::WebContentDecryptionModuleSessionImpl(
    const scoped_refptr<CdmSessionAdapter>& adapter)
    : adapter_(adapter),
      is_closed_(false),
      next_available_result_index_(1),
      weak_ptr_factory_(this) {
}

WebContentDecryptionModuleSessionImpl::
    ~WebContentDecryptionModuleSessionImpl() {
  if (!web_session_id_.empty())
    adapter_->RemoveSession(web_session_id_);

  // Release any WebContentDecryptionModuleResult objects that are left. Their
  // index will have been passed down via a CdmPromise, but it uses a WeakPtr.
  DLOG_IF(WARNING, outstanding_results_.size() > 0)
      << "Clearing " << outstanding_results_.size() << " results";
  for (ResultMap::iterator it = outstanding_results_.begin();
       it != outstanding_results_.end();
       ++it) {
    it->second.completeWithError(
        blink::WebContentDecryptionModuleExceptionInvalidStateError,
        0,
        "Outstanding request being cancelled.");
  }
  outstanding_results_.clear();
}

void WebContentDecryptionModuleSessionImpl::setClientInterface(Client* client) {
  client_ = client;
}

blink::WebString WebContentDecryptionModuleSessionImpl::sessionId() const {
  return blink::WebString::fromUTF8(web_session_id_);
}

void WebContentDecryptionModuleSessionImpl::initializeNewSession(
    const blink::WebString& init_data_type,
    const uint8* init_data,
    size_t init_data_length) {
  DCHECK(base::IsStringASCII(init_data_type));

  std::string init_data_type_as_ascii = base::UTF16ToASCII(init_data_type);
  DLOG_IF(WARNING, init_data_type_as_ascii.find('/') != std::string::npos)
      << "init_data_type '" << init_data_type_as_ascii
      << "' may be a MIME type";

  // Attempt to translate content types.
  // TODO(sandersd): Remove once tests stop using content types.
  // http://crbug.com/385874
  std::string content_type = base::StringToLowerASCII(init_data_type_as_ascii);
  if (content_type == "audio/mp4" || content_type == "video/mp4") {
    init_data_type_as_ascii = "cenc";
  } else if (content_type == "audio/webm" || content_type == "video/webm") {
    init_data_type_as_ascii = "webm";
  }

  scoped_ptr<media::NewSessionCdmPromise> promise(
      new media::NewSessionCdmPromise(
          base::Bind(&WebContentDecryptionModuleSessionImpl::SessionCreated,
                     weak_ptr_factory_.GetWeakPtr(),
                     kReservedIndex),
          base::Bind(&WebContentDecryptionModuleSessionImpl::OnSessionError,
                     weak_ptr_factory_.GetWeakPtr()),
          adapter_->GetKeySystemUMAPrefix() + kCreateSessionUMAName));
  adapter_->InitializeNewSession(init_data_type_as_ascii,
                                 init_data,
                                 init_data_length,
                                 media::MediaKeys::TEMPORARY_SESSION,
                                 promise.Pass());
}

void WebContentDecryptionModuleSessionImpl::update(const uint8* response,
                                                   size_t response_length) {
  DCHECK(response);
  scoped_ptr<media::SimpleCdmPromise> promise(new media::SimpleCdmPromise(
      base::Bind(&WebContentDecryptionModuleSessionImpl::OnSessionReady,
                 weak_ptr_factory_.GetWeakPtr()),
      base::Bind(&WebContentDecryptionModuleSessionImpl::OnSessionError,
                 weak_ptr_factory_.GetWeakPtr())));
  adapter_->UpdateSession(
      web_session_id_, response, response_length, promise.Pass());
}

void WebContentDecryptionModuleSessionImpl::release() {
  scoped_ptr<media::SimpleCdmPromise> promise(new media::SimpleCdmPromise(
      base::Bind(&WebContentDecryptionModuleSessionImpl::OnSessionClosed,
                 weak_ptr_factory_.GetWeakPtr()),
      base::Bind(&WebContentDecryptionModuleSessionImpl::OnSessionError,
                 weak_ptr_factory_.GetWeakPtr())));
  adapter_->ReleaseSession(web_session_id_, promise.Pass());
}

void WebContentDecryptionModuleSessionImpl::initializeNewSession(
    const blink::WebString& init_data_type,
    const uint8* init_data,
    size_t init_data_length,
    const blink::WebString& session_type,
    blink::WebContentDecryptionModuleResult result) {
  uint32 result_index = AddResult(result);

  // TODO(ddorwin): Guard against this in supported types check and remove this.
  // Chromium only supports ASCII MIME types.
  if (!base::IsStringASCII(init_data_type)) {
    NOTREACHED();
    SessionError(result_index,
                 media::MediaKeys::NOT_SUPPORTED_ERROR,
                 0,
                 "The initialization data type " + init_data_type.utf8() +
                     " is not supported by the key system.");
    return;
  }

  std::string init_data_type_as_ascii = base::UTF16ToASCII(init_data_type);
  DLOG_IF(WARNING, init_data_type_as_ascii.find('/') != std::string::npos)
      << "init_data_type '" << init_data_type_as_ascii
      << "' may be a MIME type";

  scoped_ptr<media::NewSessionCdmPromise> promise(
      new media::NewSessionCdmPromise(
          base::Bind(&WebContentDecryptionModuleSessionImpl::SessionCreated,
                     weak_ptr_factory_.GetWeakPtr(),
                     result_index),
          base::Bind(&WebContentDecryptionModuleSessionImpl::SessionError,
                     weak_ptr_factory_.GetWeakPtr(),
                     result_index),
          adapter_->GetKeySystemUMAPrefix() + kCreateSessionUMAName));
  adapter_->InitializeNewSession(init_data_type_as_ascii,
                                 init_data,
                                 init_data_length,
                                 media::MediaKeys::TEMPORARY_SESSION,
                                 promise.Pass());
}

void WebContentDecryptionModuleSessionImpl::update(
    const uint8* response,
    size_t response_length,
    blink::WebContentDecryptionModuleResult result) {
  DCHECK(response);
  uint32 result_index = AddResult(result);
  scoped_ptr<media::SimpleCdmPromise> promise(new media::SimpleCdmPromise(
      base::Bind(
          &WebContentDecryptionModuleSessionImpl::SessionUpdatedOrReleased,
          weak_ptr_factory_.GetWeakPtr(),
          result_index),
      base::Bind(&WebContentDecryptionModuleSessionImpl::SessionError,
                 weak_ptr_factory_.GetWeakPtr(),
                 result_index)));
  adapter_->UpdateSession(
      web_session_id_, response, response_length, promise.Pass());
}

void WebContentDecryptionModuleSessionImpl::release(
    blink::WebContentDecryptionModuleResult result) {
  uint32 result_index = AddResult(result);
  scoped_ptr<media::SimpleCdmPromise> promise(new media::SimpleCdmPromise(
      base::Bind(
          &WebContentDecryptionModuleSessionImpl::SessionUpdatedOrReleased,
          weak_ptr_factory_.GetWeakPtr(),
          result_index),
      base::Bind(&WebContentDecryptionModuleSessionImpl::SessionError,
                 weak_ptr_factory_.GetWeakPtr(),
                 result_index)));
  adapter_->ReleaseSession(web_session_id_, promise.Pass());
}

void WebContentDecryptionModuleSessionImpl::OnSessionMessage(
    const std::vector<uint8>& message,
    const GURL& destination_url) {
  DCHECK(client_) << "Client not set before message event";
  client_->message(
      message.empty() ? NULL : &message[0], message.size(), destination_url);
}

void WebContentDecryptionModuleSessionImpl::OnSessionReady() {
  client_->ready();
}

void WebContentDecryptionModuleSessionImpl::OnSessionClosed() {
  if (!is_closed_) {
    is_closed_ = true;
    client_->close();
  }
}

void WebContentDecryptionModuleSessionImpl::OnSessionError(
    media::MediaKeys::Exception exception_code,
    uint32 system_code,
    const std::string& error_message) {
  // Convert |exception_code| back to MediaKeyErrorCode if possible.
  // TODO(jrummell): Update this conversion when promises flow
  // back into blink:: (as blink:: will have its own error definition).
  switch (exception_code) {
    case media::MediaKeys::CLIENT_ERROR:
      client_->error(Client::MediaKeyErrorCodeClient, system_code);
      break;
    default:
      // This will include all other CDM4 errors and any error generated
      // by CDM5 or later.
      client_->error(Client::MediaKeyErrorCodeUnknown, system_code);
      break;
  }
}

void WebContentDecryptionModuleSessionImpl::SessionCreated(
    uint32 result_index,
    const std::string& web_session_id) {
  blink::WebContentDecryptionModuleResult::SessionStatus status;

  // CDM will return NULL if the session to be loaded can't be found.
  if (web_session_id.empty()) {
    status = blink::WebContentDecryptionModuleResult::SessionNotFound;
  } else {
    DCHECK(web_session_id_.empty())
        << "Session ID may not be changed once set.";
    web_session_id_ = web_session_id;
    status =
        adapter_->RegisterSession(web_session_id_,
                                  weak_ptr_factory_.GetWeakPtr())
            ? blink::WebContentDecryptionModuleResult::NewSession
            : blink::WebContentDecryptionModuleResult::SessionAlreadyExists;
  }

  ResultMap::iterator it = outstanding_results_.find(result_index);
  if (it != outstanding_results_.end()) {
    blink::WebContentDecryptionModuleResult& result = it->second;
    result.completeWithSession(status);
    outstanding_results_.erase(result_index);
  }
}

void WebContentDecryptionModuleSessionImpl::SessionUpdatedOrReleased(
    uint32 result_index) {
  ResultMap::iterator it = outstanding_results_.find(result_index);
  DCHECK(it != outstanding_results_.end());
  blink::WebContentDecryptionModuleResult& result = it->second;
  result.complete();
  outstanding_results_.erase(it);
}

void WebContentDecryptionModuleSessionImpl::SessionError(
    uint32 result_index,
    media::MediaKeys::Exception exception_code,
    uint32 system_code,
    const std::string& error_message) {
  ResultMap::iterator it = outstanding_results_.find(result_index);
  DCHECK(it != outstanding_results_.end());
  blink::WebContentDecryptionModuleResult& result = it->second;
  result.completeWithError(ConvertException(exception_code),
                           system_code,
                           blink::WebString::fromUTF8(error_message));
  outstanding_results_.erase(it);
}

uint32 WebContentDecryptionModuleSessionImpl::AddResult(
    blink::WebContentDecryptionModuleResult result) {
  uint32 result_index = next_available_result_index_++;
  DCHECK(result_index != kReservedIndex);
  outstanding_results_.insert(std::make_pair(result_index, result));
  return result_index;
}

}  // namespace content
