/*
 * Copyright (C) 2013 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "modules/encryptedmedia/MediaKeySession.h"

#include <cmath>
#include <limits>
#include "bindings/core/v8/ScriptPromise.h"
#include "bindings/core/v8/ScriptPromiseResolver.h"
#include "core/dom/DOMArrayBuffer.h"
#include "core/dom/DOMException.h"
#include "core/dom/ExceptionCode.h"
#include "core/dom/ExecutionContext.h"
#include "core/dom/TaskRunnerHelper.h"
#include "core/events/Event.h"
#include "core/events/GenericEventQueue.h"
#include "modules/encryptedmedia/ContentDecryptionModuleResultPromise.h"
#include "modules/encryptedmedia/EncryptedMediaUtils.h"
#include "modules/encryptedmedia/MediaKeyMessageEvent.h"
#include "modules/encryptedmedia/MediaKeys.h"
#include "platform/ContentDecryptionModuleResult.h"
#include "platform/InstanceCounters.h"
#include "platform/Timer.h"
#include "platform/bindings/DOMWrapperWorld.h"
#include "platform/bindings/ScriptState.h"
#include "platform/bindings/V8ThrowException.h"
#include "platform/network/mime/ContentType.h"
#include "platform/wtf/ASCIICType.h"
#include "platform/wtf/PtrUtil.h"
#include "public/platform/WebContentDecryptionModule.h"
#include "public/platform/WebContentDecryptionModuleException.h"
#include "public/platform/WebContentDecryptionModuleSession.h"
#include "public/platform/WebEncryptedMediaKeyInformation.h"
#include "public/platform/WebString.h"
#include "public/platform/WebURL.h"

#define MEDIA_KEY_SESSION_LOG_LEVEL 3

namespace {

// Minimum and maximum length for session ids.
enum { MinSessionIdLength = 1, MaxSessionIdLength = 512 };

}  // namespace

namespace blink {

// Checks that |sessionId| looks correct and returns whether all checks pass.
static bool IsValidSessionId(const String& session_id) {
  if ((session_id.length() < MinSessionIdLength) ||
      (session_id.length() > MaxSessionIdLength))
    return false;

  if (!session_id.ContainsOnlyASCII())
    return false;

  // Check that the sessionId only contains alphanumeric characters.
  for (unsigned i = 0; i < session_id.length(); ++i) {
    if (!IsASCIIAlphanumeric(session_id[i]))
      return false;
  }

  return true;
}

static bool IsPersistentSessionType(WebEncryptedMediaSessionType session_type) {
  // This implements section 5.1.1 Is persistent session type? from
  // https://w3c.github.io/encrypted-media/#is-persistent-session-type
  switch (session_type) {
    case WebEncryptedMediaSessionType::kTemporary:
      return false;
    case WebEncryptedMediaSessionType::kPersistentLicense:
      return true;
    case WebEncryptedMediaSessionType::kPersistentReleaseMessage:
      return true;
    case blink::WebEncryptedMediaSessionType::kUnknown:
      break;
  }

  NOTREACHED();
  return false;
}

static ScriptPromise CreateRejectedPromiseNotCallable(
    ScriptState* script_state) {
  return ScriptPromise::RejectWithDOMException(
      script_state,
      DOMException::Create(kInvalidStateError, "The session is not callable."));
}

static ScriptPromise CreateRejectedPromiseAlreadyClosed(
    ScriptState* script_state) {
  return ScriptPromise::RejectWithDOMException(
      script_state, DOMException::Create(kInvalidStateError,
                                         "The session is already closed."));
}

static ScriptPromise CreateRejectedPromiseAlreadyInitialized(
    ScriptState* script_state) {
  return ScriptPromise::RejectWithDOMException(
      script_state,
      DOMException::Create(kInvalidStateError,
                           "The session is already initialized."));
}

// A class holding a pending action.
class MediaKeySession::PendingAction final
    : public GarbageCollectedFinalized<MediaKeySession::PendingAction> {
 public:
  enum Type { kGenerateRequest, kLoad, kUpdate, kClose, kRemove };

  Type GetType() const { return type_; }

  ContentDecryptionModuleResult* Result() const { return result_; }

  DOMArrayBuffer* Data() const {
    DCHECK(type_ == kGenerateRequest || type_ == kUpdate);
    return data_;
  }

  WebEncryptedMediaInitDataType InitDataType() const {
    DCHECK_EQ(kGenerateRequest, type_);
    return init_data_type_;
  }

  const String& SessionId() const {
    DCHECK_EQ(kLoad, type_);
    return string_data_;
  }

  static PendingAction* CreatePendingGenerateRequest(
      ContentDecryptionModuleResult* result,
      WebEncryptedMediaInitDataType init_data_type,
      DOMArrayBuffer* init_data) {
    DCHECK(result);
    DCHECK(init_data);
    return new PendingAction(kGenerateRequest, result, init_data_type,
                             init_data, String());
  }

  static PendingAction* CreatePendingLoadRequest(
      ContentDecryptionModuleResult* result,
      const String& session_id) {
    DCHECK(result);
    return new PendingAction(kLoad, result,
                             WebEncryptedMediaInitDataType::kUnknown, nullptr,
                             session_id);
  }

  static PendingAction* CreatePendingUpdate(
      ContentDecryptionModuleResult* result,
      DOMArrayBuffer* data) {
    DCHECK(result);
    DCHECK(data);
    return new PendingAction(kUpdate, result,
                             WebEncryptedMediaInitDataType::kUnknown, data,
                             String());
  }

  static PendingAction* CreatePendingClose(
      ContentDecryptionModuleResult* result) {
    DCHECK(result);
    return new PendingAction(kClose, result,
                             WebEncryptedMediaInitDataType::kUnknown, nullptr,
                             String());
  }

  static PendingAction* CreatePendingRemove(
      ContentDecryptionModuleResult* result) {
    DCHECK(result);
    return new PendingAction(kRemove, result,
                             WebEncryptedMediaInitDataType::kUnknown, nullptr,
                             String());
  }

  ~PendingAction() {}

  DEFINE_INLINE_TRACE() {
    visitor->Trace(result_);
    visitor->Trace(data_);
  }

 private:
  PendingAction(Type type,
                ContentDecryptionModuleResult* result,
                WebEncryptedMediaInitDataType init_data_type,
                DOMArrayBuffer* data,
                const String& string_data)
      : type_(type),
        result_(result),
        init_data_type_(init_data_type),
        data_(data),
        string_data_(string_data) {}

  const Type type_;
  const Member<ContentDecryptionModuleResult> result_;
  const WebEncryptedMediaInitDataType init_data_type_;
  const Member<DOMArrayBuffer> data_;
  const String string_data_;
};

// This class wraps the promise resolver used when initializing a new session
// and is passed to Chromium to fullfill the promise. This implementation of
// completeWithSession() will resolve the promise with void, while
// completeWithError() will reject the promise with an exception. complete()
// is not expected to be called, and will reject the promise.
class NewSessionResultPromise : public ContentDecryptionModuleResultPromise {
 public:
  NewSessionResultPromise(ScriptState* script_state, MediaKeySession* session)
      : ContentDecryptionModuleResultPromise(script_state), session_(session) {}

  ~NewSessionResultPromise() override {}

  // ContentDecryptionModuleResult implementation.
  void CompleteWithSession(
      WebContentDecryptionModuleResult::SessionStatus status) override {
    if (!IsValidToFulfillPromise())
      return;

    if (status != WebContentDecryptionModuleResult::kNewSession) {
      NOTREACHED();
      Reject(kInvalidStateError, "Unexpected completion.");
    }

    session_->FinishGenerateRequest();
    Resolve();
  }

  DEFINE_INLINE_TRACE() {
    visitor->Trace(session_);
    ContentDecryptionModuleResultPromise::Trace(visitor);
  }

 private:
  Member<MediaKeySession> session_;
};

// This class wraps the promise resolver used when loading a session
// and is passed to Chromium to fullfill the promise. This implementation of
// completeWithSession() will resolve the promise with true/false, while
// completeWithError() will reject the promise with an exception. complete()
// is not expected to be called, and will reject the promise.
class LoadSessionResultPromise : public ContentDecryptionModuleResultPromise {
 public:
  LoadSessionResultPromise(ScriptState* script_state, MediaKeySession* session)
      : ContentDecryptionModuleResultPromise(script_state), session_(session) {}

  ~LoadSessionResultPromise() override {}

  // ContentDecryptionModuleResult implementation.
  void CompleteWithSession(
      WebContentDecryptionModuleResult::SessionStatus status) override {
    if (!IsValidToFulfillPromise())
      return;

    switch (status) {
      case WebContentDecryptionModuleResult::kNewSession:
        session_->FinishLoad();
        Resolve(true);
        return;

      case WebContentDecryptionModuleResult::kSessionNotFound:
        Resolve(false);
        return;

      case WebContentDecryptionModuleResult::kSessionAlreadyExists:
        NOTREACHED();
        Reject(kInvalidStateError, "Unexpected completion.");
        return;
    }

    NOTREACHED();
  }

  DEFINE_INLINE_TRACE() {
    visitor->Trace(session_);
    ContentDecryptionModuleResultPromise::Trace(visitor);
  }

 private:
  Member<MediaKeySession> session_;
};

// This class wraps the promise resolver used by update/close/remove. The
// implementation of complete() will resolve the promise with void. All other
// complete() methods are not expected to be called (and will reject the
// promise).
class SimpleResultPromise : public ContentDecryptionModuleResultPromise {
 public:
  SimpleResultPromise(ScriptState* script_state, MediaKeySession* session)
      : ContentDecryptionModuleResultPromise(script_state), session_(session) {}

  ~SimpleResultPromise() override {}

  // ContentDecryptionModuleResultPromise implementation.
  void Complete() override {
    if (!IsValidToFulfillPromise())
      return;

    Resolve();
  }

  DEFINE_INLINE_TRACE() {
    visitor->Trace(session_);
    ContentDecryptionModuleResultPromise::Trace(visitor);
  }

 private:
  // Keep track of the MediaKeySession that created this promise so that it
  // remains reachable as long as this promise is reachable.
  Member<MediaKeySession> session_;
};

MediaKeySession* MediaKeySession::Create(
    ScriptState* script_state,
    MediaKeys* media_keys,
    WebEncryptedMediaSessionType session_type) {
  return new MediaKeySession(script_state, media_keys, session_type);
}

MediaKeySession::MediaKeySession(ScriptState* script_state,
                                 MediaKeys* media_keys,
                                 WebEncryptedMediaSessionType session_type)
    : ContextLifecycleObserver(ExecutionContext::From(script_state)),
      async_event_queue_(GenericEventQueue::Create(this)),
      media_keys_(media_keys),
      session_type_(session_type),
      expiration_(std::numeric_limits<double>::quiet_NaN()),
      key_statuses_map_(new MediaKeyStatusMap()),
      is_uninitialized_(true),
      is_callable_(false),
      is_closed_(false),
      closed_promise_(new ClosedPromise(ExecutionContext::From(script_state),
                                        this,
                                        ClosedPromise::kClosed)),
      action_timer_(
          TaskRunnerHelper::Get(TaskType::kMiscPlatformAPI, script_state),
          this,
          &MediaKeySession::ActionTimerFired) {
  DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ")";
  InstanceCounters::IncrementCounter(InstanceCounters::kMediaKeySessionCounter);

  // Create the matching Chromium object. It will not be usable until
  // initializeNewSession() is called in response to the user calling
  // generateRequest().
  WebContentDecryptionModule* cdm = media_keys->ContentDecryptionModule();
  session_ = WTF::WrapUnique(cdm->CreateSession());
  session_->SetClientInterface(this);

  // From https://w3c.github.io/encrypted-media/#createSession:
  // MediaKeys::createSession(), step 3.
  // 3.1 Let the sessionId attribute be the empty string.
  DCHECK(sessionId().IsEmpty());

  // 3.2 Let the expiration attribute be NaN.
  DCHECK(std::isnan(expiration_));

  // 3.3 Let the closed attribute be a new promise.
  DCHECK(!closed(script_state).IsUndefinedOrNull());

  // 3.4 Let the keyStatuses attribute be empty.
  DCHECK_EQ(0u, key_statuses_map_->size());

  // 3.5 Let the session type be sessionType.
  DCHECK(session_type_ != WebEncryptedMediaSessionType::kUnknown);

  // 3.6 Let uninitialized be true.
  DCHECK(is_uninitialized_);

  // 3.7 Let callable be false.
  DCHECK(!is_callable_);

  // 3.8 Let the use distinctive identifier value be this object's
  // use distinctive identifier.
  // FIXME: Implement this (http://crbug.com/448922).

  // 3.9 Let the cdm implementation value be this object's cdm implementation.
  // 3.10 Let the cdm instance value be this object's cdm instance.
}

MediaKeySession::~MediaKeySession() {
  DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ")";
  InstanceCounters::DecrementCounter(InstanceCounters::kMediaKeySessionCounter);
}

void MediaKeySession::Dispose() {
  // Promptly clears a raw reference from content/ to an on-heap object
  // so that content/ doesn't access it in a lazy sweeping phase.
  session_.reset();
}

String MediaKeySession::sessionId() const {
  return session_->SessionId();
}

ScriptPromise MediaKeySession::closed(ScriptState* script_state) {
  return closed_promise_->Promise(script_state->World());
}

MediaKeyStatusMap* MediaKeySession::keyStatuses() {
  return key_statuses_map_;
}

ScriptPromise MediaKeySession::generateRequest(
    ScriptState* script_state,
    const String& init_data_type_string,
    const DOMArrayPiece& init_data) {
  DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL)
      << __func__ << "(" << this << ") " << init_data_type_string;

  // From https://w3c.github.io/encrypted-media/#generateRequest:
  // Generates a request based on the initData. When this method is invoked,
  // the user agent must run the following steps:

  // 1. If this object is closed, return a promise rejected with an
  //    InvalidStateError.
  if (is_closed_)
    return CreateRejectedPromiseAlreadyClosed(script_state);

  // 2. If this object's uninitialized value is false, return a promise
  //    rejected with an InvalidStateError.
  if (!is_uninitialized_)
    return CreateRejectedPromiseAlreadyInitialized(script_state);

  // 3. Let this object's uninitialized be false.
  is_uninitialized_ = false;

  // 4. If initDataType is the empty string, return a promise rejected
  //    with a newly created TypeError.
  if (init_data_type_string.IsEmpty()) {
    return ScriptPromise::Reject(script_state,
                                 V8ThrowException::CreateTypeError(
                                     script_state->GetIsolate(),
                                     "The initDataType parameter is empty."));
  }

  // 5. If initData is an empty array, return a promise rejected with a
  //    newly created TypeError.
  if (!init_data.ByteLength()) {
    return ScriptPromise::Reject(
        script_state,
        V8ThrowException::CreateTypeError(script_state->GetIsolate(),
                                          "The initData parameter is empty."));
  }

  // 6. If the Key System implementation represented by this object's cdm
  //    implementation value does not support initDataType as an
  //    Initialization Data Type, return a promise rejected with a new
  //    DOMException whose name is NotSupportedError. String comparison
  //    is case-sensitive.
  //    (blink side doesn't know what the CDM supports, so the proper check
  //     will be done on the Chromium side. However, we can verify that
  //     |initDataType| is one of the registered values.)
  WebEncryptedMediaInitDataType init_data_type =
      EncryptedMediaUtils::ConvertToInitDataType(init_data_type_string);
  if (init_data_type == WebEncryptedMediaInitDataType::kUnknown) {
    return ScriptPromise::RejectWithDOMException(
        script_state, DOMException::Create(kNotSupportedError,
                                           "The initialization data type '" +
                                               init_data_type_string +
                                               "' is not supported."));
  }

  // 7. Let init data be a copy of the contents of the initData parameter.
  DOMArrayBuffer* init_data_buffer =
      DOMArrayBuffer::Create(init_data.Data(), init_data.ByteLength());

  // 8. Let session type be this object's session type.
  //    (Done in constructor.)

  // 9. Let promise be a new promise.
  NewSessionResultPromise* result =
      new NewSessionResultPromise(script_state, this);
  ScriptPromise promise = result->Promise();

  // 10. Run the following steps asynchronously (done in generateRequestTask())
  pending_actions_.push_back(PendingAction::CreatePendingGenerateRequest(
      result, init_data_type, init_data_buffer));
  DCHECK(!action_timer_.IsActive());
  action_timer_.StartOneShot(0, BLINK_FROM_HERE);

  // 11. Return promise.
  return promise;
}

void MediaKeySession::GenerateRequestTask(
    ContentDecryptionModuleResult* result,
    WebEncryptedMediaInitDataType init_data_type,
    DOMArrayBuffer* init_data_buffer) {
  // NOTE: Continue step 10 of MediaKeySession::generateRequest().
  DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ")";

  // initializeNewSession() in Chromium will execute steps 10.1 to 10.9.
  session_->InitializeNewSession(
      init_data_type, static_cast<unsigned char*>(init_data_buffer->Data()),
      init_data_buffer->ByteLength(), session_type_, result->Result());

  // Remaining steps (10.10) executed in finishGenerateRequest(),
  // called when |result| is resolved.
}

void MediaKeySession::FinishGenerateRequest() {
  // NOTE: Continue step 10.10 of MediaKeySession::generateRequest().
  DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ")";

  // 10.10.1 If any of the preceding steps failed, reject promise with a
  //         new DOMException whose name is the appropriate error name.
  //         (Done by CDM calling result.completeWithError() as appropriate.)
  // 10.10.2 Set the sessionId attribute to session id.
  DCHECK(!sessionId().IsEmpty());

  // 10.10.3 Let this object's callable be true.
  is_callable_ = true;

  // 10.10.4 Run the Queue a "message" Event algorithm on the session,
  //         providing message type and message.
  //         (Done by the CDM.)
  // 10.10.5 Resolve promise.
  //         (Done by NewSessionResultPromise.)
}

ScriptPromise MediaKeySession::load(ScriptState* script_state,
                                    const String& session_id) {
  DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL)
      << __func__ << "(" << this << ") " << session_id;

  // From https://w3c.github.io/encrypted-media/#load:
  // Loads the data stored for the specified session into this object. When
  // this method is invoked, the user agent must run the following steps:

  // 1. If this object is closed, return a promise rejected with an
  //    InvalidStateError.
  if (is_closed_)
    return CreateRejectedPromiseAlreadyClosed(script_state);

  // 2. If this object's uninitialized value is false, return a promise
  //    rejected with an InvalidStateError.
  if (!is_uninitialized_)
    return CreateRejectedPromiseAlreadyInitialized(script_state);

  // 3. Let this object's uninitialized value be false.
  is_uninitialized_ = false;

  // 4. If sessionId is the empty string, return a promise rejected with
  //    a newly created TypeError.
  if (session_id.IsEmpty()) {
    return ScriptPromise::Reject(
        script_state,
        V8ThrowException::CreateTypeError(script_state->GetIsolate(),
                                          "The sessionId parameter is empty."));
  }

  // 5. If the result of running the "Is persistent session type?" algorithm
  //    on this object's session type is false, return a promise rejected
  //    with a newly created TypeError.
  if (!IsPersistentSessionType(session_type_)) {
    return ScriptPromise::Reject(
        script_state,
        V8ThrowException::CreateTypeError(
            script_state->GetIsolate(), "The session type is not persistent."));
  }

  // 6. Let origin be the origin of this object's Document.
  //    (Available as getExecutionContext()->getSecurityOrigin() anytime.)

  // 7. Let promise be a new promise.
  LoadSessionResultPromise* result =
      new LoadSessionResultPromise(script_state, this);
  ScriptPromise promise = result->Promise();

  // 8. Run the following steps asynchronously (done in loadTask())
  pending_actions_.push_back(
      PendingAction::CreatePendingLoadRequest(result, session_id));
  DCHECK(!action_timer_.IsActive());
  action_timer_.StartOneShot(0, BLINK_FROM_HERE);

  // 9. Return promise.
  return promise;
}

void MediaKeySession::LoadTask(ContentDecryptionModuleResult* result,
                               const String& session_id) {
  // NOTE: Continue step 8 of MediaKeySession::load().
  DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ")";

  // 8.1 Let sanitized session ID be a validated and/or sanitized
  //     version of sessionId. The user agent should thoroughly
  //     validate the sessionId value before passing it to the CDM.
  //     At a minimum, this should include checking that the length
  //     and value (e.g. alphanumeric) are reasonable.
  // 8.2 If the preceding step failed, or if sanitized session ID
  //     is empty, reject promise with a newly created TypeError.
  if (!IsValidSessionId(session_id)) {
    result->CompleteWithError(kWebContentDecryptionModuleExceptionTypeError, 0,
                              "Invalid sessionId");
    return;
  }

  // 8.3 If there is an unclosed session in the object's Document
  //     whose sessionId attribute is sanitized session ID, reject
  //     promise with a new DOMException whose name is
  //     QuotaExceededError. In other words, do not create a session
  //     if a non-closed session, regardless of type, already exists
  //     for this sanitized session ID in this browsing context.
  //     (Done in the CDM.)

  // 8.4 Let expiration time be NaN.
  //     (Done in the constructor.)
  DCHECK(std::isnan(expiration_));

  // load() in Chromium will execute steps 8.5 through 8.8.
  session_->Load(session_id, result->Result());

  // Remaining step (8.9) executed in finishLoad(), called when |result|
  // is resolved.
}

void MediaKeySession::FinishLoad() {
  // NOTE: Continue step 8.9 of MediaKeySession::load().
  DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ")";

  // 8.9.1 If any of the preceding steps failed, reject promise with a new
  //       DOMException whose name is the appropriate error name.
  //       (Done by CDM calling result.completeWithError() as appropriate.)

  // 8.9.2 Set the sessionId attribute to sanitized session ID.
  DCHECK(!sessionId().IsEmpty());

  // 8.9.3 Let this object's callable be true.
  is_callable_ = true;

  // 8.9.4 If the loaded session contains information about any keys (there
  //       are known keys), run the update key statuses algorithm on the
  //       session, providing each key's key ID along with the appropriate
  //       MediaKeyStatus. Should additional processing be necessary to
  //       determine with certainty the status of a key, use the non-"usable"
  //       MediaKeyStatus value that corresponds to the reason for the
  //       additional processing. Once the additional processing for one or
  //       more keys has completed, run the update key statuses algorithm
  //       again if any of the statuses has changed.
  //       (Done by the CDM.)

  // 8.9.5 Run the Update Expiration algorithm on the session,
  //       providing expiration time.
  //       (Done by the CDM.)

  // 8.9.6 If message is not null, run the queue a "message" event algorithm
  //       on the session, providing message type and message.
  //       (Done by the CDM.)

  // 8.9.7 Resolve promise with true.
  //       (Done by LoadSessionResultPromise.)
}

ScriptPromise MediaKeySession::update(ScriptState* script_state,
                                      const DOMArrayPiece& response) {
  DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ")";

  // From https://w3c.github.io/encrypted-media/#update:
  // Provides messages, including licenses, to the CDM. When this method is
  // invoked, the user agent must run the following steps:

  // 1. If this object is closed, return a promise rejected with an
  //    InvalidStateError.
  if (is_closed_)
    return CreateRejectedPromiseAlreadyClosed(script_state);

  // 2. If this object's callable value is false, return a promise
  //    rejected with an InvalidStateError.
  if (!is_callable_)
    return CreateRejectedPromiseNotCallable(script_state);

  // 3. If response is an empty array, return a promise rejected with a
  //    newly created TypeError.
  if (!response.ByteLength()) {
    return ScriptPromise::Reject(
        script_state,
        V8ThrowException::CreateTypeError(script_state->GetIsolate(),
                                          "The response parameter is empty."));
  }

  // 4. Let response copy be a copy of the contents of the response parameter.
  DOMArrayBuffer* response_copy =
      DOMArrayBuffer::Create(response.Data(), response.ByteLength());

  // 5. Let promise be a new promise.
  SimpleResultPromise* result = new SimpleResultPromise(script_state, this);
  ScriptPromise promise = result->Promise();

  // 6. Run the following steps asynchronously (done in updateTask())
  pending_actions_.push_back(
      PendingAction::CreatePendingUpdate(result, response_copy));
  if (!action_timer_.IsActive())
    action_timer_.StartOneShot(0, BLINK_FROM_HERE);

  // 7. Return promise.
  return promise;
}

void MediaKeySession::UpdateTask(ContentDecryptionModuleResult* result,
                                 DOMArrayBuffer* sanitized_response) {
  // NOTE: Continue step 6 of MediaKeySession::update().
  DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ")";

  // update() in Chromium will execute steps 6.1 through 6.8.
  session_->Update(static_cast<unsigned char*>(sanitized_response->Data()),
                   sanitized_response->ByteLength(), result->Result());

  // Last step (6.8.2 Resolve promise) will be done when |result| is resolved.
}

ScriptPromise MediaKeySession::close(ScriptState* script_state) {
  DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ")";

  // From https://w3c.github.io/encrypted-media/#close:
  // Indicates that the application no longer needs the session and the CDM
  // should release any resources associated with the session and close it.
  // Persisted data should not be released or cleared.
  // When this method is invoked, the user agent must run the following steps:

  // 1. Let session be the associated MediaKeySession object.
  // 2. If session is closed, return a resolved promise.
  if (is_closed_)
    return ScriptPromise::CastUndefined(script_state);

  // 3. If session's callable value is false, return a promise rejected with
  //    an InvalidStateError.
  if (!is_callable_)
    return CreateRejectedPromiseNotCallable(script_state);

  // 4. Let promise be a new promise.
  SimpleResultPromise* result = new SimpleResultPromise(script_state, this);
  ScriptPromise promise = result->Promise();

  // 5. Run the following steps in parallel (done in closeTask()).
  pending_actions_.push_back(PendingAction::CreatePendingClose(result));
  if (!action_timer_.IsActive())
    action_timer_.StartOneShot(0, BLINK_FROM_HERE);

  // 6. Return promise.
  return promise;
}

void MediaKeySession::CloseTask(ContentDecryptionModuleResult* result) {
  // NOTE: Continue step 4 of MediaKeySession::close().
  DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ")";

  // close() in Chromium will execute steps 5.1 through 5.3.
  session_->Close(result->Result());

  // Last step (5.3.2 Resolve promise) will be done when |result| is resolved.
}

ScriptPromise MediaKeySession::remove(ScriptState* script_state) {
  DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ")";

  // From https://w3c.github.io/encrypted-media/#remove:
  // Removes stored session data associated with this object. When this
  // method is invoked, the user agent must run the following steps:

  // 1. If this object is closed, return a promise rejected with an
  //    InvalidStateError.
  if (is_closed_)
    return CreateRejectedPromiseAlreadyClosed(script_state);

  // 2. If this object's callable value is false, return a promise rejected
  //    with an InvalidStateError.
  if (!is_callable_)
    return CreateRejectedPromiseNotCallable(script_state);

  // 3. Let promise be a new promise.
  SimpleResultPromise* result = new SimpleResultPromise(script_state, this);
  ScriptPromise promise = result->Promise();

  // 4. Run the following steps asynchronously (done in removeTask()).
  pending_actions_.push_back(PendingAction::CreatePendingRemove(result));
  if (!action_timer_.IsActive())
    action_timer_.StartOneShot(0, BLINK_FROM_HERE);

  // 5. Return promise.
  return promise;
}

void MediaKeySession::RemoveTask(ContentDecryptionModuleResult* result) {
  // NOTE: Continue step 4 of MediaKeySession::remove().
  DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ")";

  // remove() in Chromium will execute steps 4.1 through 4.5.
  session_->Remove(result->Result());

  // Last step (4.5.6 Resolve promise) will be done when |result| is resolved.
}

void MediaKeySession::ActionTimerFired(TimerBase*) {
  DCHECK(pending_actions_.size());

  // Resolving promises now run synchronously and may result in additional
  // actions getting added to the queue. As a result, swap the queue to
  // a local copy to avoid problems if this happens.
  HeapDeque<Member<PendingAction>> pending_actions;
  pending_actions.Swap(pending_actions_);

  while (!pending_actions.IsEmpty()) {
    PendingAction* action = pending_actions.TakeFirst();

    switch (action->GetType()) {
      case PendingAction::kGenerateRequest:
        GenerateRequestTask(action->Result(), action->InitDataType(),
                            action->Data());
        break;

      case PendingAction::kLoad:
        LoadTask(action->Result(), action->SessionId());
        break;

      case PendingAction::kUpdate:
        UpdateTask(action->Result(), action->Data());
        break;

      case PendingAction::kClose:
        CloseTask(action->Result());
        break;

      case PendingAction::kRemove:
        RemoveTask(action->Result());
        break;
    }
  }
}

// Queue a task to fire a simple event named keymessage at the new object.
void MediaKeySession::Message(MessageType message_type,
                              const unsigned char* message,
                              size_t message_length) {
  DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ")";

  // Verify that 'message' not fired before session initialization is complete.
  DCHECK(is_callable_);

  // From https://w3c.github.io/encrypted-media/#queue-message:
  // The following steps are run:
  // 1. Let the session be the specified MediaKeySession object.
  // 2. Queue a task to fire a simple event named message at the session.
  //    The event is of type MediaKeyMessageEvent and has:
  //    -> messageType = the specified message type
  //    -> message = the specified message

  MediaKeyMessageEventInit init;
  switch (message_type) {
    case WebContentDecryptionModuleSession::Client::MessageType::
        kLicenseRequest:
      init.setMessageType("license-request");
      break;
    case WebContentDecryptionModuleSession::Client::MessageType::
        kLicenseRenewal:
      init.setMessageType("license-renewal");
      break;
    case WebContentDecryptionModuleSession::Client::MessageType::
        kLicenseRelease:
      init.setMessageType("license-release");
      break;
  }
  init.setMessage(DOMArrayBuffer::Create(static_cast<const void*>(message),
                                         message_length));

  MediaKeyMessageEvent* event =
      MediaKeyMessageEvent::Create(EventTypeNames::message, init);
  event->SetTarget(this);
  async_event_queue_->EnqueueEvent(event);
}

void MediaKeySession::Close() {
  DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ")";

  // From http://w3c.github.io/encrypted-media/#session-closed
  // 1. Let session be the associated MediaKeySession object.
  // 2. If session's session type is "persistent-usage-record", execute the
  //    following steps in parallel:
  //    1. Let cdm be the CDM instance represented by session's cdm instance
  //       value.
  //    2. Use cdm to store session's record of key usage, if it exists.
  //    ("persistent-usage-record" not supported by Chrome.)

  // 3. Run the Update Key Statuses algorithm on the session, providing an
  //    empty sequence.
  KeysStatusesChange(WebVector<WebEncryptedMediaKeyInformation>(), false);

  // 4. Run the Update Expiration algorithm on the session, providing NaN.
  ExpirationChanged(std::numeric_limits<double>::quiet_NaN());

  // 5. Let promise be the closed attribute of the session.
  // 6. Resolve promise.
  closed_promise_->Resolve(ToV8UndefinedGenerator());

  // After this algorithm has run, event handlers for the events queued by
  // this algorithm will be executed, but no further events can be queued.
  // As a result, no messages can be sent by the CDM as a result of closing
  // the session.
  is_closed_ = true;
}

void MediaKeySession::ExpirationChanged(double updated_expiry_time_in_ms) {
  DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL)
      << __func__ << "(" << this << ") " << updated_expiry_time_in_ms;

  // From https://w3c.github.io/encrypted-media/#update-expiration:
  // The following steps are run:
  // 1. Let the session be the associated MediaKeySession object.
  // 2. Let expiration time be NaN.
  double expiration_time = std::numeric_limits<double>::quiet_NaN();

  // 3. If the new expiration time is not NaN, let expiration time be the
  //    new expiration time in milliseconds since 01 January 1970 UTC.
  if (!std::isnan(updated_expiry_time_in_ms))
    expiration_time = updated_expiry_time_in_ms;

  // 4. Set the session's expiration attribute to expiration time.
  expiration_ = expiration_time;
}

void MediaKeySession::KeysStatusesChange(
    const WebVector<WebEncryptedMediaKeyInformation>& keys,
    bool has_additional_usable_key) {
  DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL)
      << __func__ << "(" << this << ") with " << keys.size()
      << " keys and hasAdditionalUsableKey is "
      << (has_additional_usable_key ? "true" : "false");

  // From https://w3c.github.io/encrypted-media/#update-key-statuses:
  // The following steps are run:
  // 1. Let the session be the associated MediaKeySession object.
  // 2. Let the input statuses be the sequence of pairs key ID and
  //    associated MediaKeyStatus pairs.
  // 3. Let the statuses be session's keyStatuses attribute.

  // 4. Run the following steps to replace the contents of statuses:
  // 4.1 Empty statuses.
  key_statuses_map_->Clear();

  // 4.2 For each pair in input statuses.
  for (size_t i = 0; i < keys.size(); ++i) {
    // 4.2.1 Let pair be the pair.
    const auto& key = keys[i];
    // 4.2.2 Insert an entry for pair's key ID into statuses with the
    //       value of pair's MediaKeyStatus value.
    key_statuses_map_->AddEntry(
        key.Id(), EncryptedMediaUtils::ConvertKeyStatusToString(key.Status()));
  }

  // 5. Queue a task to fire a simple event named keystatuseschange
  //    at the session.
  Event* event = Event::Create(EventTypeNames::keystatuseschange);
  event->SetTarget(this);
  async_event_queue_->EnqueueEvent(event);

  // 6. Queue a task to run the attempt to resume playback if necessary
  //    algorithm on each of the media element(s) whose mediaKeys attribute
  //    is the MediaKeys object that created the session. The user agent
  //    may choose to skip this step if it knows resuming will fail.
  // FIXME: Attempt to resume playback if |hasAdditionalUsableKey| is true.
  // http://crbug.com/413413
}

const AtomicString& MediaKeySession::InterfaceName() const {
  return EventTargetNames::MediaKeySession;
}

ExecutionContext* MediaKeySession::GetExecutionContext() const {
  return ContextLifecycleObserver::GetExecutionContext();
}

bool MediaKeySession::HasPendingActivity() const {
  // Remain around if there are pending events or MediaKeys is still around
  // and we're not closed.
  DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL)
      << __func__ << "(" << this << ")"
      << (!pending_actions_.IsEmpty() ? " !pending_actions_.IsEmpty()" : "")
      << (async_event_queue_->HasPendingEvents()
              ? " async_event_queue_->HasPendingEvents()"
              : "")
      << ((media_keys_ && !is_closed_) ? " media_keys_ && !is_closed_" : "");

  return !pending_actions_.IsEmpty() ||
         async_event_queue_->HasPendingEvents() || (media_keys_ && !is_closed_);
}

void MediaKeySession::ContextDestroyed(ExecutionContext*) {
  // Stop the CDM from firing any more events for this session.
  session_.reset();
  is_closed_ = true;
  action_timer_.Stop();
  pending_actions_.clear();
  async_event_queue_->Close();
}

DEFINE_TRACE(MediaKeySession) {
  visitor->Trace(async_event_queue_);
  visitor->Trace(pending_actions_);
  visitor->Trace(media_keys_);
  visitor->Trace(key_statuses_map_);
  visitor->Trace(closed_promise_);
  EventTargetWithInlineData::Trace(visitor);
  ContextLifecycleObserver::Trace(visitor);
}

}  // namespace blink
