summaryrefslogtreecommitdiff
path: root/Source/WebCore/Modules/encryptedmedia
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/Modules/encryptedmedia')
-rw-r--r--Source/WebCore/Modules/encryptedmedia/CDM.cpp663
-rw-r--r--Source/WebCore/Modules/encryptedmedia/CDM.h122
-rw-r--r--Source/WebCore/Modules/encryptedmedia/CDMInstance.h92
-rw-r--r--Source/WebCore/Modules/encryptedmedia/CDMPrivate.h63
-rw-r--r--Source/WebCore/Modules/encryptedmedia/InitDataRegistry.cpp165
-rw-r--r--Source/WebCore/Modules/encryptedmedia/InitDataRegistry.h68
-rw-r--r--Source/WebCore/Modules/encryptedmedia/MediaKeyMessageEvent.cpp52
-rw-r--r--Source/WebCore/Modules/encryptedmedia/MediaKeyMessageEvent.h67
-rw-r--r--Source/WebCore/Modules/encryptedmedia/MediaKeyMessageEvent.idl48
-rw-r--r--Source/WebCore/Modules/encryptedmedia/MediaKeyMessageEventInit.h54
-rw-r--r--Source/WebCore/Modules/encryptedmedia/MediaKeyMessageType.h44
-rw-r--r--Source/WebCore/Modules/encryptedmedia/MediaKeySession.cpp709
-rw-r--r--Source/WebCore/Modules/encryptedmedia/MediaKeySession.h119
-rw-r--r--Source/WebCore/Modules/encryptedmedia/MediaKeySession.idl44
-rw-r--r--Source/WebCore/Modules/encryptedmedia/MediaKeySessionType.h43
-rw-r--r--Source/WebCore/Modules/encryptedmedia/MediaKeySessionType.idl35
-rw-r--r--Source/WebCore/Modules/encryptedmedia/MediaKeyStatus.h47
-rw-r--r--Source/WebCore/Modules/encryptedmedia/MediaKeyStatusMap.cpp112
-rw-r--r--Source/WebCore/Modules/encryptedmedia/MediaKeyStatusMap.h81
-rw-r--r--Source/WebCore/Modules/encryptedmedia/MediaKeyStatusMap.idl47
-rw-r--r--Source/WebCore/Modules/encryptedmedia/MediaKeySystemAccess.cpp118
-rw-r--r--Source/WebCore/Modules/encryptedmedia/MediaKeySystemAccess.h65
-rw-r--r--Source/WebCore/Modules/encryptedmedia/MediaKeySystemAccess.idl37
-rw-r--r--Source/WebCore/Modules/encryptedmedia/MediaKeySystemConfiguration.h55
-rw-r--r--Source/WebCore/Modules/encryptedmedia/MediaKeySystemConfiguration.idl40
-rw-r--r--Source/WebCore/Modules/encryptedmedia/MediaKeySystemMediaCapability.h44
-rw-r--r--Source/WebCore/Modules/encryptedmedia/MediaKeySystemMediaCapability.idl35
-rw-r--r--Source/WebCore/Modules/encryptedmedia/MediaKeys.cpp114
-rw-r--r--Source/WebCore/Modules/encryptedmedia/MediaKeys.h75
-rw-r--r--Source/WebCore/Modules/encryptedmedia/MediaKeys.idl36
-rw-r--r--Source/WebCore/Modules/encryptedmedia/MediaKeysRequirement.h43
-rw-r--r--Source/WebCore/Modules/encryptedmedia/MediaKeysRequirement.idl36
-rw-r--r--Source/WebCore/Modules/encryptedmedia/MediaKeysRestrictions.h42
-rw-r--r--Source/WebCore/Modules/encryptedmedia/NavigatorEME.cpp109
-rw-r--r--Source/WebCore/Modules/encryptedmedia/NavigatorEME.h50
-rw-r--r--Source/WebCore/Modules/encryptedmedia/NavigatorEME.idl34
-rw-r--r--Source/WebCore/Modules/encryptedmedia/legacy/LegacyCDM.cpp151
-rw-r--r--Source/WebCore/Modules/encryptedmedia/legacy/LegacyCDM.h81
-rw-r--r--Source/WebCore/Modules/encryptedmedia/legacy/LegacyCDMPrivate.h49
-rw-r--r--Source/WebCore/Modules/encryptedmedia/legacy/LegacyCDMPrivateClearKey.cpp68
-rw-r--r--Source/WebCore/Modules/encryptedmedia/legacy/LegacyCDMPrivateClearKey.h57
-rw-r--r--Source/WebCore/Modules/encryptedmedia/legacy/LegacyCDMPrivateMediaPlayer.cpp68
-rw-r--r--Source/WebCore/Modules/encryptedmedia/legacy/LegacyCDMPrivateMediaPlayer.h58
-rw-r--r--Source/WebCore/Modules/encryptedmedia/legacy/LegacyCDMSessionClearKey.cpp209
-rw-r--r--Source/WebCore/Modules/encryptedmedia/legacy/LegacyCDMSessionClearKey.h59
-rw-r--r--Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeyMessageEvent.cpp61
-rw-r--r--Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeyMessageEvent.h70
-rw-r--r--Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeyMessageEvent.idl37
-rw-r--r--Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeyNeededEvent.cpp58
-rw-r--r--Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeyNeededEvent.h66
-rw-r--r--Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeyNeededEvent.idl35
-rw-r--r--Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeySession.cpp256
-rw-r--r--Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeySession.h106
-rw-r--r--Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeySession.idl41
-rw-r--r--Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeys.cpp165
-rw-r--r--Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeys.h70
-rw-r--r--Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeys.idl34
57 files changed, 5407 insertions, 0 deletions
diff --git a/Source/WebCore/Modules/encryptedmedia/CDM.cpp b/Source/WebCore/Modules/encryptedmedia/CDM.cpp
new file mode 100644
index 000000000..7588b0628
--- /dev/null
+++ b/Source/WebCore/Modules/encryptedmedia/CDM.cpp
@@ -0,0 +1,663 @@
+/*
+ * Copyright (C) 2016 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 "CDM.h"
+
+#if ENABLE(ENCRYPTED_MEDIA)
+
+#include "CDMPrivate.h"
+#include "Document.h"
+#include "InitDataRegistry.h"
+#include "MediaKeysRestrictions.h"
+#include "MediaPlayer.h"
+#include "NotImplemented.h"
+#include "ParsedContentType.h"
+#include "ScriptExecutionContext.h"
+#include "SecurityOrigin.h"
+#include <wtf/NeverDestroyed.h>
+
+namespace WebCore {
+
+static Vector<CDMFactory*>& cdmFactories()
+{
+ static NeverDestroyed<Vector<CDMFactory*>> factories;
+ return factories;
+}
+
+static std::unique_ptr<CDMPrivate> createCDMPrivateForKeySystem(const String& keySystem, CDM& cdm)
+{
+ for (auto* factory : cdmFactories()) {
+ if (factory->supportsKeySystem(keySystem))
+ return factory->createCDM(cdm);
+ }
+ ASSERT_NOT_REACHED();
+ return nullptr;
+}
+
+void CDM::registerCDMFactory(CDMFactory& factory)
+{
+ ASSERT(!cdmFactories().contains(&factory));
+ cdmFactories().append(&factory);
+}
+
+void CDM::unregisterCDMFactory(CDMFactory& factory)
+{
+ ASSERT(cdmFactories().contains(&factory));
+ cdmFactories().removeAll(&factory);
+}
+
+bool CDM::supportsKeySystem(const String& keySystem)
+{
+ for (auto* factory : cdmFactories()) {
+ if (factory->supportsKeySystem(keySystem))
+ return true;
+ }
+ return false;
+}
+
+Ref<CDM> CDM::create(Document& document, const String& keySystem)
+{
+ return adoptRef(*new CDM(document, keySystem));
+}
+
+CDM::CDM(Document& document, const String& keySystem)
+ : ContextDestructionObserver(&document)
+ , m_keySystem(keySystem)
+ , m_private(createCDMPrivateForKeySystem(keySystem, *this))
+ , m_weakPtrFactory(this)
+{
+ ASSERT(supportsKeySystem(keySystem));
+ for (auto* factory : cdmFactories()) {
+ if (!factory->supportsKeySystem(keySystem))
+ continue;
+ m_private = factory->createCDM(*this);
+ }
+}
+
+CDM::~CDM() = default;
+
+void CDM::getSupportedConfiguration(MediaKeySystemConfiguration&& candidateConfiguration, SupportedConfigurationCallback&& callback)
+{
+ // https://w3c.github.io/encrypted-media/#get-supported-configuration
+ // W3C Editor's Draft 09 November 2016
+
+ // 3.1.1.1 Get Supported Configuration
+ // Given a Key Systems implementation implementation, MediaKeySystemConfiguration candidate configuration, and origin,
+ // this algorithm returns a supported configuration or NotSupported as appropriate.
+
+ // 1. Let supported configuration be ConsentDenied.
+ // 2. Initialize restrictions to indicate that no configurations have had user consent denied.
+ MediaKeysRestrictions restrictions { };
+ doSupportedConfigurationStep(WTFMove(candidateConfiguration), WTFMove(restrictions), WTFMove(callback));
+}
+
+void CDM::doSupportedConfigurationStep(MediaKeySystemConfiguration&& candidateConfiguration, MediaKeysRestrictions&& restrictions, SupportedConfigurationCallback&& callback)
+{
+ // https://w3c.github.io/encrypted-media/#get-supported-configuration
+ // W3C Editor's Draft 09 November 2016, ctd.
+
+ // 3.1.1.1 Get Supported Configuration
+ // 3. Repeat the following step while supported configuration is ConsentDenied:
+ // 3.1. Let supported configuration and, if provided, restrictions be the result of executing the
+ // Get Supported Configuration and Consent algorithm with implementation, candidate configuration,
+ // restrictions and origin.
+ auto optionalConfiguration = getSupportedConfiguration(candidateConfiguration, restrictions);
+ if (!optionalConfiguration) {
+ callback(std::nullopt);
+ return;
+ }
+
+ auto consentCallback = [weakThis = createWeakPtr(), callback = WTFMove(callback)] (ConsentStatus status, MediaKeySystemConfiguration&& configuration, MediaKeysRestrictions&& restrictions) mutable {
+ if (!weakThis) {
+ callback(std::nullopt);
+ return;
+ }
+ // 3.1.1.2 Get Supported Configuration and Consent, ctd.
+ // 22. Let consent status and updated restrictions be the result of running the Get Consent Status algorithm on accumulated configuration,
+ // restrictions and origin and follow the steps for the value of consent status from the following list:
+ switch (status) {
+ case ConsentStatus::ConsentDenied:
+ // ↳ ConsentDenied:
+ // Return ConsentDenied and updated restrictions.
+ weakThis->doSupportedConfigurationStep(WTFMove(configuration), WTFMove(restrictions), WTFMove(callback));
+ return;
+
+ case ConsentStatus::InformUser:
+ // ↳ InformUser
+ // Inform the user that accumulated configuration is in use in the origin including, specifically, the information that
+ // Distinctive Identifier(s) and/or Distinctive Permanent Identifier(s) as appropriate will be used if the
+ // distinctiveIdentifier member of accumulated configuration is "required". Continue to the next step.
+ // NOTE: Implement.
+ break;
+
+ case ConsentStatus::Allowed:
+ // ↳ Allowed:
+ // Continue to the next step.
+ break;
+ }
+ // 23. Return accumulated configuration.
+ callback(WTFMove(configuration));
+ };
+ getConsentStatus(WTFMove(optionalConfiguration.value()), WTFMove(restrictions), consentCallback);
+}
+
+bool CDM::isPersistentType(MediaKeySessionType sessionType)
+{
+ // https://w3c.github.io/encrypted-media/#is-persistent-session-type
+ // W3C Editor's Draft 09 November 2016
+
+ // 5.1.1. Is persistent session type?
+ // 1. Let the session type be the specified MediaKeySessionType value.
+ // 2. Follow the steps for the value of session type from the following list:
+ switch (sessionType) {
+ case MediaKeySessionType::Temporary:
+ // ↳ "temporary"
+ return false;
+ case MediaKeySessionType::PersistentLicense:
+ case MediaKeySessionType::PersistentUsageRecord:
+ // ↳ "persistent-license"
+ return true;
+ }
+}
+
+std::optional<MediaKeySystemConfiguration> CDM::getSupportedConfiguration(const MediaKeySystemConfiguration& candidateConfiguration, MediaKeysRestrictions& restrictions)
+{
+ // https://w3c.github.io/encrypted-media/#get-supported-configuration-and-consent
+ // W3C Editor's Draft 09 November 2016
+
+ ASSERT(m_private);
+ if (!m_private)
+ return std::nullopt;
+
+ // 3.1.1.2 Get Supported Configuration and Consent
+ // Given a Key Systems implementation implementation, MediaKeySystemConfiguration candidate configuration,
+ // restrictions and origin, this algorithm returns a supported configuration, NotSupported, or ConsentDenied
+ // as appropriate and, in the ConsentDenied case, restrictions.
+
+ // 1. Let accumulated configuration be a new MediaKeySystemConfiguration dictionary.
+ MediaKeySystemConfiguration accumulatedConfiguration { };
+
+ // 2. Set the label member of accumulated configuration to equal the label member of candidate configuration.
+ accumulatedConfiguration.label = candidateConfiguration.label;
+
+ // 3. If the initDataTypes member of candidate configuration is non-empty, run the following steps:
+ if (!candidateConfiguration.initDataTypes.isEmpty()) {
+ // 3.1. Let supported types be an empty sequence of DOMStrings.
+ Vector<String> supportedTypes;
+
+ // 3.2. For each value in candidate configuration's initDataTypes member:
+ for (auto initDataType : candidateConfiguration.initDataTypes) {
+ // 3.2.1. Let initDataType be the value.
+ // 3.2.2. If the implementation supports generating requests based on initDataType, add initDataType
+ // to supported types. String comparison is case-sensitive. The empty string is never supported.
+ if (initDataType.isEmpty())
+ continue;
+
+ if (m_private && m_private->supportsInitDataType(initDataType))
+ supportedTypes.append(initDataType);
+ }
+
+ // 3.3. If supported types is empty, return NotSupported.
+ if (supportedTypes.isEmpty())
+ return std::nullopt;
+
+ // 3.4. Set the initDataTypes member of accumulated configuration to supported types.
+ accumulatedConfiguration.initDataTypes = WTFMove(supportedTypes);
+ }
+
+ // 4. Let distinctive identifier requirement be the value of candidate configuration's distinctiveIdentifier member.
+ MediaKeysRequirement distinctiveIdentifierRequirement = candidateConfiguration.distinctiveIdentifier;
+
+ // 5. If distinctive identifier requirement is "optional" and Distinctive Identifiers are not allowed according to
+ // restrictions, set distinctive identifier requirement to "not-allowed".
+ if (distinctiveIdentifierRequirement == MediaKeysRequirement::Optional && restrictions.distinctiveIdentifierDenied)
+ distinctiveIdentifierRequirement = MediaKeysRequirement::NotAllowed;
+
+ // 6. Follow the steps for distinctive identifier requirement from the following list:
+ switch (distinctiveIdentifierRequirement) {
+ case MediaKeysRequirement::Required:
+ // ↳ "required"
+ // If the implementation does not support use of Distinctive Identifier(s) in combination
+ // with accumulated configuration and restrictions, return NotSupported.
+ if (m_private->distinctiveIdentifiersRequirement(accumulatedConfiguration, restrictions) == MediaKeysRequirement::NotAllowed)
+ return std::nullopt;
+ break;
+
+ case MediaKeysRequirement::Optional:
+ // ↳ "optional"
+ // Continue with the following steps.
+ break;
+
+ case MediaKeysRequirement::NotAllowed:
+ // ↳ "not-allowed"
+ // If the implementation requires use Distinctive Identifier(s) or Distinctive Permanent Identifier(s)
+ // in combination with accumulated configuration and restrictions, return NotSupported.
+ if (m_private->distinctiveIdentifiersRequirement(accumulatedConfiguration, restrictions) == MediaKeysRequirement::Required)
+ return std::nullopt;
+ break;
+ }
+
+ // 7. Set the distinctiveIdentifier member of accumulated configuration to equal distinctive identifier requirement.
+ accumulatedConfiguration.distinctiveIdentifier = distinctiveIdentifierRequirement;
+
+ // 8. Let persistent state requirement be equal to the value of candidate configuration's persistentState member.
+ MediaKeysRequirement persistentStateRequirement = candidateConfiguration.persistentState;
+
+ // 9. If persistent state requirement is "optional" and persisting state is not allowed according to restrictions,
+ // set persistent state requirement to "not-allowed".
+ if (persistentStateRequirement == MediaKeysRequirement::Optional && restrictions.persistentStateDenied)
+ persistentStateRequirement = MediaKeysRequirement::NotAllowed;
+
+ // 10. Follow the steps for persistent state requirement from the following list:
+ switch (persistentStateRequirement) {
+ case MediaKeysRequirement::Required:
+ // ↳ "required"
+ // If the implementation does not support persisting state in combination with accumulated configuration
+ // and restrictions, return NotSupported.
+ if (m_private->persistentStateRequirement(accumulatedConfiguration, restrictions) == MediaKeysRequirement::NotAllowed)
+ return std::nullopt;
+ break;
+
+ case MediaKeysRequirement::Optional:
+ // ↳ "optional"
+ // Continue with the following steps.
+ break;
+
+ case MediaKeysRequirement::NotAllowed:
+ // ↳ "not-allowed"
+ // If the implementation requires persisting state in combination with accumulated configuration
+ // and restrictions, return NotSupported
+ if (m_private->persistentStateRequirement(accumulatedConfiguration, restrictions) == MediaKeysRequirement::Required)
+ return std::nullopt;
+ break;
+ }
+
+ // 11. Set the persistentState member of accumulated configuration to equal the value of persistent state requirement.
+ accumulatedConfiguration.persistentState = persistentStateRequirement;
+
+ // 12. Follow the steps for the first matching condition from the following list:
+ Vector<MediaKeySessionType> sessionTypes;
+
+ if (!candidateConfiguration.sessionTypes.isEmpty()) {
+ // ↳ If the sessionTypes member is present [WebIDL] in candidate configuration
+ // Let session types be candidate configuration's sessionTypes member.
+ sessionTypes = candidateConfiguration.sessionTypes;
+ } else {
+ // ↳ Otherwise
+ // Let session types be [ "temporary" ].
+ sessionTypes = { MediaKeySessionType::Temporary };
+ }
+
+ // 13. For each value in session types:
+ for (auto& sessionType : sessionTypes) {
+ // 13.1. Let session type be the value.
+ // 13.2. If accumulated configuration's persistentState value is "not-allowed" and the
+ // Is persistent session type? algorithm returns true for session type return NotSupported.
+ if (accumulatedConfiguration.persistentState == MediaKeysRequirement::NotAllowed && isPersistentType(sessionType))
+ return std::nullopt;
+
+ // 13.3. If the implementation does not support session type in combination with accumulated configuration
+ // and restrictions for other reasons, return NotSupported.
+ if (!m_private->supportsSessionTypeWithConfiguration(sessionType, accumulatedConfiguration))
+ return std::nullopt;
+
+ // 13.4 If accumulated configuration's persistentState value is "optional" and the result of running the Is
+ // persistent session type? algorithm on session type is true, change accumulated configuration's persistentState
+ // value to "required".
+ if (accumulatedConfiguration.persistentState == MediaKeysRequirement::Optional && isPersistentType(sessionType))
+ accumulatedConfiguration.persistentState = MediaKeysRequirement::Required;
+ }
+
+ // 14. Set the sessionTypes member of accumulated configuration to session types.
+ accumulatedConfiguration.sessionTypes = sessionTypes;
+
+ // 15. If the videoCapabilities and audioCapabilities members in candidate configuration are both empty, return NotSupported.
+ if (candidateConfiguration.videoCapabilities.isEmpty() && candidateConfiguration.audioCapabilities.isEmpty())
+ return std::nullopt;
+
+ // 16. ↳ If the videoCapabilities member in candidate configuration is non-empty:
+ if (!candidateConfiguration.videoCapabilities.isEmpty()) {
+ // 16.1. Let video capabilities be the result of executing the Get Supported Capabilities for Audio/Video Type algorithm on
+ // Video, candidate configuration's videoCapabilities member, accumulated configuration, and restrictions.
+ auto videoCapabilities = getSupportedCapabilitiesForAudioVideoType(AudioVideoType::Video, candidateConfiguration.videoCapabilities, accumulatedConfiguration, restrictions);
+
+ // 16.2. If video capabilities is null, return NotSupported.
+ if (!videoCapabilities)
+ return std::nullopt;
+
+ // 16.3 Set the videoCapabilities member of accumulated configuration to video capabilities.
+ accumulatedConfiguration.videoCapabilities = WTFMove(videoCapabilities.value());
+ } else {
+ // 16. ↳ Otherwise:
+ // Set the videoCapabilities member of accumulated configuration to an empty sequence.
+ accumulatedConfiguration.videoCapabilities = { };
+ }
+
+ // 17. ↳ If the audioCapabilities member in candidate configuration is non-empty:
+ if (!candidateConfiguration.audioCapabilities.isEmpty()) {
+ // 17.1. Let audio capabilities be the result of executing the Get Supported Capabilities for Audio/Video Type algorithm on
+ // Audio, candidate configuration's audioCapabilities member, accumulated configuration, and restrictions.
+ auto audioCapabilities = getSupportedCapabilitiesForAudioVideoType(AudioVideoType::Audio, candidateConfiguration.audioCapabilities, accumulatedConfiguration, restrictions);
+
+ // 17.2. If audio capabilities is null, return NotSupported.
+ if (!audioCapabilities)
+ return std::nullopt;
+
+ // 17.3 Set the audioCapabilities member of accumulated configuration to audio capabilities.
+ accumulatedConfiguration.audioCapabilities = WTFMove(audioCapabilities.value());
+ } else {
+ // 17. ↳ Otherwise:
+ // Set the audioCapabilities member of accumulated configuration to an empty sequence.
+ accumulatedConfiguration.audioCapabilities = { };
+ }
+
+ // 18. If accumulated configuration's distinctiveIdentifier value is "optional", follow the steps for the first matching
+ // condition from the following list:
+ if (accumulatedConfiguration.distinctiveIdentifier == MediaKeysRequirement::Optional) {
+ // ↳ If the implementation requires use Distinctive Identifier(s) or Distinctive Permanent Identifier(s) for any of the
+ // combinations in accumulated configuration
+ if (m_private->distinctiveIdentifiersRequirement(accumulatedConfiguration, restrictions) == MediaKeysRequirement::Required) {
+ // Change accumulated configuration's distinctiveIdentifier value to "required".
+ accumulatedConfiguration.distinctiveIdentifier = MediaKeysRequirement::Required;
+ } else {
+ // ↳ Otherwise
+ // Change accumulated configuration's distinctiveIdentifier value to "not-allowed".
+ accumulatedConfiguration.distinctiveIdentifier = MediaKeysRequirement::NotAllowed;
+ }
+ }
+
+ // 19. If accumulated configuration's persistentState value is "optional", follow the steps for the first matching
+ // condition from the following list:
+ if (accumulatedConfiguration.persistentState == MediaKeysRequirement::Optional) {
+ // ↳ If the implementation requires persisting state for any of the combinations in accumulated configuration
+ if (m_private->persistentStateRequirement(accumulatedConfiguration, restrictions) == MediaKeysRequirement::Required) {
+ // Change accumulated configuration's persistentState value to "required".
+ accumulatedConfiguration.persistentState = MediaKeysRequirement::Required;
+ } else {
+ // ↳ Otherwise
+ // Change accumulated configuration's persistentState value to "not-allowed".
+ accumulatedConfiguration.persistentState = MediaKeysRequirement::NotAllowed;
+ }
+ }
+
+ // 20. If implementation in the configuration specified by the combination of the values in accumulated configuration
+ // is not supported or not allowed in the origin, return NotSupported.
+ if (!m_private->supportsConfiguration(accumulatedConfiguration))
+ return std::nullopt;
+
+ Document* document = downcast<Document>(m_scriptExecutionContext);
+ if (!document)
+ return std::nullopt;
+
+ SecurityOrigin& origin = document->securityOrigin();
+ SecurityOrigin& topOrigin = document->topOrigin();
+
+ if ((accumulatedConfiguration.distinctiveIdentifier == MediaKeysRequirement::Required || accumulatedConfiguration.persistentState == MediaKeysRequirement::Required) && !origin.canAccessLocalStorage(&topOrigin))
+ return std::nullopt;
+
+ return WTFMove(accumulatedConfiguration);
+ // NOTE: Continued in getConsentStatus().
+}
+
+std::optional<Vector<MediaKeySystemMediaCapability>> CDM::getSupportedCapabilitiesForAudioVideoType(CDM::AudioVideoType type, const Vector<MediaKeySystemMediaCapability>& requestedCapabilities, const MediaKeySystemConfiguration& partialConfiguration, MediaKeysRestrictions& restrictions)
+{
+ // https://w3c.github.io/encrypted-media/#get-supported-capabilities-for-audio-video-type
+ // W3C Editor's Draft 09 November 2016
+
+ ASSERT(m_private);
+ if (!m_private)
+ return std::nullopt;
+
+ // 3.1.1.3 Get Supported Capabilities for Audio/Video Type
+
+ // Given an audio/video type, MediaKeySystemMediaCapability sequence requested media capabilities, MediaKeySystemConfiguration
+ // partial configuration, and restrictions, this algorithm returns a sequence of supported MediaKeySystemMediaCapability values
+ // for this audio/video type or null as appropriate.
+
+ // 1. Let local accumulated configuration be a local copy of partial configuration.
+ MediaKeySystemConfiguration accumulatedConfiguration = partialConfiguration;
+
+ // 2. Let supported media capabilities be an empty sequence of MediaKeySystemMediaCapability dictionaries.
+ Vector<MediaKeySystemMediaCapability> supportedMediaCapabilities { };
+
+ // 3. For each requested media capability in requested media capabilities:
+ for (auto& requestedCapability : requestedCapabilities) {
+ // 3.1. Let content type be requested media capability's contentType member.
+ // 3.2. Let robustness be requested media capability's robustness member.
+ String robustness = requestedCapability.robustness;
+
+ // 3.3. If content type is the empty string, return null.
+ if (requestedCapability.contentType.isEmpty())
+ return std::nullopt;
+
+ // 3.4. If content type is an invalid or unrecognized MIME type, continue to the next iteration.
+ if (!isValidContentType(requestedCapability.contentType))
+ continue;
+
+ // 3.5. Let container be the container type specified by content type.
+ ParsedContentType contentType { requestedCapability.contentType };
+ String container = contentType.mimeType();
+
+ // 3.6. If the user agent does not support container, continue to the next iteration. The case-sensitivity
+ // of string comparisons is determined by the appropriate RFC.
+ // 3.7. Let parameters be the RFC 6381 [RFC6381] parameters, if any, specified by content type.
+ // 3.8. If the user agent does not recognize one or more parameters, continue to the next iteration.
+ // 3.9. Let media types be the set of codecs and codec constraints specified by parameters. The case-sensitivity
+ // of string comparisons is determined by the appropriate RFC or other specification.
+ String codecs = contentType.parameterValueForName("codecs");
+ if (contentType.parameterCount() > (codecs.isEmpty() ? 0 : 1))
+ continue;
+
+ // 3.10. If media types is empty:
+ if (codecs.isEmpty()) {
+ // ↳ If container normatively implies a specific set of codecs and codec constraints:
+ // ↳ Otherwise:
+ notImplemented();
+ }
+
+ // 3.11. If content type is not strictly a audio/video type, continue to the next iteration.
+ // 3.12. If robustness is not the empty string and contains an unrecognized value or a value not supported by
+ // implementation, continue to the next iteration. String comparison is case-sensitive.
+ if (!robustness.isEmpty() && !m_private->supportsRobustness(robustness))
+ continue;
+
+ // 3.13. If the user agent and implementation definitely support playback of encrypted media data for the
+ // combination of container, media types, robustness and local accumulated configuration in combination
+ // with restrictions:
+ MediaEngineSupportParameters parameters;
+ parameters.type = contentType.mimeType();
+ parameters.codecs = codecs;
+ if (!MediaPlayer::supportsType(parameters, nullptr)) {
+ // Try with Media Source:
+ parameters.isMediaSource = true;
+ if (!MediaPlayer::supportsType(parameters, nullptr))
+ continue;
+ }
+
+ if (!m_private->supportsConfigurationWithRestrictions(accumulatedConfiguration, restrictions))
+ continue;
+
+ // 3.13.1. Add requested media capability to supported media capabilities.
+ supportedMediaCapabilities.append(requestedCapability);
+
+ // 3.13.2. ↳ If audio/video type is Video:
+ // Add requested media capability to the videoCapabilities member of local accumulated configuration.
+ if (type == AudioVideoType::Video)
+ accumulatedConfiguration.videoCapabilities.append(requestedCapability);
+ // 3.13.2. ↳ If audio/video type is Audio:
+ // Add requested media capability to the audioCapabilities member of local accumulated configuration.
+ else
+ accumulatedConfiguration.audioCapabilities.append(requestedCapability);
+ }
+
+ // 4. If supported media capabilities is empty, return null.
+ if (supportedMediaCapabilities.isEmpty())
+ return std::nullopt;
+
+ // 5. Return supported media capabilities.
+ return supportedMediaCapabilities;
+}
+
+void CDM::getConsentStatus(MediaKeySystemConfiguration&& accumulatedConfiguration, MediaKeysRestrictions&& restrictions, ConsentStatusCallback&& callback)
+{
+ // https://w3c.github.io/encrypted-media/#get-supported-configuration-and-consent
+ // W3C Editor's Draft 09 November 2016
+ if (!m_scriptExecutionContext) {
+ callback(ConsentStatus::ConsentDenied, WTFMove(accumulatedConfiguration), WTFMove(restrictions));
+ return;
+ }
+
+ // NOTE: In the future, these checks belowe will involve asking the page client, possibly across a process boundary.
+ // They will by necessity be asynchronous with callbacks. For now, imply this behavior by performing it in an async task.
+
+ m_scriptExecutionContext->postTask([this, weakThis = createWeakPtr(), accumulatedConfiguration = WTFMove(accumulatedConfiguration), restrictions = WTFMove(restrictions), callback = WTFMove(callback)] (ScriptExecutionContext&) mutable {
+ if (!weakThis || !m_private) {
+ callback(ConsentStatus::ConsentDenied, WTFMove(accumulatedConfiguration), WTFMove(restrictions));
+ return;
+ }
+
+ Document* document = downcast<Document>(m_scriptExecutionContext);
+ if (!document) {
+ callback(ConsentStatus::ConsentDenied, WTFMove(accumulatedConfiguration), WTFMove(restrictions));
+ return;
+ }
+
+ SecurityOrigin& origin = document->securityOrigin();
+ SecurityOrigin& topOrigin = document->topOrigin();
+
+ // 3.1.1.2 Get Supported Configuration and Consent, ctd.
+ // 21. If accumulated configuration's distinctiveIdentifier value is "required" and the Distinctive Identifier(s) associated
+ // with accumulated configuration are not unique per origin and profile and clearable:
+ if (accumulatedConfiguration.distinctiveIdentifier == MediaKeysRequirement::Required && !m_private->distinctiveIdentifiersAreUniquePerOriginAndClearable(accumulatedConfiguration)) {
+ // 21.1. Update restrictions to reflect that all configurations described by accumulated configuration do not have user consent.
+ restrictions.distinctiveIdentifierDenied = true;
+ callback(ConsentStatus::ConsentDenied, WTFMove(accumulatedConfiguration), WTFMove(restrictions));
+ return;
+ }
+
+ // https://w3c.github.io/encrypted-media/#get-consent-status
+ // 3.1.1.4 Get Consent Status
+ // Given an accumulated configuration, restrictions and origin, this algorithm returns the consent status for accumulated
+ // configuration and origin as one of ConsentDenied, InformUser or Allowed, together with an updated value for restrictions
+ // in the ConsentDenied case.
+
+ // 1. If there is persisted denial for origin indicating that accumulated configuration is not allowed, run the following steps:
+ // 1.1. Update restrictions to reflect the configurations for which consent has been denied.
+ // 1.2. Return ConsentDenied and restrictions.
+ // 2. If there is persisted consent for origin indicating accumulated configuration is allowed, return Allowed.
+ // NOTE: persisted denial / consent unimplemented.
+
+ // 3. If any of the following are true:
+ // ↳ The distinctiveIdentifier member of accumulated configuration is not "not-allowed" and the combination of the User Agent,
+ // implementation and accumulated configuration does not follow all the recommendations of Allow Persistent Data to Be Cleared
+ // with respect to Distinctive Identifier(s).
+ // NOTE: assume that implementations follow all recommendations.
+
+ // ↳ The user agent requires explicit user consent for the accumulated configuration for other reasons.
+ // NOTE: assume the user agent does not require explicit user consent.
+
+ // 3.1. Request user consent to use accumulated configuration in the origin and wait for the user response.
+ // The consent must include consent to use a Distinctive Identifier(s) and/or Distinctive Permanent Identifier(s) as appropriate
+ // if accumulated configuration's distinctiveIdentifier member is "required".
+ // 3.2. If consent was denied, run the following steps:
+ // 3.2.1. Update restrictions to reflect the configurations for which consent was denied.
+ // 3.2.1. Return ConsentDenied and restrictions.
+ // NOTE: assume implied consent if the combination of origin and topOrigin allows it.
+ if (accumulatedConfiguration.distinctiveIdentifier == MediaKeysRequirement::Required && !origin.canAccessLocalStorage(&topOrigin)) {
+ restrictions.distinctiveIdentifierDenied = true;
+ callback(ConsentStatus::ConsentDenied, WTFMove(accumulatedConfiguration), WTFMove(restrictions));
+ return;
+ }
+
+ // 4. If the distinctiveIdentifier member of accumulated configuration is not "not-allowed", return InformUser.
+ if (accumulatedConfiguration.distinctiveIdentifier != MediaKeysRequirement::NotAllowed) {
+ callback(ConsentStatus::InformUser, WTFMove(accumulatedConfiguration), WTFMove(restrictions));
+ return;
+ }
+
+ // 5. If the user agent requires informing the user for the accumulated configuration for other reasons, return InformUser.
+ // NOTE: assume the user agent does not require informing the user.
+
+ // 6. Return Allowed.
+ callback(ConsentStatus::Allowed, WTFMove(accumulatedConfiguration), WTFMove(restrictions));
+ });
+}
+
+void CDM::loadAndInitialize()
+{
+ if (m_private)
+ m_private->loadAndInitialize();
+}
+
+RefPtr<CDMInstance> CDM::createInstance()
+{
+ if (!m_private)
+ return nullptr;
+ return m_private->createInstance();
+}
+
+bool CDM::supportsServerCertificates() const
+{
+ return m_private && m_private->supportsServerCertificates();
+}
+
+bool CDM::supportsSessions() const
+{
+ return m_private && m_private->supportsSessions();
+}
+
+bool CDM::supportsInitDataType(const AtomicString& initDataType) const
+{
+ return m_private && m_private->supportsInitDataType(initDataType);
+}
+
+RefPtr<SharedBuffer> CDM::sanitizeInitData(const AtomicString& initDataType, const SharedBuffer& initData)
+{
+ return InitDataRegistry::shared().sanitizeInitData(initDataType, initData);
+}
+
+bool CDM::supportsInitData(const AtomicString& initDataType, const SharedBuffer& initData)
+{
+ return m_private && m_private->supportsInitData(initDataType, initData);
+}
+
+RefPtr<SharedBuffer> CDM::sanitizeResponse(const SharedBuffer& response)
+{
+ if (!m_private)
+ return nullptr;
+ return m_private->sanitizeResponse(response);
+}
+
+std::optional<String> CDM::sanitizeSessionId(const String& sessionId)
+{
+ if (!m_private)
+ return std::nullopt;
+ return m_private->sanitizeSessionId(sessionId);
+}
+
+}
+
+#endif
diff --git a/Source/WebCore/Modules/encryptedmedia/CDM.h b/Source/WebCore/Modules/encryptedmedia/CDM.h
new file mode 100644
index 000000000..c43ee747d
--- /dev/null
+++ b/Source/WebCore/Modules/encryptedmedia/CDM.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2016 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(ENCRYPTED_MEDIA)
+
+#include "ContextDestructionObserver.h"
+#include "MediaKeySystemConfiguration.h"
+#include "SharedBuffer.h"
+#include <functional>
+#include <wtf/HashSet.h>
+#include <wtf/Ref.h>
+#include <wtf/RefCounted.h>
+#include <wtf/WeakPtr.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class CDM;
+class CDMInstance;
+class CDMPrivate;
+class Document;
+class ScriptExecutionContext;
+class SharedBuffer;
+
+struct MediaKeysRestrictions;
+
+class CDMFactory {
+public:
+ virtual ~CDMFactory() { };
+ virtual std::unique_ptr<CDMPrivate> createCDM(CDM&) = 0;
+ virtual bool supportsKeySystem(const String&) = 0;
+};
+
+class CDM : public RefCounted<CDM>, private ContextDestructionObserver {
+public:
+ WEBCORE_EXPORT static void registerCDMFactory(CDMFactory&);
+ WEBCORE_EXPORT static void unregisterCDMFactory(CDMFactory&);
+
+ static bool supportsKeySystem(const String&);
+ static bool isPersistentType(MediaKeySessionType);
+
+ static Ref<CDM> create(Document&, const String& keySystem);
+ ~CDM();
+
+ using SupportedConfigurationCallback = std::function<void(std::optional<MediaKeySystemConfiguration>)>;
+ void getSupportedConfiguration(MediaKeySystemConfiguration&& candidateConfiguration, SupportedConfigurationCallback&&);
+
+ const String& keySystem() const { return m_keySystem; }
+
+ void loadAndInitialize();
+ RefPtr<CDMInstance> createInstance();
+ bool supportsServerCertificates() const;
+ bool supportsSessions() const;
+ bool supportsInitDataType(const AtomicString&) const;
+
+ RefPtr<SharedBuffer> sanitizeInitData(const AtomicString& initDataType, const SharedBuffer&);
+ bool supportsInitData(const AtomicString& initDataType, const SharedBuffer&);
+
+ RefPtr<SharedBuffer> sanitizeResponse(const SharedBuffer&);
+
+ std::optional<String> sanitizeSessionId(const String& sessionId);
+
+private:
+ CDM(Document&, const String& keySystem);
+
+ enum class ConfigurationStatus {
+ Supported,
+ NotSupported,
+ ConsentDenied,
+ };
+
+ enum class ConsentStatus {
+ ConsentDenied,
+ InformUser,
+ Allowed,
+ };
+
+ enum class AudioVideoType {
+ Audio,
+ Video,
+ };
+
+ void doSupportedConfigurationStep(MediaKeySystemConfiguration&& candidateConfiguration, MediaKeysRestrictions&&, SupportedConfigurationCallback&&);
+ std::optional<MediaKeySystemConfiguration> getSupportedConfiguration(const MediaKeySystemConfiguration& candidateConfiguration, MediaKeysRestrictions&);
+ std::optional<Vector<MediaKeySystemMediaCapability>> getSupportedCapabilitiesForAudioVideoType(AudioVideoType, const Vector<MediaKeySystemMediaCapability>& requestedCapabilities, const MediaKeySystemConfiguration& partialConfiguration, MediaKeysRestrictions&);
+
+ WeakPtr<CDM> createWeakPtr() { return m_weakPtrFactory.createWeakPtr(); }
+
+ using ConsentStatusCallback = std::function<void(ConsentStatus, MediaKeySystemConfiguration&&, MediaKeysRestrictions&&)>;
+ void getConsentStatus(MediaKeySystemConfiguration&& accumulatedConfiguration, MediaKeysRestrictions&&, ConsentStatusCallback&&);
+ String m_keySystem;
+ std::unique_ptr<CDMPrivate> m_private;
+ WeakPtrFactory<CDM> m_weakPtrFactory;
+};
+
+}
+
+#endif
diff --git a/Source/WebCore/Modules/encryptedmedia/CDMInstance.h b/Source/WebCore/Modules/encryptedmedia/CDMInstance.h
new file mode 100644
index 000000000..d4d84d86e
--- /dev/null
+++ b/Source/WebCore/Modules/encryptedmedia/CDMInstance.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2017 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(ENCRYPTED_MEDIA)
+
+#include "MediaKeyMessageType.h"
+#include "MediaKeySessionType.h"
+#include "MediaKeyStatus.h"
+#include <utility>
+#include <wtf/Forward.h>
+#include <wtf/Optional.h>
+#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+struct MediaKeySystemConfiguration;
+class SharedBuffer;
+
+class CDMInstance : public RefCounted<CDMInstance> {
+public:
+ virtual ~CDMInstance() { }
+
+ enum SuccessValue {
+ Failed,
+ Succeeded,
+ };
+
+ using LicenseType = MediaKeySessionType;
+ using KeyStatus = MediaKeyStatus;
+ using MessageType = MediaKeyMessageType;
+
+ virtual SuccessValue initializeWithConfiguration(const MediaKeySystemConfiguration&) = 0;
+ virtual SuccessValue setDistinctiveIdentifiersAllowed(bool) = 0;
+ virtual SuccessValue setPersistentStateAllowed(bool) = 0;
+ virtual SuccessValue setServerCertificate(Ref<SharedBuffer>&&) = 0;
+
+ using LicenseCallback = Function<void(Ref<SharedBuffer>&& message, const String& sessionId, bool needsIndividualization, SuccessValue succeeded)>;
+ virtual void requestLicense(LicenseType, const AtomicString& initDataType, Ref<SharedBuffer>&& initData, LicenseCallback) = 0;
+
+ using KeyStatusVector = Vector<std::pair<Ref<SharedBuffer>, KeyStatus>>;
+ using Message = std::pair<MessageType, Ref<SharedBuffer>>;
+ using LicenseUpdateCallback = Function<void(bool sessionWasClosed, std::optional<KeyStatusVector>&& changedKeys, std::optional<double>&& changedExpiration, std::optional<Message>&& message, SuccessValue succeeded)>;
+ virtual void updateLicense(const String& sessionId, LicenseType, const SharedBuffer& response, LicenseUpdateCallback) = 0;
+
+ enum class SessionLoadFailure {
+ None,
+ NoSessionData,
+ MismatchedSessionType,
+ QuotaExceeded,
+ Other,
+ };
+
+ using LoadSessionCallback = Function<void(std::optional<KeyStatusVector>&&, std::optional<double>&&, std::optional<Message>&&, SuccessValue, SessionLoadFailure)>;
+ virtual void loadSession(LicenseType, const String& sessionId, const String& origin, LoadSessionCallback) = 0;
+
+ using CloseSessionCallback = Function<void()>;
+ virtual void closeSession(const String& sessionId, CloseSessionCallback) = 0;
+
+ using RemoveSessionDataCallback = Function<void(KeyStatusVector&&, std::optional<Ref<SharedBuffer>>&&, SuccessValue)>;
+ virtual void removeSessionData(const String& sessionId, LicenseType, RemoveSessionDataCallback) = 0;
+
+ virtual void storeRecordOfKeyUsage(const String& sessionId) = 0;
+};
+
+}
+
+#endif
diff --git a/Source/WebCore/Modules/encryptedmedia/CDMPrivate.h b/Source/WebCore/Modules/encryptedmedia/CDMPrivate.h
new file mode 100644
index 000000000..44f27d86e
--- /dev/null
+++ b/Source/WebCore/Modules/encryptedmedia/CDMPrivate.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2016 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(ENCRYPTED_MEDIA)
+
+#include "CDMInstance.h"
+#include "MediaKeySessionType.h"
+#include "MediaKeysRequirement.h"
+#include <wtf/Forward.h>
+
+namespace WebCore {
+
+struct MediaKeySystemConfiguration;
+struct MediaKeysRestrictions;
+
+class CDMPrivate {
+public:
+ virtual ~CDMPrivate() { }
+
+ virtual bool supportsInitDataType(const AtomicString&) const = 0;
+ virtual bool supportsConfiguration(const MediaKeySystemConfiguration&) const = 0;
+ virtual bool supportsConfigurationWithRestrictions(const MediaKeySystemConfiguration&, const MediaKeysRestrictions&) const = 0;
+ virtual bool supportsSessionTypeWithConfiguration(MediaKeySessionType&, const MediaKeySystemConfiguration&) const = 0;
+ virtual bool supportsRobustness(const String&) const = 0;
+ virtual MediaKeysRequirement distinctiveIdentifiersRequirement(const MediaKeySystemConfiguration&, const MediaKeysRestrictions&) const = 0;
+ virtual MediaKeysRequirement persistentStateRequirement(const MediaKeySystemConfiguration&, const MediaKeysRestrictions&) const = 0;
+ virtual bool distinctiveIdentifiersAreUniquePerOriginAndClearable(const MediaKeySystemConfiguration&) const = 0;
+ virtual RefPtr<CDMInstance> createInstance() = 0;
+ virtual void loadAndInitialize() = 0;
+ virtual bool supportsServerCertificates() const = 0;
+ virtual bool supportsSessions() const = 0;
+ virtual bool supportsInitData(const AtomicString&, const SharedBuffer&) const = 0;
+ virtual RefPtr<SharedBuffer> sanitizeResponse(const SharedBuffer&) const = 0;
+ virtual std::optional<String> sanitizeSessionId(const String&) const = 0;
+};
+
+}
+
+#endif
diff --git a/Source/WebCore/Modules/encryptedmedia/InitDataRegistry.cpp b/Source/WebCore/Modules/encryptedmedia/InitDataRegistry.cpp
new file mode 100644
index 000000000..f5b4758e0
--- /dev/null
+++ b/Source/WebCore/Modules/encryptedmedia/InitDataRegistry.cpp
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2017 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 "InitDataRegistry.h"
+
+#if ENABLE(ENCRYPTED_MEDIA)
+
+#include "NotImplemented.h"
+#include "SharedBuffer.h"
+#include "inspector/InspectorValues.h"
+#include <wtf/NeverDestroyed.h>
+#include <wtf/text/Base64.h>
+
+using namespace Inspector;
+
+namespace WebCore {
+
+static Vector<Ref<SharedBuffer>> extractKeyIDsKeyids(const SharedBuffer& buffer)
+{
+ // 1. Format
+ // https://w3c.github.io/encrypted-media/format-registry/initdata/keyids.html#format
+ String json { buffer.data(), buffer.size() };
+
+ RefPtr<InspectorValue> value;
+ if (!InspectorValue::parseJSON(json, value))
+ return { };
+
+ RefPtr<InspectorObject> object;
+ if (!value->asObject(object))
+ return { };
+
+ RefPtr<InspectorArray> kidsArray;
+ if (!object->getArray("kids", kidsArray))
+ return { };
+
+ Vector<Ref<SharedBuffer>> keyIDs;
+ for (auto& value : *kidsArray) {
+ String keyID;
+ if (!value->asString(keyID))
+ continue;
+
+ Vector<char> keyIDData;
+ if (!WTF::base64URLDecode(keyID, { keyIDData }))
+ continue;
+
+ Ref<SharedBuffer> keyIDBuffer = SharedBuffer::adoptVector(keyIDData);
+ keyIDs.append(WTFMove(keyIDBuffer));
+ }
+
+ return keyIDs;
+}
+
+static RefPtr<SharedBuffer> sanitizeKeyids(const SharedBuffer& buffer)
+{
+ // 1. Format
+ // https://w3c.github.io/encrypted-media/format-registry/initdata/keyids.html#format
+ Vector<Ref<SharedBuffer>> keyIDBuffer = extractKeyIDsKeyids(buffer);
+ if (keyIDBuffer.isEmpty())
+ return nullptr;
+
+ auto object = InspectorObject::create();
+ auto kidsArray = InspectorArray::create();
+ for (auto& buffer : keyIDBuffer)
+ kidsArray->pushString(WTF::base64URLEncode(buffer->data(), buffer->size()));
+ object->setArray("kids", WTFMove(kidsArray));
+
+ CString jsonData = object->toJSONString().utf8();
+ return SharedBuffer::create(jsonData.data(), jsonData.length());
+}
+
+static RefPtr<SharedBuffer> sanitizeCenc(const SharedBuffer& buffer)
+{
+ // 4. Common SystemID and PSSH Box Format
+ // https://w3c.github.io/encrypted-media/format-registry/initdata/cenc.html#common-system
+ notImplemented();
+ return buffer.copy();
+}
+
+static Vector<Ref<SharedBuffer>> extractKeyIDsCenc(const SharedBuffer&)
+{
+ // 4. Common SystemID and PSSH Box Format
+ // https://w3c.github.io/encrypted-media/format-registry/initdata/cenc.html#common-system
+ notImplemented();
+ return { };
+}
+
+static RefPtr<SharedBuffer> sanitizeWebM(const SharedBuffer& buffer)
+{
+ // 1. Format
+ // https://w3c.github.io/encrypted-media/format-registry/initdata/webm.html#format
+ notImplemented();
+ return buffer.copy();
+}
+
+static Vector<Ref<SharedBuffer>> extractKeyIDsWebM(const SharedBuffer&)
+{
+ // 1. Format
+ // https://w3c.github.io/encrypted-media/format-registry/initdata/webm.html#format
+ notImplemented();
+ return { };
+}
+
+InitDataRegistry& InitDataRegistry::shared()
+{
+ static NeverDestroyed<InitDataRegistry> registry;
+ return registry.get();
+}
+
+InitDataRegistry::InitDataRegistry()
+{
+ registerInitDataType("keyids", { &sanitizeKeyids, &extractKeyIDsKeyids });
+ registerInitDataType("cenc", { &sanitizeCenc, &extractKeyIDsCenc });
+ registerInitDataType("webm", { &sanitizeWebM, &extractKeyIDsWebM });
+}
+
+InitDataRegistry::~InitDataRegistry() = default;
+
+RefPtr<SharedBuffer> InitDataRegistry::sanitizeInitData(const AtomicString& initDataType, const SharedBuffer& buffer)
+{
+ auto iter = m_types.find(initDataType);
+ if (iter == m_types.end() || !iter->value.sanitizeInitData)
+ return nullptr;
+ return iter->value.sanitizeInitData(buffer);
+}
+
+Vector<Ref<SharedBuffer>> InitDataRegistry::extractKeyIDs(const AtomicString& initDataType, const SharedBuffer& buffer)
+{
+ auto iter = m_types.find(initDataType);
+ if (iter == m_types.end() || !iter->value.sanitizeInitData)
+ return { };
+ return iter->value.extractKeyIDs(buffer);
+}
+
+void InitDataRegistry::registerInitDataType(const AtomicString& initDataType, InitDataTypeCallbacks&& callbacks)
+{
+ ASSERT(!m_types.contains(initDataType));
+ m_types.set(initDataType, WTFMove(callbacks));
+}
+
+}
+
+#endif // ENABLE(ENCRYPTED_MEDIA)
diff --git a/Source/WebCore/Modules/encryptedmedia/InitDataRegistry.h b/Source/WebCore/Modules/encryptedmedia/InitDataRegistry.h
new file mode 100644
index 000000000..39bfa0453
--- /dev/null
+++ b/Source/WebCore/Modules/encryptedmedia/InitDataRegistry.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2017 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(ENCRYPTED_MEDIA)
+
+#include <wtf/Function.h>
+#include <wtf/HashMap.h>
+#include <wtf/Ref.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+#include <wtf/text/AtomicString.h>
+#include <wtf/text/AtomicStringHash.h>
+
+namespace WebCore {
+
+class SharedBuffer;
+
+class InitDataRegistry {
+public:
+ WEBCORE_EXPORT static InitDataRegistry& shared();
+ friend class NeverDestroyed<InitDataRegistry>;
+
+ RefPtr<SharedBuffer> sanitizeInitData(const AtomicString& initDataType, const SharedBuffer&);
+ WEBCORE_EXPORT Vector<Ref<SharedBuffer>> extractKeyIDs(const AtomicString& initDataType, const SharedBuffer&);
+
+ struct InitDataTypeCallbacks {
+ using SanitizeInitDataCallback = Function<RefPtr<SharedBuffer>(const SharedBuffer&)>;
+ using ExtractKeyIDsCallback = Function<Vector<Ref<SharedBuffer>>(const SharedBuffer&)>;
+
+ SanitizeInitDataCallback sanitizeInitData;
+ ExtractKeyIDsCallback extractKeyIDs;
+ };
+ void registerInitDataType(const AtomicString& initDataType, InitDataTypeCallbacks&&);
+
+private:
+ InitDataRegistry();
+ ~InitDataRegistry();
+
+ HashMap<AtomicString, InitDataTypeCallbacks> m_types;
+};
+
+}
+
+#endif // ENABLE(ENCRYPTED_MEDIA)
diff --git a/Source/WebCore/Modules/encryptedmedia/MediaKeyMessageEvent.cpp b/Source/WebCore/Modules/encryptedmedia/MediaKeyMessageEvent.cpp
new file mode 100644
index 000000000..2b39ec4bf
--- /dev/null
+++ b/Source/WebCore/Modules/encryptedmedia/MediaKeyMessageEvent.cpp
@@ -0,0 +1,52 @@
+/*
+ * 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 "MediaKeyMessageEvent.h"
+
+#if ENABLE(ENCRYPTED_MEDIA)
+
+namespace WebCore {
+
+MediaKeyMessageEvent::MediaKeyMessageEvent(const AtomicString& type, const MediaKeyMessageEvent::Init& initializer, IsTrusted isTrusted)
+ : Event(type, initializer, isTrusted)
+ , m_messageType(initializer.messageType)
+ , m_message(initializer.message)
+{
+}
+
+MediaKeyMessageEvent::~MediaKeyMessageEvent() = default;
+
+EventInterface MediaKeyMessageEvent::eventInterface() const
+{
+ return MediaKeyMessageEventInterfaceType;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(ENCRYPTED_MEDIA)
diff --git a/Source/WebCore/Modules/encryptedmedia/MediaKeyMessageEvent.h b/Source/WebCore/Modules/encryptedmedia/MediaKeyMessageEvent.h
new file mode 100644
index 000000000..a633c51a6
--- /dev/null
+++ b/Source/WebCore/Modules/encryptedmedia/MediaKeyMessageEvent.h
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#if ENABLE(ENCRYPTED_MEDIA)
+
+#include "Event.h"
+#include "MediaKeyMessageEventInit.h"
+#include "MediaKeyMessageType.h"
+#include <runtime/ArrayBuffer.h>
+
+namespace WebCore {
+
+class MediaKeyMessageEvent final : public Event {
+public:
+ using Type = MediaKeyMessageType;
+ using Init = MediaKeyMessageEventInit;
+
+ virtual ~MediaKeyMessageEvent();
+
+ static Ref<MediaKeyMessageEvent> create(const AtomicString& type, const MediaKeyMessageEventInit& initializer, IsTrusted isTrusted = IsTrusted::No)
+ {
+ return adoptRef(*new MediaKeyMessageEvent(type, initializer, isTrusted));
+ }
+
+ Type messageType() const { return m_messageType; }
+ RefPtr<JSC::ArrayBuffer> message() const { return m_message; }
+
+private:
+ MediaKeyMessageEvent(const AtomicString&, const MediaKeyMessageEventInit&, IsTrusted);
+
+ // Event
+ EventInterface eventInterface() const override;
+
+ MediaKeyMessageType m_messageType;
+ RefPtr<JSC::ArrayBuffer> m_message;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(ENCRYPTED_MEDIA)
diff --git a/Source/WebCore/Modules/encryptedmedia/MediaKeyMessageEvent.idl b/Source/WebCore/Modules/encryptedmedia/MediaKeyMessageEvent.idl
new file mode 100644
index 000000000..2cfbc6a53
--- /dev/null
+++ b/Source/WebCore/Modules/encryptedmedia/MediaKeyMessageEvent.idl
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+enum MediaKeyMessageType {
+ "license-request",
+ "license-renewal",
+ "license-release",
+ "individualization-request"
+};
+
+dictionary MediaKeyMessageEventInit : EventInit {
+ required MediaKeyMessageType messageType;
+ required ArrayBuffer message;
+};
+
+[
+ Conditional=ENCRYPTED_MEDIA,
+ Constructor(DOMString type, MediaKeyMessageEventInit eventInitDict),
+ EnabledAtRuntime=EncryptedMediaAPI
+] interface MediaKeyMessageEvent : Event {
+ readonly attribute MediaKeyMessageType messageType;
+ readonly attribute ArrayBuffer message;
+};
diff --git a/Source/WebCore/Modules/encryptedmedia/MediaKeyMessageEventInit.h b/Source/WebCore/Modules/encryptedmedia/MediaKeyMessageEventInit.h
new file mode 100644
index 000000000..0bf130e4e
--- /dev/null
+++ b/Source/WebCore/Modules/encryptedmedia/MediaKeyMessageEventInit.h
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#if ENABLE(ENCRYPTED_MEDIA)
+
+#include "Event.h"
+#include "MediaKeyMessageType.h"
+#include <runtime/ArrayBuffer.h>
+
+namespace WebCore {
+
+struct MediaKeyMessageEventInit : EventInit {
+ MediaKeyMessageEventInit() = default;
+
+ MediaKeyMessageEventInit(MediaKeyMessageType messageType, RefPtr<JSC::ArrayBuffer>&& message)
+ : EventInit()
+ , messageType(messageType)
+ , message(WTFMove(message))
+ { }
+
+ MediaKeyMessageType messageType;
+ RefPtr<JSC::ArrayBuffer> message;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(ENCRYPTED_MEDIA)
diff --git a/Source/WebCore/Modules/encryptedmedia/MediaKeyMessageType.h b/Source/WebCore/Modules/encryptedmedia/MediaKeyMessageType.h
new file mode 100644
index 000000000..da7361eaa
--- /dev/null
+++ b/Source/WebCore/Modules/encryptedmedia/MediaKeyMessageType.h
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#if ENABLE(ENCRYPTED_MEDIA)
+
+namespace WebCore {
+
+enum class MediaKeyMessageType {
+ LicenseRequest,
+ LicenseRenewal,
+ LicenseRelease,
+ IndividualizationRequest
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(ENCRYPTED_MEDIA)
diff --git a/Source/WebCore/Modules/encryptedmedia/MediaKeySession.cpp b/Source/WebCore/Modules/encryptedmedia/MediaKeySession.cpp
new file mode 100644
index 000000000..220f6dbed
--- /dev/null
+++ b/Source/WebCore/Modules/encryptedmedia/MediaKeySession.cpp
@@ -0,0 +1,709 @@
+/*
+ * 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 "MediaKeySession.h"
+
+#if ENABLE(ENCRYPTED_MEDIA)
+
+#include "CDM.h"
+#include "CDMInstance.h"
+#include "Document.h"
+#include "EventNames.h"
+#include "MediaKeyMessageEvent.h"
+#include "MediaKeyMessageType.h"
+#include "MediaKeyStatusMap.h"
+#include "NotImplemented.h"
+#include "SecurityOrigin.h"
+#include "SharedBuffer.h"
+#include <wtf/NeverDestroyed.h>
+
+namespace WebCore {
+
+Ref<MediaKeySession> MediaKeySession::create(ScriptExecutionContext& context, MediaKeySessionType sessionType, bool useDistinctiveIdentifier, Ref<CDM>&& implementation, Ref<CDMInstance>&& instance)
+{
+ auto session = adoptRef(*new MediaKeySession(context, sessionType, useDistinctiveIdentifier, WTFMove(implementation), WTFMove(instance)));
+ session->suspendIfNeeded();
+ return session;
+}
+
+MediaKeySession::MediaKeySession(ScriptExecutionContext& context, MediaKeySessionType sessionType, bool useDistinctiveIdentifier, Ref<CDM>&& implementation, Ref<CDMInstance>&& instance)
+ : ActiveDOMObject(&context)
+ , m_expiration(std::numeric_limits<double>::quiet_NaN())
+ , m_keyStatuses(MediaKeyStatusMap::create(*this))
+ , m_useDistinctiveIdentifier(useDistinctiveIdentifier)
+ , m_sessionType(sessionType)
+ , m_implementation(WTFMove(implementation))
+ , m_instance(WTFMove(instance))
+ , m_eventQueue(*this)
+ , m_weakPtrFactory(this)
+{
+ // https://w3c.github.io/encrypted-media/#dom-mediakeys-setservercertificate
+ // W3C Editor's Draft 09 November 2016
+ // createSession(), ctd.
+
+ // 3.1. Let the sessionId attribute be the empty string.
+ // 3.2. Let the expiration attribute be NaN.
+ // 3.3. Let the closed attribute be a new promise.
+ // 3.4. Let key status be a new empty MediaKeyStatusMap object, and initialize it as follows:
+ // 3.4.1. Let the size attribute be 0.
+ // 3.5. Let the session type value be sessionType.
+ // 3.6. Let the uninitialized value be true.
+ // 3.7. Let the callable value be false.
+ // 3.8. Let the use distinctive identifier value be this object's use distinctive identifier value.
+ // 3.9. Let the cdm implementation value be this object's cdm implementation.
+ // 3.10. Let the cdm instance value be this object's cdm instance.
+
+ UNUSED_PARAM(m_callable);
+ UNUSED_PARAM(m_sessionType);
+ UNUSED_PARAM(m_useDistinctiveIdentifier);
+ UNUSED_PARAM(m_closed);
+ UNUSED_PARAM(m_uninitialized);
+}
+
+MediaKeySession::~MediaKeySession()
+{
+ m_keyStatuses->detachSession();
+}
+
+const String& MediaKeySession::sessionId() const
+{
+ return m_sessionId;
+}
+
+double MediaKeySession::expiration() const
+{
+ return m_expiration;
+}
+
+Ref<MediaKeyStatusMap> MediaKeySession::keyStatuses() const
+{
+ return m_keyStatuses.copyRef();
+}
+
+void MediaKeySession::generateRequest(const AtomicString& initDataType, const BufferSource& initData, Ref<DeferredPromise>&& promise)
+{
+ // https://w3c.github.io/encrypted-media/#dom-mediakeysession-generaterequest
+ // W3C Editor's Draft 09 November 2016
+
+ // When this method is invoked, the user agent must run the following steps:
+ // 1. If this object is closed, return a promise rejected with an InvalidStateError.
+ // 2. If this object's uninitialized value is false, return a promise rejected with an InvalidStateError.
+ if (m_closed || !m_uninitialized) {
+ promise->reject(INVALID_STATE_ERR);
+ return;
+ }
+
+ // 3. Let this object's uninitialized value be false.
+ m_uninitialized = false;
+
+ // 4. If initDataType is the empty string, return a promise rejected with a newly created TypeError.
+ // 5. If initData is an empty array, return a promise rejected with a newly created TypeError.
+ if (initDataType.isEmpty() || !initData.length()) {
+ promise->reject(TypeError);
+ return;
+ }
+
+ // 6. If the Key System implementation represented by this object's cdm implementation value does not support
+ // initDataType as an Initialization Data Type, return a promise rejected with a NotSupportedError. String
+ // comparison is case-sensitive.
+ if (!m_implementation->supportsInitDataType(initDataType)) {
+ promise->reject(NOT_SUPPORTED_ERR);
+ return;
+ }
+
+ // 7. Let init data be a copy of the contents of the initData parameter.
+ // 8. Let session type be this object's session type.
+ // 9. Let promise be a new promise.
+ // 10. Run the following steps in parallel:
+ m_taskQueue.enqueueTask([this, initData = SharedBuffer::create(initData.data(), initData.length()), initDataType, promise = WTFMove(promise)] () mutable {
+ // 10.1. If the init data is not valid for initDataType, reject promise with a newly created TypeError.
+ // 10.2. Let sanitized init data be a validated and sanitized version of init data.
+ RefPtr<SharedBuffer> sanitizedInitData = m_implementation->sanitizeInitData(initDataType, initData);
+
+ // 10.3. If the preceding step failed, reject promise with a newly created TypeError.
+ if (!sanitizedInitData) {
+ promise->reject(TypeError);
+ return;
+ }
+
+ // 10.4. If sanitized init data is empty, reject promise with a NotSupportedError.
+ if (sanitizedInitData->isEmpty()) {
+ promise->reject(NOT_SUPPORTED_ERR);
+ return;
+ }
+
+ // 10.5. Let session id be the empty string.
+ // 10.6. Let message be null.
+ // 10.7. Let message type be null.
+ // 10.8. Let cdm be the CDM instance represented by this object's cdm instance value.
+ // 10.9. Use the cdm to execute the following steps:
+ // 10.9.1. If the sanitized init data is not supported by the cdm, reject promise with a NotSupportedError.
+ if (!m_implementation->supportsInitData(initDataType, *sanitizedInitData)) {
+ promise->reject(NOT_SUPPORTED_ERR);
+ return;
+ }
+
+ // 10.9.2 Follow the steps for the value of session type from the following list:
+ // ↳ "temporary"
+ // Let requested license type be a temporary non-persistable license.
+ // ↳ "persistent-license"
+ // Let requested license type be a persistable license.
+ // ↳ "persistent-usage-record"
+ // 1. Initialize this object's record of key usage as follows.
+ // Set the list of key IDs known to the session to an empty list.
+ // Set the first decrypt time to null.
+ // Set the latest decrypt time to null.
+ // 2. Let requested license type be a non-persistable license that will
+ // persist a record of key usage.
+
+ if (m_sessionType == MediaKeySessionType::PersistentUsageRecord) {
+ m_recordOfKeyUsage.clear();
+ m_firstDecryptTime = 0;
+ m_latestDecryptTime = 0;
+ }
+
+ m_instance->requestLicense(m_sessionType, initDataType, WTFMove(initData), [this, weakThis = m_weakPtrFactory.createWeakPtr(), promise = WTFMove(promise)] (Ref<SharedBuffer>&& message, const String& sessionId, bool needsIndividualization, CDMInstance::SuccessValue succeeded) mutable {
+ if (!weakThis)
+ return;
+
+ // 10.9.3. Let session id be a unique Session ID string.
+
+ MediaKeyMessageType messageType;
+ if (!needsIndividualization) {
+ // 10.9.4. If a license request for the requested license type can be generated based on the sanitized init data:
+ // 10.9.4.1. Let message be a license request for the requested license type generated based on the sanitized init data interpreted per initDataType.
+ // 10.9.4.2. Let message type be "license-request".
+ messageType = MediaKeyMessageType::LicenseRequest;
+ } else {
+ // 10.9.5. Otherwise:
+ // 10.9.5.1. Let message be the request that needs to be processed before a license request request for the requested license
+ // type can be generated based on the sanitized init data.
+ // 10.9.5.2. Let message type reflect the type of message, either "license-request" or "individualization-request".
+ messageType = MediaKeyMessageType::IndividualizationRequest;
+ }
+
+ // 10.10. Queue a task to run the following steps:
+ m_taskQueue.enqueueTask([this, promise = WTFMove(promise), message = WTFMove(message), messageType, sessionId, succeeded] () mutable {
+ // 10.10.1. If any of the preceding steps failed, reject promise with a new DOMException whose name is the appropriate error name.
+ if (succeeded == CDMInstance::SuccessValue::Failed) {
+ promise->reject(NOT_SUPPORTED_ERR);
+ return;
+ }
+ // 10.10.2. Set the sessionId attribute to session id.
+ m_sessionId = sessionId;
+
+ // 10.9.3. Let this object's callable value be true.
+ m_callable = true;
+
+ // 10.9.3. Run the Queue a "message" Event algorithm on the session, providing message type and message.
+ enqueueMessage(messageType, message);
+
+ // 10.9.3. Resolve promise.
+ promise->resolve();
+ });
+ });
+ });
+
+ // 11. Return promise.
+}
+
+void MediaKeySession::load(const String& sessionId, Ref<DeferredPromise>&& promise)
+{
+ // https://w3c.github.io/encrypted-media/#dom-mediakeysession-load
+ // W3C Editor's Draft 09 November 2016
+
+ // 1. If this object is closed, return a promise rejected with an InvalidStateError.
+ // 2. If this object's uninitialized value is false, return a promise rejected with an InvalidStateError.
+ if (m_closed || !m_uninitialized) {
+ promise->reject(INVALID_STATE_ERR);
+ return;
+ }
+
+ // 3. Let this object's uninitialized value be false.
+ m_uninitialized = false;
+
+ // 4. If sessionId is the empty string, return a promise rejected with a newly created TypeError.
+ // 5. If the result of running the Is persistent session type? algorithm on this object's session type is false, return a promise rejected with a newly created TypeError.
+ if (sessionId.isEmpty() || m_sessionType == MediaKeySessionType::Temporary) {
+ promise->reject(TypeError);
+ return;
+ }
+
+ // 6. Let origin be the origin of this object's Document.
+ // This is retrieved in the following task.
+
+ // 7. Let promise be a new promise.
+ // 8. Run the following steps in parallel:
+ m_taskQueue.enqueueTask([this, sessionId, promise = WTFMove(promise)] () mutable {
+ // 8.1. Let sanitized session ID be a validated and/or sanitized version of sessionId.
+ // 8.2. If the preceding step failed, or if sanitized session ID is empty, reject promise with a newly created TypeError.
+ std::optional<String> sanitizedSessionId = m_implementation->sanitizeSessionId(sessionId);
+ if (!sanitizedSessionId || sanitizedSessionId->isEmpty()) {
+ promise->reject(TypeError);
+ return;
+ }
+
+ // 8.3. If there is a MediaKeySession object that is not closed in this object's Document whose sessionId attribute is sanitized session ID, reject promise with a QuotaExceededError.
+ // FIXME: This needs a global MediaKeySession tracker.
+
+ String origin;
+ if (auto* document = downcast<Document>(scriptExecutionContext()))
+ origin = document->securityOrigin().toString();
+
+ // 8.4. Let expiration time be NaN.
+ // 8.5. Let message be null.
+ // 8.6. Let message type be null.
+ // 8.7. Let cdm be the CDM instance represented by this object's cdm instance value.
+ // 8.8. Use the cdm to execute the following steps:
+ m_instance->loadSession(m_sessionType, *sanitizedSessionId, origin, [this, weakThis = m_weakPtrFactory.createWeakPtr(), promise = WTFMove(promise), sanitizedSessionId = *sanitizedSessionId] (std::optional<CDMInstance::KeyStatusVector>&& knownKeys, std::optional<double>&& expiration, std::optional<CDMInstance::Message>&& message, CDMInstance::SuccessValue succeeded, CDMInstance::SessionLoadFailure failure) mutable {
+ // 8.8.1. If there is no data stored for the sanitized session ID in the origin, resolve promise with false and abort these steps.
+ // 8.8.2. If the stored session's session type is not the same as the current MediaKeySession session type, reject promise with a newly created TypeError.
+ // 8.8.3. Let session data be the data stored for the sanitized session ID in the origin. This must not include data from other origin(s) or that is not associated with an origin.
+ // 8.8.4. If there is a MediaKeySession object that is not closed in any Document and that represents the session data, reject promise with a QuotaExceededError.
+ // 8.8.5. Load the session data.
+ // 8.8.6. If the session data indicates an expiration time for the session, let expiration time be the expiration time in milliseconds since 01 January 1970 UTC.
+ // 8.8.7. If the CDM needs to send a message:
+ // 8.8.7.1. Let message be a message generated by the CDM based on the session data.
+ // 8.8.7.2. Let message type be the appropriate MediaKeyMessageType for the message.
+ // NOTE: Steps 8.8.1. through 8.8.7. should be implemented in CDMInstance.
+
+ if (succeeded == CDMInstance::SuccessValue::Failed) {
+ switch (failure) {
+ case CDMInstance::SessionLoadFailure::NoSessionData:
+ promise->resolve<IDLBoolean>(false);
+ return;
+ case CDMInstance::SessionLoadFailure::MismatchedSessionType:
+ promise->reject(TypeError);
+ return;
+ case CDMInstance::SessionLoadFailure::QuotaExceeded:
+ promise->reject(QUOTA_EXCEEDED_ERR);
+ return;
+ case CDMInstance::SessionLoadFailure::None:
+ case CDMInstance::SessionLoadFailure::Other:
+ // In any other case, the session load failure will cause a rejection in the following task.
+ break;
+ }
+ }
+
+ // 8.9. Queue a task to run the following steps:
+ m_taskQueue.enqueueTask([this, knownKeys = WTFMove(knownKeys), expiration = WTFMove(expiration), message = WTFMove(message), sanitizedSessionId, succeeded, promise = WTFMove(promise)] () mutable {
+ // 8.9.1. If any of the preceding steps failed, reject promise with a the appropriate error name.
+ if (succeeded == CDMInstance::SuccessValue::Failed) {
+ promise->reject(NOT_SUPPORTED_ERR);
+ return;
+ }
+
+ // 8.9.2. Set the sessionId attribute to sanitized session ID.
+ // 8.9.3. Let this object's callable value be true.
+ m_sessionId = sanitizedSessionId;
+ m_callable = true;
+
+ // 8.9.4. If the loaded session contains information about any keys (there are known keys), run the Update Key Statuses algorithm on the session, providing each key's key ID along with the appropriate MediaKeyStatus.
+ if (knownKeys)
+ updateKeyStatuses(WTFMove(*knownKeys));
+
+ // 8.9.5. Run the Update Expiration algorithm on the session, providing expiration time.
+ // This must be run, and NaN is the default value if the CDM instance doesn't provide one.
+ updateExpiration(expiration.value_or(std::numeric_limits<double>::quiet_NaN()));
+
+ // 8.9.6. If message is not null, run the Queue a "message" Event algorithm on the session, providing message type and message.
+ if (message)
+ enqueueMessage(message->first, WTFMove(message->second));
+
+ // 8.9.7. Resolve promise with true.
+ promise->resolve<IDLBoolean>(true);
+ });
+ });
+ });
+
+ // 9. Return promise.
+}
+
+void MediaKeySession::update(const BufferSource& response, Ref<DeferredPromise>&& promise)
+{
+ // https://w3c.github.io/encrypted-media/#dom-mediakeysession-update
+ // W3C Editor's Draft 09 November 2016
+
+ // When this method is invoked, the user agent must run the following steps:
+ // 1. If this object is closed, return a promise rejected with an InvalidStateError.
+ // 2. If this object's callable value is false, return a promise rejected with an InvalidStateError.
+ if (m_closed || !m_callable) {
+ promise->reject(INVALID_STATE_ERR);
+ return;
+ }
+
+ // 3. If response is an empty array, return a promise rejected with a newly created TypeError.
+ if (!response.length()) {
+ promise->reject(TypeError);
+ return;
+ }
+
+ // 4. Let response copy be a copy of the contents of the response parameter.
+ // 5. Let promise be a new promise.
+ // 6. Run the following steps in parallel:
+ m_taskQueue.enqueueTask([this, response = SharedBuffer::create(response.data(), response.length()), promise = WTFMove(promise)] () mutable {
+ // 6.1. Let sanitized response be a validated and/or sanitized version of response copy.
+ RefPtr<SharedBuffer> sanitizedResponse = m_implementation->sanitizeResponse(response);
+
+ // 6.2. If the preceding step failed, or if sanitized response is empty, reject promise with a newly created TypeError.
+ if (!sanitizedResponse || sanitizedResponse->isEmpty()) {
+ promise->reject(TypeError);
+ return;
+ }
+
+ // 6.3. Let message be null.
+ // 6.4. Let message type be null.
+ // 6.5. Let session closed be false.
+ // 6.6. Let cdm be the CDM instance represented by this object's cdm instance value.
+ // 6.7. Use the cdm to execute the following steps:
+ m_instance->updateLicense(m_sessionId, m_sessionType, *sanitizedResponse, [this, weakThis = m_weakPtrFactory.createWeakPtr(), promise = WTFMove(promise)] (bool sessionWasClosed, std::optional<CDMInstance::KeyStatusVector>&& changedKeys, std::optional<double>&& changedExpiration, std::optional<CDMInstance::Message>&& message, CDMInstance::SuccessValue succeeded) mutable {
+ if (!weakThis)
+ return;
+
+ // 6.7.1. If the format of sanitized response is invalid in any way, reject promise with a newly created TypeError.
+ // 6.7.2. Process sanitized response, following the stipulation for the first matching condition from the following list:
+ // ↳ If sanitized response contains a license or key(s)
+ // Process sanitized response, following the stipulation for the first matching condition from the following list:
+ // ↳ If sessionType is "temporary" and sanitized response does not specify that session data, including any license, key(s), or similar session data it contains, should be stored
+ // Process sanitized response, not storing any session data.
+ // ↳ If sessionType is "persistent-license" and sanitized response contains a persistable license
+ // Process sanitized response, storing the license/key(s) and related session data contained in sanitized response. Such data must be stored such that only the origin of this object's Document can access it.
+ // ↳ If sessionType is "persistent-usage-record" and sanitized response contains a non-persistable license
+ // Run the following steps:
+ // 6.7.2.3.1. Process sanitized response, not storing any session data.
+ // 6.7.2.3.2. If processing sanitized response results in the addition of keys to the set of known keys, add the key IDs of these keys to this object's record of key usage.
+ // ↳ Otherwise
+ // Reject promise with a newly created TypeError.
+ // ↳ If sanitized response contains a record of license destruction acknowledgement and sessionType is "persistent-license"
+ // Run the following steps:
+ // 6.7.2.1. Close the key session and clear all stored session data associated with this object, including the sessionId and record of license destruction.
+ // 6.7.2.2. Set session closed to true.
+ // ↳ Otherwise
+ // Process sanitized response, not storing any session data.
+ // NOTE: Steps 6.7.1. and 6.7.2. should be implemented in CDMInstance.
+
+ if (succeeded == CDMInstance::SuccessValue::Failed) {
+ promise->reject(TypeError);
+ return;
+ }
+
+ // 6.7.3. If a message needs to be sent to the server, execute the following steps:
+ // 6.7.3.1. Let message be that message.
+ // 6.7.3.2. Let message type be the appropriate MediaKeyMessageType for the message.
+ // 6.8. Queue a task to run the following steps:
+ m_taskQueue.enqueueTask([this, sessionWasClosed, changedKeys = WTFMove(changedKeys), changedExpiration = WTFMove(changedExpiration), message = WTFMove(message), promise = WTFMove(promise)] () mutable {
+ // 6.8.1.
+ if (sessionWasClosed) {
+ // ↳ If session closed is true:
+ // Run the Session Closed algorithm on this object.
+ sessionClosed();
+ } else {
+ // ↳ Otherwise:
+ // Run the following steps:
+ // 6.8.1.1. If the set of keys known to the CDM for this object changed or the status of any key(s) changed, run the Update Key Statuses
+ // algorithm on the session, providing each known key's key ID along with the appropriate MediaKeyStatus. Should additional
+ // processing be necessary to determine with certainty the status of a key, use "status-pending". Once the additional processing
+ // for one or more keys has completed, run the Update Key Statuses algorithm again with the actual status(es).
+ if (changedKeys)
+ updateKeyStatuses(WTFMove(*changedKeys));
+
+ // 6.8.1.2. If the expiration time for the session changed, run the Update Expiration algorithm on the session, providing the new expiration time.
+ if (changedExpiration)
+ updateExpiration(*changedExpiration);
+
+ // 6.8.1.3. If any of the preceding steps failed, reject promise with a new DOMException whose name is the appropriate error name.
+ // FIXME: At this point the implementations of preceding steps can't fail.
+
+ // 6.8.1.4. If message is not null, run the Queue a "message" Event algorithm on the session, providing message type and message.
+ if (message) {
+ MediaKeyMessageType messageType;
+ switch (message->first) {
+ case CDMInstance::MessageType::LicenseRequest:
+ messageType = MediaKeyMessageType::LicenseRequest;
+ break;
+ case CDMInstance::MessageType::LicenseRenewal:
+ messageType = MediaKeyMessageType::LicenseRenewal;
+ break;
+ case CDMInstance::MessageType::LicenseRelease:
+ messageType = MediaKeyMessageType::LicenseRelease;
+ break;
+ case CDMInstance::MessageType::IndividualizationRequest:
+ messageType = MediaKeyMessageType::IndividualizationRequest;
+ break;
+ }
+
+ enqueueMessage(messageType, WTFMove(message->second));
+ }
+ }
+
+ // 6.8.2. Resolve promise.
+ promise->resolve();
+ });
+ });
+ });
+
+ // 7. Return promise.
+}
+
+void MediaKeySession::close(Ref<DeferredPromise>&& promise)
+{
+ // https://w3c.github.io/encrypted-media/#dom-mediakeysession-close
+ // W3C Editor's Draft 09 November 2016
+
+ // 1. Let session be the associated MediaKeySession object.
+ // 2. If session is closed, return a resolved promise.
+ if (m_closed) {
+ promise->resolve();
+ return;
+ }
+
+ // 3. If session's callable value is false, return a promise rejected with an InvalidStateError.
+ if (!m_callable) {
+ promise->reject(INVALID_STATE_ERR);
+ return;
+ }
+
+ // 4. Let promise be a new promise.
+ // 5. Run the following steps in parallel:
+ m_taskQueue.enqueueTask([this, promise = WTFMove(promise)] () mutable {
+ // 5.1. Let cdm be the CDM instance represented by session's cdm instance value.
+ // 5.2. Use cdm to close the key session associated with session.
+ m_instance->closeSession(m_sessionId, [this, weakThis = m_weakPtrFactory.createWeakPtr(), promise = WTFMove(promise)] () mutable {
+ if (!weakThis)
+ return;
+
+ // 5.3. Queue a task to run the following steps:
+ m_taskQueue.enqueueTask([this, promise = WTFMove(promise)] () mutable {
+ // 5.3.1. Run the Session Closed algorithm on the session.
+ sessionClosed();
+
+ // 5.3.2. Resolve promise.
+ promise->resolve();
+ });
+ });
+ });
+
+ // 6. Return promise.
+}
+
+void MediaKeySession::remove(Ref<DeferredPromise>&& promise)
+{
+ // https://w3c.github.io/encrypted-media/#dom-mediakeysession-remove
+ // W3C Editor's Draft 09 November 2016
+
+ // 1. If this object is closed, return a promise rejected with an InvalidStateError.
+ // 2. If this object's callable value is false, return a promise rejected with an InvalidStateError.
+ if (m_closed || !m_callable) {
+ promise->reject(INVALID_STATE_ERR);
+ return;
+ }
+
+ // 3. Let promise be a new promise.
+ // 4. Run the following steps in parallel:
+ m_taskQueue.enqueueTask([this, promise = WTFMove(promise)] () mutable {
+ // 4.1. Let cdm be the CDM instance represented by this object's cdm instance value.
+ // 4.2. Let message be null.
+ // 4.3. Let message type be null.
+
+ // 4.4. Use the cdm to execute the following steps:
+ m_instance->removeSessionData(m_sessionId, m_sessionType, [this, weakThis = m_weakPtrFactory.createWeakPtr(), promise = WTFMove(promise)] (CDMInstance::KeyStatusVector&& keys, std::optional<Ref<SharedBuffer>>&& message, CDMInstance::SuccessValue succeeded) mutable {
+ if (!weakThis)
+ return;
+
+ // 4.4.1. If any license(s) and/or key(s) are associated with the session:
+ // 4.4.1.1. Destroy the license(s) and/or key(s) associated with the session.
+ // 4.4.1.2. Follow the steps for the value of this object's session type from the following list:
+ // ↳ "temporary"
+ // 4.4.1.2.1.1 Continue with the following steps.
+ // ↳ "persistent-license"
+ // 4.4.1.2.2.1. Let record of license destruction be a record of license destruction for the license represented by this object.
+ // 4.4.1.2.2.2. Store the record of license destruction.
+ // 4.4.1.2.2.3. Let message be a message containing or reflecting the record of license destruction.
+ // ↳ "persistent-usage-record"
+ // 4.4.1.2.3.1. Store this object's record of key usage.
+ // 4.4.1.2.3.2. Let message be a message containing or reflecting this object's record of key usage.
+ // NOTE: Step 4.4.1. should be implemented in CDMInstance.
+
+ // 4.5. Queue a task to run the following steps:
+ m_taskQueue.enqueueTask([this, keys = WTFMove(keys), message = WTFMove(message), succeeded, promise = WTFMove(promise)] () mutable {
+ // 4.5.1. Run the Update Key Statuses algorithm on the session, providing all key ID(s) in the session along with the "released" MediaKeyStatus value for each.
+ updateKeyStatuses(WTFMove(keys));
+
+ // 4.5.2. Run the Update Expiration algorithm on the session, providing NaN.
+ updateExpiration(std::numeric_limits<double>::quiet_NaN());
+
+ // 4.5.3. If any of the preceding steps failed, reject promise with a new DOMException whose name is the appropriate error name.
+ if (succeeded == CDMInstance::SuccessValue::Failed) {
+ promise->reject(NOT_SUPPORTED_ERR);
+ return;
+ }
+
+ // 4.5.4. Let message type be "license-release".
+ // 4.5.5. If message is not null, run the Queue a "message" Event algorithm on the session, providing message type and message.
+ if (message)
+ enqueueMessage(MediaKeyMessageType::LicenseRelease, *message);
+
+ // 4.5.6. Resolve promise.
+ promise->resolve();
+ });
+ });
+ });
+
+ // 5. Return promise.
+}
+
+void MediaKeySession::registerClosedPromise(ClosedPromise&& promise)
+{
+ ASSERT(!m_closedPromise);
+ if (m_closed) {
+ promise.resolve();
+ return;
+ }
+ m_closedPromise = WTFMove(promise);
+}
+
+void MediaKeySession::enqueueMessage(MediaKeyMessageType messageType, const SharedBuffer& message)
+{
+ // 6.4.1 Queue a "message" Event
+ // https://w3c.github.io/encrypted-media/#queue-message
+ // W3C Editor's Draft 09 November 2016
+
+ // The following steps are run:
+ // 1. Let the session be the specified MediaKeySession object.
+ // 2. Queue a task to create an event named message that does not bubble and is not cancellable using the MediaKeyMessageEvent
+ // interface with its type attribute set to message and its isTrusted attribute initialized to true, and dispatch it at the
+ // session.
+ auto messageEvent = MediaKeyMessageEvent::create(eventNames().messageEvent, {messageType, message.createArrayBuffer()}, Event::IsTrusted::Yes);
+ m_eventQueue.enqueueEvent(WTFMove(messageEvent));
+}
+
+void MediaKeySession::updateKeyStatuses(CDMInstance::KeyStatusVector&& inputStatuses)
+{
+ // https://w3c.github.io/encrypted-media/#update-key-statuses
+ // W3C Editor's Draft 09 November 2016
+
+ // 1. Let the session be the associated MediaKeySession object.
+ // 2. Let the input statuses be the sequence of pairs key ID and associated MediaKeyStatus pairs.
+ // 3. Let the statuses be session's keyStatuses attribute.
+ // 4. Run the following steps to replace the contents of statuses:
+ // 4.1. Empty statuses.
+ // 4.2. For each pair in input statuses.
+ // 4.2.1. Let pair be the pair.
+ // 4.2.2. Insert an entry for pair's key ID into statuses with the value of pair's MediaKeyStatus value.
+
+ static auto toMediaKeyStatus = [] (CDMInstance::KeyStatus status) -> MediaKeyStatus {
+ switch (status) {
+ case CDMInstance::KeyStatus::Usable:
+ return MediaKeyStatus::Usable;
+ case CDMInstance::KeyStatus::Expired:
+ return MediaKeyStatus::Expired;
+ case CDMInstance::KeyStatus::Released:
+ return MediaKeyStatus::Released;
+ case CDMInstance::KeyStatus::OutputRestricted:
+ return MediaKeyStatus::OutputRestricted;
+ case CDMInstance::KeyStatus::OutputDownscaled:
+ return MediaKeyStatus::OutputDownscaled;
+ case CDMInstance::KeyStatus::StatusPending:
+ return MediaKeyStatus::StatusPending;
+ case CDMInstance::KeyStatus::InternalError:
+ return MediaKeyStatus::InternalError;
+ };
+ };
+
+ m_statuses.clear();
+ m_statuses.reserveCapacity(inputStatuses.size());
+ for (auto& status : inputStatuses)
+ m_statuses.uncheckedAppend({ WTFMove(status.first), toMediaKeyStatus(status.second) });
+
+ // 5. Queue a task to fire a simple event named keystatuseschange at the session.
+ m_eventQueue.enqueueEvent(Event::create(eventNames().keystatuseschangeEvent, false, false));
+
+ // 6. Queue a task to run the Attempt to Resume Playback If Necessary algorithm on each of the media element(s) whose mediaKeys attribute is the MediaKeys object that created the session.
+ // FIXME: Implement.
+}
+
+void MediaKeySession::updateExpiration(double)
+{
+ notImplemented();
+}
+
+void MediaKeySession::sessionClosed()
+{
+ // https://w3c.github.io/encrypted-media/#session-closed
+ // W3C Editor's Draft 09 November 2016
+
+ // 1. Let session be the associated MediaKeySession object.
+ // 2. If session's session type is "persistent-usage-record", execute the following steps in parallel:
+ if (m_sessionType == MediaKeySessionType::PersistentUsageRecord) {
+ // 2.1. Let cdm be the CDM instance represented by session's cdm instance value.
+ // 2.2. Use cdm to store session's record of key usage, if it exists.
+ m_instance->storeRecordOfKeyUsage(m_sessionId);
+ }
+
+ // 3. Run the Update Key Statuses algorithm on the session, providing an empty sequence.
+ updateKeyStatuses({ });
+
+ // 4. Run the Update Expiration algorithm on the session, providing NaN.
+ updateExpiration(std::numeric_limits<double>::quiet_NaN());
+
+ // Let's consider the session closed before any promise on the 'closed' attribute is resolved.
+ m_closed = true;
+
+ // 5. Let promise be the closed attribute of the session.
+ // 6. Resolve promise.
+ if (m_closedPromise)
+ m_closedPromise->resolve();
+}
+
+bool MediaKeySession::hasPendingActivity() const
+{
+ notImplemented();
+ return false;
+}
+
+const char* MediaKeySession::activeDOMObjectName() const
+{
+ notImplemented();
+ return "MediaKeySession";
+}
+
+bool MediaKeySession::canSuspendForDocumentSuspension() const
+{
+ notImplemented();
+ return false;
+}
+
+void MediaKeySession::stop()
+{
+ notImplemented();
+}
+
+} // namespace WebCore
+
+#endif
diff --git a/Source/WebCore/Modules/encryptedmedia/MediaKeySession.h b/Source/WebCore/Modules/encryptedmedia/MediaKeySession.h
new file mode 100644
index 000000000..0ce875d89
--- /dev/null
+++ b/Source/WebCore/Modules/encryptedmedia/MediaKeySession.h
@@ -0,0 +1,119 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#if ENABLE(ENCRYPTED_MEDIA)
+
+#include "ActiveDOMObject.h"
+#include "CDMInstance.h"
+#include "EventTarget.h"
+#include "GenericEventQueue.h"
+#include "GenericTaskQueue.h"
+#include "JSDOMPromise.h"
+#include "MediaKeyMessageType.h"
+#include "MediaKeySessionType.h"
+#include "MediaKeyStatus.h"
+#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
+#include <wtf/WeakPtr.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class BufferSource;
+class CDM;
+class MediaKeyStatusMap;
+class MediaKeys;
+class SharedBuffer;
+
+class MediaKeySession final : public RefCounted<MediaKeySession>, public EventTargetWithInlineData, public ActiveDOMObject {
+public:
+ static Ref<MediaKeySession> create(ScriptExecutionContext&, MediaKeySessionType, bool useDistinctiveIdentifier, Ref<CDM>&&, Ref<CDMInstance>&&);
+ virtual ~MediaKeySession();
+
+ using RefCounted<MediaKeySession>::ref;
+ using RefCounted<MediaKeySession>::deref;
+
+ const String& sessionId() const;
+ double expiration() const;
+ Ref<MediaKeyStatusMap> keyStatuses() const;
+
+ void generateRequest(const AtomicString&, const BufferSource&, Ref<DeferredPromise>&&);
+ void load(const String&, Ref<DeferredPromise>&&);
+ void update(const BufferSource&, Ref<DeferredPromise>&&);
+ void close(Ref<DeferredPromise>&&);
+ void remove(Ref<DeferredPromise>&&);
+
+ using ClosedPromise = DOMPromise<void>;
+ void registerClosedPromise(ClosedPromise&&);
+
+ const Vector<std::pair<Ref<SharedBuffer>, MediaKeyStatus>>& statuses() const { return m_statuses; }
+
+private:
+ MediaKeySession(ScriptExecutionContext&, MediaKeySessionType, bool useDistinctiveIdentifier, Ref<CDM>&&, Ref<CDMInstance>&&);
+ void enqueueMessage(MediaKeyMessageType, const SharedBuffer&);
+ void updateKeyStatuses(CDMInstance::KeyStatusVector&&);
+ void updateExpiration(double);
+ void sessionClosed();
+
+ // EventTarget
+ EventTargetInterface eventTargetInterface() const override { return MediaKeySessionEventTargetInterfaceType; }
+ ScriptExecutionContext* scriptExecutionContext() const override { return ActiveDOMObject::scriptExecutionContext(); }
+ void refEventTarget() override { ref(); }
+ void derefEventTarget() override { deref(); }
+
+ // ActiveDOMObject
+ bool hasPendingActivity() const override;
+ const char* activeDOMObjectName() const override;
+ bool canSuspendForDocumentSuspension() const override;
+ void stop() override;
+
+ String m_sessionId;
+ double m_expiration;
+ std::optional<ClosedPromise> m_closedPromise;
+ Ref<MediaKeyStatusMap> m_keyStatuses;
+ bool m_closed { false };
+ bool m_uninitialized { true };
+ bool m_callable { false };
+ bool m_useDistinctiveIdentifier;
+ MediaKeySessionType m_sessionType;
+ Ref<CDM> m_implementation;
+ Ref<CDMInstance> m_instance;
+ GenericEventQueue m_eventQueue;
+ GenericTaskQueue<Timer> m_taskQueue;
+ Vector<Ref<SharedBuffer>> m_recordOfKeyUsage;
+ double m_firstDecryptTime { 0 };
+ double m_latestDecryptTime { 0 };
+ Vector<std::pair<Ref<SharedBuffer>, MediaKeyStatus>> m_statuses;
+ WeakPtrFactory<MediaKeySession> m_weakPtrFactory;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(ENCRYPTED_MEDIA)
diff --git a/Source/WebCore/Modules/encryptedmedia/MediaKeySession.idl b/Source/WebCore/Modules/encryptedmedia/MediaKeySession.idl
new file mode 100644
index 000000000..52223a8b8
--- /dev/null
+++ b/Source/WebCore/Modules/encryptedmedia/MediaKeySession.idl
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+[
+ Conditional=ENCRYPTED_MEDIA,
+ EnabledAtRuntime=EncryptedMediaAPI
+] interface MediaKeySession : EventTarget {
+ readonly attribute DOMString sessionId;
+ readonly attribute unrestricted double expiration;
+ [CustomGetter, CachedAttribute] readonly attribute Promise<void> closed;
+ readonly attribute MediaKeyStatusMap keyStatuses;
+ attribute EventHandler onkeystatuseschange;
+ attribute EventHandler onmessage;
+ Promise<void> generateRequest(DOMString initDataType, BufferSource initData);
+ Promise<bool> load(DOMString sessionId);
+ Promise<void> update(BufferSource response);
+ Promise<void> close();
+ Promise<void> remove();
+};
diff --git a/Source/WebCore/Modules/encryptedmedia/MediaKeySessionType.h b/Source/WebCore/Modules/encryptedmedia/MediaKeySessionType.h
new file mode 100644
index 000000000..f31c87c1a
--- /dev/null
+++ b/Source/WebCore/Modules/encryptedmedia/MediaKeySessionType.h
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#if ENABLE(ENCRYPTED_MEDIA)
+
+namespace WebCore {
+
+enum class MediaKeySessionType {
+ Temporary,
+ PersistentUsageRecord,
+ PersistentLicense
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(ENCRYPTED_MEDIA)
diff --git a/Source/WebCore/Modules/encryptedmedia/MediaKeySessionType.idl b/Source/WebCore/Modules/encryptedmedia/MediaKeySessionType.idl
new file mode 100644
index 000000000..a92e8f6ad
--- /dev/null
+++ b/Source/WebCore/Modules/encryptedmedia/MediaKeySessionType.idl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+[
+ Conditional=ENCRYPTED_MEDIA,
+ ImplementedAs=MediaKeySessionType,
+ ExportMacro=WEBCORE_TESTSUPPORT_EXPORT
+]
+enum MediaKeySessionType {
+ "temporary",
+ "persistent-usage-record",
+ "persistent-license"
+};
diff --git a/Source/WebCore/Modules/encryptedmedia/MediaKeyStatus.h b/Source/WebCore/Modules/encryptedmedia/MediaKeyStatus.h
new file mode 100644
index 000000000..c3cf4c897
--- /dev/null
+++ b/Source/WebCore/Modules/encryptedmedia/MediaKeyStatus.h
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#if ENABLE(ENCRYPTED_MEDIA)
+
+namespace WebCore {
+
+enum class MediaKeyStatus {
+ Usable,
+ Expired,
+ Released,
+ OutputRestricted,
+ OutputDownscaled,
+ StatusPending,
+ InternalError
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(ENCRYPTED_MEDIA)
diff --git a/Source/WebCore/Modules/encryptedmedia/MediaKeyStatusMap.cpp b/Source/WebCore/Modules/encryptedmedia/MediaKeyStatusMap.cpp
new file mode 100644
index 000000000..fc0451eed
--- /dev/null
+++ b/Source/WebCore/Modules/encryptedmedia/MediaKeyStatusMap.cpp
@@ -0,0 +1,112 @@
+/*
+ * 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 "MediaKeyStatusMap.h"
+
+#if ENABLE(ENCRYPTED_MEDIA)
+
+#include "JSMediaKeyStatusMap.h"
+#include "MediaKeySession.h"
+#include "SharedBuffer.h"
+
+namespace WebCore {
+
+MediaKeyStatusMap::MediaKeyStatusMap(const MediaKeySession& session)
+ : m_session(&session)
+{
+}
+
+MediaKeyStatusMap::~MediaKeyStatusMap() = default;
+
+void MediaKeyStatusMap::detachSession()
+{
+ m_session = nullptr;
+}
+
+unsigned long MediaKeyStatusMap::size()
+{
+ if (!m_session)
+ return 0;
+ return m_session->statuses().size();
+}
+
+static bool keyIdsMatch(const SharedBuffer& a, const BufferSource& b)
+{
+ auto length = a.size();
+ if (!length || length != b.length())
+ return false;
+ return !std::memcmp(a.data(), b.data(), length);
+}
+
+bool MediaKeyStatusMap::has(const BufferSource& keyId)
+{
+ if (!m_session)
+ return false;
+
+ auto& statuses = m_session->statuses();
+ return std::any_of(statuses.begin(), statuses.end(),
+ [&keyId] (auto& it) { return keyIdsMatch(it.first, keyId); });
+}
+
+JSC::JSValue MediaKeyStatusMap::get(JSC::ExecState& state, const BufferSource& keyId)
+{
+ if (!m_session)
+ return JSC::jsUndefined();
+
+ auto& statuses = m_session->statuses();
+ auto it = std::find_if(statuses.begin(), statuses.end(),
+ [&keyId] (auto& it) { return keyIdsMatch(it.first, keyId); });
+
+ if (it == statuses.end())
+ return JSC::jsUndefined();
+ return convertEnumerationToJS(state, it->second);
+}
+
+MediaKeyStatusMap::Iterator::Iterator(MediaKeyStatusMap& map)
+ : m_map(map)
+{
+}
+
+std::optional<WTF::KeyValuePair<BufferSource::VariantType, MediaKeyStatus>> MediaKeyStatusMap::Iterator::next()
+{
+ if (!m_map->m_session)
+ return std::nullopt;
+
+ auto& statuses = m_map->m_session->statuses();
+ if (m_index >= statuses.size())
+ return std::nullopt;
+
+ auto& pair = statuses[m_index++];
+ auto buffer = ArrayBuffer::create(pair.first->data(), pair.first->size());
+ return WTF::KeyValuePair<BufferSource::VariantType, MediaKeyStatus> { RefPtr<ArrayBuffer>(WTFMove(buffer)), pair.second };
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(ENCRYPTED_MEDIA)
diff --git a/Source/WebCore/Modules/encryptedmedia/MediaKeyStatusMap.h b/Source/WebCore/Modules/encryptedmedia/MediaKeyStatusMap.h
new file mode 100644
index 000000000..34c5ed795
--- /dev/null
+++ b/Source/WebCore/Modules/encryptedmedia/MediaKeyStatusMap.h
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#if ENABLE(ENCRYPTED_MEDIA)
+
+#include "BufferSource.h"
+#include "MediaKeyStatus.h"
+#include <runtime/JSCJSValueInlines.h>
+#include <wtf/Optional.h>
+#include <wtf/Ref.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class MediaKeySession;
+class SharedBuffer;
+
+class MediaKeyStatusMap : public RefCounted<MediaKeyStatusMap> {
+public:
+ using Status = MediaKeyStatus;
+
+ static Ref<MediaKeyStatusMap> create(const MediaKeySession& session)
+ {
+ return adoptRef(*new MediaKeyStatusMap(session));
+ }
+
+ virtual ~MediaKeyStatusMap();
+
+ void detachSession();
+
+ unsigned long size();
+ bool has(const BufferSource&);
+ JSC::JSValue get(JSC::ExecState&, const BufferSource&);
+
+ class Iterator {
+ public:
+ explicit Iterator(MediaKeyStatusMap&);
+ std::optional<WTF::KeyValuePair<BufferSource::VariantType, MediaKeyStatus>> next();
+
+ private:
+ Ref<MediaKeyStatusMap> m_map;
+ size_t m_index { 0 };
+ };
+ Iterator createIterator() { return Iterator(*this); }
+
+private:
+ MediaKeyStatusMap(const MediaKeySession&);
+
+ const MediaKeySession* m_session;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(ENCRYPTED_MEDIA)
diff --git a/Source/WebCore/Modules/encryptedmedia/MediaKeyStatusMap.idl b/Source/WebCore/Modules/encryptedmedia/MediaKeyStatusMap.idl
new file mode 100644
index 000000000..b3215ae83
--- /dev/null
+++ b/Source/WebCore/Modules/encryptedmedia/MediaKeyStatusMap.idl
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+enum MediaKeyStatus {
+ "usable",
+ "expired",
+ "released",
+ "output-restricted",
+ "output-downscaled",
+ "status-pending",
+ "internal-error"
+};
+
+[
+ Conditional=ENCRYPTED_MEDIA,
+ EnabledAtRuntime=EncryptedMediaAPI
+] interface MediaKeyStatusMap {
+ iterable<BufferSource, MediaKeyStatus>;
+ readonly attribute unsigned long size;
+ boolean has(BufferSource keyId);
+ [CallWith=ScriptState] any get(BufferSource keyId);
+};
diff --git a/Source/WebCore/Modules/encryptedmedia/MediaKeySystemAccess.cpp b/Source/WebCore/Modules/encryptedmedia/MediaKeySystemAccess.cpp
new file mode 100644
index 000000000..d84a48d06
--- /dev/null
+++ b/Source/WebCore/Modules/encryptedmedia/MediaKeySystemAccess.cpp
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2016 Metrological Group B.V.
+ * Copyright (C) 2016 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "MediaKeySystemAccess.h"
+
+#if ENABLE(ENCRYPTED_MEDIA)
+
+#include "CDM.h"
+#include "CDMInstance.h"
+#include "JSMediaKeys.h"
+#include "MediaKeySystemConfiguration.h"
+#include "MediaKeys.h"
+
+namespace WebCore {
+
+Ref<MediaKeySystemAccess> MediaKeySystemAccess::create(const String& keySystem, MediaKeySystemConfiguration&& configuration, Ref<CDM>&& implementation)
+{
+ return adoptRef(*new MediaKeySystemAccess(keySystem, WTFMove(configuration), WTFMove(implementation)));
+}
+
+MediaKeySystemAccess::MediaKeySystemAccess(const String& keySystem, MediaKeySystemConfiguration&& configuration, Ref<CDM>&& implementation)
+ : m_keySystem(keySystem)
+ , m_configuration(new MediaKeySystemConfiguration(WTFMove(configuration)))
+ , m_implementation(WTFMove(implementation))
+{
+}
+
+MediaKeySystemAccess::~MediaKeySystemAccess() = default;
+
+void MediaKeySystemAccess::createMediaKeys(Ref<DeferredPromise>&& promise)
+{
+ // https://w3c.github.io/encrypted-media/#dom-mediakeysystemaccess-createmediakeys
+ // W3C Editor's Draft 09 November 2016
+
+ // When this method is invoked, the user agent must run the following steps:
+ // 1. Let promise be a new promise.
+ // 2. Run the following steps in parallel:
+ m_taskQueue.enqueueTask([this, promise = WTFMove(promise)] () mutable {
+ // 2.1. Let configuration be the value of this object's configuration value.
+ // 2.2. Let use distinctive identifier be true if the value of configuration's distinctiveIdentifier member is "required" and false otherwise.
+ bool useDistinctiveIdentifier = m_configuration->distinctiveIdentifier == MediaKeysRequirement::Required;
+
+ // 2.3. Let persistent state allowed be true if the value of configuration's persistentState member is "required" and false otherwise.
+ bool persistentStateAllowed = m_configuration->persistentState == MediaKeysRequirement::Required;
+
+ // 2.4. Load and initialize the Key System implementation represented by this object's cdm implementation value if necessary.
+ m_implementation->loadAndInitialize();
+
+ // 2.5. Let instance be a new instance of the Key System implementation represented by this object's cdm implementation value.
+ auto instance = m_implementation->createInstance();
+ if (!instance) {
+ promise->reject(INVALID_STATE_ERR);
+ return;
+ }
+
+ // 2.6. Initialize instance to enable, disable and/or select Key System features using configuration.
+ if (instance->initializeWithConfiguration(*m_configuration) == CDMInstance::Failed) {
+ promise->reject(NotAllowedError);
+ return;
+ }
+
+ // 2.7. If use distinctive identifier is false, prevent instance from using Distinctive Identifier(s) and Distinctive Permanent Identifier(s).
+ if (!useDistinctiveIdentifier && instance->setDistinctiveIdentifiersAllowed(false) == CDMInstance::Failed) {
+ promise->reject(NotAllowedError);
+ return;
+ }
+
+ // 2.8. If persistent state allowed is false, prevent instance from persisting any state related to the application or origin of this object's Document.
+ if (!persistentStateAllowed && instance->setPersistentStateAllowed(false) == CDMInstance::Failed) {
+ promise->reject(NotAllowedError);
+ return;
+ }
+
+ // 2.9. If any of the preceding steps failed, reject promise with a new DOMException whose name is the appropriate error name.
+ // 2.10. Let media keys be a new MediaKeys object, and initialize it as follows:
+ // 2.10.1. Let the use distinctive identifier value be use distinctive identifier.
+ // 2.10.2. Let the persistent state allowed value be persistent state allowed.
+ // 2.10.3. Let the supported session types value be be the value of configuration's sessionTypes member.
+ // 2.10.4. Let the cdm implementation value be this object's cdm implementation value.
+ // 2.10.5. Let the cdm instance value be instance.
+ auto mediaKeys = MediaKeys::create(useDistinctiveIdentifier, persistentStateAllowed, m_configuration->sessionTypes, m_implementation.copyRef(), instance.releaseNonNull());
+
+ // 2.11. Resolve promise with media keys.
+ promise->resolveWithNewlyCreated<IDLInterface<MediaKeys>>(WTFMove(mediaKeys));
+ });
+
+ // 3. Return promise.
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(ENCRYPTED_MEDIA)
diff --git a/Source/WebCore/Modules/encryptedmedia/MediaKeySystemAccess.h b/Source/WebCore/Modules/encryptedmedia/MediaKeySystemAccess.h
new file mode 100644
index 000000000..a113e2601
--- /dev/null
+++ b/Source/WebCore/Modules/encryptedmedia/MediaKeySystemAccess.h
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#if ENABLE(ENCRYPTED_MEDIA)
+
+#include "GenericTaskQueue.h"
+#include "JSDOMPromise.h"
+#include <wtf/RefCounted.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class CDM;
+class MediaKeys;
+
+struct MediaKeySystemConfiguration;
+
+class MediaKeySystemAccess : public RefCounted<MediaKeySystemAccess> {
+public:
+ static Ref<MediaKeySystemAccess> create(const String& keySystem, MediaKeySystemConfiguration&&, Ref<CDM>&&);
+ ~MediaKeySystemAccess();
+
+ const String& keySystem() const { return m_keySystem; }
+ const MediaKeySystemConfiguration& getConfiguration() const { return *m_configuration; }
+ void createMediaKeys(Ref<DeferredPromise>&&);
+
+private:
+ MediaKeySystemAccess(const String& keySystem, MediaKeySystemConfiguration&&, Ref<CDM>&&);
+
+ String m_keySystem;
+ std::unique_ptr<MediaKeySystemConfiguration> m_configuration;
+ Ref<CDM> m_implementation;
+ GenericTaskQueue<Timer> m_taskQueue;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(ENCRYPTED_MEDIA)
diff --git a/Source/WebCore/Modules/encryptedmedia/MediaKeySystemAccess.idl b/Source/WebCore/Modules/encryptedmedia/MediaKeySystemAccess.idl
new file mode 100644
index 000000000..30a825e15
--- /dev/null
+++ b/Source/WebCore/Modules/encryptedmedia/MediaKeySystemAccess.idl
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+[
+ Conditional=ENCRYPTED_MEDIA,
+ EnabledAtRuntime=EncryptedMediaAPI,
+ ImplementationLacksVTable,
+] interface MediaKeySystemAccess {
+ readonly attribute DOMString keySystem;
+ MediaKeySystemConfiguration getConfiguration();
+ Promise<MediaKeys> createMediaKeys();
+};
diff --git a/Source/WebCore/Modules/encryptedmedia/MediaKeySystemConfiguration.h b/Source/WebCore/Modules/encryptedmedia/MediaKeySystemConfiguration.h
new file mode 100644
index 000000000..7f358fd9d
--- /dev/null
+++ b/Source/WebCore/Modules/encryptedmedia/MediaKeySystemConfiguration.h
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#if ENABLE(ENCRYPTED_MEDIA)
+
+#include "MediaKeySessionType.h"
+#include "MediaKeySystemMediaCapability.h"
+#include "MediaKeysRequirement.h"
+#include <wtf/Vector.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+struct MediaKeySystemConfiguration {
+ using KeysRequirement = MediaKeysRequirement;
+
+ String label;
+ Vector<String> initDataTypes;
+ Vector<MediaKeySystemMediaCapability> audioCapabilities;
+ Vector<MediaKeySystemMediaCapability> videoCapabilities;
+ MediaKeysRequirement distinctiveIdentifier;
+ MediaKeysRequirement persistentState;
+ Vector<MediaKeySessionType> sessionTypes;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(ENCRYPTED_MEDIA)
diff --git a/Source/WebCore/Modules/encryptedmedia/MediaKeySystemConfiguration.idl b/Source/WebCore/Modules/encryptedmedia/MediaKeySystemConfiguration.idl
new file mode 100644
index 000000000..466cc800f
--- /dev/null
+++ b/Source/WebCore/Modules/encryptedmedia/MediaKeySystemConfiguration.idl
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+[
+ Conditional=ENCRYPTED_MEDIA,
+ JSGenerateToJSObject
+] dictionary MediaKeySystemConfiguration {
+ DOMString label = "";
+ sequence<DOMString> initDataTypes = [];
+ sequence<MediaKeySystemMediaCapability> audioCapabilities = [];
+ sequence<MediaKeySystemMediaCapability> videoCapabilities = [];
+ MediaKeysRequirement distinctiveIdentifier = "optional";
+ MediaKeysRequirement persistentState = "optional";
+ sequence<MediaKeySessionType> sessionTypes;
+};
diff --git a/Source/WebCore/Modules/encryptedmedia/MediaKeySystemMediaCapability.h b/Source/WebCore/Modules/encryptedmedia/MediaKeySystemMediaCapability.h
new file mode 100644
index 000000000..ba7200542
--- /dev/null
+++ b/Source/WebCore/Modules/encryptedmedia/MediaKeySystemMediaCapability.h
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#if ENABLE(ENCRYPTED_MEDIA)
+
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+struct MediaKeySystemMediaCapability {
+ String contentType;
+ String robustness;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(ENCRYPTED_MEDIA)
diff --git a/Source/WebCore/Modules/encryptedmedia/MediaKeySystemMediaCapability.idl b/Source/WebCore/Modules/encryptedmedia/MediaKeySystemMediaCapability.idl
new file mode 100644
index 000000000..3204794da
--- /dev/null
+++ b/Source/WebCore/Modules/encryptedmedia/MediaKeySystemMediaCapability.idl
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+[
+ Conditional=ENCRYPTED_MEDIA,
+ JSGenerateToJSObject,
+] dictionary MediaKeySystemMediaCapability {
+ DOMString contentType = "";
+ DOMString robustness = "";
+};
diff --git a/Source/WebCore/Modules/encryptedmedia/MediaKeys.cpp b/Source/WebCore/Modules/encryptedmedia/MediaKeys.cpp
new file mode 100644
index 000000000..c8bc5ae29
--- /dev/null
+++ b/Source/WebCore/Modules/encryptedmedia/MediaKeys.cpp
@@ -0,0 +1,114 @@
+/*
+ * 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 "MediaKeys.h"
+
+#if ENABLE(ENCRYPTED_MEDIA)
+
+#include "CDM.h"
+#include "CDMInstance.h"
+#include "MediaKeySession.h"
+#include "SharedBuffer.h"
+
+namespace WebCore {
+
+MediaKeys::MediaKeys(bool useDistinctiveIdentifier, bool persistentStateAllowed, const Vector<MediaKeySessionType>& supportedSessionTypes, Ref<CDM>&& implementation, Ref<CDMInstance>&& instance)
+ : m_useDistinctiveIdentifier(useDistinctiveIdentifier)
+ , m_persistentStateAllowed(persistentStateAllowed)
+ , m_supportedSessionTypes(supportedSessionTypes)
+ , m_implementation(WTFMove(implementation))
+ , m_instance(WTFMove(instance))
+{
+}
+
+MediaKeys::~MediaKeys() = default;
+
+ExceptionOr<Ref<MediaKeySession>> MediaKeys::createSession(ScriptExecutionContext& context, MediaKeySessionType sessionType)
+{
+ // https://w3c.github.io/encrypted-media/#dom-mediakeys-setservercertificate
+ // W3C Editor's Draft 09 November 2016
+
+ // When this method is invoked, the user agent must run the following steps:
+ // 1. If this object's supported session types value does not contain sessionType, throw [WebIDL] a NotSupportedError.
+ if (!m_supportedSessionTypes.contains(sessionType))
+ return Exception(NOT_SUPPORTED_ERR);
+
+ // 2. If the implementation does not support MediaKeySession operations in the current state, throw [WebIDL] an InvalidStateError.
+ if (!m_implementation->supportsSessions())
+ return Exception(INVALID_STATE_ERR);
+
+ // 3. Let session be a new MediaKeySession object, and initialize it as follows:
+ // NOTE: Continued in MediaKeySession.
+ // 4. Return session.
+ return MediaKeySession::create(context, sessionType, m_useDistinctiveIdentifier, m_implementation.copyRef(), m_instance.copyRef());
+}
+
+void MediaKeys::setServerCertificate(const BufferSource& serverCertificate, Ref<DeferredPromise>&& promise)
+{
+ // https://w3c.github.io/encrypted-media/#dom-mediakeys-setservercertificate
+ // W3C Editor's Draft 09 November 2016
+
+ // When this method is invoked, the user agent must run the following steps:
+ // 1. If the Key System implementation represented by this object's cdm implementation value does not support
+ // server certificates, return a promise resolved with false.
+ if (!m_implementation->supportsServerCertificates()) {
+ promise->resolve<IDLBoolean>(false);
+ return;
+ }
+
+ // 2. If serverCertificate is an empty array, return a promise rejected with a new a newly created TypeError.
+ if (!serverCertificate.length()) {
+ promise->reject(TypeError);
+ return;
+ }
+
+ // 3. Let certificate be a copy of the contents of the serverCertificate parameter.
+ auto certificate = SharedBuffer::create(serverCertificate.data(), serverCertificate.length());
+
+ // 4. Let promise be a new promise.
+ // 5. Run the following steps in parallel:
+
+ m_taskQueue.enqueueTask([this, certificate = WTFMove(certificate), promise = WTFMove(promise)] () mutable {
+ // 5.1. Use this object's cdm instance to process certificate.
+ if (m_instance->setServerCertificate(WTFMove(certificate)) == CDMInstance::Failed) {
+ // 5.2. If the preceding step failed, resolve promise with a new DOMException whose name is the appropriate error name.
+ promise->reject(INVALID_STATE_ERR);
+ return;
+ }
+
+ // 5.1. Resolve promise with true.
+ promise->resolve<IDLBoolean>(true);
+ });
+
+ // 6. Return promise.
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(ENCRYPTED_MEDIA)
diff --git a/Source/WebCore/Modules/encryptedmedia/MediaKeys.h b/Source/WebCore/Modules/encryptedmedia/MediaKeys.h
new file mode 100644
index 000000000..bd80bd2c9
--- /dev/null
+++ b/Source/WebCore/Modules/encryptedmedia/MediaKeys.h
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#if ENABLE(ENCRYPTED_MEDIA)
+
+#include "ExceptionOr.h"
+#include "GenericTaskQueue.h"
+#include "JSDOMPromise.h"
+#include "MediaKeySessionType.h"
+#include <wtf/Ref.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class CDM;
+class CDMInstance;
+class BufferSource;
+class MediaKeySession;
+
+class MediaKeys : public RefCounted<MediaKeys> {
+public:
+ using KeySessionType = MediaKeySessionType;
+
+ static Ref<MediaKeys> create(bool useDistinctiveIdentifier, bool persistentStateAllowed, const Vector<MediaKeySessionType>& supportedSessionTypes, Ref<CDM>&& implementation, Ref<CDMInstance>&& instance)
+ {
+ return adoptRef(*new MediaKeys(useDistinctiveIdentifier, persistentStateAllowed, supportedSessionTypes, WTFMove(implementation), WTFMove(instance)));
+ }
+
+ ~MediaKeys();
+
+ ExceptionOr<Ref<MediaKeySession>> createSession(ScriptExecutionContext&, MediaKeySessionType);
+
+ void setServerCertificate(const BufferSource&, Ref<DeferredPromise>&&);
+
+protected:
+ MediaKeys(bool useDistinctiveIdentifier, bool persistentStateAllowed, const Vector<MediaKeySessionType>&, Ref<CDM>&&, Ref<CDMInstance>&&);
+
+ bool m_useDistinctiveIdentifier;
+ bool m_persistentStateAllowed;
+ Vector<MediaKeySessionType> m_supportedSessionTypes;
+ Ref<CDM> m_implementation;
+ Ref<CDMInstance> m_instance;
+ GenericTaskQueue<Timer> m_taskQueue;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(ENCRYPTED_MEDIA)
diff --git a/Source/WebCore/Modules/encryptedmedia/MediaKeys.idl b/Source/WebCore/Modules/encryptedmedia/MediaKeys.idl
new file mode 100644
index 000000000..781850420
--- /dev/null
+++ b/Source/WebCore/Modules/encryptedmedia/MediaKeys.idl
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+[
+ Conditional=ENCRYPTED_MEDIA,
+ EnabledAtRuntime=EncryptedMediaAPI,
+ ImplementationLacksVTable,
+] interface MediaKeys {
+ [CallWith=ScriptExecutionContext, MayThrowException] MediaKeySession createSession(optional MediaKeySessionType sessionType = "temporary");
+ Promise<bool> setServerCertificate(BufferSource serverCertificate);
+};
diff --git a/Source/WebCore/Modules/encryptedmedia/MediaKeysRequirement.h b/Source/WebCore/Modules/encryptedmedia/MediaKeysRequirement.h
new file mode 100644
index 000000000..c6af6b4fe
--- /dev/null
+++ b/Source/WebCore/Modules/encryptedmedia/MediaKeysRequirement.h
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#if ENABLE(ENCRYPTED_MEDIA)
+
+namespace WebCore {
+
+enum class MediaKeysRequirement {
+ Required,
+ Optional,
+ NotAllowed
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(ENCRYPTED_MEDIA)
diff --git a/Source/WebCore/Modules/encryptedmedia/MediaKeysRequirement.idl b/Source/WebCore/Modules/encryptedmedia/MediaKeysRequirement.idl
new file mode 100644
index 000000000..a30897918
--- /dev/null
+++ b/Source/WebCore/Modules/encryptedmedia/MediaKeysRequirement.idl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+[
+ Conditional=ENCRYPTED_MEDIA,
+ ImplementedAs=MediaKeysRequirement,
+ ExportMacro=WEBCORE_TESTSUPPORT_EXPORT
+]
+enum MediaKeysRequirement {
+ "required",
+ "optional",
+ "not-allowed"
+};
+
diff --git a/Source/WebCore/Modules/encryptedmedia/MediaKeysRestrictions.h b/Source/WebCore/Modules/encryptedmedia/MediaKeysRestrictions.h
new file mode 100644
index 000000000..0be8567f6
--- /dev/null
+++ b/Source/WebCore/Modules/encryptedmedia/MediaKeysRestrictions.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2016 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(ENCRYPTED_MEDIA)
+
+#include <wtf/HashSet.h>
+
+namespace WebCore {
+
+struct MediaKeysRestrictions {
+ bool distinctiveIdentifierDenied { false };
+ bool persistentStateDenied { false };
+ HashSet<String> deniedSessionTypes;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(ENCRYPTED_MEDIA)
diff --git a/Source/WebCore/Modules/encryptedmedia/NavigatorEME.cpp b/Source/WebCore/Modules/encryptedmedia/NavigatorEME.cpp
new file mode 100644
index 000000000..edc9a0c7b
--- /dev/null
+++ b/Source/WebCore/Modules/encryptedmedia/NavigatorEME.cpp
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2016 Metrological Group B.V.
+ * Copyright (C) 2016 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "NavigatorEME.h"
+
+#if ENABLE(ENCRYPTED_MEDIA)
+
+#include "CDM.h"
+#include "Document.h"
+#include "JSMediaKeySystemAccess.h"
+
+namespace WebCore {
+
+static void tryNextSupportedConfiguration(RefPtr<CDM>&& implementation, Vector<MediaKeySystemConfiguration>&& supportedConfigurations, RefPtr<DeferredPromise>&&);
+
+void NavigatorEME::requestMediaKeySystemAccess(Navigator&, Document& document, const String& keySystem, Vector<MediaKeySystemConfiguration>&& supportedConfigurations, Ref<DeferredPromise>&& promise)
+{
+ // https://w3c.github.io/encrypted-media/#dom-navigator-requestmediakeysystemaccess
+ // W3C Editor's Draft 09 November 2016
+
+ // When this method is invoked, the user agent must run the following steps:
+ // 1. If keySystem is the empty string, return a promise rejected with a newly created TypeError.
+ // 2. If supportedConfigurations is empty, return a promise rejected with a newly created TypeError.
+ if (keySystem.isEmpty() || supportedConfigurations.isEmpty()) {
+ promise->reject(TypeError);
+ return;
+ }
+
+ document.postTask([keySystem, supportedConfigurations = WTFMove(supportedConfigurations), promise = WTFMove(promise), &document] (ScriptExecutionContext&) mutable {
+ // 3. Let document be the calling context's Document.
+ // 4. Let origin be the origin of document.
+ // 5. Let promise be a new promise.
+ // 6. Run the following steps in parallel:
+ // 6.1. If keySystem is not one of the Key Systems supported by the user agent, reject promise with a NotSupportedError.
+ // String comparison is case-sensitive.
+ if (!CDM::supportsKeySystem(keySystem)) {
+ promise->reject(NOT_SUPPORTED_ERR);
+ return;
+ }
+
+ // 6.2. Let implementation be the implementation of keySystem.
+ RefPtr<CDM> implementation = CDM::create(document, keySystem);
+ tryNextSupportedConfiguration(WTFMove(implementation), WTFMove(supportedConfigurations), WTFMove(promise));
+ });
+}
+
+static void tryNextSupportedConfiguration(RefPtr<CDM>&& implementation, Vector<MediaKeySystemConfiguration>&& supportedConfigurations, RefPtr<DeferredPromise>&& promise)
+{
+ // 6.3. For each value in supportedConfigurations:
+ if (!supportedConfigurations.isEmpty()) {
+ // 6.3.1. Let candidate configuration be the value.
+ // 6.3.2. Let supported configuration be the result of executing the Get Supported Configuration
+ // algorithm on implementation, candidate configuration, and origin.
+ MediaKeySystemConfiguration candidateCofiguration = WTFMove(supportedConfigurations.first());
+ supportedConfigurations.remove(0);
+
+ CDM::SupportedConfigurationCallback callback = [implementation = implementation, supportedConfigurations = WTFMove(supportedConfigurations), promise] (std::optional<MediaKeySystemConfiguration> supportedConfiguration) mutable {
+ // 6.3.3. If supported configuration is not NotSupported, run the following steps:
+ if (supportedConfiguration) {
+ // 6.3.3.1. Let access be a new MediaKeySystemAccess object, and initialize it as follows:
+ // 6.3.3.1.1. Set the keySystem attribute to keySystem.
+ // 6.3.3.1.2. Let the configuration value be supported configuration.
+ // 6.3.3.1.3. Let the cdm implementation value be implementation.
+ auto access = MediaKeySystemAccess::create(implementation->keySystem(), WTFMove(supportedConfiguration.value()), implementation.releaseNonNull());
+ // 6.3.3.2. Resolve promise with access and abort the parallel steps of this algorithm.
+ promise->resolveWithNewlyCreated<IDLInterface<MediaKeySystemAccess>>(WTFMove(access));
+ return;
+ }
+
+ tryNextSupportedConfiguration(WTFMove(implementation), WTFMove(supportedConfigurations), WTFMove(promise));
+ };
+ implementation->getSupportedConfiguration(WTFMove(candidateCofiguration), WTFMove(callback));
+ return;
+ }
+
+
+ // 6.4. Reject promise with a NotSupportedError.
+ promise->reject(NOT_SUPPORTED_ERR);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(ENCRYPTED_MEDIA)
diff --git a/Source/WebCore/Modules/encryptedmedia/NavigatorEME.h b/Source/WebCore/Modules/encryptedmedia/NavigatorEME.h
new file mode 100644
index 000000000..4c204e941
--- /dev/null
+++ b/Source/WebCore/Modules/encryptedmedia/NavigatorEME.h
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#if ENABLE(ENCRYPTED_MEDIA)
+
+#include "JSDOMPromise.h"
+#include "MediaKeySystemConfiguration.h"
+#include "Supplementable.h"
+
+namespace WebCore {
+
+class MediaKeySystemAccess;
+class Navigator;
+class Page;
+
+class NavigatorEME final : public Supplement<Page> {
+public:
+ static void requestMediaKeySystemAccess(Navigator&, Document&, const String&, Vector<MediaKeySystemConfiguration>&&, Ref<DeferredPromise>&&);
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(ENCRYPTED_MEDIA)
diff --git a/Source/WebCore/Modules/encryptedmedia/NavigatorEME.idl b/Source/WebCore/Modules/encryptedmedia/NavigatorEME.idl
new file mode 100644
index 000000000..99df263b2
--- /dev/null
+++ b/Source/WebCore/Modules/encryptedmedia/NavigatorEME.idl
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+[
+ Conditional=ENCRYPTED_MEDIA,
+ EnabledAtRuntime=EncryptedMediaAPI
+] partial interface Navigator {
+ [CallWith=Document] Promise<MediaKeySystemAccess> requestMediaKeySystemAccess(DOMString keySystem, sequence<MediaKeySystemConfiguration> supportedConfiguration);
+};
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;
+};