diff --git a/Libraries/LibWeb/CMakeLists.txt b/Libraries/LibWeb/CMakeLists.txt index 64b0e557c48..8dd32119fac 100644 --- a/Libraries/LibWeb/CMakeLists.txt +++ b/Libraries/LibWeb/CMakeLists.txt @@ -314,6 +314,7 @@ set(SOURCES HTML/AudioTrack.cpp HTML/AudioTrackList.cpp HTML/AutocompleteElement.cpp + HTML/BarProp.cpp HTML/BeforeUnloadEvent.cpp HTML/BroadcastChannel.cpp HTML/BrowsingContext.cpp diff --git a/Libraries/LibWeb/Forward.h b/Libraries/LibWeb/Forward.h index f25a6cf5a4c..5481b19c46c 100644 --- a/Libraries/LibWeb/Forward.h +++ b/Libraries/LibWeb/Forward.h @@ -417,6 +417,7 @@ namespace Web::HTML { class AnimationFrameCallbackDriver; class AudioTrack; class AudioTrackList; +class BarProp; class BeforeUnloadEvent; class BroadcastChannel; class BrowsingContext; diff --git a/Libraries/LibWeb/HTML/BarProp.cpp b/Libraries/LibWeb/HTML/BarProp.cpp new file mode 100644 index 00000000000..ee7657c5cb0 --- /dev/null +++ b/Libraries/LibWeb/HTML/BarProp.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2025, the Ladybird developers. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include + +namespace Web::HTML { + +GC_DEFINE_ALLOCATOR(BarProp); + +GC::Ref BarProp::create(JS::Realm& realm) +{ + return realm.create(realm); +} + +BarProp::BarProp(JS::Realm& realm) + : Bindings::PlatformObject(realm) +{ +} + +// https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-barprop-visible +bool BarProp::visible() const +{ + // 1. Let browsingContext be this's relevant global object's browsing context. + auto& global_object = HTML::relevant_global_object(*this); + auto* browsing_context = as(global_object).associated_document().browsing_context(); + + // 2. If browsingContext is null, then return true. + if (!browsing_context) { + return true; + } + + // 3. Return the negation of browsingContext's top-level browsing context's is popup. + return browsing_context->top_level_browsing_context()->is_popup() != TokenizedFeature::Popup::Yes; +} + +void BarProp::initialize(JS::Realm& realm) +{ + Base::initialize(realm); + WEB_SET_PROTOTYPE_FOR_INTERFACE(BarProp); +} +} diff --git a/Libraries/LibWeb/HTML/BarProp.h b/Libraries/LibWeb/HTML/BarProp.h new file mode 100644 index 00000000000..d3b0a47778d --- /dev/null +++ b/Libraries/LibWeb/HTML/BarProp.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2025, the Ladybird developers. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include + +namespace Web::HTML { + +// https://html.spec.whatwg.org/multipage/nav-history-apis.html#barprop +class BarProp : public Bindings::PlatformObject { + WEB_PLATFORM_OBJECT(BarProp, Bindings::PlatformObject); + GC_DECLARE_ALLOCATOR(BarProp); + +public: + BarProp(JS::Realm&); + static GC::Ref create(JS::Realm&); + + [[nodiscard]] bool visible() const; + +private: + virtual void initialize(JS::Realm&) override; +}; +} diff --git a/Libraries/LibWeb/HTML/BarProp.idl b/Libraries/LibWeb/HTML/BarProp.idl new file mode 100644 index 00000000000..2143bae3091 --- /dev/null +++ b/Libraries/LibWeb/HTML/BarProp.idl @@ -0,0 +1,6 @@ + +// https://html.spec.whatwg.org/multipage/nav-history-apis.html#barprop +[Exposed=Window] +interface BarProp { + readonly attribute boolean visible; +}; diff --git a/Libraries/LibWeb/HTML/BrowsingContext.h b/Libraries/LibWeb/HTML/BrowsingContext.h index d0f5bf30256..466de1f3aa3 100644 --- a/Libraries/LibWeb/HTML/BrowsingContext.h +++ b/Libraries/LibWeb/HTML/BrowsingContext.h @@ -77,6 +77,7 @@ public: void set_opener_browsing_context(GC::Ptr browsing_context) { m_opener_browsing_context = browsing_context; } void set_is_popup(TokenizedFeature::Popup is_popup) { m_is_popup = is_popup; } + [[nodiscard]] TokenizedFeature::Popup is_popup() const { return m_is_popup; } SandboxingFlagSet popup_sandboxing_flag_set() const { return m_popup_sandboxing_flag_set; } void set_popup_sandboxing_flag_set(SandboxingFlagSet value) { m_popup_sandboxing_flag_set = value; } diff --git a/Libraries/LibWeb/HTML/Window.cpp b/Libraries/LibWeb/HTML/Window.cpp index 646f5d6981a..a665b2dbbdf 100644 --- a/Libraries/LibWeb/HTML/Window.cpp +++ b/Libraries/LibWeb/HTML/Window.cpp @@ -128,6 +128,12 @@ void Window::visit_edges(JS::Cell::Visitor& visitor) visitor.visit(m_pdf_viewer_plugin_objects); visitor.visit(m_pdf_viewer_mime_type_objects); visitor.visit(m_close_watcher_manager); + visitor.visit(m_locationbar); + visitor.visit(m_menubar); + visitor.visit(m_personalbar); + visitor.visit(m_scrollbars); + visitor.visit(m_statusbar); + visitor.visit(m_toolbar); } void Window::finalize() @@ -920,6 +926,60 @@ void Window::blur() // The blur() method steps are to do nothing. } +// https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-window-locationbar +GC::Ref Window::locationbar() +{ + if (!m_locationbar) + m_locationbar = BarProp::create(realm()); + + return *m_locationbar; +} + +// https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-window-menubar +GC::Ref Window::menubar() +{ + if (!m_menubar) + m_menubar = BarProp::create(realm()); + + return *m_menubar; +} + +// https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-window-personalbar +GC::Ref Window::personalbar() +{ + if (!m_personalbar) + m_personalbar = BarProp::create(realm()); + + return *m_personalbar; +} + +// https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-window-scrollbars +GC::Ref Window::scrollbars() +{ + if (!m_scrollbars) + m_scrollbars = BarProp::create(realm()); + + return *m_scrollbars; +} + +// https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-window-statusbar +GC::Ref Window::statusbar() +{ + if (!m_statusbar) + m_statusbar = BarProp::create(realm()); + + return *m_statusbar; +} + +// https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-window-toolbar +GC::Ref Window::toolbar() +{ + if (!m_toolbar) + m_toolbar = BarProp::create(realm()); + + return *m_toolbar; +} + // https://html.spec.whatwg.org/multipage/window-object.html#dom-frames GC::Ref Window::frames() const { diff --git a/Libraries/LibWeb/HTML/Window.h b/Libraries/LibWeb/HTML/Window.h index 4a8645973c0..7b427d03443 100644 --- a/Libraries/LibWeb/HTML/Window.h +++ b/Libraries/LibWeb/HTML/Window.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -173,6 +174,15 @@ public: void focus(); void blur(); + // For historical reasons, the Window interface had some properties that represented the visibility of certain web browser interface elements. + // For privacy and interoperability reasons, those properties now return values that represent whether the Window's browsing context's is popup property is true or false. + GC::Ref locationbar(); + GC::Ref menubar(); + GC::Ref personalbar(); + GC::Ref scrollbars(); + GC::Ref statusbar(); + GC::Ref toolbar(); + GC::Ref frames() const; u32 length(); GC::Ptr top() const; @@ -332,6 +342,13 @@ private: // https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-window-status // When the Window object is created, the attribute must be set to the empty string. It does not do anything else. String m_status; + + GC::Ptr m_locationbar; + GC::Ptr m_menubar; + GC::Ptr m_personalbar; + GC::Ptr m_scrollbars; + GC::Ptr m_statusbar; + GC::Ptr m_toolbar; }; void run_animation_frame_callbacks(DOM::Document&, double now); diff --git a/Libraries/LibWeb/HTML/Window.idl b/Libraries/LibWeb/HTML/Window.idl index 37c546ac635..cd1e11585ab 100644 --- a/Libraries/LibWeb/HTML/Window.idl +++ b/Libraries/LibWeb/HTML/Window.idl @@ -34,6 +34,13 @@ interface Window : EventTarget { undefined focus(); undefined blur(); + [Replaceable] readonly attribute BarProp locationbar; + [Replaceable] readonly attribute BarProp menubar; + [Replaceable] readonly attribute BarProp personalbar; + [Replaceable] readonly attribute BarProp scrollbars; + [Replaceable] readonly attribute BarProp statusbar; + [Replaceable] readonly attribute BarProp toolbar; + // other browsing contexts [Replaceable] readonly attribute WindowProxy frames; [Replaceable] readonly attribute unsigned long length; diff --git a/Libraries/LibWeb/idl_files.cmake b/Libraries/LibWeb/idl_files.cmake index 54d1da8b7fb..6d6af4e6a62 100644 --- a/Libraries/LibWeb/idl_files.cmake +++ b/Libraries/LibWeb/idl_files.cmake @@ -110,6 +110,7 @@ libweb_js_bindings(Geometry/DOMRectList) libweb_js_bindings(Geometry/DOMRectReadOnly) libweb_js_bindings(HTML/AudioTrack) libweb_js_bindings(HTML/AudioTrackList) +libweb_js_bindings(HTML/BarProp) libweb_js_bindings(HTML/BeforeUnloadEvent) libweb_js_bindings(HTML/BroadcastChannel) libweb_js_bindings(HTML/CanvasGradient) diff --git a/Tests/LibWeb/Text/expected/HTML/window-barprops.txt b/Tests/LibWeb/Text/expected/HTML/window-barprops.txt new file mode 100644 index 00000000000..1255fc75307 --- /dev/null +++ b/Tests/LibWeb/Text/expected/HTML/window-barprops.txt @@ -0,0 +1,6 @@ +locationbar is BarProp: true visible: true +menubar is BarProp: true visible: true +personalbar is BarProp: true visible: true +scrollbars is BarProp: true visible: true +statusbar is BarProp: true visible: true +toolbar is BarProp: true visible: true diff --git a/Tests/LibWeb/Text/expected/all-window-properties.txt b/Tests/LibWeb/Text/expected/all-window-properties.txt index df057954b11..4406c33fe37 100644 --- a/Tests/LibWeb/Text/expected/all-window-properties.txt +++ b/Tests/LibWeb/Text/expected/all-window-properties.txt @@ -23,6 +23,7 @@ AudioParam AudioScheduledSourceNode AudioTrack AudioTrackList +BarProp BaseAudioContext BeforeUnloadEvent BigInt diff --git a/Tests/LibWeb/Text/input/HTML/window-barprops.html b/Tests/LibWeb/Text/input/HTML/window-barprops.html new file mode 100644 index 00000000000..c5fcbe24e02 --- /dev/null +++ b/Tests/LibWeb/Text/input/HTML/window-barprops.html @@ -0,0 +1,23 @@ + + +