1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 04:17:35 +00:00

LibWeb: Re-implement HTML::Navigator using IDL

Get rid of the bespoke NavigatorObject class and use the modern IDL
strategies for creating platform objects to re-implement Navigator and
its associcated mixin interfaces. While we're here, implement it in a
way that brings WorkerNavigator up to spec :^)
This commit is contained in:
Andrew Kaster 2022-10-08 20:53:08 -06:00 committed by Andreas Kling
parent 14e1513077
commit 2d5bee256e
27 changed files with 343 additions and 208 deletions

View file

@ -0,0 +1,27 @@
/*
* Copyright (c) 2022, Andrew Kaster <akaster@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibJS/Heap/Heap.h>
#include <LibJS/Runtime/Realm.h>
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/HTML/Navigator.h>
namespace Web::HTML {
JS::NonnullGCPtr<Navigator> Navigator::create(JS::Realm& realm)
{
return *realm.heap().allocate<Navigator>(realm, realm);
}
Navigator::Navigator(JS::Realm& realm)
: PlatformObject(realm)
{
set_prototype(&Bindings::cached_web_prototype(realm, "Navigator"));
}
Navigator::~Navigator() = default;
}

View file

@ -0,0 +1,48 @@
/*
* Copyright (c) 2022, Andrew Kaster <akaster@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibWeb/Bindings/PlatformObject.h>
#include <LibWeb/HTML/NavigatorConcurrentHardware.h>
#include <LibWeb/HTML/NavigatorID.h>
#include <LibWeb/HTML/NavigatorLanguage.h>
#include <LibWeb/HTML/NavigatorOnLine.h>
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<Navigator> 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&);
};
}

View file

@ -0,0 +1,41 @@
#import <HTML/NavigatorID.idl>
#import <HTML/NavigatorLanguage.idl>
#import <HTML/NavigatorOnLine.idl>
#import <HTML/NavigatorConcurrentHardware.idl>
// 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;

View file

@ -0,0 +1,17 @@
/*
* Copyright (c) 2022, Andrew Kaster <akaster@serenityos.org>
*
* 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; }
};
}

View file

@ -0,0 +1,4 @@
// https://html.spec.whatwg.org/multipage/workers.html#navigatorconcurrenthardware
interface mixin NavigatorConcurrentHardware {
readonly attribute unsigned long long hardwareConcurrency;
};

View file

@ -0,0 +1,53 @@
/*
* Copyright (c) 2022, Andrew Kaster <akaster@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/String.h>
#include <LibWeb/HTML/NavigatorID.h>
#include <LibWeb/Loader/ResourceLoader.h>
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();
}
}

View file

@ -0,0 +1,51 @@
/*
* Copyright (c) 2022, Andrew Kaster <akaster@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/String.h>
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()
};
}

View file

@ -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 ""
};

View file

@ -0,0 +1,28 @@
/*
* Copyright (c) 2022, Andrew Kaster <akaster@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/String.h>
#include <AK/Vector.h>
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<String> languages() const { return m_current_preferred_languages; }
protected:
Vector<String> m_current_preferred_languages = { "en-US" };
};
}

View file

@ -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<DOMString> languages;
// This is supposed to be a FrozenArray that always returns the same object
sequence<DOMString> languages();
};

View file

@ -0,0 +1,18 @@
/*
* Copyright (c) 2022, Andrew Kaster <akaster@serenityos.org>
*
* 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; }
};
}

View file

@ -0,0 +1,4 @@
// https://html.spec.whatwg.org/multipage/system-state.html#navigatoronline
interface mixin NavigatorOnLine {
readonly attribute boolean onLine;
};

View file

@ -17,7 +17,6 @@
#include <LibWeb/Bindings/CSSNamespace.h>
#include <LibWeb/Bindings/ExceptionOrUtils.h>
#include <LibWeb/Bindings/LocationObject.h>
#include <LibWeb/Bindings/NavigatorObject.h>
#include <LibWeb/Bindings/Replaceable.h>
#include <LibWeb/Bindings/WindowExposedInterfaces.h>
#include <LibWeb/Bindings/WindowPrototype.h>
@ -33,6 +32,7 @@
#include <LibWeb/HTML/EventHandler.h>
#include <LibWeb/HTML/EventLoop/EventLoop.h>
#include <LibWeb/HTML/MessageEvent.h>
#include <LibWeb/HTML/Navigator.h>
#include <LibWeb/HTML/Origin.h>
#include <LibWeb/HTML/PageTransitionEvent.h>
#include <LibWeb/HTML/Scripting/ClassicScript.h>
@ -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<WindowEnvironmentSettingsObject>)
m_location_object = heap().allocate<Bindings::LocationObject>(realm, realm);
auto* m_navigator_object = heap().allocate<Bindings::NavigatorObject>(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<HTML::Navigator>(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);

View file

@ -157,6 +157,7 @@ private:
JS::GCPtr<HighResolutionTime::Performance> m_performance;
JS::GCPtr<Crypto::Crypto> m_crypto;
JS::GCPtr<CSS::Screen> m_screen;
JS::GCPtr<HTML::Navigator> m_navigator;
AnimationFrameCallbackDriver m_animation_frame_callback_driver;

View file

@ -79,7 +79,6 @@ private:
JS::GCPtr<WorkerLocation> m_location;
// FIXME: Implement WorkerNavigator according to the spec
JS::GCPtr<WorkerNavigator> m_navigator;
// FIXME: Add all these internal slots

View file

@ -5,6 +5,7 @@
*/
#include <LibJS/Heap/Heap.h>
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/HTML/WorkerGlobalScope.h>
#include <LibWeb/HTML/WorkerNavigator.h>
@ -18,7 +19,7 @@ JS::NonnullGCPtr<WorkerNavigator> 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;

View file

@ -7,11 +7,18 @@
#pragma once
#include <LibWeb/Bindings/PlatformObject.h>
#include <LibWeb/HTML/NavigatorConcurrentHardware.h>
#include <LibWeb/HTML/NavigatorID.h>
#include <LibWeb/HTML/NavigatorLanguage.h>
#include <LibWeb/HTML/NavigatorOnLine.h>
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:

View file

@ -1,8 +1,13 @@
#import <HTML/NavigatorID.idl>
#import <HTML/NavigatorLanguage.idl>
#import <HTML/NavigatorOnLine.idl>
#import <HTML/NavigatorConcurrentHardware.idl>
// 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;