// Copyright 2017 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 "cobalt/dom/eme/media_keys.h"

#include "base/bind.h"
#include "base/trace_event/trace_event.h"
#include "cobalt/base/polymorphic_downcast.h"
#include "cobalt/dom/dom_settings.h"
#include "cobalt/dom/eme/eme_helpers.h"
#include "cobalt/dom/eme/media_key_session.h"
#include "cobalt/web/context.h"
#include "cobalt/web/dom_exception.h"

namespace cobalt {
namespace dom {
namespace eme {

MediaKeys::MediaKeys(script::EnvironmentSettings* settings,
                     const scoped_refptr<media::DrmSystem>& drm_system,
                     script::ScriptValueFactory* script_value_factory)
    : dom_settings_(base::polymorphic_downcast<DOMSettings*>(settings)),
      script_value_factory_(script_value_factory),
      drm_system_(drm_system) {
  SB_DCHECK(drm_system_->is_valid())
      << "DrmSystem provided on initialization is invalid.";
}

// See https://www.w3.org/TR/encrypted-media/#dom-mediakeys-createsession.
scoped_refptr<MediaKeySession> MediaKeys::CreateSession(
    MediaKeySessionType session_type, script::ExceptionState* exception_state) {
  TRACE_EVENT1("cobalt::dom::eme", "MediaKeys::CreateSession()", "session_type",
               session_type);
  // 1. If this object's supported session types value does not contain
  //    sessionType, throw a NotSupportedError.
  if (session_type != kMediaKeySessionTypeTemporary) {
    web::DOMException::Raise(web::DOMException::kNotSupportedErr,
                             exception_state);
    return NULL;
  }

  // 3. Let session be a new MediaKeySession object.
  //
  // |MediaKeys| are passed to |MediaKeySession| as weak pointer because the
  // order of destruction is not guaranteed due to JavaScript memory management.
  scoped_refptr<MediaKeySession> session(new MediaKeySession(
      dom_settings_, drm_system_, script_value_factory_,
      base::Bind(&MediaKeys::OnSessionClosed, AsWeakPtr())));
  open_sessions_.push_back(session);
  return session;
}

MediaKeys::BoolPromiseHandle MediaKeys::SetServerCertificate(
    const web::BufferSource& server_certificate) {
  TRACE_EVENT0("cobalt::dom::eme", "MediaKeys::SetServerCertificate()");
  BoolPromiseHandle promise = script_value_factory_->CreateBasicPromise<bool>();

  // 1. If the Key System implementation represented by this object's cdm
  //    implementation value does not support server certificates, return a
  //    promise resolved with false.
  if (!drm_system_->IsServerCertificateUpdatable()) {
    promise->Resolve(false);
    return promise;
  }

  // 2. If serverCertificate is an empty array, return a promise rejected with a
  //    newly created TypeError.
  const uint8* server_certificate_buffer;
  int server_certificate_buffer_size = 0;
  web::GetBufferAndSize(server_certificate, &server_certificate_buffer,
                        &server_certificate_buffer_size);

  if (server_certificate_buffer_size == 0) {
    promise->Reject(script::kTypeError);
    return promise;
  }

  // 3. Let certificate be a copy of the contents of the serverCertificate
  //    parameter.
  // 4. Let promise be a new promise.
  // 5. Run the following steps in parallel:
  // 5.1 Let sanitized certificate be a validated and/or sanitized version of
  //     certificate.
  // 5.2 Use this object's cdm instance to process sanitized certificate.
  drm_system_->UpdateServerCertificate(
      server_certificate_buffer, server_certificate_buffer_size,
      base::Bind(&MediaKeys::OnServerCertificateUpdated, base::AsWeakPtr(this),
                 base::Owned(new BoolPromiseValue::Reference(this, promise))));

  // 5.3 and 5.4 are pending processing in OnServerCertificateUpdated().
  // 6. Return promise.
  return promise;
}

script::Handle<script::Uint8Array> MediaKeys::GetMetrics(
    script::ExceptionState* exception_state) {
  TRACE_EVENT0("cobalt::dom::eme", "MediaKeys::GetMetrics()");
  std::vector<uint8_t> metrics;
  if (drm_system_->GetMetrics(&metrics)) {
    return script::Uint8Array::New(
        dom_settings_->context()->global_environment(), metrics.data(),
        metrics.size());
  }
  web::DOMException::Raise(web::DOMException::kNotSupportedErr,
                           exception_state);
  return script::Handle<script::Uint8Array>();
}

void MediaKeys::OnSessionClosed(MediaKeySession* session) {
  // Erase-remove idiom, see
  // https://en.wikipedia.org/wiki/Erase%E2%80%93remove_idiom.
  open_sessions_.erase(
      std::remove(open_sessions_.begin(), open_sessions_.end(), session),
      open_sessions_.end());
}

void MediaKeys::OnServerCertificateUpdated(
    BoolPromiseValue::Reference* promise_reference, SbDrmStatus status,
    const std::string& error_message) {
  // 5.3 If the preceding step failed, resolve promise with a new DOMException
  //     whose name is the appropriate error name.
  if (status != kSbDrmStatusSuccess) {
    RejectPromise(promise_reference, status, error_message);
    return;
  }
  // 5.4 Resolve promise with true.
  promise_reference->value().Resolve(true);
}

void MediaKeys::TraceMembers(script::Tracer* tracer) {
  tracer->TraceItems(open_sessions_);
}

MediaKeys::~MediaKeys() {}

}  // namespace eme
}  // namespace dom
}  // namespace cobalt
