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

#if ENABLE(ENCRYPTED_MEDIA)

#include "CDMKeySystemConfiguration.h"
#include "CDMRestrictions.h"
#include "CDMSessionType.h"
#include "SharedBuffer.h"
#include <wtf/JSONValues.h>
#include <wtf/MainThread.h>
#include <wtf/NeverDestroyed.h>
#include <wtf/text/Base64.h>

namespace WebCore {

// ClearKey CENC SystemID.
// https://www.w3.org/TR/eme-initdata-cenc/#common-system
const uint8_t clearKeyCencSystemId[] = { 0x10, 0x77, 0xef, 0xec, 0xc0, 0xb2, 0x4d, 0x02, 0xac, 0xe3, 0x3c, 0x1e, 0x52, 0xe2, 0xfb, 0x4b };
const unsigned clearKeyCencSystemIdSize = sizeof(clearKeyCencSystemId);
const unsigned keyIdSize = 16;

class ClearKeyState {
    using KeyStore = HashMap<String, Vector<CDMInstanceClearKey::Key>>;

public:
    static ClearKeyState& singleton();

    KeyStore& keys() { return m_keys; }

private:
    friend class NeverDestroyed<ClearKeyState>;
    ClearKeyState();
    KeyStore m_keys;
};

ClearKeyState& ClearKeyState::singleton()
{
    static NeverDestroyed<ClearKeyState> s_state;
    return s_state;
}

ClearKeyState::ClearKeyState() = default;

static RefPtr<JSON::Object> parseJSONObject(const SharedBuffer& buffer)
{
    // Fail on large buffers whose size doesn't fit into a 32-bit unsigned integer.
    size_t size = buffer.size();
    if (size > std::numeric_limits<unsigned>::max())
        return nullptr;

    // Parse the buffer contents as JSON, returning the root object (if any).
    String json { buffer.data(), static_cast<unsigned>(size) };
    RefPtr<JSON::Value> value;
    RefPtr<JSON::Object> object;
    if (!JSON::Value::parseJSON(json, value) || !value->asObject(object))
        return nullptr;

    return object;
}

static Optional<Vector<CDMInstanceClearKey::Key>> parseLicenseFormat(const JSON::Object& root)
{
    // If the 'keys' key is present in the root object, parse the JSON further
    // according to the specified 'license' format.
    auto it = root.find("keys");
    if (it == root.end())
        return WTF::nullopt;

    // Retrieve the keys array.
    RefPtr<JSON::Array> keysArray;
    if (!it->value->asArray(keysArray))
        return WTF::nullopt;

    Vector<CDMInstanceClearKey::Key> decodedKeys;
    bool validFormat = std::all_of(keysArray->begin(), keysArray->end(),
        [&decodedKeys] (const auto& value) {
            RefPtr<JSON::Object> keyObject;
            if (!value->asObject(keyObject))
                return false;

            String keyType;
            if (!keyObject->getString("kty", keyType) || !equalLettersIgnoringASCIICase(keyType, "oct"))
                return false;

            String keyID, keyValue;
            if (!keyObject->getString("kid", keyID) || !keyObject->getString("k", keyValue))
                return false;

            Vector<char> keyIDData, keyValueData;
            if (!WTF::base64URLDecode(keyID, { keyIDData }) || !WTF::base64URLDecode(keyValue, { keyValueData }))
                return false;

            decodedKeys.append({ CDMInstanceSession::KeyStatus::Usable, SharedBuffer::create(WTFMove(keyIDData)), SharedBuffer::create(WTFMove(keyValueData)) });
            return true;
        });
    if (!validFormat)
        return WTF::nullopt;
    return decodedKeys;
}

static bool parseLicenseReleaseAcknowledgementFormat(const JSON::Object& root)
{
    // If the 'kids' key is present in the root object, parse the JSON further
    // according to the specified 'license release acknowledgement' format.
    auto it = root.find("kids");
    if (it == root.end())
        return false;

    // Retrieve the kids array.
    RefPtr<JSON::Array> kidsArray;
    if (!it->value->asArray(kidsArray))
        return false;

    // FIXME: Return the key IDs and validate them.
    return true;
}

// https://www.w3.org/TR/eme-initdata-cenc/#common-system
// 4.1 Definition
// The SystemID is 1077efec-c0b2-4d02-ace3-3c1e52e2fb4b.
// The PSSH box format is as follows. It follows version 1 of the 'pssh' box as defined in [CENC].
// pssh = [
// 0x00, 0x00, 0x00, 0x4c, 0x70, 0x73, 0x73, 0x68, // BMFF box header (76 bytes, 'pssh')
// 0x01, 0x00, 0x00, 0x00,                         // Full box header (version = 1, flags = 0)
// 0x10, 0x77, 0xef, 0xec, 0xc0, 0xb2, 0x4d, 0x02, // SystemID
// 0xac, 0xe3, 0x3c, 0x1e, 0x52, 0xe2, 0xfb, 0x4b,
// 0x00, 0x00, 0x00, 0x02,                         // KidCount (2)
// 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, // First KID ("0123456789012345")
// 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
// 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, // Second KID ("ABCDEFGHIJKLMNOP")
// 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
// 0x00, 0x00, 0x00, 0x00,                         // Size of Data (0)
// ];

// This function extracts the KeyIds count and the location of the first KeyId in initData buffer.
static std::pair<unsigned, unsigned> extractKeyidsLocationFromCencInitData(const SharedBuffer& initData)
{
    std::pair<unsigned, unsigned> keyIdsMap(0, 0);

    // Check the initData size.
    if (initData.isEmpty() || initData.size() > std::numeric_limits<unsigned>::max())
        return keyIdsMap;

    const char* data = initData.data();
    unsigned initDataSize = initData.size();
    unsigned index = 0;
    unsigned psshSize = 0;

    // Search in the concatenated or the simple InitData, the ClearKey PSSH.
    bool foundPssh = false;
    while (true) {

        // Check the overflow InitData.
        if (index + 12 + clearKeyCencSystemIdSize >= initDataSize)
            return keyIdsMap;

        psshSize = data[index + 2] * 256 + data[index + 3];

        // Check the pssh size
        if (!psshSize)
            return keyIdsMap;

        // 12 = BMFF box header + Full box header.
        if (!memcmp(&data[index + 12], clearKeyCencSystemId, clearKeyCencSystemIdSize)) {
            foundPssh = true;
            break;
        }
        index += psshSize;
    }

    // Check if the InitData contains the ClearKey PSSH.
    if (!foundPssh)
        return keyIdsMap;

    index += (12 + clearKeyCencSystemIdSize); // 12 (BMFF box header + Full box header) + SystemID size.

    // Check the overflow.
    if (index + 3 >= initDataSize)
        return keyIdsMap;

    keyIdsMap.first = data[index + 3]; // Read the KeyIdsCount.
    index += 4; // KeyIdsCount size.

    // Check the overflow.
    if ((index + (keyIdsMap.first * keyIdSize)) >= initDataSize)
        return keyIdsMap;

    keyIdsMap.second = index; // The location of the first KeyId in initData.

    return keyIdsMap;
}

// This function checks if the initData sharedBuffer is a valid CENC initData.
static bool isCencInitData(const SharedBuffer& initData)
{
    std::pair<unsigned, unsigned> keyIdsMap = extractKeyidsLocationFromCencInitData(initData);
    return ((keyIdsMap.first) && (keyIdsMap.second));
}

static Ref<SharedBuffer> extractKeyidsFromCencInitData(const SharedBuffer& initData)
{
    Ref<SharedBuffer> keyIds = SharedBuffer::create();

    std::pair<unsigned, unsigned> keyIdsMap = extractKeyidsLocationFromCencInitData(initData);
    unsigned keyIdCount = keyIdsMap.first;
    unsigned index = keyIdsMap.second;

    // Check if initData is a valid CENC initData.
    if (!keyIdCount || !index)
        return keyIds;

    const char* data = initData.data();

    auto object = JSON::Object::create();
    auto keyIdsArray = JSON::Array::create();

    // Read the KeyId
    // 9.1.3 License Request Format
    // This section describes the format of the license request provided to the application via the message attribute of the message event.
    // The format is a JSON object containing the following members:
    // "kids"
    // An array of key IDs. Each element of the array is the base64url encoding of the octet sequence containing the key ID value.
    for (unsigned i = 0; i < keyIdCount; i++) {
        String keyId = WTF::base64URLEncode(&data[index], keyIdSize);
        keyIdsArray->pushString(keyId);
        index += keyIdSize;
    }

    object->setArray("kids", WTFMove(keyIdsArray));
    CString jsonData = object->toJSONString().utf8();
    keyIds->append(jsonData.data(), jsonData.length());
    return keyIds;
}

static Ref<SharedBuffer> extractKeyIdFromWebMInitData(const SharedBuffer& initData)
{
    Ref<SharedBuffer> keyIds = SharedBuffer::create();

    // Check if initData is a valid WebM initData.
    if (initData.isEmpty() || initData.size() > std::numeric_limits<unsigned>::max())
        return keyIds;

    auto object = JSON::Object::create();
    auto keyIdsArray = JSON::Array::create();

    // Read the KeyId
    // 9.1.3 License Request Format
    // This section describes the format of the license request provided to the application via the message attribute of the message event.
    // The format is a JSON object containing the following members:
    // "kids"
    // An array of key IDs. Each element of the array is the base64url encoding of the octet sequence containing the key ID value.
    String keyId = WTF::base64URLEncode(initData.data(), initData.size());
    keyIdsArray->pushString(keyId);

    object->setArray("kids", WTFMove(keyIdsArray));
    CString jsonData = object->toJSONString().utf8();
    keyIds->append(jsonData.data(), jsonData.length());
    return keyIds;
}

CDMFactoryClearKey& CDMFactoryClearKey::singleton()
{
    static NeverDestroyed<CDMFactoryClearKey> s_factory;
    return s_factory;
}

CDMFactoryClearKey::CDMFactoryClearKey() = default;
CDMFactoryClearKey::~CDMFactoryClearKey() = default;

std::unique_ptr<CDMPrivate> CDMFactoryClearKey::createCDM(const String& keySystem)
{
#ifdef NDEBUG
    UNUSED_PARAM(keySystem);
#else
    ASSERT(supportsKeySystem(keySystem));
#endif
    return makeUnique<CDMPrivateClearKey>();
}

bool CDMFactoryClearKey::supportsKeySystem(const String& keySystem)
{
    // `org.w3.clearkey` is the only supported key system.
    return equalLettersIgnoringASCIICase(keySystem, "org.w3.clearkey");
}

CDMPrivateClearKey::CDMPrivateClearKey() = default;
CDMPrivateClearKey::~CDMPrivateClearKey() = default;

bool CDMPrivateClearKey::supportsInitDataType(const AtomString& initDataType) const
{
    // `keyids` and 'cenc' are the only supported init data type.
    return (equalLettersIgnoringASCIICase(initDataType, "keyids") || equalLettersIgnoringASCIICase(initDataType, "cenc") || equalLettersIgnoringASCIICase(initDataType, "webm"));
}

static bool containsPersistentLicenseType(const Vector<CDMSessionType>& types)
{
    return std::any_of(types.begin(), types.end(),
        [] (auto& sessionType) { return sessionType == CDMSessionType::PersistentLicense; });
}

bool CDMPrivateClearKey::supportsConfiguration(const CDMKeySystemConfiguration& configuration) const
{
    // Reject any configuration that marks distinctive identifier as required.
    if (configuration.distinctiveIdentifier == CDMRequirement::Required)
        return false;

    // Reject any configuration that marks persistent state as required, unless
    // the 'persistent-license' session type has to be supported.
    if (configuration.persistentState == CDMRequirement::Required && !containsPersistentLicenseType(configuration.sessionTypes))
        return false;

    return true;
}

bool CDMPrivateClearKey::supportsConfigurationWithRestrictions(const CDMKeySystemConfiguration& configuration, const CDMRestrictions& restrictions) const
{
    // Reject any configuration that marks distincitive identifier as required, or that marks
    // distinctive identifier as optional even when restrictions mark it as denied.
    if ((configuration.distinctiveIdentifier == CDMRequirement::Optional && restrictions.distinctiveIdentifierDenied)
        || configuration.distinctiveIdentifier == CDMRequirement::Required)
        return false;

    // Reject any configuration that marks persistent state as optional even when
    // restrictions mark it as denied.
    if (configuration.persistentState == CDMRequirement::Optional && restrictions.persistentStateDenied)
        return false;

    // Reject any configuration that marks persistent state as required, unless
    // the 'persistent-license' session type has to be supported.
    if (configuration.persistentState == CDMRequirement::Required && !containsPersistentLicenseType(configuration.sessionTypes))
        return false;

    return true;
}

bool CDMPrivateClearKey::supportsSessionTypeWithConfiguration(CDMSessionType& sessionType, const CDMKeySystemConfiguration& configuration) const
{
    // Only support the 'temporary' and 'persistent-license' session types.
    if (sessionType != CDMSessionType::Temporary && sessionType != CDMSessionType::PersistentLicense)
        return false;
    return supportsConfiguration(configuration);
}

bool CDMPrivateClearKey::supportsRobustness(const String& robustness) const
{
    // Only empty `robustness` string is supported.
    return robustness.isEmpty();
}

CDMRequirement CDMPrivateClearKey::distinctiveIdentifiersRequirement(const CDMKeySystemConfiguration&, const CDMRestrictions& restrictions) const
{
    // Distinctive identifier is not allowed if it's been denied, otherwise it's optional.
    if (restrictions.distinctiveIdentifierDenied)
        return CDMRequirement::NotAllowed;
    return CDMRequirement::Optional;
}

CDMRequirement CDMPrivateClearKey::persistentStateRequirement(const CDMKeySystemConfiguration&, const CDMRestrictions& restrictions) const
{
    // Persistent state is not allowed if it's been denied, otherwise it's optional.
    if (restrictions.persistentStateDenied)
        return CDMRequirement::NotAllowed;
    return CDMRequirement::Optional;
}

bool CDMPrivateClearKey::distinctiveIdentifiersAreUniquePerOriginAndClearable(const CDMKeySystemConfiguration&) const
{
    return false;
}

RefPtr<CDMInstance> CDMPrivateClearKey::createInstance()
{
    return adoptRef(new CDMInstanceClearKey);
}

void CDMPrivateClearKey::loadAndInitialize()
{
    // No-op.
}

bool CDMPrivateClearKey::supportsServerCertificates() const
{
    // Server certificates are not supported.
    return false;
}

bool CDMPrivateClearKey::supportsSessions() const
{
    // Sessions are supported.
    return true;
}

bool CDMPrivateClearKey::supportsInitData(const AtomString& initDataType, const SharedBuffer& initData) const
{
    // Validate the initData buffer as an JSON object in keyids case.
    if (equalLettersIgnoringASCIICase(initDataType, "keyids") && parseJSONObject(initData))
        return true;

    // Validate the initData buffer as CENC initData.
    if (equalLettersIgnoringASCIICase(initDataType, "cenc") && isCencInitData(initData))
        return true;

    // Validate the initData buffer as WebM initData.
    if (equalLettersIgnoringASCIICase(initDataType, "webm") && !initData.isEmpty())
        return true;

    return false;
}

RefPtr<SharedBuffer> CDMPrivateClearKey::sanitizeResponse(const SharedBuffer& response) const
{
    // Validate the response buffer as an JSON object.
    if (!parseJSONObject(response))
        return nullptr;

    return response.copy();
}

Optional<String> CDMPrivateClearKey::sanitizeSessionId(const String& sessionId) const
{
    // Validate the session ID string as an 32-bit integer.
    bool ok;
    sessionId.toUIntStrict(&ok);
    if (!ok)
        return WTF::nullopt;
    return sessionId;
}

// This is for thread-safety during an architectural situation that is
// less than ideal. The GStreamer decryptors currently need to iterate
// all known session keys to find the key data for priming
// GCrypt. Ideally, all decryption would be the responsibility of
// ProxyCDM object like this one. What the background GStreamer
// thread was doing was getting copies (i.e. ref()'s) of SharedBuffers
// created on the main-thread. With the new safety assertions in
// WebKit, we can no longer do this. Instead, convert the refcounted
// SharedBuffers into Strings which can be safely copied across
// threads.
static ProxyCDMClearKey::Key isolatedKey(const CDMInstanceClearKey::Key& key)
{
    return { key.status, String(key.keyIDData->data(), key.keyIDData->size()), String(key.keyValueData->data(), key.keyValueData->size()) };
}

const Vector<ProxyCDMClearKey::Key> ProxyCDMClearKey::isolatedKeys() const
{
    // Return the keys of all sessions, may be copied to background threads.
    Vector<ProxyCDMClearKey::Key> allKeys { };
    auto locker = holdLock(m_keysMutex);
    size_t initialCapacity = 0;
    for (auto& keyVector : ClearKeyState::singleton().keys().values())
        initialCapacity += keyVector.size();
    allKeys.reserveInitialCapacity(initialCapacity);

    for (auto& keyVector : ClearKeyState::singleton().keys().values()) {
        for (auto& key : keyVector)
            allKeys.uncheckedAppend(isolatedKey(key));
    }

    return allKeys;
}

CDMInstanceClearKey::CDMInstanceClearKey()
    : m_proxyCDM(adoptRef(*new ProxyCDMClearKey()))
{
}

CDMInstanceClearKey::~CDMInstanceClearKey() = default;

CDMInstance::SuccessValue CDMInstanceClearKey::initializeWithConfiguration(const CDMKeySystemConfiguration&)
{
    // No-op.
    return Succeeded;
}

CDMInstance::SuccessValue CDMInstanceClearKey::setDistinctiveIdentifiersAllowed(bool allowed)
{
    // Reject setting distinctive identifiers as allowed.
    return !allowed ? Succeeded : Failed;
}

CDMInstance::SuccessValue CDMInstanceClearKey::setPersistentStateAllowed(bool allowed)
{
    // Reject setting persistent state as allowed.
    return !allowed ? Succeeded : Failed;
}

CDMInstance::SuccessValue CDMInstanceClearKey::setServerCertificate(Ref<SharedBuffer>&&)
{
    // Reject setting any server certificate.
    return Failed;
}

CDMInstance::SuccessValue CDMInstanceClearKey::setStorageDirectory(const String& storageDirectory)
{
    // Reject any persistent state storage.
    return storageDirectory.isEmpty() ? Succeeded : Failed;
}

const String& CDMInstanceClearKey::keySystem() const
{
    static const NeverDestroyed<String> s_keySystem { MAKE_STATIC_STRING_IMPL("org.w3.clearkey") };

    return s_keySystem;
}

RefPtr<CDMInstanceSession> CDMInstanceClearKey::createSession()
{
    return adoptRef(new CDMInstanceSessionClearKey());
}

void CDMInstanceSessionClearKey::requestLicense(LicenseType, const AtomString& initDataType, Ref<SharedBuffer>&& initData, LicenseCallback&& callback)
{
    static uint32_t s_sessionIdValue = 0;
    ++s_sessionIdValue;

    if (equalLettersIgnoringASCIICase(initDataType, "cenc"))
        initData = extractKeyidsFromCencInitData(initData.get());

    if (equalLettersIgnoringASCIICase(initDataType, "webm"))
        initData = extractKeyIdFromWebMInitData(initData.get());

    callOnMainThread(
        [weakThis = makeWeakPtr(*this), callback = WTFMove(callback), initData = WTFMove(initData), sessionIdValue = s_sessionIdValue]() mutable {
            if (!weakThis)
                return;

            callback(WTFMove(initData), String::number(sessionIdValue), false, Succeeded);
        });
}

void CDMInstanceSessionClearKey::updateLicense(const String& sessionId, LicenseType, const SharedBuffer& response, LicenseUpdateCallback&& callback)
{
    // Use a helper functor that schedules the callback dispatch, avoiding
    // duplicated callOnMainThread() calls.
    auto dispatchCallback =
        [this, &callback](bool sessionWasClosed, Optional<KeyStatusVector>&& changedKeys, SuccessValue succeeded) {
            callOnMainThread(
                [weakThis = makeWeakPtr(*this), callback = WTFMove(callback), sessionWasClosed, changedKeys = WTFMove(changedKeys), succeeded] () mutable {
                    if (!weakThis)
                        return;

                    callback(sessionWasClosed, WTFMove(changedKeys), WTF::nullopt, WTF::nullopt, succeeded);
                });
        };

    // Parse the response buffer as an JSON object.
    RefPtr<JSON::Object> root = parseJSONObject(response);
    if (!root) {
        dispatchCallback(false, WTF::nullopt, SuccessValue::Failed);
        return;
    }

    // Parse the response using 'license' formatting, if possible.
    if (auto decodedKeys = parseLicenseFormat(*root)) {
        // Retrieve the target Vector of Key objects for this session.
        auto& keyVector = ClearKeyState::singleton().keys().ensure(sessionId, [] { return Vector<CDMInstanceClearKey::Key> { }; }).iterator->value;

        // For each decoded key, find an existing item for the decoded key's ID. If none exist,
        // the key is decoded. Otherwise, the key is updated in case there's a mismatch between
        // the size or data of the existing and proposed key.
        bool keysChanged = false;
        for (auto& key : *decodedKeys) {
            auto it = std::find_if(keyVector.begin(), keyVector.end(),
                [&key] (const CDMInstanceClearKey::Key& containedKey) {
                    return containedKey.keyIDData->size() == key.keyIDData->size()
                        && !std::memcmp(containedKey.keyIDData->data(), key.keyIDData->data(), containedKey.keyIDData->size());
                });
            if (it != keyVector.end()) {
                auto& existingKey = it->keyValueData;
                auto& proposedKey = key.keyValueData;

                // Update the existing Key if it differs from the proposed key in key value.
                if (existingKey->size() != proposedKey->size() || std::memcmp(existingKey->data(), proposedKey->data(), existingKey->size())) {
                    *it = WTFMove(key);
                    keysChanged = true;
                }
            } else {
                // In case a Key for this key ID doesn't exist yet, append the new one to keyVector.
                keyVector.append(WTFMove(key));
                keysChanged = true;
            }
        }

        // In case of changed keys, we have to provide a KeyStatusVector of all the keys for
        // this session.
        Optional<KeyStatusVector> changedKeys;
        if (keysChanged) {
            // First a helper Vector is constructed, cotaining pairs of SharedBuffer RefPtrs
            // representint key ID data, and the corresponding key statuses.
            // We can't use KeyStatusVector here because this Vector has to be sorted, which
            // is not possible to do on Ref<> objects.
            Vector<std::pair<RefPtr<SharedBuffer>, KeyStatus>> keys;
            keys.reserveInitialCapacity(keyVector.size());
            for (auto& it : keyVector)
                keys.uncheckedAppend(std::pair<RefPtr<SharedBuffer>, KeyStatus> { it.keyIDData, it.status });

            // Sort first by size, second by data.
            std::sort(keys.begin(), keys.end(),
                [] (const auto& a, const auto& b) {
                    if (a.first->size() != b.first->size())
                        return a.first->size() < b.first->size();

                    return std::memcmp(a.first->data(), b.first->data(), a.first->size()) < 0;
                });

            // Finally construct the mirroring KeyStatusVector object and move it into the
            // Optional<> object that will be passed to the callback.
            KeyStatusVector keyStatusVector;
            keyStatusVector.reserveInitialCapacity(keys.size());
            for (auto& it : keys)
                keyStatusVector.uncheckedAppend(std::pair<Ref<SharedBuffer>, KeyStatus> { *it.first, it.second });

            changedKeys = WTFMove(keyStatusVector);
        }

        dispatchCallback(false, WTFMove(changedKeys), SuccessValue::Succeeded);
        return;
    }

    // Parse the response using 'license release acknowledgement' formatting, if possible.
    if (parseLicenseReleaseAcknowledgementFormat(*root)) {
        // FIXME: Retrieve the key ID information and use it to validate the keys for this sessionId.
        ClearKeyState::singleton().keys().remove(sessionId);
        dispatchCallback(true, WTF::nullopt, SuccessValue::Succeeded);
        return;
    }

    // Bail in case no format was recognized.
    dispatchCallback(false, WTF::nullopt, SuccessValue::Failed);
}

void CDMInstanceSessionClearKey::loadSession(LicenseType, const String& sessionId, const String&, LoadSessionCallback&& callback)
{
    // Use a helper functor that schedules the callback dispatch, avoiding duplicated callOnMainThread() calls.
    auto dispatchCallback =
        [this, &callback](Optional<KeyStatusVector>&& existingKeys, SuccessValue success, SessionLoadFailure loadFailure) {
            callOnMainThread(
                [weakThis = makeWeakPtr(*this), callback = WTFMove(callback), existingKeys = WTFMove(existingKeys), success, loadFailure]() mutable {
                    if (!weakThis)
                        return;

                    callback(WTFMove(existingKeys), WTF::nullopt, WTF::nullopt, success, loadFailure);
                });
        };

    // Construct the KeyStatusVector object, representing all the known keys for this session.
    KeyStatusVector keyStatusVector;
    {
        auto& keys = ClearKeyState::singleton().keys();
        auto it = keys.find(sessionId);
        if (it == keys.end()) {
            dispatchCallback(WTF::nullopt, Failed, SessionLoadFailure::NoSessionData);
            return;
        }

        auto& keyVector = it->value;
        keyStatusVector.reserveInitialCapacity(keyVector.size());
        for (auto& key : keyVector)
            keyStatusVector.uncheckedAppend(std::pair<Ref<SharedBuffer>, KeyStatus> { *key.keyIDData, key.status });
    }

    dispatchCallback(WTFMove(keyStatusVector), Succeeded, SessionLoadFailure::None);
}

void CDMInstanceSessionClearKey::closeSession(const String&, CloseSessionCallback&& callback)
{
    callOnMainThread(
        [weakThis = makeWeakPtr(*this), callback = WTFMove(callback)] () mutable {
            if (!weakThis)
                return;

            callback();
        });
}

void CDMInstanceSessionClearKey::removeSessionData(const String& sessionId, LicenseType, RemoveSessionDataCallback&& callback)
{
    // Use a helper functor that schedules the callback dispatch, avoiding duplicated callOnMainThread() calls.
    auto dispatchCallback =
        [this, &callback](KeyStatusVector&& keyStatusVector, Optional<Ref<SharedBuffer>>&& message, SuccessValue success) {
            callOnMainThread(
                [weakThis = makeWeakPtr(*this), callback = WTFMove(callback), keyStatusVector = WTFMove(keyStatusVector), message = WTFMove(message), success]() mutable {
                    if (!weakThis)
                        return;

                    callback(WTFMove(keyStatusVector), WTFMove(message), success);
                });
        };

    // Construct the KeyStatusVector object, representing released keys, and the message in the
    // 'license release' format.
    KeyStatusVector keyStatusVector;
    RefPtr<SharedBuffer> message;
    {
        // Retrieve information for the given session ID, bailing if none is found.
        auto& keys = ClearKeyState::singleton().keys();
        auto it = keys.find(sessionId);
        if (it == keys.end()) {
            dispatchCallback(KeyStatusVector { }, WTF::nullopt, SuccessValue::Failed);
            return;
        }

        // Retrieve the Key vector, containing all the keys for this session, and
        // then remove the key map entry for this session.
        auto keyVector = WTFMove(it->value);
        keys.remove(it);

        // Construct the KeyStatusVector object, pairing key IDs with the 'released' status.
        keyStatusVector.reserveInitialCapacity(keyVector.size());
        for (auto& key : keyVector)
            keyStatusVector.uncheckedAppend(std::pair<Ref<SharedBuffer>, KeyStatus> { *key.keyIDData, KeyStatus::Released });

        // Construct JSON that represents the 'license release' format, creating a 'kids' array
        // of base64URL-encoded key IDs for all keys that were associated with this session.
        auto rootObject = JSON::Object::create();
        {
            auto array = JSON::Array::create();
            for (auto& key : keyVector) {
                ASSERT(key.keyIDData->size() <= std::numeric_limits<unsigned>::max());
                array->pushString(WTF::base64URLEncode(key.keyIDData->data(), static_cast<unsigned>(key.keyIDData->size())));
            }
            rootObject->setArray("kids", WTFMove(array));
        }

        // Copy the JSON data into a SharedBuffer object.
        String messageString = rootObject->toJSONString();
        CString messageCString = messageString.utf8();
        message = SharedBuffer::create(messageCString.data(), messageCString.length());
    }

    dispatchCallback(WTFMove(keyStatusVector), Ref<SharedBuffer>(*message), SuccessValue::Succeeded);
}

void CDMInstanceSessionClearKey::storeRecordOfKeyUsage(const String&)
{
}

} // namespace WebCore

#endif // ENABLE(ENCRYPTED_MEDIA)
