From 7969161f07e882467a2d275b780e9d6c8779deaa Mon Sep 17 00:00:00 2001 From: Simon Wanner Date: Wed, 16 Mar 2022 17:15:11 +0100 Subject: [PATCH] LibWeb: Implement window.name Right now the only functionality supported is getting/setting via JS and resetting when browsing cross origin. The HTML Specification (7.11 Browsing the web) also specifies how the name should be restored from history entries, but we don't have those yet. --- .../LibWeb/Bindings/WindowObject.cpp | 14 +++++++++++++ .../Libraries/LibWeb/Bindings/WindowObject.h | 3 +++ .../Libraries/LibWeb/HTML/BrowsingContext.cpp | 13 ++++++++++++ .../Libraries/LibWeb/HTML/BrowsingContext.h | 4 ++++ Userland/Libraries/LibWeb/HTML/Window.cpp | 20 +++++++++++++++++++ Userland/Libraries/LibWeb/HTML/Window.h | 3 +++ 6 files changed, 57 insertions(+) diff --git a/Userland/Libraries/LibWeb/Bindings/WindowObject.cpp b/Userland/Libraries/LibWeb/Bindings/WindowObject.cpp index a616a69d8d..acb1f1ca8f 100644 --- a/Userland/Libraries/LibWeb/Bindings/WindowObject.cpp +++ b/Userland/Libraries/LibWeb/Bindings/WindowObject.cpp @@ -68,6 +68,7 @@ void WindowObject::initialize_global_object() define_native_accessor("top", top_getter, nullptr, JS::Attribute::Enumerable); define_native_accessor("parent", parent_getter, {}, JS::Attribute::Enumerable); define_native_accessor("document", document_getter, {}, JS::Attribute::Enumerable); + define_native_accessor("name", name_getter, name_setter, JS::Attribute::Enumerable); define_native_accessor("history", history_getter, {}, JS::Attribute::Enumerable); define_native_accessor("performance", performance_getter, {}, JS::Attribute::Enumerable); define_native_accessor("crypto", crypto_getter, {}, JS::Attribute::Enumerable); @@ -657,6 +658,19 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::session_storage_getter) return wrap(global_object, *impl->session_storage()); } +JS_DEFINE_NATIVE_FUNCTION(WindowObject::name_getter) +{ + auto* impl = TRY(impl_from(vm, global_object)); + return JS::js_string(vm, impl->name()); +} + +JS_DEFINE_NATIVE_FUNCTION(WindowObject::name_setter) +{ + auto* impl = TRY(impl_from(vm, global_object)); + impl->set_name(TRY(vm.argument(0).to_string(global_object))); + return JS::js_undefined(); +} + #define __ENUMERATE(attribute, event_name) \ JS_DEFINE_NATIVE_FUNCTION(WindowObject::attribute##_getter) \ { \ diff --git a/Userland/Libraries/LibWeb/Bindings/WindowObject.h b/Userland/Libraries/LibWeb/Bindings/WindowObject.h index 3cf9939b58..f50780828e 100644 --- a/Userland/Libraries/LibWeb/Bindings/WindowObject.h +++ b/Userland/Libraries/LibWeb/Bindings/WindowObject.h @@ -80,6 +80,9 @@ private: JS_DECLARE_NATIVE_FUNCTION(document_getter); + JS_DECLARE_NATIVE_FUNCTION(name_getter); + JS_DECLARE_NATIVE_FUNCTION(name_setter); + JS_DECLARE_NATIVE_FUNCTION(performance_getter); JS_DECLARE_NATIVE_FUNCTION(history_getter); JS_DECLARE_NATIVE_FUNCTION(screen_getter); diff --git a/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp b/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp index c9ea049b27..28650df280 100644 --- a/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp +++ b/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp @@ -80,6 +80,19 @@ void BrowsingContext::set_active_document(DOM::Document* document) if (m_active_document) m_active_document->detach_from_browsing_context({}, *this); + // https://html.spec.whatwg.org/multipage/browsing-the-web.html#resetBCName + // FIXME: The rest of set_active_document does not follow the spec very closely, this just implements the + // relevant steps for resetting the browsing context name and should be updated closer to the spec once + // the other parts of history handling/navigating are implemented + // 3. If newDocument's origin is not same origin with the current entry's document's origin, then: + if (!document || !m_active_document || !document->origin().is_same_origin(m_active_document->origin())) { + // 3. If the browsing context is a top-level browsing context, but not an auxiliary browsing context + // whose disowned is false, then set the browsing context's name to the empty string. + // FIXME: this is not checking the second part of the condition yet + if (is_top_level()) + m_name = String::empty(); + } + m_active_document = document; if (m_active_document) { diff --git a/Userland/Libraries/LibWeb/HTML/BrowsingContext.h b/Userland/Libraries/LibWeb/HTML/BrowsingContext.h index 067303e2be..70b938551f 100644 --- a/Userland/Libraries/LibWeb/HTML/BrowsingContext.h +++ b/Userland/Libraries/LibWeb/HTML/BrowsingContext.h @@ -107,6 +107,9 @@ public: RefPtr currently_focused_area(); + String const& name() const { return m_name; } + void set_name(String const& name) { m_name = name; } + private: explicit BrowsingContext(Page&, HTML::BrowsingContextContainer*); @@ -129,6 +132,7 @@ private: HashTable m_viewport_clients; HashMap m_frame_nesting_levels; + String m_name; }; } diff --git a/Userland/Libraries/LibWeb/HTML/Window.cpp b/Userland/Libraries/LibWeb/HTML/Window.cpp index 255f699457..9db4f3dc7f 100644 --- a/Userland/Libraries/LibWeb/HTML/Window.cpp +++ b/Userland/Libraries/LibWeb/HTML/Window.cpp @@ -613,4 +613,24 @@ DOM::ExceptionOr Window::post_message(JS::Value message, String const&) return {}; } +// https://html.spec.whatwg.org/multipage/window-object.html#dom-name +String Window::name() const +{ + // 1. If this's browsing context is null, then return the empty string. + if (!browsing_context()) + return String::empty(); + // 2. Return this's browsing context's name. + return browsing_context()->name(); +} + +// https://html.spec.whatwg.org/multipage/window-object.html#dom-name +void Window::set_name(String const& name) +{ + // 1. If this's browsing context is null, then return. + if (!browsing_context()) + return; + // 2. Set this's browsing context's name to the given value. + browsing_context()->set_name(name); +} + } diff --git a/Userland/Libraries/LibWeb/HTML/Window.h b/Userland/Libraries/LibWeb/HTML/Window.h index 252e7da939..41a5a1f0af 100644 --- a/Userland/Libraries/LibWeb/HTML/Window.h +++ b/Userland/Libraries/LibWeb/HTML/Window.h @@ -110,6 +110,9 @@ public: DOM::ExceptionOr post_message(JS::Value, String const& target_origin); + String name() const; + void set_name(String const&); + private: explicit Window(DOM::Document&);