diff options
Diffstat (limited to 'Source/WebCore/Modules/encryptedmedia/legacy')
21 files changed, 1799 insertions, 0 deletions
diff --git a/Source/WebCore/Modules/encryptedmedia/legacy/LegacyCDM.cpp b/Source/WebCore/Modules/encryptedmedia/legacy/LegacyCDM.cpp new file mode 100644 index 000000000..4e333f856 --- /dev/null +++ b/Source/WebCore/Modules/encryptedmedia/legacy/LegacyCDM.cpp @@ -0,0 +1,151 @@ +/* + * 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" + +#if ENABLE(LEGACY_ENCRYPTED_MEDIA) + +#include "LegacyCDM.h" + +#include "LegacyCDMPrivateClearKey.h" +#include "LegacyCDMPrivateMediaPlayer.h" +#include "LegacyCDMSession.h" +#include "MediaPlayer.h" +#include "WebKitMediaKeys.h" +#include <wtf/NeverDestroyed.h> +#include <wtf/text/WTFString.h> + +#if PLATFORM(MAC) && ENABLE(MEDIA_SOURCE) +#include "CDMPrivateMediaSourceAVFObjC.h" +#endif + +namespace WebCore { + +struct CDMFactory { + WTF_MAKE_NONCOPYABLE(CDMFactory); WTF_MAKE_FAST_ALLOCATED; +public: + CDMFactory(CreateCDM constructor, CDMSupportsKeySystem supportsKeySystem, CDMSupportsKeySystemAndMimeType supportsKeySystemAndMimeType) + : constructor(constructor) + , supportsKeySystem(supportsKeySystem) + , supportsKeySystemAndMimeType(supportsKeySystemAndMimeType) + { + } + + CreateCDM constructor; + CDMSupportsKeySystem supportsKeySystem; + CDMSupportsKeySystemAndMimeType supportsKeySystemAndMimeType; +}; + +static Vector<CDMFactory*>& installedCDMFactories() +{ + static NeverDestroyed<Vector<CDMFactory*>> cdms; + static bool queriedCDMs = false; + if (!queriedCDMs) { + queriedCDMs = true; + + cdms.get().append(new CDMFactory([](CDM* cdm) { return std::make_unique<CDMPrivateClearKey>(cdm); }, + CDMPrivateClearKey::supportsKeySystem, CDMPrivateClearKey::supportsKeySystemAndMimeType)); + + // FIXME: initialize specific UA CDMs. http://webkit.org/b/109318, http://webkit.org/b/109320 + cdms.get().append(new CDMFactory([](CDM* cdm) { return std::make_unique<CDMPrivateMediaPlayer>(cdm); }, + CDMPrivateMediaPlayer::supportsKeySystem, CDMPrivateMediaPlayer::supportsKeySystemAndMimeType)); + +#if PLATFORM(MAC) && ENABLE(MEDIA_SOURCE) + cdms.get().append(new CDMFactory([](CDM* cdm) { return std::make_unique<CDMPrivateMediaSourceAVFObjC>(cdm); }, + CDMPrivateMediaSourceAVFObjC::supportsKeySystem, CDMPrivateMediaSourceAVFObjC::supportsKeySystemAndMimeType)); +#endif + } + + return cdms; +} + +void CDM::registerCDMFactory(CreateCDM constructor, CDMSupportsKeySystem supportsKeySystem, CDMSupportsKeySystemAndMimeType supportsKeySystemAndMimeType) +{ + installedCDMFactories().append(new CDMFactory(constructor, supportsKeySystem, supportsKeySystemAndMimeType)); +} + +static CDMFactory* CDMFactoryForKeySystem(const String& keySystem) +{ + for (auto& factory : installedCDMFactories()) { + if (factory->supportsKeySystem(keySystem)) + return factory; + } + return 0; +} + +bool CDM::supportsKeySystem(const String& keySystem) +{ + return CDMFactoryForKeySystem(keySystem); +} + +bool CDM::keySystemSupportsMimeType(const String& keySystem, const String& mimeType) +{ + if (CDMFactory* factory = CDMFactoryForKeySystem(keySystem)) + return factory->supportsKeySystemAndMimeType(keySystem, mimeType); + return false; +} + +std::unique_ptr<CDM> CDM::create(const String& keySystem) +{ + if (!supportsKeySystem(keySystem)) + return nullptr; + + return std::make_unique<CDM>(keySystem); +} + +CDM::CDM(const String& keySystem) + : m_keySystem(keySystem) + , m_client(nullptr) +{ + m_private = CDMFactoryForKeySystem(keySystem)->constructor(this); +} + +CDM::~CDM() +{ +} + +bool CDM::supportsMIMEType(const String& mimeType) const +{ + return m_private->supportsMIMEType(mimeType); +} + +std::unique_ptr<CDMSession> CDM::createSession(CDMSessionClient& client) +{ + auto session = m_private->createSession(&client); + if (mediaPlayer()) + mediaPlayer()->setCDMSession(session.get()); + return session; +} + +MediaPlayer* CDM::mediaPlayer() const +{ + if (!m_client) + return 0; + return m_client->cdmMediaPlayer(this); +} + +} + +#endif // ENABLE(LEGACY_ENCRYPTED_MEDIA) diff --git a/Source/WebCore/Modules/encryptedmedia/legacy/LegacyCDM.h b/Source/WebCore/Modules/encryptedmedia/legacy/LegacyCDM.h new file mode 100644 index 000000000..2a00b7e0f --- /dev/null +++ b/Source/WebCore/Modules/encryptedmedia/legacy/LegacyCDM.h @@ -0,0 +1,81 @@ +/* + * 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. + */ + +#pragma once + +#if ENABLE(LEGACY_ENCRYPTED_MEDIA) + +#include "LegacyCDMSession.h" +#include <runtime/Uint8Array.h> +#include <wtf/Forward.h> +#include <wtf/text/WTFString.h> + +namespace WebCore { + +class CDM; +class CDMPrivateInterface; +class MediaPlayer; + +typedef std::function<std::unique_ptr<CDMPrivateInterface> (CDM*)> CreateCDM; +typedef bool (*CDMSupportsKeySystem)(const String&); +typedef bool (*CDMSupportsKeySystemAndMimeType)(const String&, const String&); + +class CDMClient { +public: + virtual ~CDMClient() { } + + virtual MediaPlayer* cdmMediaPlayer(const CDM*) const = 0; +}; + +class CDM { +public: + explicit CDM(const String& keySystem); + + enum CDMErrorCode { NoError, UnknownError, ClientError, ServiceError, OutputError, HardwareChangeError, DomainError }; + static bool supportsKeySystem(const String&); + static bool keySystemSupportsMimeType(const String& keySystem, const String& mimeType); + static std::unique_ptr<CDM> create(const String& keySystem); + WEBCORE_EXPORT static void registerCDMFactory(CreateCDM, CDMSupportsKeySystem, CDMSupportsKeySystemAndMimeType); + ~CDM(); + + bool supportsMIMEType(const String&) const; + std::unique_ptr<CDMSession> createSession(CDMSessionClient&); + + const String& keySystem() const { return m_keySystem; } + + CDMClient* client() const { return m_client; } + void setClient(CDMClient* client) { m_client = client; } + + MediaPlayer* mediaPlayer() const; + +private: + String m_keySystem; + std::unique_ptr<CDMPrivateInterface> m_private; + CDMClient* m_client; +}; + +} + +#endif // ENABLE(LEGACY_ENCRYPTED_MEDIA) diff --git a/Source/WebCore/Modules/encryptedmedia/legacy/LegacyCDMPrivate.h b/Source/WebCore/Modules/encryptedmedia/legacy/LegacyCDMPrivate.h new file mode 100644 index 000000000..de46b063b --- /dev/null +++ b/Source/WebCore/Modules/encryptedmedia/legacy/LegacyCDMPrivate.h @@ -0,0 +1,49 @@ +/* + * 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. + */ + +#pragma once + +#if ENABLE(LEGACY_ENCRYPTED_MEDIA) + +#include <wtf/text/WTFString.h> + +namespace WebCore { + +class CDMSession; +class CDMSessionClient; + +class CDMPrivateInterface { +public: + CDMPrivateInterface() { } + virtual ~CDMPrivateInterface() { } + + virtual bool supportsMIMEType(const String&) = 0; + + virtual std::unique_ptr<CDMSession> createSession(CDMSessionClient*) = 0; +}; + +} // namespace WebCore + +#endif // ENABLE(LEGACY_ENCRYPTED_MEDIA) diff --git a/Source/WebCore/Modules/encryptedmedia/legacy/LegacyCDMPrivateClearKey.cpp b/Source/WebCore/Modules/encryptedmedia/legacy/LegacyCDMPrivateClearKey.cpp new file mode 100644 index 000000000..c5582c429 --- /dev/null +++ b/Source/WebCore/Modules/encryptedmedia/legacy/LegacyCDMPrivateClearKey.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2015 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 "LegacyCDMPrivateClearKey.h" + +#if ENABLE(LEGACY_ENCRYPTED_MEDIA) + +#include "LegacyCDM.h" +#include "LegacyCDMSessionClearKey.h" +#include "ContentType.h" +#include "MediaPlayer.h" + +namespace WebCore { + +bool CDMPrivateClearKey::supportsKeySystem(const String& keySystem) +{ + if (!equalLettersIgnoringASCIICase(keySystem, "org.w3c.clearkey")) + return false; + + // The MediaPlayer must also support the key system: + return MediaPlayer::supportsKeySystem(keySystem, emptyString()); +} + +bool CDMPrivateClearKey::supportsKeySystemAndMimeType(const String& keySystem, const String& mimeType) +{ + if (!equalLettersIgnoringASCIICase(keySystem, "org.w3c.clearkey")) + return false; + + // The MediaPlayer must also support the key system: + return MediaPlayer::supportsKeySystem(keySystem, mimeType); +} + +bool CDMPrivateClearKey::supportsMIMEType(const String& mimeType) +{ + return MediaPlayer::supportsKeySystem(m_cdm->keySystem(), mimeType); +} + +std::unique_ptr<CDMSession> CDMPrivateClearKey::createSession(CDMSessionClient* client) +{ + return std::make_unique<CDMSessionClearKey>(client); +} + +} + +#endif diff --git a/Source/WebCore/Modules/encryptedmedia/legacy/LegacyCDMPrivateClearKey.h b/Source/WebCore/Modules/encryptedmedia/legacy/LegacyCDMPrivateClearKey.h new file mode 100644 index 000000000..a674e7a40 --- /dev/null +++ b/Source/WebCore/Modules/encryptedmedia/legacy/LegacyCDMPrivateClearKey.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2015 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. + */ + +#pragma once + +#if ENABLE(LEGACY_ENCRYPTED_MEDIA) + +#include "LegacyCDMPrivate.h" + +namespace WebCore { + +class CDM; + +class CDMPrivateClearKey : public CDMPrivateInterface { +public: + explicit CDMPrivateClearKey(CDM* cdm) + : m_cdm(cdm) + { + } + + virtual ~CDMPrivateClearKey() { } + + static bool supportsKeySystem(const String&); + static bool supportsKeySystemAndMimeType(const String& keySystem, const String& mimeType); + + bool supportsMIMEType(const String& mimeType) override; + std::unique_ptr<CDMSession> createSession(CDMSessionClient*) override; + +protected: + CDM* m_cdm; +}; + +} // namespace WebCore + +#endif // ENABLE(LEGACY_ENCRYPTED_MEDIA) diff --git a/Source/WebCore/Modules/encryptedmedia/legacy/LegacyCDMPrivateMediaPlayer.cpp b/Source/WebCore/Modules/encryptedmedia/legacy/LegacyCDMPrivateMediaPlayer.cpp new file mode 100644 index 000000000..f46fba264 --- /dev/null +++ b/Source/WebCore/Modules/encryptedmedia/legacy/LegacyCDMPrivateMediaPlayer.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2014 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 "LegacyCDMPrivateMediaPlayer.h" + +#if ENABLE(LEGACY_ENCRYPTED_MEDIA) + +#include "LegacyCDM.h" +#include "LegacyCDMSession.h" +#include "ContentType.h" +#include "MediaPlayer.h" + +#if PLATFORM(IOS) +#include "SoftLinking.h" +#endif + +namespace WebCore { + +bool CDMPrivateMediaPlayer::supportsKeySystem(const String& keySystem) +{ + return MediaPlayer::supportsKeySystem(keySystem, emptyString()); +} + +bool CDMPrivateMediaPlayer::supportsKeySystemAndMimeType(const String& keySystem, const String& mimeType) +{ + return MediaPlayer::supportsKeySystem(keySystem, mimeType); +} + +bool CDMPrivateMediaPlayer::supportsMIMEType(const String& mimeType) +{ + return MediaPlayer::supportsKeySystem(m_cdm->keySystem(), mimeType); +} + +std::unique_ptr<CDMSession> CDMPrivateMediaPlayer::createSession(CDMSessionClient* client) +{ + MediaPlayer* mediaPlayer = m_cdm->mediaPlayer(); + if (!mediaPlayer) + return nullptr; + + return mediaPlayer->createSession(m_cdm->keySystem(), client); +} + +} + +#endif diff --git a/Source/WebCore/Modules/encryptedmedia/legacy/LegacyCDMPrivateMediaPlayer.h b/Source/WebCore/Modules/encryptedmedia/legacy/LegacyCDMPrivateMediaPlayer.h new file mode 100644 index 000000000..6facef6ae --- /dev/null +++ b/Source/WebCore/Modules/encryptedmedia/legacy/LegacyCDMPrivateMediaPlayer.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2014 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. + */ + +#pragma once + +#include "LegacyCDMPrivate.h" + +#if ENABLE(LEGACY_ENCRYPTED_MEDIA) + +namespace WebCore { + +class CDM; + +class CDMPrivateMediaPlayer : public CDMPrivateInterface { +public: + explicit CDMPrivateMediaPlayer(CDM* cdm) + : m_cdm(cdm) + { } + + static bool supportsKeySystem(const String&); + static bool supportsKeySystemAndMimeType(const String& keySystem, const String& mimeType); + + virtual ~CDMPrivateMediaPlayer() { } + + bool supportsMIMEType(const String& mimeType) override; + std::unique_ptr<CDMSession> createSession(CDMSessionClient*) override; + + CDM* cdm() const { return m_cdm; } + +protected: + CDM* m_cdm; +}; + +} // namespace WebCore + +#endif // ENABLE(LEGACY_ENCRYPTED_MEDIA) diff --git a/Source/WebCore/Modules/encryptedmedia/legacy/LegacyCDMSessionClearKey.cpp b/Source/WebCore/Modules/encryptedmedia/legacy/LegacyCDMSessionClearKey.cpp new file mode 100644 index 000000000..e08a368bc --- /dev/null +++ b/Source/WebCore/Modules/encryptedmedia/legacy/LegacyCDMSessionClearKey.cpp @@ -0,0 +1,209 @@ +/* + * Copyright (C) 2015 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 "LegacyCDMSessionClearKey.h" + +#include "JSMainThreadExecState.h" +#include "Logging.h" +#include "TextEncoding.h" +#include "UUID.h" +#include "WebKitMediaKeyError.h" +#include <runtime/JSGlobalObject.h> +#include <runtime/JSLock.h> +#include <runtime/JSONObject.h> +#include <runtime/VM.h> +#include <wtf/NeverDestroyed.h> +#include <wtf/text/Base64.h> + +#if ENABLE(LEGACY_ENCRYPTED_MEDIA) + +using namespace JSC; + +namespace WebCore { + +static VM& clearKeyVM() +{ + static NeverDestroyed<RefPtr<VM>> vm; + if (!vm.get()) + vm.get() = VM::create(); + + return *vm.get(); +} + +CDMSessionClearKey::CDMSessionClearKey(CDMSessionClient* client) + : m_client(client) + , m_sessionId(createCanonicalUUIDString()) +{ +} + +CDMSessionClearKey::~CDMSessionClearKey() +{ +} + +RefPtr<Uint8Array> CDMSessionClearKey::generateKeyRequest(const String& mimeType, Uint8Array* initData, String& destinationURL, unsigned short& errorCode, uint32_t& systemCode) +{ + UNUSED_PARAM(mimeType); + UNUSED_PARAM(destinationURL); + UNUSED_PARAM(systemCode); + + if (!initData) { + errorCode = WebKitMediaKeyError::MEDIA_KEYERR_CLIENT; + return nullptr; + } + m_initData = initData; + + bool sawError = false; + String keyID = UTF8Encoding().decode(reinterpret_cast_ptr<char*>(m_initData->baseAddress()), m_initData->byteLength(), true, sawError); + if (sawError) { + errorCode = WebKitMediaKeyError::MEDIA_KEYERR_CLIENT; + return nullptr; + } + + return initData; +} + +void CDMSessionClearKey::releaseKeys() +{ + m_cachedKeys.clear(); +} + +bool CDMSessionClearKey::update(Uint8Array* rawKeysData, RefPtr<Uint8Array>& nextMessage, unsigned short& errorCode, uint32_t& systemCode) +{ + UNUSED_PARAM(nextMessage); + UNUSED_PARAM(systemCode); + ASSERT(rawKeysData); + + do { + auto rawKeysString = String::fromUTF8(rawKeysData->data(), rawKeysData->length()); + if (rawKeysString.isEmpty()) { + LOG(Media, "CDMSessionClearKey::update(%p) - failed: empty message", this); + continue; + } + + auto& vm = clearKeyVM(); + JSLockHolder lock(vm); + auto scope = DECLARE_THROW_SCOPE(vm); + auto* globalObject = JSGlobalObject::create(vm, JSGlobalObject::createStructure(vm, jsNull())); + auto& state = *globalObject->globalExec(); + + auto keysDataValue = JSONParse(&state, rawKeysString); + if (scope.exception() || !keysDataValue.isObject()) { + LOG(Media, "CDMSessionClearKey::update(%p) - failed: invalid JSON", this); + break; + } + + auto keysArrayValue = asObject(keysDataValue)->get(&state, Identifier::fromString(&state, "keys")); + if (scope.exception() || !isJSArray(keysArrayValue)) { + LOG(Media, "CDMSessionClearKey::update(%p) - failed: keys array missing or empty", this); + break; + } + + auto keysArray = asArray(keysArrayValue); + auto length = keysArray->length(); + if (!length) { + LOG(Media, "CDMSessionClearKey::update(%p) - failed: keys array missing or empty", this); + break; + } + + bool foundValidKey = false; + for (unsigned i = 0; i < length; ++i) { + auto keyValue = keysArray->getIndex(&state, i); + + if (scope.exception() || !keyValue.isObject()) { + LOG(Media, "CDMSessionClearKey::update(%p) - failed: null keyDictionary", this); + continue; + } + + auto keyObject = asObject(keyValue); + + auto getStringProperty = [&scope, &state, &keyObject](const char* name) -> String { + auto value = keyObject->get(&state, Identifier::fromString(&state, name)); + if (scope.exception() || !value.isString()) + return { }; + + auto string = asString(value)->value(&state); + if (scope.exception()) + return { }; + + return string; + }; + + auto algorithm = getStringProperty("alg"); + if (!equalLettersIgnoringASCIICase(algorithm, "a128kw")) { + LOG(Media, "CDMSessionClearKey::update(%p) - failed: algorithm unsupported", this); + continue; + } + + auto keyType = getStringProperty("kty"); + if (!equalLettersIgnoringASCIICase(keyType, "oct")) { + LOG(Media, "CDMSessionClearKey::update(%p) - failed: keyType unsupported", this); + continue; + } + + auto keyId = getStringProperty("kid"); + if (keyId.isEmpty()) { + LOG(Media, "CDMSessionClearKey::update(%p) - failed: keyId missing or empty", this); + continue; + } + + auto rawKeyData = getStringProperty("k"); + if (rawKeyData.isEmpty()) { + LOG(Media, "CDMSessionClearKey::update(%p) - failed: key missing or empty", this); + continue; + } + + Vector<uint8_t> keyData; + if (!base64Decode(rawKeyData, keyData) || keyData.isEmpty()) { + LOG(Media, "CDMSessionClearKey::update(%p) - failed: unable to base64 decode key", this); + continue; + } + + m_cachedKeys.set(keyId, WTFMove(keyData)); + foundValidKey = true; + } + + if (foundValidKey) + return true; + + } while (false); + + errorCode = WebKitMediaKeyError::MEDIA_KEYERR_CLIENT; + return false; +} + +RefPtr<ArrayBuffer> CDMSessionClearKey::cachedKeyForKeyID(const String& keyId) const +{ + if (!m_cachedKeys.contains(keyId)) + return nullptr; + + auto keyData = m_cachedKeys.get(keyId); + RefPtr<Uint8Array> keyDataArray = Uint8Array::create(keyData.data(), keyData.size()); + return keyDataArray->unsharedBuffer(); +} + +} + +#endif diff --git a/Source/WebCore/Modules/encryptedmedia/legacy/LegacyCDMSessionClearKey.h b/Source/WebCore/Modules/encryptedmedia/legacy/LegacyCDMSessionClearKey.h new file mode 100644 index 000000000..e1e735a40 --- /dev/null +++ b/Source/WebCore/Modules/encryptedmedia/legacy/LegacyCDMSessionClearKey.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2015 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. + */ + +#pragma once + +#include "LegacyCDMSession.h" +#include <wtf/HashMap.h> +#include <wtf/text/WTFString.h> + +#if ENABLE(LEGACY_ENCRYPTED_MEDIA) + +namespace WebCore { + +class CDMSessionClearKey : public CDMSession { +public: + CDMSessionClearKey(CDMSessionClient*); + virtual ~CDMSessionClearKey(); + + // CDMSessionPrivate + CDMSessionType type() override { return CDMSessionTypeClearKey; } + void setClient(CDMSessionClient* client) override { m_client = client; } + const String& sessionId() const override { return m_sessionId; } + RefPtr<Uint8Array> generateKeyRequest(const String& mimeType, Uint8Array*, String&, unsigned short&, uint32_t&) override; + void releaseKeys() override; + bool update(Uint8Array*, RefPtr<Uint8Array>&, unsigned short&, uint32_t&) override; + RefPtr<ArrayBuffer> cachedKeyForKeyID(const String&) const override; + +protected: + CDMSessionClient* m_client; + RefPtr<Uint8Array> m_initData; + HashMap<String, Vector<uint8_t>> m_cachedKeys; + String m_sessionId; +}; + +} // namespace WebCore + +#endif // ENABLE(LEGACY_ENCRYPTED_MEDIA) diff --git a/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeyMessageEvent.cpp b/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeyMessageEvent.cpp new file mode 100644 index 000000000..2efadf15c --- /dev/null +++ b/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeyMessageEvent.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2012 Google 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. ``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 + * 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 "WebKitMediaKeyMessageEvent.h" + +#if ENABLE(LEGACY_ENCRYPTED_MEDIA) + +#include <runtime/Uint8Array.h> + +namespace WebCore { + +WebKitMediaKeyMessageEvent::WebKitMediaKeyMessageEvent(const AtomicString& type, Uint8Array* message, const String& destinationURL) + : Event(type, false, false) + , m_message(message) + , m_destinationURL(destinationURL) +{ +} + + +WebKitMediaKeyMessageEvent::WebKitMediaKeyMessageEvent(const AtomicString& type, const Init& initializer, IsTrusted isTrusted) + : Event(type, initializer, isTrusted) + , m_message(initializer.message) + , m_destinationURL(initializer.destinationURL) +{ +} + +WebKitMediaKeyMessageEvent::~WebKitMediaKeyMessageEvent() +{ +} + +EventInterface WebKitMediaKeyMessageEvent::eventInterface() const +{ + return WebKitMediaKeyMessageEventInterfaceType; +} + +} // namespace WebCore + +#endif diff --git a/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeyMessageEvent.h b/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeyMessageEvent.h new file mode 100644 index 000000000..51946f213 --- /dev/null +++ b/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeyMessageEvent.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2012 Google Inc. All rights reserved. + * 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. ``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 + * 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. + */ + +#pragma once + +#if ENABLE(LEGACY_ENCRYPTED_MEDIA) + +#include "Event.h" +#include "WebKitMediaKeyError.h" + +namespace WebCore { + +class WebKitMediaKeyMessageEvent : public Event { +public: + virtual ~WebKitMediaKeyMessageEvent(); + + static Ref<WebKitMediaKeyMessageEvent> create(const AtomicString& type, Uint8Array* message, const String& destinationURL) + { + return adoptRef(*new WebKitMediaKeyMessageEvent(type, message, destinationURL)); + } + + struct Init : EventInit { + RefPtr<Uint8Array> message; + String destinationURL; + }; + + static Ref<WebKitMediaKeyMessageEvent> create(const AtomicString& type, const Init& initializer, IsTrusted isTrusted = IsTrusted::No) + { + return adoptRef(*new WebKitMediaKeyMessageEvent(type, initializer, isTrusted)); + } + + EventInterface eventInterface() const override; + + Uint8Array* message() const { return m_message.get(); } + String destinationURL() const { return m_destinationURL; } + +private: + WebKitMediaKeyMessageEvent(const AtomicString& type, Uint8Array* message, const String& destinationURL); + WebKitMediaKeyMessageEvent(const AtomicString& type, const Init&, IsTrusted); + + RefPtr<Uint8Array> m_message; + String m_destinationURL; +}; + +} // namespace WebCore + +#endif // ENABLE(LEGACY_ENCRYPTED_MEDIA) diff --git a/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeyMessageEvent.idl b/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeyMessageEvent.idl new file mode 100644 index 000000000..09609128f --- /dev/null +++ b/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeyMessageEvent.idl @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2012 Google 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. ``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 + * 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. + */ + +[ + Conditional=LEGACY_ENCRYPTED_MEDIA, + Constructor(DOMString type, optional WebKitMediaKeyMessageEventInit eventInitDict), +] interface WebKitMediaKeyMessageEvent : Event { + readonly attribute Uint8Array message; + readonly attribute DOMString destinationURL; +}; + +dictionary WebKitMediaKeyMessageEventInit : EventInit { + Uint8Array? message = null; + DOMString destinationURL = ""; +}; diff --git a/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeyNeededEvent.cpp b/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeyNeededEvent.cpp new file mode 100644 index 000000000..e538c1cce --- /dev/null +++ b/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeyNeededEvent.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2012 Google 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. ``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 + * 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 "WebKitMediaKeyNeededEvent.h" + +#if ENABLE(LEGACY_ENCRYPTED_MEDIA) + +#include <runtime/Uint8Array.h> + +namespace WebCore { + +WebKitMediaKeyNeededEvent::WebKitMediaKeyNeededEvent(const AtomicString& type, Uint8Array* initData) + : Event(type, false, false) + , m_initData(initData) +{ +} + +WebKitMediaKeyNeededEvent::WebKitMediaKeyNeededEvent(const AtomicString& type, const Init& initializer, IsTrusted isTrusted) + : Event(type, initializer, isTrusted) + , m_initData(initializer.initData) +{ +} + +WebKitMediaKeyNeededEvent::~WebKitMediaKeyNeededEvent() +{ +} + +EventInterface WebKitMediaKeyNeededEvent::eventInterface() const +{ + return WebKitMediaKeyNeededEventInterfaceType; +} + +} // namespace WebCore + +#endif diff --git a/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeyNeededEvent.h b/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeyNeededEvent.h new file mode 100644 index 000000000..de487d5df --- /dev/null +++ b/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeyNeededEvent.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2012 Google 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. ``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 + * 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. + */ + +#pragma once + +#if ENABLE(LEGACY_ENCRYPTED_MEDIA) + +#include "Event.h" +#include "WebKitMediaKeyError.h" + +namespace WebCore { + +class WebKitMediaKeyNeededEvent : public Event { +public: + virtual ~WebKitMediaKeyNeededEvent(); + + static Ref<WebKitMediaKeyNeededEvent> create(const AtomicString& type, Uint8Array* initData) + { + return adoptRef(*new WebKitMediaKeyNeededEvent(type, initData)); + } + + struct Init : EventInit { + RefPtr<Uint8Array> initData; + }; + + static Ref<WebKitMediaKeyNeededEvent> create(const AtomicString& type, const Init& initializer, IsTrusted isTrusted = IsTrusted::No) + { + return adoptRef(*new WebKitMediaKeyNeededEvent(type, initializer, isTrusted)); + } + + EventInterface eventInterface() const override; + + Uint8Array* initData() const { return m_initData.get(); } + +private: + WebKitMediaKeyNeededEvent(const AtomicString& type, Uint8Array* initData); + WebKitMediaKeyNeededEvent(const AtomicString& type, const Init&, IsTrusted); + + RefPtr<Uint8Array> m_initData; +}; + +} // namespace WebCore + +#endif // ENABLE(LEGACY_ENCRYPTED_MEDIA) diff --git a/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeyNeededEvent.idl b/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeyNeededEvent.idl new file mode 100644 index 000000000..823646e8c --- /dev/null +++ b/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeyNeededEvent.idl @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2012 Google 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. ``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 + * 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. + */ + +[ + Conditional=LEGACY_ENCRYPTED_MEDIA, + Constructor(DOMString type, optional WebKitMediaKeyNeededEventInit eventInitDict), +] interface WebKitMediaKeyNeededEvent : Event { + readonly attribute Uint8Array initData; +}; + +dictionary WebKitMediaKeyNeededEventInit : EventInit { + Uint8Array? initData = null; +}; diff --git a/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeySession.cpp b/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeySession.cpp new file mode 100644 index 000000000..7e9e68cd2 --- /dev/null +++ b/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeySession.cpp @@ -0,0 +1,256 @@ +/* + * 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 "WebKitMediaKeySession.h" + +#if ENABLE(LEGACY_ENCRYPTED_MEDIA) + +#include "Document.h" +#include "EventNames.h" +#include "ExceptionCode.h" +#include "FileSystem.h" +#include "SecurityOriginData.h" +#include "Settings.h" +#include "WebKitMediaKeyError.h" +#include "WebKitMediaKeyMessageEvent.h" +#include "WebKitMediaKeys.h" + +namespace WebCore { + +Ref<WebKitMediaKeySession> WebKitMediaKeySession::create(ScriptExecutionContext& context, WebKitMediaKeys& keys, const String& keySystem) +{ + auto session = adoptRef(*new WebKitMediaKeySession(context, keys, keySystem)); + session->suspendIfNeeded(); + return session; +} + +WebKitMediaKeySession::WebKitMediaKeySession(ScriptExecutionContext& context, WebKitMediaKeys& keys, const String& keySystem) + : ActiveDOMObject(&context) + , m_keys(&keys) + , m_keySystem(keySystem) + , m_asyncEventQueue(*this) + , m_session(keys.cdm().createSession(*this)) + , m_keyRequestTimer(*this, &WebKitMediaKeySession::keyRequestTimerFired) + , m_addKeyTimer(*this, &WebKitMediaKeySession::addKeyTimerFired) +{ +} + +WebKitMediaKeySession::~WebKitMediaKeySession() +{ + if (m_session) + m_session->setClient(nullptr); + + m_asyncEventQueue.cancelAllEvents(); +} + +void WebKitMediaKeySession::close() +{ + if (m_session) + m_session->releaseKeys(); +} + +RefPtr<ArrayBuffer> WebKitMediaKeySession::cachedKeyForKeyId(const String& keyId) const +{ + return m_session ? m_session->cachedKeyForKeyID(keyId) : nullptr; +} + +const String& WebKitMediaKeySession::sessionId() const +{ + return m_session->sessionId(); +} + +void WebKitMediaKeySession::generateKeyRequest(const String& mimeType, Ref<Uint8Array>&& initData) +{ + m_pendingKeyRequests.append({ mimeType, WTFMove(initData) }); + m_keyRequestTimer.startOneShot(0); +} + +void WebKitMediaKeySession::keyRequestTimerFired() +{ + ASSERT(m_pendingKeyRequests.size()); + if (!m_session) + return; + + while (!m_pendingKeyRequests.isEmpty()) { + auto request = m_pendingKeyRequests.takeFirst(); + + // NOTE: Continued from step 5 in MediaKeys::createSession(). + // The user agent will asynchronously execute the following steps in the task: + + // 1. Let cdm be the cdm loaded in the MediaKeys constructor. + // 2. Let destinationURL be null. + String destinationURL; + WebKitMediaKeyError::Code errorCode = 0; + uint32_t systemCode = 0; + + // 3. Use cdm to generate a key request and follow the steps for the first matching condition from the following list: + + auto keyRequest = m_session->generateKeyRequest(request.mimeType, request.initData.ptr(), destinationURL, errorCode, systemCode); + + // Otherwise [if a request is not successfully generated]: + if (errorCode) { + // 3.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 + // 3.2. Set the MediaKeySession object's error attribute to the error object created in the previous step. + // 3.3. queue a task to fire a simple event named keyerror at the MediaKeySession object. + sendError(errorCode, systemCode); + // 3.4. Abort the task. + continue; + } + + // 4. queue a task to fire a simple event named keymessage at the new object + // The event is of type MediaKeyMessageEvent and has: + // message = key request + // destinationURL = destinationURL + if (keyRequest) + sendMessage(keyRequest.get(), destinationURL); + } +} + +ExceptionOr<void> WebKitMediaKeySession::update(Ref<Uint8Array>&& key) +{ + // From <http://dvcs.w3.org/hg/html-media/raw-file/tip/encrypted-media/encrypted-media.html#dom-addkey>: + // The addKey(key) method must run the following steps: + // 1. If the first or second argument [sic] is an empty array, throw an INVALID_ACCESS_ERR. + // NOTE: the reference to a "second argument" is a spec bug. + if (!key->length()) + return Exception { INVALID_ACCESS_ERR }; + + // 2. Schedule a task to handle the call, providing key. + m_pendingKeys.append(WTFMove(key)); + m_addKeyTimer.startOneShot(0); + + return { }; +} + +void WebKitMediaKeySession::addKeyTimerFired() +{ + ASSERT(m_pendingKeys.size()); + if (!m_session) + return; + + while (!m_pendingKeys.isEmpty()) { + auto pendingKey = m_pendingKeys.takeFirst(); + unsigned short errorCode = 0; + uint32_t systemCode = 0; + + // NOTE: Continued from step 2. of MediaKeySession::update() + // 2.1. Let cdm be the cdm loaded in the MediaKeys constructor. + // NOTE: This is m_session. + // 2.2. Let 'did store key' be false. + bool didStoreKey = false; + // 2.3. Let 'next message' be null. + RefPtr<Uint8Array> nextMessage; + // 2.4. Use cdm to handle key. + didStoreKey = m_session->update(pendingKey.ptr(), nextMessage, errorCode, systemCode); + // 2.5. If did store key is true and the media element is waiting for a key, queue a task to attempt to resume playback. + // TODO: Find and restart the media element + + // 2.6. If next message is not null, queue a task to fire a simple event named keymessage at the MediaKeySession object. + // The event is of type MediaKeyMessageEvent and has: + // message = next message + // destinationURL = null + if (nextMessage) + sendMessage(nextMessage.get(), emptyString()); + + // 2.7. If did store key is true, queue a task to fire a simple event named keyadded at the MediaKeySession object. + if (didStoreKey) { + auto keyaddedEvent = Event::create(eventNames().webkitkeyaddedEvent, false, false); + keyaddedEvent->setTarget(this); + m_asyncEventQueue.enqueueEvent(WTFMove(keyaddedEvent)); + + ASSERT(m_keys); + m_keys->keyAdded(); + } + + // 2.8. If any of the preceding steps in the task failed + if (errorCode) { + // 2.8.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.8.2. Set the MediaKeySession object's error attribute to the error object created in the previous step. + // 2.8.3. queue a task to fire a simple event named keyerror at the MediaKeySession object. + sendError(errorCode, systemCode); + // 2.8.4. Abort the task. + // NOTE: no-op + } + } +} + +void WebKitMediaKeySession::sendMessage(Uint8Array* message, String destinationURL) +{ + auto event = WebKitMediaKeyMessageEvent::create(eventNames().webkitkeymessageEvent, message, destinationURL); + event->setTarget(this); + m_asyncEventQueue.enqueueEvent(WTFMove(event)); +} + +void WebKitMediaKeySession::sendError(MediaKeyErrorCode errorCode, uint32_t systemCode) +{ + m_error = WebKitMediaKeyError::create(errorCode, systemCode); + + auto keyerrorEvent = Event::create(eventNames().webkitkeyerrorEvent, false, false); + keyerrorEvent->setTarget(this); + m_asyncEventQueue.enqueueEvent(WTFMove(keyerrorEvent)); +} + +String WebKitMediaKeySession::mediaKeysStorageDirectory() const +{ + auto* document = downcast<Document>(scriptExecutionContext()); + if (!document) + return emptyString(); + + auto storageDirectory = document->settings().mediaKeysStorageDirectory(); + if (storageDirectory.isEmpty()) + return emptyString(); + + return pathByAppendingComponent(storageDirectory, SecurityOriginData::fromSecurityOrigin(document->securityOrigin()).databaseIdentifier()); +} + +bool WebKitMediaKeySession::hasPendingActivity() const +{ + return (m_keys && m_session) || m_asyncEventQueue.hasPendingEvents(); +} + +void WebKitMediaKeySession::stop() +{ + close(); +} + +const char* WebKitMediaKeySession::activeDOMObjectName() const +{ + return "WebKitMediaKeySession"; +} + +bool WebKitMediaKeySession::canSuspendForDocumentSuspension() const +{ + // FIXME: We should try and do better here. + return false; +} + +} + +#endif diff --git a/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeySession.h b/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeySession.h new file mode 100644 index 000000000..c466c3c6d --- /dev/null +++ b/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeySession.h @@ -0,0 +1,106 @@ +/* + * 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. + */ + +#pragma once + +#if ENABLE(LEGACY_ENCRYPTED_MEDIA) + +#include "ActiveDOMObject.h" +#include "LegacyCDMSession.h" +#include "EventTarget.h" +#include "ExceptionOr.h" +#include "GenericEventQueue.h" +#include "Timer.h" +#include <runtime/Uint8Array.h> +#include <wtf/Deque.h> + +namespace WebCore { + +class WebKitMediaKeyError; +class WebKitMediaKeys; + +class WebKitMediaKeySession final : public RefCounted<WebKitMediaKeySession>, public EventTargetWithInlineData, private ActiveDOMObject, private CDMSessionClient { +public: + static Ref<WebKitMediaKeySession> create(ScriptExecutionContext&, WebKitMediaKeys&, const String& keySystem); + ~WebKitMediaKeySession(); + + WebKitMediaKeyError* error() { return m_error.get(); } + const String& keySystem() const { return m_keySystem; } + const String& sessionId() const; + ExceptionOr<void> update(Ref<Uint8Array>&& key); + void close(); + + CDMSession* session() { return m_session.get(); } + + void detachKeys() { m_keys = nullptr; } + + void generateKeyRequest(const String& mimeType, Ref<Uint8Array>&& initData); + RefPtr<ArrayBuffer> cachedKeyForKeyId(const String& keyId) const; + + using RefCounted::ref; + using RefCounted::deref; + + bool hasPendingActivity() const final; + +private: + WebKitMediaKeySession(ScriptExecutionContext&, WebKitMediaKeys&, const String& keySystem); + void keyRequestTimerFired(); + void addKeyTimerFired(); + + void sendMessage(Uint8Array*, String destinationURL) final; + void sendError(MediaKeyErrorCode, uint32_t systemCode) final; + String mediaKeysStorageDirectory() const final; + + void refEventTarget() final { ref(); } + void derefEventTarget() final { deref(); } + + void stop() final; + bool canSuspendForDocumentSuspension() const final; + const char* activeDOMObjectName() const final; + + EventTargetInterface eventTargetInterface() const final { return WebKitMediaKeySessionEventTargetInterfaceType; } + ScriptExecutionContext* scriptExecutionContext() const final { return ActiveDOMObject::scriptExecutionContext(); } + + WebKitMediaKeys* m_keys; + String m_keySystem; + String m_sessionId; + RefPtr<WebKitMediaKeyError> m_error; + GenericEventQueue m_asyncEventQueue; + std::unique_ptr<CDMSession> m_session; + + struct PendingKeyRequest { + String mimeType; + Ref<Uint8Array> initData; + }; + Deque<PendingKeyRequest> m_pendingKeyRequests; + Timer m_keyRequestTimer; + + Deque<Ref<Uint8Array>> m_pendingKeys; + Timer m_addKeyTimer; +}; + +} + +#endif // ENABLE(LEGACY_ENCRYPTED_MEDIA) diff --git a/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeySession.idl b/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeySession.idl new file mode 100644 index 000000000..b9ffb2c61 --- /dev/null +++ b/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeySession.idl @@ -0,0 +1,41 @@ +/* + * 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. ``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 + * 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. + */ + +[ + ActiveDOMObject, + Conditional=LEGACY_ENCRYPTED_MEDIA, +] interface WebKitMediaKeySession : EventTarget { + readonly attribute WebKitMediaKeyError error; + + readonly attribute DOMString keySystem; + readonly attribute DOMString sessionId; + + [MayThrowException] void update(Uint8Array key); + void close(); + + attribute EventHandler onwebkitkeyadded; + attribute EventHandler onwebkitkeyerror; + attribute EventHandler onwebkitkeymessage; +}; diff --git a/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeys.cpp b/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeys.cpp new file mode 100644 index 000000000..fcfbb0a74 --- /dev/null +++ b/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeys.cpp @@ -0,0 +1,165 @@ +/* + * 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 "WebKitMediaKeys.h" + +#if ENABLE(LEGACY_ENCRYPTED_MEDIA) + +#include "ExceptionCode.h" +#include "HTMLMediaElement.h" +#include "WebKitMediaKeySession.h" + +namespace WebCore { + +ExceptionOr<Ref<WebKitMediaKeys>> WebKitMediaKeys::create(const String& keySystem) +{ + // From <http://dvcs.w3.org/hg/html-media/raw-file/tip/encrypted-media/encrypted-media.html#dom-media-keys-constructor>: + // The MediaKeys(keySystem) constructor must run the following steps: + + // 1. If keySystem is null or an empty string, throw an INVALID_ACCESS_ERR exception and abort these steps. + if (keySystem.isEmpty()) + return Exception { INVALID_ACCESS_ERR }; + + // 2. If keySystem is not one of the user agent's supported Key Systems, throw a NOT_SUPPORTED_ERR and abort these steps. + if (!CDM::supportsKeySystem(keySystem)) + return Exception { NOT_SUPPORTED_ERR }; + + // 3. Let cdm be the content decryption module corresponding to keySystem. + // 4. Load cdm if necessary. + auto cdm = CDM::create(keySystem); + + // 5. Create a new MediaKeys object. + // 5.1 Let the keySystem attribute be keySystem. + // 6. Return the new object to the caller. + return adoptRef(*new WebKitMediaKeys(keySystem, WTFMove(cdm))); +} + +WebKitMediaKeys::WebKitMediaKeys(const String& keySystem, std::unique_ptr<CDM>&& cdm) + : m_keySystem(keySystem) + , m_cdm(WTFMove(cdm)) +{ + m_cdm->setClient(this); +} + +WebKitMediaKeys::~WebKitMediaKeys() +{ + // From <http://dvcs.w3.org/hg/html-media/raw-file/tip/encrypted-media/encrypted-media.html#dom-media-keys-constructor>: + // When destroying a MediaKeys object, follow the steps in close(). + for (auto& session : m_sessions) { + session->close(); + session->detachKeys(); + } +} + +ExceptionOr<Ref<WebKitMediaKeySession>> WebKitMediaKeys::createSession(ScriptExecutionContext& context, const String& type, Ref<Uint8Array>&& initData) +{ + // From <http://www.w3.org/TR/2014/WD-encrypted-media-20140218/#dom-createsession>: + // The createSession(type, initData) method must run the following steps: + // Note: The contents of initData are container-specific Initialization Data. + + // 1. If contentType is null or an empty string, throw an INVALID_ACCESS_ERR exception and abort these steps. + if (type.isEmpty()) + return Exception { INVALID_ACCESS_ERR }; + + // 2. If initData is an empty array, throw an INVALID_ACCESS_ERR exception and abort these steps. + if (!initData->length()) + return Exception { INVALID_ACCESS_ERR }; + + // 3. If type contains a MIME type that is not supported or is not supported by the keySystem, throw + // a NOT_SUPPORTED_ERR exception and abort these steps. + if (!m_cdm->supportsMIMEType(type)) + return Exception { NOT_SUPPORTED_ERR }; + + // 4. Create a new MediaKeySession object. + // 4.1 Let the keySystem attribute be keySystem. + // 4.2 Let the sessionId attribute be a unique Session ID string. It may be generated by cdm. + auto session = WebKitMediaKeySession::create(context, *this, m_keySystem); + + m_sessions.append(session.copyRef()); + + // 5. Schedule a task to initialize the session, providing contentType, initData, and the new object. + session->generateKeyRequest(type, WTFMove(initData)); + + // 6. Return the new object to the caller. + return WTFMove(session); +} + +bool WebKitMediaKeys::isTypeSupported(const String& keySystem, const String& mimeType) +{ + // 1. If keySystem contains an unrecognized or unsupported Key System, return false and abort these steps. + // Key system string comparison is case-sensitive. + if (keySystem.isEmpty() || !CDM::supportsKeySystem(keySystem)) + return false; + + // 2. If type is null or an empty string, return true and abort these steps. + if (mimeType.isEmpty()) + return true; + + // 3. If the Key System specified by keySystem does not support decrypting the container and/or codec + // specified by type, return false and abort these steps. + if (!CDM::keySystemSupportsMimeType(keySystem, mimeType)) + return false; + + // 4. Return true; + return true; +} + +void WebKitMediaKeys::setMediaElement(HTMLMediaElement* element) +{ + if (m_mediaElement && m_mediaElement->player()) + m_mediaElement->player()->setCDMSession(nullptr); + + m_mediaElement = element; + + if (m_mediaElement && m_mediaElement->player() && !m_sessions.isEmpty()) + m_mediaElement->player()->setCDMSession(m_sessions.last()->session()); +} + +MediaPlayer* WebKitMediaKeys::cdmMediaPlayer(const CDM*) const +{ + if (!m_mediaElement) + return nullptr; + return m_mediaElement->player(); +} + +void WebKitMediaKeys::keyAdded() +{ + if (m_mediaElement) + m_mediaElement->keyAdded(); +} + +RefPtr<ArrayBuffer> WebKitMediaKeys::cachedKeyForKeyId(const String& keyId) const +{ + for (auto& session : m_sessions) { + if (auto key = session->cachedKeyForKeyId(keyId)) + return key; + } + return nullptr; +} + +} + +#endif diff --git a/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeys.h b/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeys.h new file mode 100644 index 000000000..64c835a1e --- /dev/null +++ b/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeys.h @@ -0,0 +1,70 @@ +/* + * 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. + */ + +#pragma once + +#if ENABLE(LEGACY_ENCRYPTED_MEDIA) + +#include "LegacyCDM.h" +#include "ExceptionOr.h" +#include <runtime/Uint8Array.h> +#include <wtf/Vector.h> + +namespace WebCore { + +class HTMLMediaElement; +class ScriptExecutionContext; +class WebKitMediaKeySession; + +class WebKitMediaKeys final : public RefCounted<WebKitMediaKeys>, private CDMClient { +public: + static ExceptionOr<Ref<WebKitMediaKeys>> create(const String& keySystem); + virtual ~WebKitMediaKeys(); + + ExceptionOr<Ref<WebKitMediaKeySession>> createSession(ScriptExecutionContext&, const String& mimeType, Ref<Uint8Array>&& initData); + static bool isTypeSupported(const String& keySystem, const String& mimeType); + const String& keySystem() const { return m_keySystem; } + + CDM& cdm() { ASSERT(m_cdm); return *m_cdm; } + + void setMediaElement(HTMLMediaElement*); + + void keyAdded(); + RefPtr<ArrayBuffer> cachedKeyForKeyId(const String& keyId) const; + +private: + MediaPlayer* cdmMediaPlayer(const CDM*) const final; + + WebKitMediaKeys(const String& keySystem, std::unique_ptr<CDM>&&); + + Vector<Ref<WebKitMediaKeySession>> m_sessions; + HTMLMediaElement* m_mediaElement { nullptr }; + String m_keySystem; + std::unique_ptr<CDM> m_cdm; +}; + +} + +#endif // ENABLE(LEGACY_ENCRYPTED_MEDIA) diff --git a/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeys.idl b/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeys.idl new file mode 100644 index 000000000..dc6494feb --- /dev/null +++ b/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeys.idl @@ -0,0 +1,34 @@ +/* + * 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. ``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 + * 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. + */ + +[ + Conditional=LEGACY_ENCRYPTED_MEDIA, + Constructor(DOMString keySystem), + ConstructorMayThrowException, +] interface WebKitMediaKeys { + [CallWith=ScriptExecutionContext, MayThrowException] WebKitMediaKeySession createSession(DOMString type, Uint8Array initData); + static boolean isTypeSupported(DOMString keySystem, optional DOMString type); + readonly attribute DOMString keySystem; +}; |