summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibWeb
diff options
context:
space:
mode:
authorAndrew Kaster <akaster@serenityos.org>2022-02-06 19:12:57 -0700
committerAndreas Kling <kling@serenityos.org>2022-02-09 17:21:05 +0100
commit820e99f97d4ad6de697a89838086f50be9c38661 (patch)
tree07d0ae1e1746ede70f086df78e2f1c36186e07fd /Userland/Libraries/LibWeb
parent8b38df72a32d9052c003c706bc95ff40794c50be (diff)
downloadserenity-820e99f97d4ad6de697a89838086f50be9c38661.zip
LibWeb: Add initial implementation for WorkerGlobalScope
This initial implementation stubs out the WorkerGlobalScope, WorkerLocation and WorkerNavigator classes. It doesn't take into account all the things that actually need passed into the constructors for these objects, nor the extra abstract operations that need to be performed on them by the rest of the Browser infrastructure. However, it does create bindings that compile and link :^)
Diffstat (limited to 'Userland/Libraries/LibWeb')
-rw-r--r--Userland/Libraries/LibWeb/CMakeLists.txt5
-rw-r--r--Userland/Libraries/LibWeb/Forward.h6
-rw-r--r--Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.cpp153
-rw-r--r--Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.h126
-rw-r--r--Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.idl25
-rw-r--r--Userland/Libraries/LibWeb/HTML/WorkerLocation.cpp124
-rw-r--r--Userland/Libraries/LibWeb/HTML/WorkerLocation.h43
-rw-r--r--Userland/Libraries/LibWeb/HTML/WorkerLocation.idl12
-rw-r--r--Userland/Libraries/LibWeb/HTML/WorkerNavigator.h23
-rw-r--r--Userland/Libraries/LibWeb/HTML/WorkerNavigator.idl8
10 files changed, 525 insertions, 0 deletions
diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt
index 762a2c96ac..8b5c86c294 100644
--- a/Userland/Libraries/LibWeb/CMakeLists.txt
+++ b/Userland/Libraries/LibWeb/CMakeLists.txt
@@ -201,6 +201,8 @@ set(SOURCES
HTML/TagNames.cpp
HTML/TextMetrics.cpp
HTML/WebSocket.cpp
+ HTML/WorkerGlobalScope.cpp
+ HTML/WorkerLocation.cpp
HighResolutionTime/Performance.cpp
ImageDecoding.cpp
InProcessWebView.cpp
@@ -498,6 +500,9 @@ libweb_js_wrapper(HTML/Storage)
libweb_js_wrapper(HTML/SubmitEvent)
libweb_js_wrapper(HTML/TextMetrics)
libweb_js_wrapper(HTML/WebSocket)
+libweb_js_wrapper(HTML/WorkerGlobalScope)
+libweb_js_wrapper(HTML/WorkerLocation)
+libweb_js_wrapper(HTML/WorkerNavigator)
libweb_js_wrapper(HighResolutionTime/Performance)
libweb_js_wrapper(IntersectionObserver/IntersectionObserver)
libweb_js_wrapper(NavigationTiming/PerformanceTiming)
diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h
index 48064f4e63..33fd353fc1 100644
--- a/Userland/Libraries/LibWeb/Forward.h
+++ b/Userland/Libraries/LibWeb/Forward.h
@@ -218,6 +218,9 @@ class SubmitEvent;
class TextMetrics;
class WebSocket;
class WindowEnvironmentSettingsObject;
+class WorkerGlobalScope;
+class WorkerLocation;
+class WorkerNavigator;
}
namespace Web::HighResolutionTime {
@@ -465,6 +468,9 @@ class URLSearchParamsWrapper;
class URLWrapper;
class WebSocketWrapper;
class WindowObject;
+class WorkerGlobalScopeWrapper;
+class WorkerLocationWrapper;
+class WorkerNavigatorWrapper;
class Wrappable;
class Wrapper;
class XMLHttpRequestConstructor;
diff --git a/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.cpp b/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.cpp
new file mode 100644
index 0000000000..312e589127
--- /dev/null
+++ b/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.cpp
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2022, Andrew Kaster <akaster@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <AK/Base64.h>
+#include <AK/String.h>
+#include <AK/Utf8View.h>
+#include <AK/Vector.h>
+#include <LibTextCodec/Decoder.h>
+#include <LibWeb/Bindings/WorkerGlobalScopeWrapper.h>
+#include <LibWeb/DOM/DOMException.h>
+#include <LibWeb/Forward.h>
+#include <LibWeb/HTML/EventHandler.h>
+#include <LibWeb/HTML/EventNames.h>
+#include <LibWeb/HTML/WorkerGlobalScope.h>
+#include <LibWeb/HTML/WorkerLocation.h>
+#include <LibWeb/HTML/WorkerNavigator.h>
+
+namespace Web::HTML {
+
+WorkerGlobalScope::WorkerGlobalScope()
+ : m_navigator(make_ref_counted<WorkerNavigator>())
+{
+}
+
+WorkerGlobalScope::~WorkerGlobalScope() { }
+
+// https://html.spec.whatwg.org/multipage/workers.html#importing-scripts-and-libraries
+DOM::ExceptionOr<void> WorkerGlobalScope::import_scripts(Vector<String> urls)
+{
+ // The algorithm may optionally be customized by supplying custom perform the fetch hooks,
+ // which if provided will be used when invoking fetch a classic worker-imported script.
+ // NOTE: Service Workers is an example of a specification that runs this algorithm with its own options for the perform the fetch hook.
+
+ // 1. FIXME: If worker global scope's type is "module", throw a TypeError exception.
+ // 2. FIXME: Let settings object be the current settings object.
+
+ // 3. If urls is empty, return.
+ if (urls.is_empty())
+ return {};
+
+ // 4. FIXME: Parse each value in urls relative to settings object. If any fail, throw a "SyntaxError" DOMException.
+ // 5. FIXME: For each url in the resulting URL records, run these substeps:
+ // 1. Fetch a classic worker-imported script given url and settings object, passing along any custom perform the fetch steps provided.
+ // If this succeeds, let script be the result. Otherwise, rethrow the exception.
+ // 2. Run the classic script script, with the rethrow errors argument set to true.
+ // NOTE: script will run until it either returns, fails to parse, fails to catch an exception,
+ // or gets prematurely aborted by the terminate a worker algorithm defined above.
+ // If an exception was thrown or if the script was prematurely aborted, then abort all these steps,
+ // letting the exception or aborting continue to be processed by the calling script.
+
+ return {};
+}
+
+JS::Object* WorkerGlobalScope::create_wrapper(JS::GlobalObject& global_object)
+{
+ return wrap(global_object, *this);
+}
+
+// https://html.spec.whatwg.org/multipage/workers.html#dom-workerglobalscope-location
+NonnullRefPtr<WorkerLocation const> WorkerGlobalScope::location() const
+{
+ // The location attribute must return the WorkerLocation object whose associated WorkerGlobalScope object is the WorkerGlobalScope object.
+ return *m_location;
+}
+
+// https://html.spec.whatwg.org/multipage/workers.html#dom-worker-navigator
+NonnullRefPtr<WorkerNavigator const> WorkerGlobalScope::navigator() const
+{
+ // The navigator attribute of the WorkerGlobalScope interface must return an instance of the WorkerNavigator interface,
+ // which represents the identity and state of the user agent (the client).
+ return *m_navigator;
+}
+
+#undef __ENUMERATE
+#define __ENUMERATE(attribute_name, event_name) \
+ void WorkerGlobalScope::set_##attribute_name(Optional<Bindings::CallbackType> value) \
+ { \
+ set_event_handler_attribute(event_name, move(value)); \
+ } \
+ Bindings::CallbackType* WorkerGlobalScope::attribute_name() \
+ { \
+ return event_handler_attribute(event_name); \
+ }
+ENUMERATE_WORKER_GLOBAL_SCOPE_EVENT_HANDLERS(__ENUMERATE)
+#undef __ENUMERATE
+
+// https://html.spec.whatwg.org/multipage/webappapis.html#dom-origin
+String WorkerGlobalScope::origin() const
+{
+ // FIXME: The origin getter steps are to return this's relevant settings object's origin, serialized.
+ return {};
+}
+
+// https://html.spec.whatwg.org/multipage/webappapis.html#dom-issecurecontext
+bool WorkerGlobalScope::is_secure_context() const
+{
+ // FIXME: The isSecureContext getter steps are to return true if this's relevant settings object is a secure context, or false otherwise.
+ return false;
+}
+
+// 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.
+ // FIXME: Is this the same thing as https://html.spec.whatwg.org/multipage/workers.html#concept-workerglobalscope-cross-origin-isolated-capability?
+ // "A WorkerGlobalScope object has an associated cross-origin isolated capability boolean. It is initially false."
+ return m_cross_origin_isolated_capability;
+}
+
+// https://html.spec.whatwg.org/multipage/webappapis.html#dom-btoa
+DOM::ExceptionOr<String> 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<u8> byte_string;
+ byte_string.ensure_capacity(data.length());
+ for (u32 code_point : Utf8View(data)) {
+ if (code_point > 0xff)
+ return DOM::InvalidCharacterError::create("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 encode_base64(byte_string.span());
+}
+
+// https://html.spec.whatwg.org/multipage/webappapis.html#dom-atob
+DOM::ExceptionOr<String> 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.view());
+
+ // 2. If decodedData is failure, then throw an "InvalidCharacterError" DOMException.
+ if (decoded_data.is_error())
+ return DOM::InvalidCharacterError::create("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");
+ VERIFY(decoder);
+ return decoder->to_utf8(decoded_data.value());
+}
+
+}
diff --git a/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.h b/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.h
new file mode 100644
index 0000000000..ba2cdc3809
--- /dev/null
+++ b/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2022, Andrew Kaster <akaster@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/Optional.h>
+#include <AK/RefCounted.h>
+#include <AK/URL.h>
+#include <LibWeb/Bindings/Wrappable.h>
+#include <LibWeb/DOM/EventTarget.h>
+#include <LibWeb/DOM/ExceptionOr.h>
+#include <LibWeb/Forward.h>
+#include <LibWeb/HTML/WorkerLocation.h>
+#include <LibWeb/HTML/WorkerNavigator.h>
+
+#define ENUMERATE_WORKER_GLOBAL_SCOPE_EVENT_HANDLERS(E) \
+ E(onerror, HTML::EventNames::error) \
+ E(onlanguagechange, HTML::EventNames::languagechange) \
+ E(ononline, HTML::EventNames::online) \
+ E(onoffline, HTML::EventNames::offline) \
+ E(onrejectionhandled, HTML::EventNames::rejectionhandled) \
+ E(onunhandledrejection, HTML::EventNames::unhandledrejection)
+
+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 RefCounted<WorkerGlobalScope>
+ , public DOM::EventTarget
+ , public Bindings::Wrappable {
+public:
+ using WrapperType = Bindings::WorkerGlobalScopeWrapper;
+
+ using RefCounted::ref;
+ using RefCounted::unref;
+
+ virtual ~WorkerGlobalScope() override;
+
+ // ^EventTarget
+ virtual void ref_event_target() override { ref(); }
+ virtual void unref_event_target() override { unref(); }
+ virtual JS::Object* create_wrapper(JS::GlobalObject&) override;
+
+ // Following methods are from the WorkerGlobalScope IDL definition
+ // https://html.spec.whatwg.org/multipage/workers.html#the-workerglobalscope-common-interface
+
+ // https://html.spec.whatwg.org/multipage/workers.html#dom-workerglobalscope-self
+ NonnullRefPtr<WorkerGlobalScope const> self() const { return *this; }
+
+ NonnullRefPtr<WorkerLocation const> location() const;
+ NonnullRefPtr<WorkerNavigator const> navigator() const;
+ DOM::ExceptionOr<void> import_scripts(Vector<String> urls);
+
+#undef __ENUMERATE
+#define __ENUMERATE(attribute_name, event_name) \
+ void set_##attribute_name(Optional<Bindings::CallbackType>); \
+ Bindings::CallbackType* attribute_name();
+ 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
+
+ String origin() const;
+ bool is_secure_context() const;
+ bool cross_origin_isolated() const;
+ DOM::ExceptionOr<String> btoa(String const& data) const;
+ DOM::ExceptionOr<String> atob(String const& data) const;
+
+ // Non-IDL public methods
+
+ AK::URL const& url() const { return m_url.value(); }
+ void set_url(AK::URL const& url) { m_url = url; }
+
+ // Spec note: While the WorkerLocation object is created after the WorkerGlobalScope object,
+ // this is not problematic as it cannot be observed from script.
+ void set_location(NonnullRefPtr<WorkerLocation> loc) { m_location = move(loc); }
+
+protected:
+ explicit WorkerGlobalScope();
+
+private:
+ RefPtr<WorkerLocation> m_location;
+
+ // FIXME: Implement WorkerNavigator according to the spec
+ NonnullRefPtr<WorkerNavigator> m_navigator;
+
+ // FIXME: Add all these internal slots
+
+ // https://html.spec.whatwg.org/multipage/workers.html#concept-WorkerGlobalScope-owner-set
+ // A WorkerGlobalScope object has an associated owner set (a set of Document and WorkerGlobalScope objects). It is initially empty and populated when the worker is created or obtained.
+ // Note: It is a set, instead of a single owner, to accommodate SharedWorkerGlobalScope objects.
+
+ // https://html.spec.whatwg.org/multipage/workers.html#concept-workerglobalscope-type
+ // A WorkerGlobalScope object has an associated type ("classic" or "module"). It is set during creation.
+
+ // https://html.spec.whatwg.org/multipage/workers.html#concept-workerglobalscope-url
+ // A WorkerGlobalScope object has an associated url (null or a URL). It is initially null.
+ Optional<AK::URL> m_url;
+
+ // https://html.spec.whatwg.org/multipage/workers.html#concept-workerglobalscope-name
+ // A WorkerGlobalScope object has an associated name (a string). It is set during creation.
+ // Note: The name can have different semantics for each subclass of WorkerGlobalScope.
+ // For DedicatedWorkerGlobalScope instances, it is simply a developer-supplied name, useful mostly for debugging purposes.
+ // For SharedWorkerGlobalScope instances, it allows obtaining a reference to a common shared worker via the SharedWorker() constructor.
+ // For ServiceWorkerGlobalScope objects, it doesn't make sense (and as such isn't exposed through the JavaScript API at all).
+
+ // https://html.spec.whatwg.org/multipage/workers.html#concept-workerglobalscope-policy-container
+ // A WorkerGlobalScope object has an associated policy container (a policy container). It is initially a new policy container.
+
+ // https://html.spec.whatwg.org/multipage/workers.html#concept-workerglobalscope-embedder-policy
+ // A WorkerGlobalScope object has an associated embedder policy (an embedder policy).
+
+ // https://html.spec.whatwg.org/multipage/workers.html#concept-workerglobalscope-module-map
+ // A WorkerGlobalScope object has an associated module map. It is a module map, initially empty.
+
+ // https://html.spec.whatwg.org/multipage/workers.html#concept-workerglobalscope-cross-origin-isolated-capability
+ bool m_cross_origin_isolated_capability { false };
+};
+
+}
diff --git a/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.idl b/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.idl
new file mode 100644
index 0000000000..d827dc315a
--- /dev/null
+++ b/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.idl
@@ -0,0 +1,25 @@
+[Exposed=Worker]
+interface WorkerGlobalScope : EventTarget {
+ readonly attribute WorkerGlobalScope self;
+ readonly attribute WorkerLocation location;
+ readonly attribute WorkerNavigator navigator;
+ undefined importScripts(USVString... urls);
+
+ // FIXME: Should be an OnErrorEventHandler
+ attribute EventHandler onerror;
+
+ attribute EventHandler onlanguagechange;
+ attribute EventHandler onoffline;
+ attribute EventHandler ononline;
+ attribute EventHandler onrejectionhandled;
+ attribute EventHandler onunhandledrejection;
+
+ // FIXME: These should all come from a WindowOrWorkerGlobalScope mixin
+ [Replaceable] readonly attribute USVString origin;
+ readonly attribute boolean isSecureContext;
+ readonly attribute boolean crossOriginIsolated;
+
+ // base64 utility methods
+ DOMString btoa(DOMString data);
+ ByteString atob(DOMString data);
+};
diff --git a/Userland/Libraries/LibWeb/HTML/WorkerLocation.cpp b/Userland/Libraries/LibWeb/HTML/WorkerLocation.cpp
new file mode 100644
index 0000000000..4499aa0aa3
--- /dev/null
+++ b/Userland/Libraries/LibWeb/HTML/WorkerLocation.cpp
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2022, Andrew Kaster <akaster@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <AK/String.h>
+#include <LibWeb/HTML/WorkerGlobalScope.h>
+#include <LibWeb/HTML/WorkerLocation.h>
+
+namespace Web::HTML {
+
+// https://html.spec.whatwg.org/multipage/workers.html#dom-workerlocation-href
+String WorkerLocation::href() const
+{
+ // The href getter steps are to return this's WorkerGlobalScope object's url, serialized.
+ return m_global_scope.url().serialize();
+}
+
+// https://html.spec.whatwg.org/multipage/workers.html#dom-workerlocation-origin
+String WorkerLocation::origin() const
+{
+ // The origin getter steps are to return the serialization of this's WorkerGlobalScope object's url's origin.
+ return m_global_scope.url().serialize_origin();
+}
+
+// https://html.spec.whatwg.org/multipage/workers.html#dom-workerlocation-protocol
+String WorkerLocation::protocol() const
+{
+ // The protocol getter steps are to return this's WorkerGlobalScope object's url's scheme, followed by ":".
+ return String::formatted("{}:", m_global_scope.url().scheme());
+}
+
+// https://html.spec.whatwg.org/multipage/workers.html#dom-workerlocation-host
+String WorkerLocation::host() const
+{
+ // The host getter steps are:
+ // 1. Let url be this's WorkerGlobalScope object's url.
+ auto const& url = m_global_scope.url();
+
+ // 2. If url's host is null, return the empty string.
+ if (url.host().is_empty())
+ return "";
+
+ // 3. If url's port is null, return url's host, serialized.
+ if (!url.port().has_value())
+ return url.host();
+
+ // 4. Return url's host, serialized, followed by ":" and url's port, serialized.
+ return String::formatted("{}:{}", url.host(), url.port().value());
+}
+
+// https://html.spec.whatwg.org/multipage/workers.html#dom-workerlocation-hostname
+String WorkerLocation::hostname() const
+{
+ // The hostname getter steps are:
+ // 1. Let host be this's WorkerGlobalScope object's url's host.
+ auto const& host = m_global_scope.url().host();
+
+ // 2. If host is null, return the empty string.
+ if (host.is_empty())
+ return "";
+
+ // 3. Return host, serialized.
+ return host;
+}
+
+// https://html.spec.whatwg.org/multipage/workers.html#dom-workerlocation-port
+String WorkerLocation::port() const
+{
+ // The port getter steps are:
+ // 1. Let port be this's WorkerGlobalScope object's url's port.
+ auto const& port = m_global_scope.url().port();
+
+ // 2. If port is null, return the empty string.
+ if (!port.has_value())
+ return "";
+ // 3. Return port, serialized.
+ return String::number(port.value());
+}
+
+// https://html.spec.whatwg.org/multipage/workers.html#dom-workerlocation-pathname
+String WorkerLocation::pathname() const
+{
+ // The pathname getter steps are to return the result of URL path serializing this's WorkerGlobalScope object's url.
+ return m_global_scope.url().path();
+}
+
+// https://html.spec.whatwg.org/multipage/workers.html#dom-workerlocation-search
+String WorkerLocation::search() const
+{
+ // The search getter steps are:
+ // 1. Let query be this's WorkerGlobalScope object's url's query.
+ auto const& query = m_global_scope.url().query();
+
+ // 2. If query is either null or the empty string, return the empty string.
+ if (query.is_empty())
+ return "";
+
+ // 3. Return "?", followed by query.
+ return String::formatted("?{}", query);
+}
+
+// https://html.spec.whatwg.org/multipage/workers.html#dom-workerlocation-hash
+String WorkerLocation::hash() const
+{
+ // The hash getter steps are:
+ // 1. Let fragment be this's WorkerGlobalScope object's url's fragment.
+ auto const& fragment = m_global_scope.url().fragment();
+
+ // 2. If fragment is either null or the empty string, return the empty string.
+ if (fragment.is_empty())
+ return "";
+
+ // 3. Return "#", followed by fragment.
+ return String::formatted("#{}", fragment);
+}
+
+WorkerLocation::WorkerLocation(WorkerGlobalScope& global_scope)
+ : m_global_scope(global_scope)
+{
+}
+
+}
diff --git a/Userland/Libraries/LibWeb/HTML/WorkerLocation.h b/Userland/Libraries/LibWeb/HTML/WorkerLocation.h
new file mode 100644
index 0000000000..384b74bfc7
--- /dev/null
+++ b/Userland/Libraries/LibWeb/HTML/WorkerLocation.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2022, Andrew Kaster <akaster@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/RefCounted.h>
+#include <LibWeb/Bindings/Wrappable.h>
+#include <LibWeb/Forward.h>
+
+namespace Web::HTML {
+
+// https://html.spec.whatwg.org/multipage/workers.html#worker-locations
+class WorkerLocation
+ : public RefCounted<WorkerLocation>
+ , public Bindings::Wrappable {
+public:
+ using WrapperType = Bindings::WorkerLocationWrapper;
+
+ static NonnullRefPtr<WorkerLocation> create(WorkerGlobalScope& global_scope)
+ {
+ return adopt_ref(*new WorkerLocation(global_scope));
+ }
+
+ String href() const;
+ String origin() const;
+ String protocol() const;
+ String host() const;
+ String hostname() const;
+ String port() const;
+ String pathname() const;
+ String search() const;
+ String hash() const;
+
+private:
+ WorkerLocation(WorkerGlobalScope&);
+
+ WorkerGlobalScope& m_global_scope;
+};
+
+}
diff --git a/Userland/Libraries/LibWeb/HTML/WorkerLocation.idl b/Userland/Libraries/LibWeb/HTML/WorkerLocation.idl
new file mode 100644
index 0000000000..464ca0c321
--- /dev/null
+++ b/Userland/Libraries/LibWeb/HTML/WorkerLocation.idl
@@ -0,0 +1,12 @@
+[Exposed=Worker]
+interface WorkerLocation {
+ stringifier readonly attribute USVString href;
+ readonly attribute USVString origin;
+ readonly attribute USVString protocol;
+ readonly attribute USVString host;
+ readonly attribute USVString hostname;
+ readonly attribute USVString port;
+ readonly attribute USVString pathname;
+ readonly attribute USVString search;
+ readonly attribute USVString hash;
+};
diff --git a/Userland/Libraries/LibWeb/HTML/WorkerNavigator.h b/Userland/Libraries/LibWeb/HTML/WorkerNavigator.h
new file mode 100644
index 0000000000..6d992e1305
--- /dev/null
+++ b/Userland/Libraries/LibWeb/HTML/WorkerNavigator.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2022, Andrew Kaster <akaster@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/RefCounted.h>
+#include <LibWeb/Bindings/Wrappable.h>
+#include <LibWeb/Forward.h>
+
+namespace Web::HTML {
+
+// FIXME: Add Mixin APIs from https://html.spec.whatwg.org/multipage/workers.html#the-workernavigator-object
+class WorkerNavigator
+ : public RefCounted<WorkerNavigator>
+ , public Bindings::Wrappable {
+public:
+ using WrapperType = Bindings::WorkerNavigatorWrapper;
+};
+
+}
diff --git a/Userland/Libraries/LibWeb/HTML/WorkerNavigator.idl b/Userland/Libraries/LibWeb/HTML/WorkerNavigator.idl
new file mode 100644
index 0000000000..41558f18c2
--- /dev/null
+++ b/Userland/Libraries/LibWeb/HTML/WorkerNavigator.idl
@@ -0,0 +1,8 @@
+[Exposed=Worker]
+interface WorkerNavigator {};
+
+// FIXME: Add these mixins that are used to prevent duplication b/w WorkerNavigator and Navigator
+// WorkerNavigator includes NavigatorID;
+// WorkerNavigator includes NavigatorLanguage;
+// WorkerNavigator includes NavigatorOnLine;
+// WorkerNavigator includes NavigatorConcurrentHardware;