From 1a6b61b0cc5552ede51cc07918402ce6ed33fcdf Mon Sep 17 00:00:00 2001 From: Linus Groh Date: Sun, 5 Mar 2023 23:58:47 +0000 Subject: [PATCH] LibWeb/HTML: Move WindowOrWorkerGlobalScope code into a mixin class This will allow us to easily share the implementations of these methods between Window and WorkerGlobalScope. The mixin class mirrors what I already did for the Fetch API's Body mixin in 5ad62833. --- Userland/Libraries/LibWeb/CMakeLists.txt | 1 + .../LibWeb/HTML/WindowOrWorkerGlobalScope.cpp | 85 +++++++++++++++++++ .../LibWeb/HTML/WindowOrWorkerGlobalScope.h | 31 +++++++ .../LibWeb/HTML/WorkerGlobalScope.cpp | 71 ---------------- .../Libraries/LibWeb/HTML/WorkerGlobalScope.h | 18 ++-- 5 files changed, 125 insertions(+), 81 deletions(-) create mode 100644 Userland/Libraries/LibWeb/HTML/WindowOrWorkerGlobalScope.cpp create mode 100644 Userland/Libraries/LibWeb/HTML/WindowOrWorkerGlobalScope.h diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index 105d2418e0..e468862db4 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -303,6 +303,7 @@ set(SOURCES HTML/Timer.cpp HTML/Window.cpp HTML/WindowEventHandlers.cpp + HTML/WindowOrWorkerGlobalScope.cpp HTML/WindowProxy.cpp HTML/Worker.cpp HTML/WorkerDebugConsoleClient.cpp diff --git a/Userland/Libraries/LibWeb/HTML/WindowOrWorkerGlobalScope.cpp b/Userland/Libraries/LibWeb/HTML/WindowOrWorkerGlobalScope.cpp new file mode 100644 index 0000000000..0837d2b9bd --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/WindowOrWorkerGlobalScope.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2022, Andrew Kaster + * Copyright (c) 2023, Linus Groh + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Web::HTML { + +WindowOrWorkerGlobalScopeMixin::~WindowOrWorkerGlobalScopeMixin() = default; + +// https://html.spec.whatwg.org/multipage/webappapis.html#dom-origin +WebIDL::ExceptionOr WindowOrWorkerGlobalScopeMixin::origin() const +{ + auto& vm = this_impl().vm(); + + // The origin getter steps are to return this's relevant settings object's origin, serialized. + return TRY_OR_THROW_OOM(vm, String::from_deprecated_string(relevant_settings_object(this_impl()).origin().serialize())); +} + +// https://html.spec.whatwg.org/multipage/webappapis.html#dom-issecurecontext +bool WindowOrWorkerGlobalScopeMixin::is_secure_context() const +{ + // The isSecureContext getter steps are to return true if this's relevant settings object is a secure context, or false otherwise. + return HTML::is_secure_context(relevant_settings_object(this_impl())); +} + +// https://html.spec.whatwg.org/multipage/webappapis.html#dom-crossoriginisolated +bool WindowOrWorkerGlobalScopeMixin::cross_origin_isolated() const +{ + // The crossOriginIsolated getter steps are to return this's relevant settings object's cross-origin isolated capability. + return relevant_settings_object(this_impl()).cross_origin_isolated_capability() == CanUseCrossOriginIsolatedAPIs::Yes; +} + +// https://html.spec.whatwg.org/multipage/webappapis.html#dom-btoa +WebIDL::ExceptionOr WindowOrWorkerGlobalScopeMixin::btoa(String const& data) const +{ + auto& vm = this_impl().vm(); + auto& realm = *vm.current_realm(); + + // The btoa(data) method must throw an "InvalidCharacterError" DOMException if data contains any character whose code point is greater than U+00FF. + Vector byte_string; + byte_string.ensure_capacity(data.bytes().size()); + for (u32 code_point : Utf8View(data)) { + if (code_point > 0xff) + return WebIDL::InvalidCharacterError::create(realm, "Data contains characters outside the range U+0000 and U+00FF"); + byte_string.append(code_point); + } + + // Otherwise, the user agent must convert data to a byte sequence whose nth byte is the eight-bit representation of the nth code point of data, + // and then must apply forgiving-base64 encode to that byte sequence and return the result. + return TRY_OR_THROW_OOM(vm, encode_base64(byte_string.span())); +} + +// https://html.spec.whatwg.org/multipage/webappapis.html#dom-atob +WebIDL::ExceptionOr WindowOrWorkerGlobalScopeMixin::atob(String const& data) const +{ + auto& vm = this_impl().vm(); + auto& realm = *vm.current_realm(); + + // 1. Let decodedData be the result of running forgiving-base64 decode on data. + auto decoded_data = decode_base64(data.bytes_as_string_view()); + + // 2. If decodedData is failure, then throw an "InvalidCharacterError" DOMException. + if (decoded_data.is_error()) + return WebIDL::InvalidCharacterError::create(realm, "Input string is not valid base64 data"); + + // 3. Return decodedData. + // decode_base64() returns a byte string. LibJS uses UTF-8 for strings. Use Latin1Decoder to convert bytes 128-255 to UTF-8. + auto decoder = TextCodec::decoder_for("windows-1252"sv); + VERIFY(decoder.has_value()); + return TRY_OR_THROW_OOM(vm, decoder->to_utf8(decoded_data.value())); +} + +} diff --git a/Userland/Libraries/LibWeb/HTML/WindowOrWorkerGlobalScope.h b/Userland/Libraries/LibWeb/HTML/WindowOrWorkerGlobalScope.h new file mode 100644 index 0000000000..4eb32ad313 --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/WindowOrWorkerGlobalScope.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2023, Linus Groh + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include + +namespace Web::HTML { + +// https://html.spec.whatwg.org/multipage/webappapis.html#windoworworkerglobalscope +class WindowOrWorkerGlobalScopeMixin { +public: + virtual ~WindowOrWorkerGlobalScopeMixin(); + + virtual Bindings::PlatformObject& this_impl() = 0; + virtual Bindings::PlatformObject const& this_impl() const = 0; + + // JS API functions + WebIDL::ExceptionOr origin() const; + bool is_secure_context() const; + bool cross_origin_isolated() const; + WebIDL::ExceptionOr btoa(String const& data) const; + WebIDL::ExceptionOr atob(String const& data) const; +}; + +} diff --git a/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.cpp b/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.cpp index 1f40f35f38..1ea4710333 100644 --- a/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.cpp +++ b/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.cpp @@ -1,26 +1,18 @@ /* * Copyright (c) 2022, Andrew Kaster - * Copyright (c) 2023, Linus Groh * * SPDX-License-Identifier: BSD-2-Clause */ -#include -#include -#include #include -#include -#include #include #include #include #include #include -#include #include #include #include -#include namespace Web::HTML { @@ -104,67 +96,4 @@ JS::NonnullGCPtr WorkerGlobalScope::navigator() const ENUMERATE_WORKER_GLOBAL_SCOPE_EVENT_HANDLERS(__ENUMERATE) #undef __ENUMERATE -// https://html.spec.whatwg.org/multipage/webappapis.html#dom-origin -WebIDL::ExceptionOr WorkerGlobalScope::origin() const -{ - auto& vm = this->vm(); - - // The origin getter steps are to return this's relevant settings object's origin, serialized. - return TRY_OR_THROW_OOM(vm, String::from_deprecated_string(relevant_settings_object(this_impl()).origin().serialize())); -} - -// https://html.spec.whatwg.org/multipage/webappapis.html#dom-issecurecontext -bool WorkerGlobalScope::is_secure_context() const -{ - // The isSecureContext getter steps are to return true if this's relevant settings object is a secure context, or false otherwise. - return HTML::is_secure_context(relevant_settings_object(*this)); -} - -// https://html.spec.whatwg.org/multipage/webappapis.html#dom-crossoriginisolated -bool WorkerGlobalScope::cross_origin_isolated() const -{ - // The crossOriginIsolated getter steps are to return this's relevant settings object's cross-origin isolated capability. - return relevant_settings_object(*this).cross_origin_isolated_capability() == CanUseCrossOriginIsolatedAPIs::Yes; -} - -// https://html.spec.whatwg.org/multipage/webappapis.html#dom-btoa -WebIDL::ExceptionOr WorkerGlobalScope::btoa(String const& data) const -{ - // FIXME: This is the same as the implementation in Bindings/WindowObject.cpp - // Find a way to share this implementation, since they come from the same mixin. - - // The btoa(data) method must throw an "InvalidCharacterError" DOMException if data contains any character whose code point is greater than U+00FF. - Vector byte_string; - byte_string.ensure_capacity(data.bytes().size()); - for (u32 code_point : Utf8View(data)) { - if (code_point > 0xff) - return WebIDL::InvalidCharacterError::create(realm(), "Data contains characters outside the range U+0000 and U+00FF"); - byte_string.append(code_point); - } - - // Otherwise, the user agent must convert data to a byte sequence whose nth byte is the eight-bit representation of the nth code point of data, - // and then must apply forgiving-base64 encode to that byte sequence and return the result. - return TRY_OR_THROW_OOM(vm(), encode_base64(byte_string.span())); -} - -// https://html.spec.whatwg.org/multipage/webappapis.html#dom-atob -WebIDL::ExceptionOr WorkerGlobalScope::atob(String const& data) const -{ - // FIXME: This is the same as the implementation in Bindings/WindowObject.cpp - // Find a way to share this implementation, since they come from the same mixin. - - // 1. Let decodedData be the result of running forgiving-base64 decode on data. - auto decoded_data = decode_base64(data.bytes_as_string_view()); - - // 2. If decodedData is failure, then throw an "InvalidCharacterError" DOMException. - if (decoded_data.is_error()) - return WebIDL::InvalidCharacterError::create(realm(), "Input string is not valid base64 data"); - - // 3. Return decodedData. - // decode_base64() returns a byte string. LibJS uses UTF-8 for strings. Use Latin1Decoder to convert bytes 128-255 to UTF-8. - auto decoder = TextCodec::decoder_for("windows-1252"sv); - VERIFY(decoder.has_value()); - return TRY_OR_THROW_OOM(vm(), decoder->to_utf8(decoded_data.value())); -} - } diff --git a/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.h b/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.h index f266519718..b2d2fae0f2 100644 --- a/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.h +++ b/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -28,12 +29,18 @@ namespace Web::HTML { // https://html.spec.whatwg.org/multipage/workers.html#the-workerglobalscope-common-interface // WorkerGlobalScope is the base class of each real WorkerGlobalScope that will be created when the // user agent runs the run a worker algorithm. -class WorkerGlobalScope : public DOM::EventTarget { +class WorkerGlobalScope + : public DOM::EventTarget + , public WindowOrWorkerGlobalScopeMixin { WEB_PLATFORM_OBJECT(WorkerGlobalScope, DOM::EventTarget); public: virtual ~WorkerGlobalScope() override; + // ^WindowOrWorkerGlobalScopeMixin + virtual Bindings::PlatformObject& this_impl() override { return *this; } + virtual Bindings::PlatformObject const& this_impl() const override { return *this; } + // Following methods are from the WorkerGlobalScope IDL definition // https://html.spec.whatwg.org/multipage/workers.html#the-workerglobalscope-common-interface @@ -51,15 +58,6 @@ public: ENUMERATE_WORKER_GLOBAL_SCOPE_EVENT_HANDLERS(__ENUMERATE) #undef __ENUMERATE - // Following methods are from the WindowOrWorkerGlobalScope mixin - // https://html.spec.whatwg.org/multipage/webappapis.html#windoworworkerglobalscope-mixin - - WebIDL::ExceptionOr origin() const; - bool is_secure_context() const; - bool cross_origin_isolated() const; - WebIDL::ExceptionOr btoa(String const& data) const; - WebIDL::ExceptionOr atob(String const& data) const; - // Non-IDL public methods AK::URL const& url() const { return m_url.value(); }