Coverage Report

Created: 2025-08-28 06:26

/src/serenity/Userland/Libraries/LibWeb/HTML/BrowsingContext.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2018-2022, Andreas Kling <kling@serenityos.org>
3
 *
4
 * SPDX-License-Identifier: BSD-2-Clause
5
 */
6
7
#pragma once
8
9
#include <AK/Function.h>
10
#include <AK/Noncopyable.h>
11
#include <AK/RefPtr.h>
12
#include <AK/WeakPtr.h>
13
#include <LibGfx/Bitmap.h>
14
#include <LibGfx/Rect.h>
15
#include <LibGfx/Size.h>
16
#include <LibJS/Forward.h>
17
#include <LibJS/Heap/Cell.h>
18
#include <LibURL/Origin.h>
19
#include <LibWeb/DOM/Position.h>
20
#include <LibWeb/HTML/ActivateTab.h>
21
#include <LibWeb/HTML/NavigableContainer.h>
22
#include <LibWeb/HTML/SandboxingFlagSet.h>
23
#include <LibWeb/HTML/SessionHistoryEntry.h>
24
#include <LibWeb/HTML/TokenizedFeatures.h>
25
#include <LibWeb/HTML/VisibilityState.h>
26
#include <LibWeb/Platform/Timer.h>
27
#include <LibWeb/TreeNode.h>
28
29
namespace Web::HTML {
30
31
class BrowsingContext final : public JS::Cell {
32
    JS_CELL(BrowsingContext, JS::Cell);
33
    JS_DECLARE_ALLOCATOR(BrowsingContext);
34
35
public:
36
    struct BrowsingContextAndDocument {
37
        JS::NonnullGCPtr<BrowsingContext> browsing_context;
38
        JS::NonnullGCPtr<DOM::Document> document;
39
    };
40
41
    static WebIDL::ExceptionOr<BrowsingContextAndDocument> create_a_new_browsing_context_and_document(JS::NonnullGCPtr<Page> page, JS::GCPtr<DOM::Document> creator, JS::GCPtr<DOM::Element> embedder, JS::NonnullGCPtr<BrowsingContextGroup> group);
42
    static WebIDL::ExceptionOr<BrowsingContextAndDocument> create_a_new_auxiliary_browsing_context_and_document(JS::NonnullGCPtr<Page> page, JS::NonnullGCPtr<HTML::BrowsingContext> opener);
43
44
    virtual ~BrowsingContext() override;
45
46
    JS::NonnullGCPtr<HTML::TraversableNavigable> top_level_traversable() const;
47
48
    JS::GCPtr<BrowsingContext> first_child() const;
49
    JS::GCPtr<BrowsingContext> next_sibling() const;
50
51
    bool is_ancestor_of(BrowsingContext const&) const;
52
    bool is_familiar_with(BrowsingContext const&) const;
53
54
    template<typename Callback>
55
    TraversalDecision for_each_in_inclusive_subtree(Callback callback) const
56
    {
57
        if (callback(*this) == TraversalDecision::Break)
58
            return TraversalDecision::Break;
59
        for (auto child = first_child(); child; child = child->next_sibling()) {
60
            if (child->for_each_in_inclusive_subtree(callback) == TraversalDecision::Break)
61
                return TraversalDecision::Break;
62
        }
63
        return TraversalDecision::Continue;
64
    }
65
66
    template<typename Callback>
67
    TraversalDecision for_each_in_inclusive_subtree(Callback callback)
68
    {
69
        if (callback(*this) == TraversalDecision::Break)
70
            return TraversalDecision::Break;
71
        for (auto child = first_child(); child; child = child->next_sibling()) {
72
            if (child->for_each_in_inclusive_subtree(callback) == TraversalDecision::Break)
73
                return TraversalDecision::Break;
74
        }
75
        return TraversalDecision::Continue;
76
    }
77
78
    template<typename Callback>
79
    TraversalDecision for_each_in_subtree(Callback callback) const
80
    {
81
        for (auto child = first_child(); child; child = child->next_sibling()) {
82
            if (child->for_each_in_inclusive_subtree(callback) == TraversalDecision::Break)
83
                return TraversalDecision::Break;
84
        }
85
        return TraversalDecision::Continue;
86
    }
87
88
    template<typename Callback>
89
    TraversalDecision for_each_in_subtree(Callback callback)
90
    {
91
        for (auto child = first_child(); child; child = child->next_sibling()) {
92
            if (child->for_each_in_inclusive_subtree(callback) == TraversalDecision::Break)
93
                return TraversalDecision::Break;
94
        }
95
        return TraversalDecision::Continue;
96
    }
97
98
    bool is_top_level() const;
99
100
    DOM::Document const* active_document() const;
101
    DOM::Document* active_document();
102
103
    HTML::WindowProxy* window_proxy();
104
    HTML::WindowProxy const* window_proxy() const;
105
106
    void set_window_proxy(JS::GCPtr<WindowProxy>);
107
108
    HTML::Window* active_window();
109
    HTML::Window const* active_window() const;
110
111
0
    Page& page() { return m_page; }
112
0
    Page const& page() const { return m_page; }
113
114
0
    u64 virtual_browsing_context_group_id() const { return m_virtual_browsing_context_group_id; }
115
116
    JS::GCPtr<BrowsingContext> top_level_browsing_context() const;
117
118
    BrowsingContextGroup* group();
119
    void set_group(BrowsingContextGroup*);
120
121
    // https://html.spec.whatwg.org/multipage/browsers.html#bcg-remove
122
    void remove();
123
124
    // https://html.spec.whatwg.org/multipage/origin.html#one-permitted-sandboxed-navigator
125
    BrowsingContext const* the_one_permitted_sandboxed_navigator() const;
126
    void set_the_one_permitted_sandboxed_navigator(BrowsingContext const*)
127
0
    {
128
        // FIXME: Implement this
129
0
    }
130
131
    bool has_navigable_been_destroyed() const;
132
133
0
    JS::GCPtr<BrowsingContext> opener_browsing_context() const { return m_opener_browsing_context; }
134
0
    void set_opener_browsing_context(JS::GCPtr<BrowsingContext> browsing_context) { m_opener_browsing_context = browsing_context; }
135
136
0
    void set_is_popup(TokenizedFeature::Popup is_popup) { m_is_popup = is_popup; }
137
138
0
    SandboxingFlagSet popup_sandboxing_flag_set() const { return m_popup_sandboxing_flag_set; }
139
0
    void set_popup_sandboxing_flag_set(SandboxingFlagSet value) { m_popup_sandboxing_flag_set = value; }
140
141
private:
142
    explicit BrowsingContext(JS::NonnullGCPtr<Page>);
143
144
    virtual void visit_edges(Cell::Visitor&) override;
145
146
    JS::NonnullGCPtr<Page> m_page;
147
148
    // https://html.spec.whatwg.org/multipage/document-sequences.html#browsing-context
149
    JS::GCPtr<HTML::WindowProxy> m_window_proxy;
150
151
    // https://html.spec.whatwg.org/multipage/browsers.html#opener-browsing-context
152
    JS::GCPtr<BrowsingContext> m_opener_browsing_context;
153
154
    // https://html.spec.whatwg.org/multipage/document-sequences.html#opener-origin-at-creation
155
    Optional<URL::Origin> m_opener_origin_at_creation;
156
157
    // https://html.spec.whatwg.org/multipage/browsers.html#is-popup
158
    TokenizedFeature::Popup m_is_popup { TokenizedFeature::Popup::No };
159
160
    // https://html.spec.whatwg.org/multipage/browsers.html#popup-sandboxing-flag-set
161
    SandboxingFlagSet m_popup_sandboxing_flag_set {};
162
163
    // https://html.spec.whatwg.org/multipage/document-sequences.html#is-auxiliary
164
    bool m_is_auxiliary { false };
165
166
    // https://html.spec.whatwg.org/multipage/document-sequences.html#browsing-context-initial-url
167
    Optional<URL::URL> m_initial_url;
168
169
    // https://html.spec.whatwg.org/multipage/document-sequences.html#virtual-browsing-context-group-id
170
    u64 m_virtual_browsing_context_group_id = { 0 };
171
172
    // https://html.spec.whatwg.org/multipage/browsers.html#tlbc-group
173
    JS::GCPtr<BrowsingContextGroup> m_group;
174
175
    JS::GCPtr<BrowsingContext> m_first_child;
176
    JS::GCPtr<BrowsingContext> m_last_child;
177
    JS::GCPtr<BrowsingContext> m_next_sibling;
178
    JS::GCPtr<BrowsingContext> m_previous_sibling;
179
};
180
181
URL::Origin determine_the_origin(Optional<URL::URL const&>, SandboxingFlagSet, Optional<URL::Origin> source_origin);
182
183
SandboxingFlagSet determine_the_creation_sandboxing_flags(BrowsingContext const&, JS::GCPtr<DOM::Element> embedder);
184
185
// FIXME: Find a better home for these
186
bool url_matches_about_blank(URL::URL const& url);
187
bool url_matches_about_srcdoc(URL::URL const& url);
188
189
}