/*
 * 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 "config.h"
#include "modules/encryptedmedia/MediaKeySession.h"

#include "bindings/core/v8/DOMWrapperWorld.h"
#include "bindings/core/v8/ScriptPromise.h"
#include "bindings/core/v8/ScriptPromiseResolver.h"
#include "bindings/core/v8/ScriptState.h"
#include "core/dom/DOMArrayBuffer.h"
#include "core/dom/DOMArrayBufferView.h"
#include "core/dom/ExceptionCode.h"
#include "core/events/Event.h"
#include "core/events/GenericEventQueue.h"
#include "core/html/MediaKeyError.h"
#include "modules/encryptedmedia/MediaKeyMessageEvent.h"
#include "modules/encryptedmedia/MediaKeys.h"
#include "modules/encryptedmedia/SimpleContentDecryptionModuleResult.h"
#include "platform/ContentDecryptionModuleResult.h"
#include "platform/ContentType.h"
#include "platform/Logging.h"
#include "platform/MIMETypeRegistry.h"
#include "platform/Timer.h"
#include "public/platform/WebContentDecryptionModule.h"
#include "public/platform/WebContentDecryptionModuleException.h"
#include "public/platform/WebContentDecryptionModuleSession.h"
#include "public/platform/WebString.h"
#include "public/platform/WebURL.h"
#include "wtf/ASCIICType.h"
#include <cmath>
#include <limits>

namespace {

// The list of possible values for |sessionType|.
const char* kTemporary = "temporary";
const char* kPersistent = "persistent";

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

} // namespace

namespace blink {

static bool isKeySystemSupportedWithInitDataType(const String& keySystem, const String& initDataType)
{
    ASSERT(!keySystem.isEmpty());

    // FIXME: initDataType != contentType. Implement this properly.
    // http://crbug.com/385874.
    String contentType = initDataType;
    if (initDataType == "webm") {
        contentType = "video/webm";
    } else if (initDataType == "cenc") {
        contentType = "video/mp4";
    }

    ContentType type(contentType);
    return MIMETypeRegistry::isSupportedEncryptedMediaMIMEType(keySystem, type.type(), type.parameter("codecs"));
}

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

    if (!sessionId.containsOnlyASCII())
        return false;

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

    return true;
}

// A class holding a pending action.
class MediaKeySession::PendingAction : public GarbageCollectedFinalized<MediaKeySession::PendingAction> {
public:
    enum Type {
        GenerateRequest,
        Load,
        Update,
        Close,
        Remove
    };

    Type type() const { return m_type; }

    const Persistent<ContentDecryptionModuleResult> result() const
    {
        return m_result;
    }

    const PassRefPtr<DOMArrayBuffer> data() const
    {
        ASSERT(m_type == GenerateRequest || m_type == Update);
        return m_data;
    }

    const String& initDataType() const
    {
        ASSERT(m_type == GenerateRequest);
        return m_stringData;
    }

    const String& sessionId() const
    {
        ASSERT(m_type == Load);
        return m_stringData;
    }

    static PendingAction* CreatePendingGenerateRequest(ContentDecryptionModuleResult* result, const String& initDataType, PassRefPtr<DOMArrayBuffer> initData)
    {
        ASSERT(result);
        ASSERT(initData);
        return new PendingAction(GenerateRequest, result, initDataType, initData);
    }

    static PendingAction* CreatePendingLoadRequest(ContentDecryptionModuleResult* result, const String& sessionId)
    {
        ASSERT(result);
        return new PendingAction(Load, result, sessionId, PassRefPtr<DOMArrayBuffer>());
    }

    static PendingAction* CreatePendingUpdate(ContentDecryptionModuleResult* result, PassRefPtr<DOMArrayBuffer> data)
    {
        ASSERT(result);
        ASSERT(data);
        return new PendingAction(Update, result, String(), data);
    }

    static PendingAction* CreatePendingClose(ContentDecryptionModuleResult* result)
    {
        ASSERT(result);
        return new PendingAction(Close, result, String(), PassRefPtr<DOMArrayBuffer>());
    }

    static PendingAction* CreatePendingRemove(ContentDecryptionModuleResult* result)
    {
        ASSERT(result);
        return new PendingAction(Remove, result, String(), PassRefPtr<DOMArrayBuffer>());
    }

    ~PendingAction()
    {
    }

    void trace(Visitor* visitor)
    {
        visitor->trace(m_result);
    }

private:
    PendingAction(Type type, ContentDecryptionModuleResult* result, const String& stringData, PassRefPtr<DOMArrayBuffer> data)
        : m_type(type)
        , m_result(result)
        , m_stringData(stringData)
        , m_data(data)
    {
    }

    const Type m_type;
    const Member<ContentDecryptionModuleResult> m_result;
    const String m_stringData;
    const RefPtr<DOMArrayBuffer> m_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 NewSessionResult : public ContentDecryptionModuleResult {
public:
    NewSessionResult(ScriptState* scriptState, MediaKeySession* session)
        : m_resolver(ScriptPromiseResolver::create(scriptState))
        , m_session(session)
    {
        WTF_LOG(Media, "NewSessionResult(%p)", this);
    }

    virtual ~NewSessionResult()
    {
        WTF_LOG(Media, "~NewSessionResult(%p)", this);
    }

    // ContentDecryptionModuleResult implementation.
    virtual void complete() override
    {
        ASSERT_NOT_REACHED();
        completeWithDOMException(InvalidStateError, "Unexpected completion.");
    }

    virtual void completeWithSession(WebContentDecryptionModuleResult::SessionStatus status) override
    {
        if (status != WebContentDecryptionModuleResult::NewSession) {
            ASSERT_NOT_REACHED();
            completeWithDOMException(InvalidStateError, "Unexpected completion.");
        }

        m_session->finishGenerateRequest();
        m_resolver->resolve();
        m_resolver.clear();
    }

    virtual void completeWithError(WebContentDecryptionModuleException exceptionCode, unsigned long systemCode, const WebString& errorMessage) override
    {
        completeWithDOMException(WebCdmExceptionToExceptionCode(exceptionCode), errorMessage);
    }

    // It is only valid to call this before completion.
    ScriptPromise promise() { return m_resolver->promise(); }

    void trace(Visitor* visitor)
    {
        visitor->trace(m_session);
        ContentDecryptionModuleResult::trace(visitor);
    }

private:
    // Reject the promise with a DOMException.
    void completeWithDOMException(ExceptionCode code, const String& errorMessage)
    {
        m_resolver->reject(DOMException::create(code, errorMessage));
        m_resolver.clear();
    }

    RefPtr<ScriptPromiseResolver> m_resolver;
    Member<MediaKeySession> m_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 LoadSessionResult : public ContentDecryptionModuleResult {
public:
    LoadSessionResult(ScriptState* scriptState, MediaKeySession* session)
        : m_resolver(ScriptPromiseResolver::create(scriptState))
        , m_session(session)
    {
        WTF_LOG(Media, "LoadSessionResult(%p)", this);
    }

    virtual ~LoadSessionResult()
    {
        WTF_LOG(Media, "~LoadSessionResult(%p)", this);
    }

    // ContentDecryptionModuleResult implementation.
    virtual void complete() override
    {
        ASSERT_NOT_REACHED();
        completeWithDOMException(InvalidStateError, "Unexpected completion.");
    }

    virtual void completeWithSession(WebContentDecryptionModuleResult::SessionStatus status) override
    {
        bool result = false;
        switch (status) {
        case WebContentDecryptionModuleResult::NewSession:
            result = true;
            break;

        case WebContentDecryptionModuleResult::SessionNotFound:
            result = false;
            break;

        case WebContentDecryptionModuleResult::SessionAlreadyExists:
            ASSERT_NOT_REACHED();
            completeWithDOMException(InvalidStateError, "Unexpected completion.");
            return;
        }

        m_session->finishLoad();
        m_resolver->resolve(result);
        m_resolver.clear();
    }

    virtual void completeWithError(WebContentDecryptionModuleException exceptionCode, unsigned long systemCode, const WebString& errorMessage) override
    {
        completeWithDOMException(WebCdmExceptionToExceptionCode(exceptionCode), errorMessage);
    }

    // It is only valid to call this before completion.
    ScriptPromise promise() { return m_resolver->promise(); }

    void trace(Visitor* visitor)
    {
        visitor->trace(m_session);
        ContentDecryptionModuleResult::trace(visitor);
    }

private:
    // Reject the promise with a DOMException.
    void completeWithDOMException(ExceptionCode code, const String& errorMessage)
    {
        m_resolver->reject(DOMException::create(code, errorMessage));
        m_resolver.clear();
    }

    RefPtr<ScriptPromiseResolver> m_resolver;
    Member<MediaKeySession> m_session;
};

MediaKeySession* MediaKeySession::create(ScriptState* scriptState, MediaKeys* mediaKeys, const String& sessionType)
{
    ASSERT(sessionType == kTemporary || sessionType == kPersistent);
    RefPtrWillBeRawPtr<MediaKeySession> session = new MediaKeySession(scriptState, mediaKeys, sessionType);
    session->suspendIfNeeded();
    return session.get();
}

bool MediaKeySession::isValidSessionType(const String& sessionType)
{
    return (sessionType == kTemporary || sessionType == kPersistent);
}

MediaKeySession::MediaKeySession(ScriptState* scriptState, MediaKeys* mediaKeys, const String& sessionType)
    : ActiveDOMObject(scriptState->executionContext())
    , m_keySystem(mediaKeys->keySystem())
    , m_asyncEventQueue(GenericEventQueue::create(this))
    , m_mediaKeys(mediaKeys)
    , m_sessionType(sessionType)
    , m_expiration(std::numeric_limits<double>::quiet_NaN())
    , m_isUninitialized(true)
    , m_isCallable(false)
    , m_isClosed(false)
    , m_closedPromise(new ClosedPromise(scriptState->executionContext(), this, ClosedPromise::Closed))
    , m_actionTimer(this, &MediaKeySession::actionTimerFired)
{
    WTF_LOG(Media, "MediaKeySession(%p)::MediaKeySession", this);

    // Create the matching Chromium object. It will not be usable until
    // initializeNewSession() is called in response to the user calling
    // generateRequest().
    WebContentDecryptionModule* cdm = mediaKeys->contentDecryptionModule();
    m_session = adoptPtr(cdm->createSession());
    m_session->setClientInterface(this);

    // MediaKeys::createSession(), step 2.
    // 2.1 Let the sessionId attribute be the empty string.
    ASSERT(sessionId().isEmpty());

    // 2.2 Let the expiration attribute be NaN.
    ASSERT(std::isnan(m_expiration));

    // 2.3 Let the closed attribute be a new promise.
    ASSERT(!closed(scriptState).isUndefinedOrNull());

    // 2.4 Let the session type be sessionType.
    ASSERT(isValidSessionType(sessionType));

    // 2.5 Let uninitialized be true.
    ASSERT(m_isUninitialized);

    // 2.6 Let callable be false.
    ASSERT(!m_isCallable);
}

MediaKeySession::~MediaKeySession()
{
    WTF_LOG(Media, "MediaKeySession(%p)::~MediaKeySession", this);
    m_session.clear();
#if !ENABLE(OILPAN)
    // MediaKeySession and m_asyncEventQueue always become unreachable
    // together. So MediaKeySession and m_asyncEventQueue are destructed in the
    // same GC. We don't need to call cancelAllEvents explicitly in Oilpan.
    m_asyncEventQueue->cancelAllEvents();
#endif
}

void MediaKeySession::setError(MediaKeyError* error)
{
    m_error = error;
}

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

ScriptPromise MediaKeySession::closed(ScriptState* scriptState)
{
    return m_closedPromise->promise(scriptState->world());
}

ScriptPromise MediaKeySession::generateRequest(ScriptState* scriptState, const String& initDataType, DOMArrayBuffer* initData)
{
    RefPtr<DOMArrayBuffer> initDataCopy = DOMArrayBuffer::create(initData->data(), initData->byteLength());
    return generateRequestInternal(scriptState, initDataType, initDataCopy.release());
}

ScriptPromise MediaKeySession::generateRequest(ScriptState* scriptState, const String& initDataType, DOMArrayBufferView* initData)
{
    RefPtr<DOMArrayBuffer> initDataCopy = DOMArrayBuffer::create(initData->baseAddress(), initData->byteLength());
    return generateRequestInternal(scriptState, initDataType, initDataCopy.release());
}

ScriptPromise MediaKeySession::generateRequestInternal(ScriptState* scriptState, const String& initDataType, PassRefPtr<DOMArrayBuffer> initData)
{
    WTF_LOG(Media, "MediaKeySession(%p)::generateRequest %s", this, initDataType.ascii().data());

    // From https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html#dom-generaterequest:
    // The generateRequest(initDataType, initData) method creates a new session
    // for the specified initData. It must run the following steps:

    // 1. If this object's uninitialized value is false, return a promise
    //    rejected with a new DOMException whose name is "InvalidStateError".
    if (!m_isUninitialized) {
        return ScriptPromise::rejectWithDOMException(
            scriptState, DOMException::create(InvalidStateError, "The session is already initialized."));
    }

    // 2. Let this object's uninitialized be false.
    m_isUninitialized = false;

    // 3. If initDataType is an empty string, return a promise rejected with a
    //    new DOMException whose name is "InvalidAccessError".
    if (initDataType.isEmpty()) {
        return ScriptPromise::rejectWithDOMException(
            scriptState, DOMException::create(InvalidAccessError, "The initDataType parameter is empty."));
    }

    // 4. If initData is an empty array, return a promise rejected with a new
    //    DOMException whose name is"InvalidAccessError".
    if (!initData->byteLength()) {
        return ScriptPromise::rejectWithDOMException(
            scriptState, DOMException::create(InvalidAccessError, "The initData parameter is empty."));
    }

    // 5. Let media keys be the MediaKeys object that created this object.
    //    (Use m_mediaKey, which was set in the constructor.)

    // 6. If the content decryption module corresponding to media keys's
    //    keySystem attribute 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.
    if (!isKeySystemSupportedWithInitDataType(m_keySystem, initDataType)) {
        return ScriptPromise::rejectWithDOMException(
            scriptState, DOMException::create(NotSupportedError, "The initialization data type '" + initDataType + "' is not supported by the key system."));
    }

    // 7. Let init data be a copy of the contents of the initData parameter.
    //    (Done before calling this method.)

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

    // 9. Let promise be a new promise.
    NewSessionResult* result = new NewSessionResult(scriptState, this);
    ScriptPromise promise = result->promise();

    // 10. Run the following steps asynchronously (documented in
    //     actionTimerFired())
    m_pendingActions.append(PendingAction::CreatePendingGenerateRequest(result, initDataType, initData));
    ASSERT(!m_actionTimer.isActive());
    m_actionTimer.startOneShot(0, FROM_HERE);

    // 11. Return promise.
    return promise;
}

ScriptPromise MediaKeySession::load(ScriptState* scriptState, const String& sessionId)
{
    WTF_LOG(Media, "MediaKeySession(%p)::load %s", this, sessionId.ascii().data());

    // From https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html#dom-load:
    // The load(sessionId) method loads the data stored for the sessionId into
    // the session represented by the object. It must run the following steps:

    // 1. If this object's uninitialized value is false, return a promise
    //    rejected with a new DOMException whose name is "InvalidStateError".
    if (!m_isUninitialized) {
        return ScriptPromise::rejectWithDOMException(
            scriptState, DOMException::create(InvalidStateError, "The session is already initialized."));
    }

    // 2. Let this object's uninitialized be false.
    m_isUninitialized = false;

    // 3. If sessionId is an empty string, return a promise rejected with a
    //    new DOMException whose name is "InvalidAccessError".
    if (sessionId.isEmpty()) {
        return ScriptPromise::rejectWithDOMException(
            scriptState, DOMException::create(InvalidAccessError, "The sessionId parameter is empty."));
    }

    // 4. If this object's session type is not "persistent", return a promise
    //    rejected with a new DOMException whose name is "InvalidAccessError".
    if (m_sessionType != kPersistent) {
        return ScriptPromise::rejectWithDOMException(
            scriptState, DOMException::create(InvalidAccessError, "The session type is not 'persistent'."));
    }

    // 5. Let media keys be the MediaKeys object that created this object.
    //    (Done in constructor.)
    ASSERT(m_mediaKeys);

    // 6. If the content decryption module corresponding to media keys's
    //    keySystem attribute does not support loading previous sessions,
    //    return a promise rejected with a new DOMException whose name is
    //    "NotSupportedError".
    //    (Done by CDM.)

    // 7. Let promise be a new promise.
    LoadSessionResult* result = new LoadSessionResult(scriptState, this);
    ScriptPromise promise = result->promise();

    // 8. Run the following steps asynchronously (documented in
    //    actionTimerFired())
    m_pendingActions.append(PendingAction::CreatePendingLoadRequest(result, sessionId));
    ASSERT(!m_actionTimer.isActive());
    m_actionTimer.startOneShot(0, FROM_HERE);

    // 9. Return promise.
    return promise;
}

ScriptPromise MediaKeySession::update(ScriptState* scriptState, DOMArrayBuffer* response)
{
    RefPtr<DOMArrayBuffer> responseCopy = DOMArrayBuffer::create(response->data(), response->byteLength());
    return updateInternal(scriptState, responseCopy.release());
}

ScriptPromise MediaKeySession::update(ScriptState* scriptState, DOMArrayBufferView* response)
{
    RefPtr<DOMArrayBuffer> responseCopy = DOMArrayBuffer::create(response->baseAddress(), response->byteLength());
    return updateInternal(scriptState, responseCopy.release());
}

ScriptPromise MediaKeySession::updateInternal(ScriptState* scriptState, PassRefPtr<DOMArrayBuffer> response)
{
    WTF_LOG(Media, "MediaKeySession(%p)::update", this);
    ASSERT(!m_isClosed);

    // From <https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html#dom-update>:
    // The update(response) method provides messages, including licenses, to the
    // CDM. It must run the following steps:
    //
    // 1. If response is an empty array, return a promise rejected with a new
    //    DOMException whose name is "InvalidAccessError" and that has the
    //    message "The response parameter is empty."
    if (!response->byteLength()) {
        return ScriptPromise::rejectWithDOMException(
            scriptState, DOMException::create(InvalidAccessError, "The response parameter is empty."));
    }

    // 2. Let message be a copy of the contents of the response parameter.
    //    (Copied in the caller.)

    // 3. Let promise be a new promise.
    SimpleContentDecryptionModuleResult* result = new SimpleContentDecryptionModuleResult(scriptState);
    ScriptPromise promise = result->promise();

    // 4. Run the following steps asynchronously (documented in
    //    actionTimerFired())
    m_pendingActions.append(PendingAction::CreatePendingUpdate(result, response));
    if (!m_actionTimer.isActive())
        m_actionTimer.startOneShot(0, FROM_HERE);

    // 5. Return promise.
    return promise;
}

ScriptPromise MediaKeySession::close(ScriptState* scriptState)
{
    WTF_LOG(Media, "MediaKeySession(%p)::close", this);

    // From https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html#dom-close:
    // The close() method allows an application to indicate that it no longer
    // needs the session and the CDM should release any resources associated
    // with this object and close it. The returned promise is resolved when the
    // request has been processed, and the closed attribute promise is resolved
    // when the session is closed. It must run the following steps:
    //
    // 1. If this object's callable value is false, return a promise rejected
    //    with a new DOMException whose name is "InvalidStateError".
    if (!m_isCallable) {
        return ScriptPromise::rejectWithDOMException(
            scriptState, DOMException::create(InvalidStateError, "The session is not callable."));
    }

    // 2. If the Session Close algorithm has been run on this object,
    //    return a resolved promise.
    if (m_isClosed)
        return ScriptPromise::cast(scriptState, ScriptValue());

    // 3. Let promise be a new promise.
    SimpleContentDecryptionModuleResult* result = new SimpleContentDecryptionModuleResult(scriptState);
    ScriptPromise promise = result->promise();

    // 4. Run the following steps asynchronously (documented in
    //    actionTimerFired()).
    m_pendingActions.append(PendingAction::CreatePendingClose(result));
    if (!m_actionTimer.isActive())
        m_actionTimer.startOneShot(0, FROM_HERE);

    // 5. Return promise.
    return promise;
}

ScriptPromise MediaKeySession::remove(ScriptState* scriptState)
{
    WTF_LOG(Media, "MediaKeySession(%p)::remove", this);

    // From https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html#dom-remove:
    // The remove() method allows an application to remove stored session data
    // associated with this object. It must run the following steps:

    // 1. If this object's callable value is false, return a promise rejected
    //    with a new DOMException whose name is "InvalidStateError".
    if (!m_isCallable) {
        return ScriptPromise::rejectWithDOMException(
            scriptState, DOMException::create(InvalidStateError, "The session is not callable."));
    }

    // 2. If this object's session type is not "persistent", return a promise
    //    rejected with a new DOMException whose name is "InvalidAccessError".
    if (m_sessionType != kPersistent) {
        return ScriptPromise::rejectWithDOMException(
            scriptState, DOMException::create(InvalidAccessError, "The session type is not 'persistent'."));
    }

    // 3. If the Session Close algorithm has been run on this object, return a
    //    promise rejected with a new DOMException whose name is
    //    "InvalidStateError".
    if (m_isClosed) {
        return ScriptPromise::rejectWithDOMException(
            scriptState, DOMException::create(InvalidStateError, "The session is already closed."));
    }

    // 4. Let promise be a new promise.
    SimpleContentDecryptionModuleResult* result = new SimpleContentDecryptionModuleResult(scriptState);
    ScriptPromise promise = result->promise();

    // 5. Run the following steps asynchronously (documented in
    //    actionTimerFired()).
    m_pendingActions.append(PendingAction::CreatePendingRemove(result));
    if (!m_actionTimer.isActive())
        m_actionTimer.startOneShot(0, FROM_HERE);

    // 6. Return promise.
    return promise;
}

void MediaKeySession::actionTimerFired(Timer<MediaKeySession>*)
{
    ASSERT(m_pendingActions.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> > pendingActions;
    pendingActions.swap(m_pendingActions);

    while (!pendingActions.isEmpty()) {
        PendingAction* action = pendingActions.takeFirst();

        switch (action->type()) {
        case PendingAction::GenerateRequest:
            WTF_LOG(Media, "MediaKeySession(%p)::actionTimerFired: GenerateRequest", this);

            // 10.1 Let request be null.
            // 10.2 Let cdm be the CDM loaded during the initialization of
            //      media keys.
            // 10.3 Use the cdm to execute the following steps:
            // 10.3.1 If the init data is not valid for initDataType, reject
            //        promise with a new DOMException whose name is
            //        "InvalidAccessError".
            // 10.3.2 If the init data is not supported by the cdm, reject
            //        promise with a new DOMException whose name is
            //        "NotSupportedError".
            // 10.3.3 Let request be a request (e.g. a license request)
            //        generated based on the init data, which is interpreted
            //        per initDataType, and session type.
            m_session->initializeNewSession(action->initDataType(), static_cast<unsigned char*>(action->data()->data()), action->data()->byteLength(), m_sessionType, action->result()->result());

            // Remainder of steps executed in finishGenerateRequest(), called
            // when |result| is resolved.
            break;

        case PendingAction::Load:
            // NOTE: Continue step 8 of MediaKeySession::load().

            // 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 previous step failed, reject promise with a new
            //     DOMException whose name is "InvalidAccessError".
            if (!isValidSessionId(action->sessionId())) {
                action->result()->completeWithError(WebContentDecryptionModuleExceptionInvalidAccessError, 0, "Invalid sessionId");
                return;
            }

            // 8.3 Let expiration time be NaN.
            //     (Done in the constructor.)
            ASSERT(std::isnan(m_expiration));

            // 8.4 Let message be null.
            // 8.5 Let message type be null.
            //     (Will be provided by the CDM if needed.)

            // 8.6 Let origin be the origin of this object's Document.
            //     (Obtained previously when CDM created.)

            // 8.7 Let cdm be the CDM loaded during the initialization of media
            //     keys.
            // 8.8 Use the cdm to execute the following steps:
            // 8.8.1 If there is no data stored for the sanitized session ID in
            //       the origin, resolve promise with false.
            // 8.8.2 Let session data be the data stored for the sanitized
            //       session ID in the origin. This must not include data from
            //       other origin(s) or that is not associated with an origin.
            // 8.8.3 If there is an unclosed "persistent" session in any
            //       Document representing the session data, reject promise
            //       with a new DOMException whose name is "QuotaExceededError".
            // 8.8.4 In other words, do not create a session if a non-closed
            //       persistent session already exists for this sanitized
            //       session ID in any browsing context.
            // 8.8.5 Load the session data.
            // 8.8.6 If the session data indicates an expiration time for the
            //       session, let expiration time be the expiration time
            //       in milliseconds since 01 January 1970 UTC.
            // 8.8.6 If the CDM needs to send a message:
            // 8.8.6.1 Let message be a message generated by the CDM based on
            //         the session data.
            // 8.8.6.2 Let message type be the appropriate MediaKeyMessageType
            //         for the message.
            // 8.9 If any of the preceding steps failed, reject promise with a
            //     new DOMException whose name is the appropriate error name.
            m_session->load(action->sessionId(), action->result()->result());

            // Remainder of steps executed in finishLoad(), called
            // when |result| is resolved.
            break;

        case PendingAction::Update:
            WTF_LOG(Media, "MediaKeySession(%p)::actionTimerFired: Update", this);
            // NOTE: Continued from step 4 of MediaKeySession::update().
            // Continue the update call by passing message to the cdm. Once
            // completed, it will resolve/reject the promise.
            m_session->update(static_cast<unsigned char*>(action->data()->data()), action->data()->byteLength(), action->result()->result());
            break;

        case PendingAction::Close:
            WTF_LOG(Media, "MediaKeySession(%p)::actionTimerFired: Close", this);
            // NOTE: Continued from step 4 of MediaKeySession::close().
            // 4.1 Let cdm be the CDM loaded during the initialization of the
            //     MediaKeys object that created this object.
            //     (Already captured when creating m_session).
            // 4.2 Use the cdm to execute the following steps:
            // 4.2.1 Process the close request. Do not remove stored session
            //       data.
            // 4.2.3 If the previous step caused the session to be closed,
            //       run the Session Close algorithm on this object.
            // 4.3 Resolve promise.
            m_session->close(action->result()->result());
            break;

        case PendingAction::Remove:
            WTF_LOG(Media, "MediaKeySession(%p)::actionTimerFired: Remove", this);
            // NOTE: Continued from step 5 of MediaKeySession::remove().
            // 5.1 Let cdm be the CDM loaded during the initialization of the
            //     MediaKeys object that created this object.
            //     (Already captured when creating m_session).
            // 5.2 Use the cdm to execute the following steps:
            // 5.2.1 Process the remove request. This may involve exchanging
            //       message(s) with the application. Unless this step fails,
            //       the CDM must have cleared all stored session data
            //       associated with this object, including the sessionId,
            //       before proceeding to the next step. (A subsequent call
            //       to load() with sessionId would fail because there is no
            //       data stored for the sessionId.)
            // 5.3 Run the following steps asynchronously once the above step
            //     has completed:
            // 5.3.1 If any of the preceding steps failed, reject promise
            //       with a new DOMException whose name is the appropriate
            //       error name.
            // 5.3.2 Run the Session Close algorithm on this object.
            // 5.3.3 Resolve promise.
            m_session->remove(action->result()->result());
            break;
        }
    }
}

void MediaKeySession::finishGenerateRequest()
{
    // 10.4 Set the sessionId attribute to a unique Session ID string.
    //      It may be obtained from cdm.
    ASSERT(!sessionId().isEmpty());

    // 10.5 If any of the preceding steps failed, reject promise with a new
    //      DOMException whose name is the appropriate error name.
    //      (Done by call to completeWithError()).

    // 10.6 Add an entry for the value of the sessionId attribute to
    //      media keys's list of active session IDs.
    // FIXME: Is this required?
    // https://www.w3.org/Bugs/Public/show_bug.cgi?id=26758

    // 10.7 Run the Queue a "message" Event algorithm on the session,
    //      providing request and null.
    //      (Done by the CDM).

    // 10.8 Let this object's callable be true.
    m_isCallable = true;
}

void MediaKeySession::finishLoad()
{
    // 8.10 Set the sessionId attribute to sanitized session ID.
    ASSERT(!sessionId().isEmpty());

    // 8.11 Let this object's callable be true.
    m_isCallable = true;

    // 8.12 If the loaded session contains usable keys, run the Usable
    //      Keys Changed algorithm on the session. The algorithm may
    //      also be run later should additional processing be necessary
    //      to determine with certainty whether one or more keys is
    //      usable.
    //      (Done by the CDM.)

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

    // 8.14 If message is not null, run the Queue a "message" Event
    //      algorithm on the session, providing message type and
    //      message.
    //      (Done by the CDM.)
}

// Queue a task to fire a simple event named keymessage at the new object.
void MediaKeySession::message(const unsigned char* message, size_t messageLength, const WebURL& destinationURL)
{
    WTF_LOG(Media, "MediaKeySession(%p)::message", this);

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

    MediaKeyMessageEventInit init;
    init.bubbles = false;
    init.cancelable = false;
    init.message = DOMArrayBuffer::create(static_cast<const void*>(message), messageLength);
    init.destinationURL = destinationURL.string();

    RefPtrWillBeRawPtr<MediaKeyMessageEvent> event = MediaKeyMessageEvent::create(EventTypeNames::message, init);
    event->setTarget(this);
    m_asyncEventQueue->enqueueEvent(event.release());
}

void MediaKeySession::ready()
{
    WTF_LOG(Media, "MediaKeySession(%p)::ready", this);

    RefPtrWillBeRawPtr<Event> event = Event::create(EventTypeNames::ready);
    event->setTarget(this);
    m_asyncEventQueue->enqueueEvent(event.release());
}

void MediaKeySession::close()
{
    WTF_LOG(Media, "MediaKeySession(%p)::close", this);

    // Once closed, the session can no longer be the target of events from
    // the CDM so this object can be garbage collected.
    m_isClosed = true;

    // Resolve the closed promise.
    m_closedPromise->resolve(V8UndefinedType());
}

// Queue a task to fire a simple event named keyadded at the MediaKeySession object.
void MediaKeySession::error(MediaKeyErrorCode errorCode, unsigned long systemCode)
{
    WTF_LOG(Media, "MediaKeySession(%p)::error: errorCode=%d, systemCode=%lu", this, errorCode, systemCode);

    MediaKeyError::Code mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_UNKNOWN;
    switch (errorCode) {
    case MediaKeyErrorCodeUnknown:
        mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_UNKNOWN;
        break;
    case MediaKeyErrorCodeClient:
        mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_CLIENT;
        break;
    }

    // 1. Create a new MediaKeyError object with the following attributes:
    //    code = the appropriate MediaKeyError code
    //    systemCode = a Key System-specific value, if provided, and 0 otherwise
    // 2. Set the MediaKeySession object's error attribute to the error object created in the previous step.
    m_error = MediaKeyError::create(mediaKeyErrorCode, systemCode);

    // 3. queue a task to fire a simple event named keyerror at the MediaKeySession object.
    RefPtrWillBeRawPtr<Event> event = Event::create(EventTypeNames::error);
    event->setTarget(this);
    m_asyncEventQueue->enqueueEvent(event.release());
}

void MediaKeySession::error(WebContentDecryptionModuleException exception, unsigned long systemCode, const WebString& errorMessage)
{
    WTF_LOG(Media, "MediaKeySession::error: exception=%d, systemCode=%lu", exception, systemCode);

    // FIXME: EME-WD MediaKeyError now derives from DOMException. Figure out how
    // to implement this without breaking prefixed EME, which has a totally
    // different definition. The spec may also change to be just a DOMException.
    // For now, simply generate an existing MediaKeyError.
    MediaKeyErrorCode errorCode;
    switch (exception) {
    case WebContentDecryptionModuleExceptionClientError:
        errorCode = MediaKeyErrorCodeClient;
        break;
    default:
        // All other exceptions get converted into Unknown.
        errorCode = MediaKeyErrorCodeUnknown;
        break;
    }
    error(errorCode, systemCode);
}

void MediaKeySession::expirationChanged(double updatedExpiryTimeInMS)
{
    m_expiration = updatedExpiryTimeInMS;
}

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

ExecutionContext* MediaKeySession::executionContext() const
{
    return ActiveDOMObject::executionContext();
}

bool MediaKeySession::hasPendingActivity() const
{
    // Remain around if there are pending events or MediaKeys is still around
    // and we're not closed.
    WTF_LOG(Media, "MediaKeySession(%p)::hasPendingActivity %s%s%s%s", this,
        ActiveDOMObject::hasPendingActivity() ? " ActiveDOMObject::hasPendingActivity()" : "",
        !m_pendingActions.isEmpty() ? " !m_pendingActions.isEmpty()" : "",
        m_asyncEventQueue->hasPendingEvents() ? " m_asyncEventQueue->hasPendingEvents()" : "",
        (m_mediaKeys && !m_isClosed) ? " m_mediaKeys && !m_isClosed" : "");

    return ActiveDOMObject::hasPendingActivity()
        || !m_pendingActions.isEmpty()
        || m_asyncEventQueue->hasPendingEvents()
        || (m_mediaKeys && !m_isClosed);
}

void MediaKeySession::stop()
{
    // Stop the CDM from firing any more events for this session.
    m_session.clear();
    m_isClosed = true;

    if (m_actionTimer.isActive())
        m_actionTimer.stop();
    m_pendingActions.clear();
    m_asyncEventQueue->close();
}

void MediaKeySession::trace(Visitor* visitor)
{
    visitor->trace(m_error);
    visitor->trace(m_asyncEventQueue);
    visitor->trace(m_pendingActions);
    visitor->trace(m_mediaKeys);
    visitor->trace(m_closedPromise);
    EventTargetWithInlineData::trace(visitor);
}

} // namespace blink
