// 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_exception.h"
#include "cobalt/dom/eme/eme_helpers.h"
#include "cobalt/dom/eme/media_key_session.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) {
    DOMException::Raise(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 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;
  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_->global_environment(),
                                   metrics.data(), metrics.size());
  }
  DOMException::Raise(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
