From 16def85153d331ec4e4a8a8f1ac570ef83057b98 Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Sun, 3 Nov 2024 21:02:07 -0500 Subject: [PATCH] LibWeb: Implement HTMLFrameElement as a NavigableContainer NavigableContainer is our home grown concept which already contains the AOs needed for frame and iframe elements. This patch simply aligns our HTMLFrameElement implementation with this class. A couple of notes: 1. The + + + + + diff --git a/Userland/Libraries/LibWeb/HTML/HTMLFrameElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLFrameElement.cpp index 66bbde29723..2330700723f 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLFrameElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLFrameElement.cpp @@ -6,15 +6,23 @@ #include #include +#include +#include +#include +#include #include +#include namespace Web::HTML { JS_DEFINE_ALLOCATOR(HTMLFrameElement); HTMLFrameElement::HTMLFrameElement(DOM::Document& document, DOM::QualifiedName qualified_name) - : HTMLElement(document, move(qualified_name)) + : NavigableContainer(document, move(qualified_name)) { + // https://html.spec.whatwg.org/multipage/obsolete.html#frames:potentially-delays-the-load-event + // The frame element potentially delays the load event. + set_potentially_delays_the_load_event(true); } HTMLFrameElement::~HTMLFrameElement() = default; @@ -25,6 +33,47 @@ void HTMLFrameElement::initialize(JS::Realm& realm) WEB_SET_PROTOTYPE_FOR_INTERFACE(HTMLFrameElement); } +// https://html.spec.whatwg.org/multipage/obsolete.html#frames:html-element-insertion-steps +void HTMLFrameElement::inserted() +{ + Base::inserted(); + + // 1. If insertedNode is not in a document tree, then return. + if (!in_a_document_tree()) + return; + + // 2. If insertedNode's root's browsing context is null, then return. + if (root().document().browsing_context() == nullptr) + return; + + // 3. Create a new child navigable for insertedNode. + MUST(create_new_child_navigable(JS::create_heap_function(realm().heap(), [this] { + // 4. Process the frame attributes for insertedNode, with initialInsertion set to true. + process_the_frame_attributes(true); + set_content_navigable_initialized(); + }))); +} + +// https://html.spec.whatwg.org/multipage/obsolete.html#frames:html-element-removing-steps +void HTMLFrameElement::removed_from(DOM::Node* node) +{ + Base::removed_from(node); + + // The frame HTML element removing steps, given removedNode, are to destroy a child navigable given removedNode. + destroy_the_child_navigable(); +} + +// https://html.spec.whatwg.org/multipage/obsolete.html#frames:frame-3 +void HTMLFrameElement::attribute_changed(FlyString const& name, Optional const& old_value, Optional const& value) +{ + Base::attribute_changed(name, old_value, value); + + // Whenever a frame element with a non-null content navigable has its src attribute set, changed, or removed, the + // user agent must process the frame attributes. + if (content_navigable() && name == HTML::AttributeNames::src) + process_the_frame_attributes(); +} + // https://html.spec.whatwg.org/multipage/interaction.html#dom-tabindex i32 HTMLFrameElement::default_tab_index_value() const { @@ -32,4 +81,28 @@ i32 HTMLFrameElement::default_tab_index_value() const return 0; } +// https://html.spec.whatwg.org/multipage/obsolete.html#process-the-frame-attributes +void HTMLFrameElement::process_the_frame_attributes(bool initial_insertion) +{ + // 1. Let url be the result of running the shared attribute processing steps for iframe and frame elements given + // element and initialInsertion. + auto url = shared_attribute_processing_steps_for_iframe_and_frame(initial_insertion); + + // 2. If url is null, then return. + if (!url.has_value()) + return; + + // 3. If url matches about:blank and initialInsertion is true, then: + if (url_matches_about_blank(*url) && initial_insertion) { + // 1. Fire an event named load at element. + dispatch_event(DOM::Event::create(realm(), HTML::EventNames::load)); + + // 2. Return. + return; + } + + // 3. Navigate an iframe or frame given element, url, and the empty string. + navigate_an_iframe_or_frame(*url, ReferrerPolicy::ReferrerPolicy::EmptyString); +} + } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLFrameElement.h b/Userland/Libraries/LibWeb/HTML/HTMLFrameElement.h index 5e236c8dbca..ea326b972c9 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLFrameElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLFrameElement.h @@ -6,13 +6,13 @@ #pragma once -#include +#include namespace Web::HTML { // NOTE: This element is marked as obsolete, but is still listed as required by the specification. -class HTMLFrameElement final : public HTMLElement { - WEB_PLATFORM_OBJECT(HTMLFrameElement, HTMLElement); +class HTMLFrameElement final : public NavigableContainer { + WEB_PLATFORM_OBJECT(HTMLFrameElement, NavigableContainer); JS_DECLARE_ALLOCATOR(HTMLFrameElement); public: @@ -24,7 +24,12 @@ private: virtual void initialize(JS::Realm&) override; // ^DOM::Element + virtual void inserted() override; + virtual void removed_from(Node*) override; + virtual void attribute_changed(FlyString const& name, Optional const& old_value, Optional const& value) override; virtual i32 default_tab_index_value() const override; + + void process_the_frame_attributes(bool initial_insertion = false); }; } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLFrameElement.idl b/Userland/Libraries/LibWeb/HTML/HTMLFrameElement.idl index ec8ad5f190d..6199b144569 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLFrameElement.idl +++ b/Userland/Libraries/LibWeb/HTML/HTMLFrameElement.idl @@ -12,8 +12,8 @@ interface HTMLFrameElement : HTMLElement { [CEReactions, Reflect=frameborder] attribute DOMString frameBorder; [CEReactions, Reflect=longdesc, URL] attribute USVString longDesc; [CEReactions, Reflect=noresize] attribute boolean noResize; - [FIXME] readonly attribute Document? contentDocument; - [FIXME] readonly attribute WindowProxy? contentWindow; + readonly attribute Document? contentDocument; + readonly attribute WindowProxy? contentWindow; [CEReactions, LegacyNullToEmptyString, Reflect=marginheight] attribute DOMString marginHeight; [CEReactions, LegacyNullToEmptyString, Reflect=marginwidth] attribute DOMString marginWidth;