2020-06-05 23:36:02 +02:00
/*
2024-10-04 13:19:50 +02:00
* Copyright ( c ) 2020 - 2021 , Andreas Kling < andreas @ ladybird . org >
2023-11-21 18:52:33 +00:00
* Copyright ( c ) 2023 , Sam Atkins < atkinssj @ serenityos . org >
2020-06-05 23:36:02 +02:00
*
2021-04-22 01:24:48 -07:00
* SPDX - License - Identifier : BSD - 2 - Clause
2020-06-05 23:36:02 +02:00
*/
2024-10-05 15:33:34 +13:00
# include <LibURL/Origin.h>
2024-04-27 12:09:58 +12:00
# include <LibWeb/Bindings/HTMLIFrameElementPrototype.h>
2024-11-08 20:14:37 +08:00
# include <LibWeb/CSS/StyleValues/DisplayStyleValue.h>
2024-11-18 07:16:26 +13:00
# include <LibWeb/DOM/DOMTokenList.h>
2020-06-05 23:36:02 +02:00
# include <LibWeb/DOM/Document.h>
2021-09-26 02:25:02 +02:00
# include <LibWeb/DOM/Event.h>
2021-11-18 15:01:28 +01:00
# include <LibWeb/HTML/BrowsingContext.h>
2020-07-26 15:08:16 +02:00
# include <LibWeb/HTML/HTMLIFrameElement.h>
2023-04-13 18:50:09 +03:00
# include <LibWeb/HTML/Navigable.h>
2022-10-10 17:22:30 +01:00
# include <LibWeb/HTML/Parser/HTMLParser.h>
2020-11-22 15:53:01 +01:00
# include <LibWeb/Layout/FrameBox.h>
2020-06-05 23:36:02 +02:00
2020-07-28 18:20:36 +02:00
namespace Web : : HTML {
2020-06-05 23:36:02 +02:00
2024-11-15 04:01:23 +13:00
GC_DEFINE_ALLOCATOR ( HTMLIFrameElement ) ;
2023-11-19 19:47:52 +01:00
2022-02-18 21:00:52 +01:00
HTMLIFrameElement : : HTMLIFrameElement ( DOM : : Document & document , DOM : : QualifiedName qualified_name )
2022-12-12 12:20:02 +01:00
: NavigableContainer ( document , move ( qualified_name ) )
2020-06-05 23:36:02 +02:00
{
}
2022-03-14 13:21:51 -06:00
HTMLIFrameElement : : ~ HTMLIFrameElement ( ) = default ;
2020-06-05 23:36:02 +02:00
2023-08-07 08:41:28 +02:00
void HTMLIFrameElement : : initialize ( JS : : Realm & realm )
2023-01-10 06:28:20 -05:00
{
2023-08-07 08:41:28 +02:00
Base : : initialize ( realm ) ;
2024-03-16 13:13:08 +01:00
WEB_SET_PROTOTYPE_FOR_INTERFACE ( HTMLIFrameElement ) ;
2023-01-10 06:28:20 -05:00
}
2024-11-15 04:01:23 +13:00
GC : : Ptr < Layout : : Node > HTMLIFrameElement : : create_layout_node ( CSS : : StyleProperties style )
2020-06-05 23:36:02 +02:00
{
2024-11-14 06:13:46 +13:00
return heap ( ) . allocate < Layout : : FrameBox > ( document ( ) , * this , move ( style ) ) ;
2020-06-05 23:36:02 +02:00
}
2024-11-08 20:14:37 +08:00
void HTMLIFrameElement : : adjust_computed_style ( CSS : : StyleProperties & style )
{
// https://drafts.csswg.org/css-display-3/#unbox
if ( style . display ( ) . is_contents ( ) )
style . set_property ( CSS : : PropertyID : : Display , CSS : : DisplayStyleValue : : create ( CSS : : Display : : from_short ( CSS : : Display : : Short : : None ) ) ) ;
}
2024-11-14 08:14:16 -05:00
void HTMLIFrameElement : : attribute_changed ( FlyString const & name , Optional < String > const & old_value , Optional < String > const & value , Optional < FlyString > const & namespace_ )
2020-06-06 15:08:36 +02:00
{
2024-11-14 08:14:16 -05:00
Base : : attribute_changed ( name , old_value , value , namespace_ ) ;
2024-01-01 16:31:14 +00:00
// https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-iframe-element:process-the-iframe-attributes-2
// https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-iframe-element:process-the-iframe-attributes-3
// Whenever an iframe element with a non-null content navigable has its srcdoc attribute set, changed, or removed,
// the user agent must process the iframe attributes.
// Similarly, whenever an iframe element with a non-null content navigable but with no srcdoc attribute specified
// has its src attribute set, changed, or removed, the user agent must process the iframe attributes.
if ( m_content_navigable ) {
if ( name = = AttributeNames : : srcdoc | | ( name = = AttributeNames : : src & & ! has_attribute ( AttributeNames : : srcdoc ) ) )
process_the_iframe_attributes ( ) ;
}
2020-06-05 23:36:02 +02:00
}
2022-03-23 20:13:34 -04:00
// https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-iframe-element:the-iframe-element-6
2021-04-06 17:58:20 +01:00
void HTMLIFrameElement : : inserted ( )
2021-04-03 16:45:14 +02:00
{
2022-03-23 20:13:34 -04:00
HTMLElement : : inserted ( ) ;
2024-11-12 18:16:08 +00:00
// The iframe HTML element insertion steps, given insertedNode, are:
// 1. If insertedNode's shadow-including root's browsing context is null, then return.
if ( ! is < DOM : : Document > ( shadow_including_root ( ) ) )
return ;
DOM : : Document & document = verify_cast < DOM : : Document > ( shadow_including_root ( ) ) ;
// NOTE: The check for "not fully active" is to prevent a crash on the dom/nodes/node-appendchild-crash.html WPT test.
if ( ! document . browsing_context ( ) | | ! document . is_fully_active ( ) )
return ;
// 2. Create a new child navigable for insertedNode.
2024-11-15 04:01:23 +13:00
MUST ( create_new_child_navigable ( GC : : create_function ( realm ( ) . heap ( ) , [ this ] {
2024-11-12 18:16:08 +00:00
// FIXME: 3. If insertedNode has a sandbox attribute, then parse the sandboxing directive given the attribute's
// value and insertedNode's iframe sandboxing flag set.
// 4. Process the iframe attributes for insertedNode, with initialInsertion set to true.
process_the_iframe_attributes ( true ) ;
set_content_navigable_initialized ( ) ;
} ) ) ) ;
2022-03-23 20:13:34 -04:00
}
2022-09-19 13:34:36 +02:00
// https://html.spec.whatwg.org/multipage/iframe-embed-object.html#process-the-iframe-attributes
void HTMLIFrameElement : : process_the_iframe_attributes ( bool initial_insertion )
{
2023-04-13 18:50:09 +03:00
if ( ! content_navigable ( ) )
return ;
2022-09-19 13:34:36 +02:00
// 1. If element's srcdoc attribute is specified, then:
if ( has_attribute ( HTML : : AttributeNames : : srcdoc ) ) {
2023-04-13 18:50:09 +03:00
// 1. Set element's current navigation was lazy loaded boolean to false.
2023-11-24 15:54:57 +00:00
set_current_navigation_was_lazy_loaded ( false ) ;
2022-09-19 13:34:36 +02:00
2023-04-13 18:50:09 +03:00
// 2. If the will lazy load element steps given element return true, then:
2022-09-19 13:34:36 +02:00
if ( will_lazy_load_element ( ) ) {
2023-11-21 18:54:36 +00:00
// 1. Set element's lazy load resumption steps to the rest of this algorithm starting with the step labeled navigate to the srcdoc resource.
set_lazy_load_resumption_steps ( [ this ] ( ) {
// 3. Navigate to the srcdoc resource: navigate an iframe or frame given element, about:srcdoc, the empty string, and the value of element's srcdoc attribute.
2024-03-18 16:22:27 +13:00
navigate_an_iframe_or_frame ( URL : : URL ( " about:srcdoc " sv ) , ReferrerPolicy : : ReferrerPolicy : : EmptyString , get_attribute ( HTML : : AttributeNames : : srcdoc ) ) ;
2023-11-21 18:54:36 +00:00
// FIXME: The resulting Document must be considered an iframe srcdoc document.
} ) ;
// 2. Set element's current navigation was lazy loaded boolean to true.
2023-11-24 15:54:57 +00:00
set_current_navigation_was_lazy_loaded ( true ) ;
2023-11-21 18:54:36 +00:00
// 3. Start intersection-observing a lazy loading element for element.
document ( ) . start_intersection_observing_a_lazy_loading_element ( * this ) ;
// 4. Return.
return ;
2022-09-19 13:34:36 +02:00
}
2023-04-13 18:50:09 +03:00
// 3. Navigate to the srcdoc resource: navigate an iframe or frame given element, about:srcdoc, the empty string, and the value of element's srcdoc attribute.
2024-03-18 16:22:27 +13:00
navigate_an_iframe_or_frame ( URL : : URL ( " about:srcdoc " sv ) , ReferrerPolicy : : ReferrerPolicy : : EmptyString , get_attribute ( HTML : : AttributeNames : : srcdoc ) ) ;
2022-09-19 13:34:36 +02:00
// FIXME: The resulting Document must be considered an iframe srcdoc document.
return ;
}
2023-04-13 18:50:09 +03:00
// 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. Run the iframe load event steps given element.
run_iframe_load_event_steps ( * this ) ;
// 2. Return.
return ;
}
2024-05-31 21:24:43 +01:00
// 4. Let referrerPolicy be the current state of element's referrerpolicy content attribute.
auto referrer_policy = ReferrerPolicy : : from_string ( get_attribute_value ( HTML : : AttributeNames : : referrerpolicy ) ) . value_or ( ReferrerPolicy : : ReferrerPolicy : : EmptyString ) ;
2023-04-13 18:50:09 +03:00
// 5. Set element's current navigation was lazy loaded boolean to false.
2023-11-24 15:54:57 +00:00
set_current_navigation_was_lazy_loaded ( false ) ;
2023-04-13 18:50:09 +03:00
// 6. If the will lazy load element steps given element return true, then:
if ( will_lazy_load_element ( ) ) {
2023-11-21 18:54:36 +00:00
// 1. Set element's lazy load resumption steps to the rest of this algorithm starting with the step labeled navigate.
set_lazy_load_resumption_steps ( [ this , url , referrer_policy ] ( ) {
// 7. Navigate: navigate an iframe or frame given element, url, and referrerPolicy.
navigate_an_iframe_or_frame ( * url , referrer_policy ) ;
} ) ;
// 2. Set element's current navigation was lazy loaded boolean to true.
2023-11-24 15:54:57 +00:00
set_current_navigation_was_lazy_loaded ( true ) ;
2023-11-21 18:54:36 +00:00
// 3. Start intersection-observing a lazy loading element for element.
document ( ) . start_intersection_observing_a_lazy_loading_element ( * this ) ;
2023-04-13 18:50:09 +03:00
// 4. Return.
return ;
}
// 7. Navigate: navigate an iframe or frame given element, url, and referrerPolicy.
navigate_an_iframe_or_frame ( * url , referrer_policy ) ;
2022-09-19 13:34:36 +02:00
}
2022-03-23 20:13:34 -04:00
// https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-iframe-element:the-iframe-element-7
void HTMLIFrameElement : : removed_from ( DOM : : Node * node )
{
HTMLElement : : removed_from ( node ) ;
2022-09-20 21:44:42 +02:00
2023-04-13 18:50:09 +03:00
// When an iframe element is removed from a document, the user agent must destroy the nested navigable of the element.
destroy_the_child_navigable ( ) ;
2021-04-03 16:45:14 +02:00
}
2021-09-26 02:25:02 +02:00
// https://html.spec.whatwg.org/multipage/iframe-embed-object.html#iframe-load-event-steps
void run_iframe_load_event_steps ( HTML : : HTMLIFrameElement & element )
{
2023-04-13 18:50:09 +03:00
// FIXME: 1. Assert: element's content navigable is not null.
if ( ! element . content_navigable ( ) ) {
2022-09-20 21:44:42 +02:00
// FIXME: For some reason, we sometimes end up here in the middle of SunSpider.
dbgln ( " FIXME: run_iframe_load_event_steps called with null nested browsing context " ) ;
return ;
}
2021-09-26 02:25:02 +02:00
2023-09-07 01:13:27 +02:00
// 2. Let childDocument be element's content navigable's active document.
[[maybe_unused]] auto child_document = element . content_navigable ( ) - > active_document ( ) ;
2021-09-26 02:25:02 +02:00
// FIXME: 3. If childDocument has its mute iframe load flag set, then return.
// FIXME: 4. Set childDocument's iframe load in progress flag.
// 5. Fire an event named load at element.
2023-08-13 13:05:26 +02:00
element . dispatch_event ( DOM : : Event : : create ( element . realm ( ) , HTML : : EventNames : : load ) ) ;
2021-09-26 02:25:02 +02:00
// FIXME: 6. Unset childDocument's iframe load in progress flag.
}
2022-11-05 03:58:14 +00:00
// https://html.spec.whatwg.org/multipage/interaction.html#dom-tabindex
i32 HTMLIFrameElement : : default_tab_index_value ( ) const
{
// See the base function for the spec comments.
return 0 ;
}
2024-11-18 07:16:26 +13:00
// https://html.spec.whatwg.org/multipage/iframe-embed-object.html#dom-iframe-sandbox
GC : : Ref < DOM : : DOMTokenList > HTMLIFrameElement : : sandbox ( )
{
// The sandbox IDL attribute must reflect the sandbox content attribute.
if ( ! m_sandbox )
m_sandbox = DOM : : DOMTokenList : : create ( * this , HTML : : AttributeNames : : sandbox ) ;
return * m_sandbox ;
}
2023-11-21 18:52:33 +00:00
void HTMLIFrameElement : : visit_edges ( Cell : : Visitor & visitor )
{
Base : : visit_edges ( visitor ) ;
visit_lazy_loading_element ( visitor ) ;
2024-11-18 07:16:26 +13:00
visitor . visit ( m_sandbox ) ;
2023-11-21 18:52:33 +00:00
}
2023-11-24 15:54:57 +00:00
void HTMLIFrameElement : : set_current_navigation_was_lazy_loaded ( bool value )
{
m_current_navigation_was_lazy_loaded = value ;
// An iframe element whose current navigation was lazy loaded boolean is false potentially delays the load event.
// https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-iframe-element:potentially-delays-the-load-event
set_potentially_delays_the_load_event ( ! value ) ;
}
2020-06-05 23:36:02 +02:00
}