diff --git a/Libraries/LibWeb/CMakeLists.txt b/Libraries/LibWeb/CMakeLists.txt index bff3b790c48..7c3ad1f8855 100644 --- a/Libraries/LibWeb/CMakeLists.txt +++ b/Libraries/LibWeb/CMakeLists.txt @@ -331,6 +331,7 @@ set(SOURCES Encoding/TextEncoderStream.cpp EncryptedMediaExtensions/Algorithms.cpp EncryptedMediaExtensions/MediaKeySystemAccess.cpp + EncryptedMediaExtensions/NavigatorEncryptedMediaExtensionsPartial.cpp EntriesAPI/FileSystemEntry.cpp EventTiming/PerformanceEventTiming.cpp Fetch/Body.cpp diff --git a/Libraries/LibWeb/EncryptedMediaExtensions/MediaKeySystemAccess.idl b/Libraries/LibWeb/EncryptedMediaExtensions/MediaKeySystemAccess.idl index 4771a61d4d4..5aebe5c92e6 100644 --- a/Libraries/LibWeb/EncryptedMediaExtensions/MediaKeySystemAccess.idl +++ b/Libraries/LibWeb/EncryptedMediaExtensions/MediaKeySystemAccess.idl @@ -35,3 +35,12 @@ enum MediaKeySessionType { "temporary", "persistent-license" }; + +// https://w3c.github.io/encrypted-media/#navigator-extension-requestmediakeysystemaccess +[Exposed=Window] +partial interface Navigator { + [SecureContext] Promise requestMediaKeySystemAccess( + Utf16DOMString keySystem, + sequence supportedConfigurations + ); +}; diff --git a/Libraries/LibWeb/EncryptedMediaExtensions/NavigatorEncryptedMediaExtensionsPartial.cpp b/Libraries/LibWeb/EncryptedMediaExtensions/NavigatorEncryptedMediaExtensionsPartial.cpp new file mode 100644 index 00000000000..5c05dc03238 --- /dev/null +++ b/Libraries/LibWeb/EncryptedMediaExtensions/NavigatorEncryptedMediaExtensionsPartial.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2025, stelar7 + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +namespace Web::EncryptedMediaExtensions { + +// https://w3c.github.io/encrypted-media/#dom-navigator-requestmediakeysystemaccess +WebIDL::ExceptionOr> NavigatorEncryptedMediaExtensionsPartial::request_media_key_system_access(Utf16String key_system, Vector supported_configurations) +{ + auto& navigator = as(*this); + auto& realm = navigator.realm(); + + // 1. If this's relevant global object's associated Document is not allowed to use the encrypted-media feature, then throw a "SecurityError" DOMException and abort these steps. + auto& associated_document = as(HTML::relevant_global_object(navigator)).associated_document(); + if (!associated_document.is_allowed_to_use_feature(DOM::PolicyControlledFeature::EncryptedMedia)) + return WebIDL::SecurityError::create(realm, "This document is not allowed to use the encrypted-media feature"_utf16); + + // 2. If keySystem is the empty string, return a promise rejected with a newly created TypeError. + if (key_system.is_empty()) + return WebIDL::create_rejected_promise(realm, JS::TypeError::create(realm, "keySystem must not be empty"_utf16)); + + // 3. If supportedConfigurations is empty, return a promise rejected with a newly created TypeError. + if (supported_configurations.is_empty()) + return WebIDL::create_rejected_promise(realm, JS::TypeError::create(realm, "supportedConfigurations must not be empty"_utf16)); + + // 4. Let document be the calling context's Document. + // FIXME: Is this the same as the associated document? + auto& document = associated_document; + + // 5. Let origin be the origin of document. + auto origin = document.origin(); + + // 6. Let promise be a new promise. + auto promise = WebIDL::create_promise(realm); + + // 7. Run the following steps in parallel: + Platform::EventLoopPlugin::the().deferred_invoke(GC::create_function(realm.heap(), [&realm, key_system, supported_configurations, origin, promise]() { + HTML::TemporaryExecutionContext context(realm, HTML::TemporaryExecutionContext::CallbacksEnabled::Yes); + + // 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 (!is_supported_key_system(key_system)) + return WebIDL::reject_promise(realm, promise, WebIDL::NotSupportedError::create(realm, "Unsupported key system"_utf16)); + + // 2. Let implementation be the implementation of keySystem. + auto implementation = key_system_from_string(key_system); + + // 3. For each value in supportedConfigurations: + for (auto const& candidate_configuration : supported_configurations) { + // 1. Let candidate configuration be the value. + + // 2. Let supported configuration be the result of executing the Get Supported Configuration algorithm on implementation, candidate configuration, and origin. + auto supported_configuration = get_supported_configuration(*implementation, candidate_configuration, origin); + + // 3. If supported configuration is not NotSupported, run the following steps: + if (supported_configuration.has_value()) { + // 1. Let access be a new MediaKeySystemAccess object, and initialize it as follows: + // 1. Set the keySystem attribute to keySystem. + // 2. Let the configuration value be supported configuration. + // 3. Let the cdm implementation value be implementation. + auto access = MediaKeySystemAccess::create(realm, key_system, *supported_configuration->configuration, move(implementation)); + + // 2. Resolve promise with access and abort the parallel steps of this algorithm. + return WebIDL::resolve_promise(realm, promise, access); + } + } + + // 4. Reject promise with a NotSupportedError. + WebIDL::reject_promise(realm, promise, WebIDL::NotSupportedError::create(realm, "No supported configurations found for the requested key system"_utf16)); + })); + + // 8. Return promise. + return promise; +} + +} diff --git a/Libraries/LibWeb/EncryptedMediaExtensions/NavigatorEncryptedMediaExtensionsPartial.h b/Libraries/LibWeb/EncryptedMediaExtensions/NavigatorEncryptedMediaExtensionsPartial.h new file mode 100644 index 00000000000..93f8061a5f5 --- /dev/null +++ b/Libraries/LibWeb/EncryptedMediaExtensions/NavigatorEncryptedMediaExtensionsPartial.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2025, stelar7 + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include + +namespace Web::EncryptedMediaExtensions { + +class NavigatorEncryptedMediaExtensionsPartial { +public: + WebIDL::ExceptionOr> request_media_key_system_access(Utf16String, Vector); + +private: + virtual ~NavigatorEncryptedMediaExtensionsPartial() = default; + + friend class HTML::Navigator; +}; + +} diff --git a/Libraries/LibWeb/HTML/Navigator.h b/Libraries/LibWeb/HTML/Navigator.h index 6d3b4bb9692..8f34b11152f 100644 --- a/Libraries/LibWeb/HTML/Navigator.h +++ b/Libraries/LibWeb/HTML/Navigator.h @@ -7,6 +7,7 @@ #pragma once #include +#include #include #include #include @@ -28,6 +29,7 @@ class Navigator : public Bindings::PlatformObject , public NavigatorConcurrentHardwareMixin , public NavigatorDeviceMemoryMixin , public Gamepad::NavigatorGamepadPartial + , public EncryptedMediaExtensions::NavigatorEncryptedMediaExtensionsPartial , public NavigatorIDMixin , public NavigatorLanguageMixin , public NavigatorOnLineMixin diff --git a/Libraries/LibWeb/HTML/Navigator.idl b/Libraries/LibWeb/HTML/Navigator.idl index 933e80c503f..2272bfcf13a 100644 --- a/Libraries/LibWeb/HTML/Navigator.idl +++ b/Libraries/LibWeb/HTML/Navigator.idl @@ -1,5 +1,6 @@ #import #import +#import #import #import #import