/src/serenity/Userland/Libraries/LibWeb/HTML/LazyLoadingElement.h
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2018-2023, Andreas Kling <kling@serenityos.org> |
3 | | * Copyright (c) 2023, Sam Atkins <atkinssj@serenityos.org> |
4 | | * |
5 | | * SPDX-License-Identifier: BSD-2-Clause |
6 | | */ |
7 | | |
8 | | #pragma once |
9 | | |
10 | | #include <LibWeb/Forward.h> |
11 | | #include <LibWeb/HTML/AttributeNames.h> |
12 | | |
13 | | namespace Web::HTML { |
14 | | |
15 | | // Lazy-loaded elements should invoke this macro to inject overridden LazyLoadingElement methods. |
16 | | #define LAZY_LOADING_ELEMENT(ElementClass) \ |
17 | | private: \ |
18 | | virtual JS::GCPtr<JS::HeapFunction<void()>> take_lazy_load_resumption_steps(Badge<DOM::Document>) override \ |
19 | 0 | { \ |
20 | 0 | return take_lazy_load_resumption_steps_internal(); \ |
21 | 0 | } \ Unexecuted instantiation: Web::HTML::HTMLImageElement::take_lazy_load_resumption_steps(AK::Badge<Web::DOM::Document>) Unexecuted instantiation: Web::HTML::HTMLIFrameElement::take_lazy_load_resumption_steps(AK::Badge<Web::DOM::Document>) |
22 | | \ |
23 | 0 | virtual bool is_lazy_loading() const override { return true; }Unexecuted instantiation: Web::HTML::HTMLImageElement::is_lazy_loading() const Unexecuted instantiation: Web::HTML::HTMLIFrameElement::is_lazy_loading() const |
24 | | |
25 | | enum class LazyLoading { |
26 | | Lazy, |
27 | | Eager, |
28 | | }; |
29 | | |
30 | | template<typename T> |
31 | | class LazyLoadingElement { |
32 | | public: |
33 | | // https://html.spec.whatwg.org/multipage/urls-and-fetching.html#lazy-loading-attributes |
34 | | [[nodiscard]] LazyLoading lazy_loading_attribute() const |
35 | 0 | { |
36 | 0 | auto& element = static_cast<T const&>(*this); |
37 | |
|
38 | 0 | auto value = element.attribute(HTML::AttributeNames::loading); |
39 | 0 | if (value.has_value() && value->equals_ignoring_ascii_case("lazy"sv)) |
40 | 0 | return LazyLoading::Lazy; |
41 | 0 | return LazyLoading::Eager; |
42 | 0 | } Unexecuted instantiation: Web::HTML::LazyLoadingElement<Web::HTML::HTMLIFrameElement>::lazy_loading_attribute() const Unexecuted instantiation: Web::HTML::LazyLoadingElement<Web::HTML::HTMLImageElement>::lazy_loading_attribute() const |
43 | | |
44 | | // https://html.spec.whatwg.org/multipage/urls-and-fetching.html#will-lazy-load-element-steps |
45 | | [[nodiscard]] bool will_lazy_load_element() const |
46 | 0 | { |
47 | 0 | auto& element = static_cast<T const&>(*this); |
48 | | |
49 | | // 1. If scripting is disabled for element, then return false. |
50 | | // Spec Note: This is an anti-tracking measure, because if a user agent supported lazy loading when scripting is |
51 | | // disabled, it would still be possible for a site to track a user's approximate scroll position throughout |
52 | | // a session, by strategically placing images in a page's markup such that a server can track how many |
53 | | // images are requested and when. |
54 | 0 | if (element.is_scripting_disabled()) |
55 | 0 | return false; |
56 | | |
57 | | // 2. If element's lazy loading attribute is in the Lazy state, then return true. |
58 | | // 3. Return false. |
59 | 0 | return lazy_loading_attribute() == LazyLoading::Lazy; |
60 | 0 | } Unexecuted instantiation: Web::HTML::LazyLoadingElement<Web::HTML::HTMLIFrameElement>::will_lazy_load_element() const Unexecuted instantiation: Web::HTML::LazyLoadingElement<Web::HTML::HTMLImageElement>::will_lazy_load_element() const |
61 | | |
62 | | void set_lazy_load_resumption_steps(Function<void()> steps) |
63 | 0 | { |
64 | 0 | auto& element = static_cast<T&>(*this); |
65 | |
|
66 | 0 | m_lazy_load_resumption_steps = JS::create_heap_function(element.vm().heap(), move(steps)); |
67 | 0 | } Unexecuted instantiation: Web::HTML::LazyLoadingElement<Web::HTML::HTMLIFrameElement>::set_lazy_load_resumption_steps(AK::Function<void ()>) Unexecuted instantiation: Web::HTML::LazyLoadingElement<Web::HTML::HTMLImageElement>::set_lazy_load_resumption_steps(AK::Function<void ()>) |
68 | | |
69 | | void visit_lazy_loading_element(JS::Cell::Visitor& visitor) |
70 | 0 | { |
71 | 0 | visitor.visit(m_lazy_load_resumption_steps); |
72 | 0 | } Unexecuted instantiation: Web::HTML::LazyLoadingElement<Web::HTML::HTMLIFrameElement>::visit_lazy_loading_element(JS::Cell::Visitor&) Unexecuted instantiation: Web::HTML::LazyLoadingElement<Web::HTML::HTMLImageElement>::visit_lazy_loading_element(JS::Cell::Visitor&) |
73 | | |
74 | | protected: |
75 | 0 | LazyLoadingElement() = default; Unexecuted instantiation: Web::HTML::LazyLoadingElement<Web::HTML::HTMLIFrameElement>::LazyLoadingElement() Unexecuted instantiation: Web::HTML::LazyLoadingElement<Web::HTML::HTMLImageElement>::LazyLoadingElement() |
76 | 0 | virtual ~LazyLoadingElement() = default; Unexecuted instantiation: Web::HTML::LazyLoadingElement<Web::HTML::HTMLIFrameElement>::~LazyLoadingElement() Unexecuted instantiation: Web::HTML::LazyLoadingElement<Web::HTML::HTMLImageElement>::~LazyLoadingElement() |
77 | | |
78 | | JS::GCPtr<JS::HeapFunction<void()>> take_lazy_load_resumption_steps_internal() |
79 | 0 | { |
80 | 0 | auto lazy_load_resumption_steps = m_lazy_load_resumption_steps; |
81 | 0 | m_lazy_load_resumption_steps = nullptr; |
82 | 0 | return lazy_load_resumption_steps; |
83 | 0 | } Unexecuted instantiation: Web::HTML::LazyLoadingElement<Web::HTML::HTMLImageElement>::take_lazy_load_resumption_steps_internal() Unexecuted instantiation: Web::HTML::LazyLoadingElement<Web::HTML::HTMLIFrameElement>::take_lazy_load_resumption_steps_internal() |
84 | | |
85 | | private: |
86 | | // https://html.spec.whatwg.org/multipage/urls-and-fetching.html#lazy-load-resumption-steps |
87 | | // Each img and iframe element has associated lazy load resumption steps, initially null. |
88 | | JS::GCPtr<JS::HeapFunction<void()>> m_lazy_load_resumption_steps; |
89 | | }; |
90 | | |
91 | | } |