/*
 * 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 "NavigatorEME.h"

#if ENABLE(ENCRYPTED_MEDIA)

#include "CDM.h"
#include "Document.h"
#include "JSMediaKeySystemAccess.h"

namespace WebCore {

static void tryNextSupportedConfiguration(RefPtr<CDM>&& implementation, Vector<MediaKeySystemConfiguration>&& supportedConfigurations, RefPtr<DeferredPromise>&&);

void NavigatorEME::requestMediaKeySystemAccess(Navigator&, Document& document, const String& keySystem, Vector<MediaKeySystemConfiguration>&& supportedConfigurations, Ref<DeferredPromise>&& promise)
{
    // https://w3c.github.io/encrypted-media/#dom-navigator-requestmediakeysystemaccess
    // W3C Editor's Draft 09 November 2016

    // When this method is invoked, the user agent must run the following steps:
    // 1. If keySystem is the empty string, return a promise rejected with a newly created TypeError.
    // 2. If supportedConfigurations is empty, return a promise rejected with a newly created TypeError.
    if (keySystem.isEmpty() || supportedConfigurations.isEmpty()) {
        promise->reject(TypeError);
        return;
    }

    document.postTask([keySystem, supportedConfigurations = WTFMove(supportedConfigurations), promise = WTFMove(promise), &document] (ScriptExecutionContext&) mutable {
        // 3. Let document be the calling context's Document.
        // 4. Let origin be the origin of document.
        // 5. Let promise be a new promise.
        // 6. Run the following steps in parallel:
        // 6.1. If keySystem is not one of the Key Systems supported by the user agent, reject promise with a NotSupportedError.
        //      String comparison is case-sensitive.
        if (!CDM::supportsKeySystem(keySystem)) {
            promise->reject(NotSupportedError);
            return;
        }

        // 6.2. Let implementation be the implementation of keySystem.
        RefPtr<CDM> implementation = CDM::create(document, keySystem);
        tryNextSupportedConfiguration(WTFMove(implementation), WTFMove(supportedConfigurations), WTFMove(promise));
    });
}

static void tryNextSupportedConfiguration(RefPtr<CDM>&& implementation, Vector<MediaKeySystemConfiguration>&& supportedConfigurations, RefPtr<DeferredPromise>&& promise)
{
    // 6.3. For each value in supportedConfigurations:
    if (!supportedConfigurations.isEmpty()) {
        // 6.3.1. Let candidate configuration be the value.
        // 6.3.2. Let supported configuration be the result of executing the Get Supported Configuration
        //        algorithm on implementation, candidate configuration, and origin.
        MediaKeySystemConfiguration candidateConfiguration = WTFMove(supportedConfigurations.first());
        supportedConfigurations.remove(0);

        CDM::SupportedConfigurationCallback callback = [implementation = implementation, supportedConfigurations = WTFMove(supportedConfigurations), promise] (std::optional<MediaKeySystemConfiguration> supportedConfiguration) mutable {
            // 6.3.3. If supported configuration is not NotSupported, run the following steps:
            if (supportedConfiguration) {
                // 6.3.3.1. Let access be a new MediaKeySystemAccess object, and initialize it as follows:
                // 6.3.3.1.1. Set the keySystem attribute to keySystem.
                // 6.3.3.1.2. Let the configuration value be supported configuration.
                // 6.3.3.1.3. Let the cdm implementation value be implementation.

                // Obtain reference to the key system string before the `implementation` RefPtr<> is cleared out.
                const String& keySystem = implementation->keySystem();
                auto access = MediaKeySystemAccess::create(keySystem, WTFMove(supportedConfiguration.value()), implementation.releaseNonNull());

                // 6.3.3.2. Resolve promise with access and abort the parallel steps of this algorithm.
                promise->resolveWithNewlyCreated<IDLInterface<MediaKeySystemAccess>>(WTFMove(access));
                return;
            }

            tryNextSupportedConfiguration(WTFMove(implementation), WTFMove(supportedConfigurations), WTFMove(promise));
        };
        implementation->getSupportedConfiguration(WTFMove(candidateConfiguration), WTFMove(callback));
        return;
    }


    // 6.4. Reject promise with a NotSupportedError.
    promise->reject(NotSupportedError);
}

} // namespace WebCore

#endif // ENABLE(ENCRYPTED_MEDIA)
