diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateWindowOrWorkerInterfaces.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateWindowOrWorkerInterfaces.cpp index 1a6a361637..f0707e1545 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateWindowOrWorkerInterfaces.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateWindowOrWorkerInterfaces.cpp @@ -69,14 +69,12 @@ static ErrorOr generate_exposed_interface_implementation(StringView class_ )~~~"); } - // FIXME: Special case window. We should convert Window, Location, and Navigator to use IDL + // FIXME: Special case window. We should convert Window and Location to use IDL if (class_name == "Window"sv) { generator.append(R"~~~(#include #include #include #include -#include -#include )~~~"); } @@ -108,12 +106,11 @@ void add_@global_object_snake_name@_exposed_interfaces(JS::Object& global, JS::R add_interface(gen, interface.name, interface.prototype_class, interface.constructor_class); } - // FIXME: Special case window. We should convert Window, Location, and Navigator to use IDL + // FIXME: Special case window. We should convert Window and Location to use IDL if (class_name == "Window"sv) { auto gen = generator.fork(); add_interface(gen, "Window"sv, "WindowPrototype"sv, "WindowConstructor"sv); add_interface(gen, "Location"sv, "LocationPrototype"sv, "LocationConstructor"sv); - add_interface(gen, "Navigator"sv, "NavigatorPrototype"sv, "NavigatorConstructor"sv); } generator.append(R"~~~( diff --git a/Userland/Libraries/LibWeb/Bindings/NavigatorConstructor.cpp b/Userland/Libraries/LibWeb/Bindings/NavigatorConstructor.cpp deleted file mode 100644 index 605df333c2..0000000000 --- a/Userland/Libraries/LibWeb/Bindings/NavigatorConstructor.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2022, the SerenityOS developers. - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include - -namespace Web::Bindings { - -NavigatorConstructor::NavigatorConstructor(JS::Realm& realm) - : NativeFunction(*realm.intrinsics().function_prototype()) -{ -} - -NavigatorConstructor::~NavigatorConstructor() = default; - -JS::ThrowCompletionOr NavigatorConstructor::call() -{ - return vm().throw_completion(JS::ErrorType::ConstructorWithoutNew, "Navigator"); -} - -JS::ThrowCompletionOr NavigatorConstructor::construct(FunctionObject&) -{ - return vm().throw_completion(JS::ErrorType::NotAConstructor, "Navigator"); -} - -void NavigatorConstructor::initialize(JS::Realm& realm) -{ - auto& vm = this->vm(); - - NativeFunction::initialize(realm); - define_direct_property(vm.names.prototype, &cached_web_prototype(realm, "Navigator"), 0); - define_direct_property(vm.names.length, JS::Value(0), JS::Attribute::Configurable); -} - -} diff --git a/Userland/Libraries/LibWeb/Bindings/NavigatorConstructor.h b/Userland/Libraries/LibWeb/Bindings/NavigatorConstructor.h deleted file mode 100644 index add6edde6c..0000000000 --- a/Userland/Libraries/LibWeb/Bindings/NavigatorConstructor.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2022, the SerenityOS developers. - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include - -namespace Web::Bindings { - -class NavigatorConstructor : public JS::NativeFunction { - JS_OBJECT(NavigatorConstructor, JS::NativeFunction); - -public: - explicit NavigatorConstructor(JS::Realm&); - virtual void initialize(JS::Realm&) override; - virtual ~NavigatorConstructor() override; - - virtual JS::ThrowCompletionOr call() override; - virtual JS::ThrowCompletionOr construct(JS::FunctionObject& new_target) override; - -private: - virtual bool has_constructor() const override { return true; } -}; - -} diff --git a/Userland/Libraries/LibWeb/Bindings/NavigatorObject.cpp b/Userland/Libraries/LibWeb/Bindings/NavigatorObject.cpp deleted file mode 100644 index e7d3ceae22..0000000000 --- a/Userland/Libraries/LibWeb/Bindings/NavigatorObject.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2020, Andreas Kling - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include - -namespace Web { -namespace Bindings { - -NavigatorObject::NavigatorObject(JS::Realm& realm) - : Object(cached_web_prototype(realm, "Navigator")) -{ -} - -void NavigatorObject::initialize(JS::Realm& realm) -{ - auto& heap = this->heap(); - auto* languages = MUST(JS::Array::create(realm, 0)); - languages->indexed_properties().append(js_string(heap, "en-US")); - - // FIXME: All of these should be in Navigator's prototype and be native accessors - u8 attr = JS::Attribute::Configurable | JS::Attribute::Writable | JS::Attribute::Enumerable; - define_direct_property("appCodeName", js_string(heap, "Mozilla"), attr); - define_direct_property("appName", js_string(heap, "Netscape"), attr); - define_direct_property("appVersion", js_string(heap, "4.0"), attr); - define_direct_property("language", languages->get_without_side_effects(0), attr); - define_direct_property("languages", languages, attr); - define_direct_property("platform", js_string(heap, "SerenityOS"), attr); - define_direct_property("product", js_string(heap, "Gecko"), attr); - - define_native_accessor(realm, "userAgent", user_agent_getter, {}, JS::Attribute::Configurable | JS::Attribute::Enumerable); - define_native_accessor(realm, "cookieEnabled", cookie_enabled_getter, {}, JS::Attribute::Configurable | JS::Attribute::Enumerable); - - define_native_function(realm, "javaEnabled", java_enabled, 0, JS::Attribute::Configurable | JS::Attribute::Enumerable); - - // FIXME: Reflect actual connectivity status. - define_direct_property("onLine", JS::Value(true), attr); -} - -JS_DEFINE_NATIVE_FUNCTION(NavigatorObject::user_agent_getter) -{ - return JS::js_string(vm, ResourceLoader::the().user_agent()); -} - -JS_DEFINE_NATIVE_FUNCTION(NavigatorObject::cookie_enabled_getter) -{ - // No way of disabling cookies right now :^) - return JS::Value(true); -} - -// https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator-javaenabled -JS_DEFINE_NATIVE_FUNCTION(NavigatorObject::java_enabled) -{ - // The NavigatorPlugins mixin's javaEnabled() method steps are to return false. - return JS::Value(false); -} - -} - -} diff --git a/Userland/Libraries/LibWeb/Bindings/NavigatorObject.h b/Userland/Libraries/LibWeb/Bindings/NavigatorObject.h deleted file mode 100644 index e91a7c6198..0000000000 --- a/Userland/Libraries/LibWeb/Bindings/NavigatorObject.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2020, Andreas Kling - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include - -namespace Web { -namespace Bindings { - -class NavigatorObject final : public JS::Object { - JS_OBJECT(NavigatorObject, JS::Object); - -public: - NavigatorObject(JS::Realm&); - virtual void initialize(JS::Realm&) override; - virtual ~NavigatorObject() override = default; - -private: - JS_DECLARE_NATIVE_FUNCTION(user_agent_getter); - JS_DECLARE_NATIVE_FUNCTION(cookie_enabled_getter); - JS_DECLARE_NATIVE_FUNCTION(java_enabled); -}; - -} -} diff --git a/Userland/Libraries/LibWeb/Bindings/NavigatorPrototype.h b/Userland/Libraries/LibWeb/Bindings/NavigatorPrototype.h deleted file mode 100644 index 504b56aaec..0000000000 --- a/Userland/Libraries/LibWeb/Bindings/NavigatorPrototype.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2022, the SerenityOS developers. - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include -#include - -namespace Web::Bindings { - -class NavigatorPrototype final : public JS::Object { - JS_OBJECT(NavigatorPrototype, JS::Object); - -public: - explicit NavigatorPrototype(JS::Realm& realm) - : JS::Object(*realm.intrinsics().object_prototype()) - { - } -}; - -} diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index 4c8a27bf07..060c4ce06a 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -10,8 +10,6 @@ set(SOURCES Bindings/LocationConstructor.cpp Bindings/LocationObject.cpp Bindings/MainThreadVM.cpp - Bindings/NavigatorConstructor.cpp - Bindings/NavigatorObject.cpp Bindings/OptionConstructor.cpp Bindings/PlatformObject.cpp Bindings/WindowConstructor.cpp @@ -245,6 +243,8 @@ set(SOURCES HTML/MessageChannel.cpp HTML/MessageEvent.cpp HTML/MessagePort.cpp + HTML/Navigator.cpp + HTML/NavigatorID.cpp HTML/PageTransitionEvent.cpp HTML/Parser/Entities.cpp HTML/Parser/HTMLEncodingDetection.cpp diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h index f225fdd09a..aee0245f86 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -304,6 +304,7 @@ class MessageChannel; class MessageEvent; class MessagePort; struct NavigationParams; +class Navigator; class Origin; class PageTransitionEvent; class Path2D; diff --git a/Userland/Libraries/LibWeb/HTML/Navigator.cpp b/Userland/Libraries/LibWeb/HTML/Navigator.cpp new file mode 100644 index 0000000000..e4af99045d --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/Navigator.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2022, Andrew Kaster + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include + +namespace Web::HTML { + +JS::NonnullGCPtr Navigator::create(JS::Realm& realm) +{ + return *realm.heap().allocate(realm, realm); +} + +Navigator::Navigator(JS::Realm& realm) + : PlatformObject(realm) +{ + set_prototype(&Bindings::cached_web_prototype(realm, "Navigator")); +} + +Navigator::~Navigator() = default; + +} diff --git a/Userland/Libraries/LibWeb/HTML/Navigator.h b/Userland/Libraries/LibWeb/HTML/Navigator.h new file mode 100644 index 0000000000..3b54013b04 --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/Navigator.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2022, Andrew Kaster + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace Web::HTML { + +class Navigator : public Bindings::PlatformObject + , public NavigatorConcurrentHardwareMixin + , public NavigatorIDMixin + , public NavigatorLanguageMixin + , public NavigatorOnLineMixin { + WEB_PLATFORM_OBJECT(Navigator, Bindings::PlatformObject); + +public: + static JS::NonnullGCPtr create(JS::Realm&); + + // FIXME: Implement NavigatorContentUtilsMixin + + // NavigatorCookies + // FIXME: Hook up to Agent level state + // https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator-cookieenabled + bool cookie_enabled() const { return true; } + + // NavigatorPlugins + // FIXME: Actually support pdf viewing + // https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator-javaenabled + bool java_enabled() const { return false; } + + // https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator-pdfviewerenabled + bool pdf_viewer_enabled() const { return false; } + + virtual ~Navigator() override; + +private: + explicit Navigator(JS::Realm&); +}; + +} diff --git a/Userland/Libraries/LibWeb/HTML/Navigator.idl b/Userland/Libraries/LibWeb/HTML/Navigator.idl new file mode 100644 index 0000000000..0c0cd29563 --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/Navigator.idl @@ -0,0 +1,41 @@ +#import +#import +#import +#import + +// https://html.spec.whatwg.org/multipage/system-state.html#navigator +[Exposed=Window] +interface Navigator { + // objects implementing this interface also implement the interfaces given below +}; + +// NOTE: As NavigatorContentUtils, NavigatorCookies, and NavigatorPlugins are not used in WorkerNavigator, +// we define them here. + +// https://html.spec.whatwg.org/multipage/system-state.html#navigatorcontentutils +interface mixin NavigatorContentUtils { + // FIXME: [SecureContext] undefined registerProtocolHandler(DOMString scheme, USVString url); + // FIXME: [SecureContext] undefined unregisterProtocolHandler(DOMString scheme, USVString url); +}; + +// https://html.spec.whatwg.org/multipage/system-state.html#navigatorcookies +interface mixin NavigatorCookies { + readonly attribute boolean cookieEnabled; +}; + +// https://html.spec.whatwg.org/multipage/system-state.html#navigatorplugins +interface mixin NavigatorPlugins { + // FIXME: [SameObject] readonly attribute PluginArray plugins; + // FIXME: [SameObject] readonly attribute MimeTypeArray mimeTypes; + boolean javaEnabled(); + readonly attribute boolean pdfViewerEnabled; +}; + +Navigator includes NavigatorID; +Navigator includes NavigatorLanguage; +Navigator includes NavigatorOnLine; +Navigator includes NavigatorContentUtils; +Navigator includes NavigatorCookies; +Navigator includes NavigatorPlugins; +Navigator includes NavigatorConcurrentHardware; + diff --git a/Userland/Libraries/LibWeb/HTML/NavigatorConcurrentHardware.h b/Userland/Libraries/LibWeb/HTML/NavigatorConcurrentHardware.h new file mode 100644 index 0000000000..0276641b35 --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/NavigatorConcurrentHardware.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2022, Andrew Kaster + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +namespace Web::HTML { + +class NavigatorConcurrentHardwareMixin { +public: + // https://html.spec.whatwg.org/multipage/workers.html#dom-navigator-hardwareconcurrency + unsigned long long hardware_concurrency() { return 1; } +}; + +} diff --git a/Userland/Libraries/LibWeb/HTML/NavigatorConcurrentHardware.idl b/Userland/Libraries/LibWeb/HTML/NavigatorConcurrentHardware.idl new file mode 100644 index 0000000000..73d82a3653 --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/NavigatorConcurrentHardware.idl @@ -0,0 +1,4 @@ +// https://html.spec.whatwg.org/multipage/workers.html#navigatorconcurrenthardware +interface mixin NavigatorConcurrentHardware { + readonly attribute unsigned long long hardwareConcurrency; +}; diff --git a/Userland/Libraries/LibWeb/HTML/NavigatorID.cpp b/Userland/Libraries/LibWeb/HTML/NavigatorID.cpp new file mode 100644 index 0000000000..935cb2caa8 --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/NavigatorID.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2022, Andrew Kaster + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include + +namespace Web::HTML { + +// https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator-appversion +String NavigatorIDMixin::app_version() const +{ + // Must return the appropriate string that starts with "5.0 (", as follows: + + // Let trail be the substring of default `User-Agent` value that follows the "Mozilla/" prefix. + auto user_agent_string = ResourceLoader::the().user_agent(); + + auto trail = user_agent_string.substring_view(strlen("Mozilla/"), user_agent_string.length() - strlen("Mozilla/")); + + // If the navigator compatibility mode is Chrome or WebKit + // NOTE: We are using Chrome for now. Make sure to update all APIs if you add a toggle for this. + + // Return trail. + return trail; + + // If the navigator compatibility mode is Gecko + // If trail starts with "5.0 (Windows", then return "5.0 (Windows)". + // Otherwise, return the prefix of trail up to but not including the first U+003B (;), concatenated with the + // character U+0029 RIGHT PARENTHESIS. For example, "5.0 (Macintosh)", "5.0 (Android 10)", or "5.0 (X11)". +} + +// https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator-platform +String NavigatorIDMixin::platform() const +{ + // Must return a string representing the platform on which the browser is executing (e.g. "MacIntel", "Win32", + // "Linux x86_64", "Linux armv81") or, for privacy and compatibility, a string that is commonly returned on another + // platform. + + // FIXME: Use some portion of the user agent string to make spoofing work 100% + return "SerenityOS"; +} + +// https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator-useragent +String NavigatorIDMixin::user_agent() const +{ + // Must return the default `User-Agent` value. + return ResourceLoader::the().user_agent(); +} + +} diff --git a/Userland/Libraries/LibWeb/HTML/NavigatorID.h b/Userland/Libraries/LibWeb/HTML/NavigatorID.h new file mode 100644 index 0000000000..ef4318a20d --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/NavigatorID.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2022, Andrew Kaster + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +namespace Web::HTML { + +class NavigatorIDMixin { +public: + // WARNING: Any information in this API that varies from user to user can be used to profile the user. In fact, if + // enough such information is available, a user can actually be uniquely identified. For this reason, user agent + // implementers are strongly urged to include as little information in this API as possible. + + // https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator-appcodename + String app_code_name() const { return "Mozilla"sv; } + + // https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator-appcodename + String app_name() const { return "Netscape"sv; } + + // https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator-appversion + String app_version() const; + + // https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator-platform + String platform() const; + + // https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator-product + String product() const { return "Gecko"sv; } + + // https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator-productsub + String product_sub() const { return "20030107"sv; } // Compatability mode "Chrome" + + // https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator-useragent + String user_agent() const; + + // https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator-vendor + String vendor() const { return "Google Inc."sv; } // Compatability mode "Chrome" + + // https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator-vendorsub + String vendor_sub() const { return ""sv; } + + // NOTE: If the navigator compatibility mode is Gecko, then the user agent must also support the following partial interface: + // bool taint_enabled() + // String oscpu() +}; + +} diff --git a/Userland/Libraries/LibWeb/HTML/NavigatorID.idl b/Userland/Libraries/LibWeb/HTML/NavigatorID.idl new file mode 100644 index 0000000000..97b20d9baf --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/NavigatorID.idl @@ -0,0 +1,12 @@ +// https://html.spec.whatwg.org/multipage/system-state.html#navigatorid +interface mixin NavigatorID { + readonly attribute DOMString appCodeName; // constant "Mozilla" + readonly attribute DOMString appName; // constant "Netscape" + readonly attribute DOMString appVersion; + readonly attribute DOMString platform; + readonly attribute DOMString product; // constant "Gecko" + [Exposed=Window] readonly attribute DOMString productSub; + readonly attribute DOMString userAgent; + [Exposed=Window] readonly attribute DOMString vendor; + [Exposed=Window] readonly attribute DOMString vendorSub; // constant "" +}; diff --git a/Userland/Libraries/LibWeb/HTML/NavigatorLanguage.h b/Userland/Libraries/LibWeb/HTML/NavigatorLanguage.h new file mode 100644 index 0000000000..514d093e7a --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/NavigatorLanguage.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022, Andrew Kaster + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +namespace Web::HTML { + +class NavigatorLanguageMixin { +public: + // https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator-language + String language() const { return m_current_preferred_languages[0]; } + + // https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator-languages + // FIXME: The same object must be returned until the user agent needs to return different values, or values in a + // different order. + Vector languages() const { return m_current_preferred_languages; } + +protected: + Vector m_current_preferred_languages = { "en-US" }; +}; + +} diff --git a/Userland/Libraries/LibWeb/HTML/NavigatorLanguage.idl b/Userland/Libraries/LibWeb/HTML/NavigatorLanguage.idl new file mode 100644 index 0000000000..adc6a986f3 --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/NavigatorLanguage.idl @@ -0,0 +1,7 @@ +// https://html.spec.whatwg.org/multipage/system-state.html#navigatorlanguage +interface mixin NavigatorLanguage { + readonly attribute DOMString language; + // FIXME: readonly attribute FrozenArray languages; + // This is supposed to be a FrozenArray that always returns the same object + sequence languages(); +}; diff --git a/Userland/Libraries/LibWeb/HTML/NavigatorOnLine.h b/Userland/Libraries/LibWeb/HTML/NavigatorOnLine.h new file mode 100644 index 0000000000..20d7480541 --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/NavigatorOnLine.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2022, Andrew Kaster + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +namespace Web::HTML { + +class NavigatorOnLineMixin { +public: + // https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator-online + // FIXME: Reflect actual connectivity status. + bool on_line() const { return true; } +}; + +} diff --git a/Userland/Libraries/LibWeb/HTML/NavigatorOnLine.idl b/Userland/Libraries/LibWeb/HTML/NavigatorOnLine.idl new file mode 100644 index 0000000000..bb87b2fb92 --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/NavigatorOnLine.idl @@ -0,0 +1,4 @@ +// https://html.spec.whatwg.org/multipage/system-state.html#navigatoronline +interface mixin NavigatorOnLine { + readonly attribute boolean onLine; +}; diff --git a/Userland/Libraries/LibWeb/HTML/Window.cpp b/Userland/Libraries/LibWeb/HTML/Window.cpp index c28301da4b..3a71f21144 100644 --- a/Userland/Libraries/LibWeb/HTML/Window.cpp +++ b/Userland/Libraries/LibWeb/HTML/Window.cpp @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -33,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -95,6 +95,7 @@ void Window::visit_edges(JS::Cell::Visitor& visitor) visitor.visit(m_screen.ptr()); visitor.visit(m_location_object); visitor.visit(m_crypto); + visitor.visit(m_navigator); for (auto& it : m_timers) visitor.visit(it.value.ptr()); } @@ -813,9 +814,9 @@ void Window::initialize_web_interfaces(Badge) m_location_object = heap().allocate(realm, realm); - auto* m_navigator_object = heap().allocate(realm, realm); - define_direct_property("navigator", m_navigator_object, JS::Attribute::Enumerable | JS::Attribute::Configurable); - define_direct_property("clientInformation", m_navigator_object, JS::Attribute::Enumerable | JS::Attribute::Configurable); + m_navigator = heap().allocate(realm, realm); + define_direct_property("navigator", m_navigator, JS::Attribute::Enumerable | JS::Attribute::Configurable); + define_direct_property("clientInformation", m_navigator, JS::Attribute::Enumerable | JS::Attribute::Configurable); // NOTE: location is marked as [LegacyUnforgeable], meaning it isn't configurable. define_native_accessor(realm, "location", location_getter, location_setter, JS::Attribute::Enumerable); diff --git a/Userland/Libraries/LibWeb/HTML/Window.h b/Userland/Libraries/LibWeb/HTML/Window.h index 07f7165c04..8e33443125 100644 --- a/Userland/Libraries/LibWeb/HTML/Window.h +++ b/Userland/Libraries/LibWeb/HTML/Window.h @@ -157,6 +157,7 @@ private: JS::GCPtr m_performance; JS::GCPtr m_crypto; JS::GCPtr m_screen; + JS::GCPtr m_navigator; AnimationFrameCallbackDriver m_animation_frame_callback_driver; diff --git a/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.h b/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.h index 2d7dee7e36..7ca3a3f822 100644 --- a/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.h +++ b/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.h @@ -79,7 +79,6 @@ private: JS::GCPtr m_location; - // FIXME: Implement WorkerNavigator according to the spec JS::GCPtr m_navigator; // FIXME: Add all these internal slots diff --git a/Userland/Libraries/LibWeb/HTML/WorkerNavigator.cpp b/Userland/Libraries/LibWeb/HTML/WorkerNavigator.cpp index 25915fa413..ecc556ff64 100644 --- a/Userland/Libraries/LibWeb/HTML/WorkerNavigator.cpp +++ b/Userland/Libraries/LibWeb/HTML/WorkerNavigator.cpp @@ -5,6 +5,7 @@ */ #include +#include #include #include @@ -18,7 +19,7 @@ JS::NonnullGCPtr WorkerNavigator::create(WorkerGlobalScope& glo WorkerNavigator::WorkerNavigator(WorkerGlobalScope& global_scope) : PlatformObject(global_scope.realm()) { - // FIXME: Set prototype once we can get to worker scope prototypes. + set_prototype(&Bindings::cached_web_prototype(global_scope.realm(), "WorkerNavigator")); } WorkerNavigator::~WorkerNavigator() = default; diff --git a/Userland/Libraries/LibWeb/HTML/WorkerNavigator.h b/Userland/Libraries/LibWeb/HTML/WorkerNavigator.h index 0d7b6e530d..a9557aa3d3 100644 --- a/Userland/Libraries/LibWeb/HTML/WorkerNavigator.h +++ b/Userland/Libraries/LibWeb/HTML/WorkerNavigator.h @@ -7,11 +7,18 @@ #pragma once #include +#include +#include +#include +#include namespace Web::HTML { -// FIXME: Add Mixin APIs from https://html.spec.whatwg.org/multipage/workers.html#the-workernavigator-object -class WorkerNavigator : public Bindings::PlatformObject { +class WorkerNavigator : public Bindings::PlatformObject + , public NavigatorConcurrentHardwareMixin + , public NavigatorIDMixin + , public NavigatorLanguageMixin + , public NavigatorOnLineMixin { WEB_PLATFORM_OBJECT(WorkerNavigator, Bindings::PlatformObject); public: diff --git a/Userland/Libraries/LibWeb/HTML/WorkerNavigator.idl b/Userland/Libraries/LibWeb/HTML/WorkerNavigator.idl index 41558f18c2..079f91ff6b 100644 --- a/Userland/Libraries/LibWeb/HTML/WorkerNavigator.idl +++ b/Userland/Libraries/LibWeb/HTML/WorkerNavigator.idl @@ -1,8 +1,13 @@ +#import +#import +#import +#import + +// https://html.spec.whatwg.org/multipage/workers.html#workernavigator [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; +WorkerNavigator includes NavigatorID; +WorkerNavigator includes NavigatorLanguage; +WorkerNavigator includes NavigatorOnLine; +WorkerNavigator includes NavigatorConcurrentHardware; diff --git a/Userland/Libraries/LibWeb/idl_files.cmake b/Userland/Libraries/LibWeb/idl_files.cmake index 9427d3d1c7..0eb277be3d 100644 --- a/Userland/Libraries/LibWeb/idl_files.cmake +++ b/Userland/Libraries/LibWeb/idl_files.cmake @@ -146,6 +146,7 @@ libweb_js_bindings(HTML/ImageData) libweb_js_bindings(HTML/MessageChannel) libweb_js_bindings(HTML/MessageEvent) libweb_js_bindings(HTML/MessagePort) +libweb_js_bindings(HTML/Navigator) libweb_js_bindings(HTML/PageTransitionEvent) libweb_js_bindings(HTML/Path2D) libweb_js_bindings(HTML/PromiseRejectionEvent)