/*
 * Copyright (C) 2016 Metrological Group B.V.
 * Copyright (C) 2016 Igalia S.L.
 *
 * 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
 * HOLDER OR 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 "MediaKeySystemAccess.h"

#if ENABLE(ENCRYPTED_MEDIA)

#include "CDM.h"
#include "CDMInstance.h"
#include "JSDOMPromiseDeferred.h"
#include "JSMediaKeys.h"
#include "MediaKeys.h"
#include "MediaKeysRequirement.h"

namespace WebCore {

Ref<MediaKeySystemAccess> MediaKeySystemAccess::create(const String& keySystem, MediaKeySystemConfiguration&& configuration, Ref<CDM>&& implementation)
{
    return adoptRef(*new MediaKeySystemAccess(keySystem, WTFMove(configuration), WTFMove(implementation)));
}

MediaKeySystemAccess::MediaKeySystemAccess(const String& keySystem, MediaKeySystemConfiguration&& configuration, Ref<CDM>&& implementation)
    : m_keySystem(keySystem)
    , m_configuration(new MediaKeySystemConfiguration(WTFMove(configuration)))
    , m_implementation(WTFMove(implementation))
{
}

MediaKeySystemAccess::~MediaKeySystemAccess() = default;

void MediaKeySystemAccess::createMediaKeys(Ref<DeferredPromise>&& promise)
{
    // https://w3c.github.io/encrypted-media/#dom-mediakeysystemaccess-createmediakeys
    // W3C Editor's Draft 09 November 2016

    // When this method is invoked, the user agent must run the following steps:
    // 1. Let promise be a new promise.
    // 2. Run the following steps in parallel:
    m_taskQueue.enqueueTask([this, promise = WTFMove(promise)] () mutable {
        // 2.1. Let configuration be the value of this object's configuration value.
        // 2.2. Let use distinctive identifier be true if the value of configuration's distinctiveIdentifier member is "required" and false otherwise.
        bool useDistinctiveIdentifier = m_configuration->distinctiveIdentifier == MediaKeysRequirement::Required;

        // 2.3. Let persistent state allowed be true if the value of configuration's persistentState member is "required" and false otherwise.
        bool persistentStateAllowed = m_configuration->persistentState == MediaKeysRequirement::Required;

        // 2.4. Load and initialize the Key System implementation represented by this object's cdm implementation value if necessary.
        m_implementation->loadAndInitialize();

        // 2.5. Let instance be a new instance of the Key System implementation represented by this object's cdm implementation value.
        auto instance = m_implementation->createInstance();
        if (!instance) {
            promise->reject(InvalidStateError);
            return;
        }

        // 2.6. Initialize instance to enable, disable and/or select Key System features using configuration.
        if (instance->initializeWithConfiguration(*m_configuration) == CDMInstance::Failed) {
            promise->reject(NotAllowedError);
            return;
        }

        // 2.7. If use distinctive identifier is false, prevent instance from using Distinctive Identifier(s) and Distinctive Permanent Identifier(s).
        if (!useDistinctiveIdentifier && instance->setDistinctiveIdentifiersAllowed(false) == CDMInstance::Failed) {
            promise->reject(NotAllowedError);
            return;
        }

        // 2.8. If persistent state allowed is false, prevent instance from persisting any state related to the application or origin of this object's Document.
        if (!persistentStateAllowed && instance->setPersistentStateAllowed(false) == CDMInstance::Failed) {
            promise->reject(NotAllowedError);
            return;
        }

        // 2.9. If any of the preceding steps failed, reject promise with a new DOMException whose name is the appropriate error name.
        // 2.10. Let media keys be a new MediaKeys object, and initialize it as follows:
        // 2.10.1. Let the use distinctive identifier value be use distinctive identifier.
        // 2.10.2. Let the persistent state allowed value be persistent state allowed.
        // 2.10.3. Let the supported session types value be be the value of configuration's sessionTypes member.
        // 2.10.4. Let the cdm implementation value be this object's cdm implementation value.
        // 2.10.5. Let the cdm instance value be instance.
        auto mediaKeys = MediaKeys::create(useDistinctiveIdentifier, persistentStateAllowed, m_configuration->sessionTypes, m_implementation.copyRef(), instance.releaseNonNull());

        // 2.11. Resolve promise with media keys.
        promise->resolveWithNewlyCreated<IDLInterface<MediaKeys>>(WTFMove(mediaKeys));
    });

    // 3. Return promise.
}

} // namespace WebCore

#endif // ENABLE(ENCRYPTED_MEDIA)
