/* * 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. // Obtain reference to the key system string before the `implementation` RefPtr<> is cleared out. const String& keySystem = implementation->keySystem(); auto access = MediaKeySystemAccess::create(keySystem, WTFMove(supportedConfiguration.value()), implementation.releaseNonNull()); // 6.3.3.2. Resolve promise with access and abort the parallel steps of this algorithm. promise->resolveWithNewlyCreated<IDLInterface<MediaKeySystemAccess>>(WTFMove(access)); return; } tryNextSupportedConfiguration(WTFMove(implementation), WTFMove(supportedConfigurations), WTFMove(promise)); }; implementation->getSupportedConfiguration(WTFMove(candidateCofiguration), WTFMove(callback)); return; } // 6.4. Reject promise with a NotSupportedError. promise->reject(NOT_SUPPORTED_ERR); } } // namespace WebCore #endif // ENABLE(ENCRYPTED_MEDIA)