/src/serenity/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2018-2022, Andreas Kling <kling@serenityos.org> |
3 | | * |
4 | | * SPDX-License-Identifier: BSD-2-Clause |
5 | | */ |
6 | | |
7 | | #include <LibWeb/Bindings/MainThreadVM.h> |
8 | | #include <LibWeb/DOM/Document.h> |
9 | | #include <LibWeb/DOM/ElementFactory.h> |
10 | | #include <LibWeb/DOM/Event.h> |
11 | | #include <LibWeb/DOM/HTMLCollection.h> |
12 | | #include <LibWeb/DOM/Range.h> |
13 | | #include <LibWeb/DOMURL/DOMURL.h> |
14 | | #include <LibWeb/HTML/BrowsingContext.h> |
15 | | #include <LibWeb/HTML/BrowsingContextGroup.h> |
16 | | #include <LibWeb/HTML/CrossOrigin/OpenerPolicy.h> |
17 | | #include <LibWeb/HTML/DocumentState.h> |
18 | | #include <LibWeb/HTML/HTMLAnchorElement.h> |
19 | | #include <LibWeb/HTML/HTMLDocument.h> |
20 | | #include <LibWeb/HTML/HTMLInputElement.h> |
21 | | #include <LibWeb/HTML/NavigableContainer.h> |
22 | | #include <LibWeb/HTML/SandboxingFlagSet.h> |
23 | | #include <LibWeb/HTML/Scripting/WindowEnvironmentSettingsObject.h> |
24 | | #include <LibWeb/HTML/TraversableNavigable.h> |
25 | | #include <LibWeb/HTML/Window.h> |
26 | | #include <LibWeb/HTML/WindowProxy.h> |
27 | | #include <LibWeb/HighResolutionTime/TimeOrigin.h> |
28 | | #include <LibWeb/Layout/BreakNode.h> |
29 | | #include <LibWeb/Layout/Viewport.h> |
30 | | #include <LibWeb/Namespace.h> |
31 | | #include <LibWeb/Page/Page.h> |
32 | | #include <LibWeb/Painting/Paintable.h> |
33 | | |
34 | | namespace Web::HTML { |
35 | | |
36 | | JS_DEFINE_ALLOCATOR(BrowsingContext); |
37 | | |
38 | | // https://html.spec.whatwg.org/multipage/urls-and-fetching.html#matches-about:blank |
39 | | bool url_matches_about_blank(URL::URL const& url) |
40 | 0 | { |
41 | | // A URL matches about:blank if its scheme is "about", its path contains a single string "blank", its username and password are the empty string, and its host is null. |
42 | 0 | return url.scheme() == "about"sv |
43 | 0 | && url.paths().size() == 1 && url.paths()[0] == "blank"sv |
44 | 0 | && url.username().is_empty() |
45 | 0 | && url.password().is_empty() |
46 | 0 | && url.host().has<Empty>(); |
47 | 0 | } |
48 | | |
49 | | // https://html.spec.whatwg.org/multipage/urls-and-fetching.html#matches-about:srcdoc |
50 | | bool url_matches_about_srcdoc(URL::URL const& url) |
51 | 0 | { |
52 | | // A URL matches about:srcdoc if its scheme is "about", its path contains a single string "srcdoc", its query is null, its username and password are the empty string, and its host is null. |
53 | 0 | return url.scheme() == "about"sv |
54 | 0 | && url.paths().size() == 1 && url.paths()[0] == "srcdoc"sv |
55 | 0 | && !url.query().has_value() |
56 | 0 | && url.username().is_empty() |
57 | 0 | && url.password().is_empty() |
58 | 0 | && url.host().has<Empty>(); |
59 | 0 | } |
60 | | |
61 | | // https://html.spec.whatwg.org/multipage/document-sequences.html#determining-the-origin |
62 | | URL::Origin determine_the_origin(Optional<URL::URL const&> url, SandboxingFlagSet sandbox_flags, Optional<URL::Origin> source_origin) |
63 | 0 | { |
64 | | // 1. If sandboxFlags has its sandboxed origin browsing context flag set, then return a new opaque origin. |
65 | 0 | if (has_flag(sandbox_flags, SandboxingFlagSet::SandboxedOrigin)) { |
66 | 0 | return URL::Origin {}; |
67 | 0 | } |
68 | | |
69 | | // 2. If url is null, then return a new opaque origin. |
70 | 0 | if (!url.has_value()) { |
71 | 0 | return URL::Origin {}; |
72 | 0 | } |
73 | | |
74 | | // 3. If url is about:srcdoc, then: |
75 | 0 | if (url == "about:srcdoc"sv) { |
76 | | // 1. Assert: sourceOrigin is non-null. |
77 | 0 | VERIFY(source_origin.has_value()); |
78 | | |
79 | | // 2. Return sourceOrigin. |
80 | 0 | return source_origin.release_value(); |
81 | 0 | } |
82 | | |
83 | | // 4. If url matches about:blank and sourceOrigin is non-null, then return sourceOrigin. |
84 | 0 | if (url_matches_about_blank(*url) && source_origin.has_value()) |
85 | 0 | return source_origin.release_value(); |
86 | | |
87 | | // 5. Return url's origin. |
88 | 0 | return url->origin(); |
89 | 0 | } |
90 | | |
91 | | // https://html.spec.whatwg.org/multipage/document-sequences.html#creating-a-new-auxiliary-browsing-context |
92 | | WebIDL::ExceptionOr<BrowsingContext::BrowsingContextAndDocument> BrowsingContext::create_a_new_auxiliary_browsing_context_and_document(JS::NonnullGCPtr<Page> page, JS::NonnullGCPtr<HTML::BrowsingContext> opener) |
93 | 0 | { |
94 | | // 1. Let openerTopLevelBrowsingContext be opener's top-level traversable's active browsing context. |
95 | 0 | auto opener_top_level_browsing_context = opener->top_level_traversable()->active_browsing_context(); |
96 | | |
97 | | // 2. Let group be openerTopLevelBrowsingContext's group. |
98 | 0 | auto group = opener_top_level_browsing_context->group(); |
99 | | |
100 | | // 3. Assert: group is non-null, as navigating invokes this directly. |
101 | 0 | VERIFY(group); |
102 | | |
103 | | // 4. Set browsingContext and document be the result of creating a new browsing context and document with opener's active document, null, and group. |
104 | 0 | auto [browsing_context, document] = TRY(create_a_new_browsing_context_and_document(page, opener->active_document(), nullptr, *group)); |
105 | | |
106 | | // 5. Set browsingContext's is auxiliary to true. |
107 | 0 | browsing_context->m_is_auxiliary = true; |
108 | | |
109 | | // 6. Append browsingContext to group. |
110 | 0 | group->append(browsing_context); |
111 | | |
112 | | // 7. Set browsingContext's opener browsing context to opener. |
113 | 0 | browsing_context->set_opener_browsing_context(opener); |
114 | | |
115 | | // 8. Set browsingContext's virtual browsing context group ID to openerTopLevelBrowsingContext's virtual browsing context group ID. |
116 | 0 | browsing_context->m_virtual_browsing_context_group_id = opener_top_level_browsing_context->m_virtual_browsing_context_group_id; |
117 | | |
118 | | // 9. Set browsingContext's opener origin at creation to opener's active document's origin. |
119 | 0 | browsing_context->m_opener_origin_at_creation = opener->active_document()->origin(); |
120 | | |
121 | | // 10. Return browsingContext and document. |
122 | 0 | return BrowsingContext::BrowsingContextAndDocument { browsing_context, document }; |
123 | 0 | } |
124 | | |
125 | | static void populate_with_html_head_body(JS::NonnullGCPtr<DOM::Document> document) |
126 | 0 | { |
127 | 0 | auto html_node = MUST(DOM::create_element(document, HTML::TagNames::html, Namespace::HTML)); |
128 | 0 | auto head_element = MUST(DOM::create_element(document, HTML::TagNames::head, Namespace::HTML)); |
129 | 0 | MUST(html_node->append_child(head_element)); |
130 | 0 | auto body_element = MUST(DOM::create_element(document, HTML::TagNames::body, Namespace::HTML)); |
131 | 0 | MUST(html_node->append_child(body_element)); |
132 | 0 | MUST(document->append_child(html_node)); |
133 | 0 | } |
134 | | |
135 | | // https://html.spec.whatwg.org/multipage/document-sequences.html#creating-a-new-browsing-context |
136 | | WebIDL::ExceptionOr<BrowsingContext::BrowsingContextAndDocument> BrowsingContext::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) |
137 | 0 | { |
138 | 0 | auto& vm = group->vm(); |
139 | | |
140 | | // 1. Let browsingContext be a new browsing context. |
141 | 0 | JS::NonnullGCPtr<BrowsingContext> browsing_context = *vm.heap().allocate_without_realm<BrowsingContext>(page); |
142 | | |
143 | | // 2. Let unsafeContextCreationTime be the unsafe shared current time. |
144 | 0 | [[maybe_unused]] auto unsafe_context_creation_time = HighResolutionTime::unsafe_shared_current_time(); |
145 | | |
146 | | // 3. Let creatorOrigin be null. |
147 | 0 | Optional<URL::Origin> creator_origin = {}; |
148 | | |
149 | | // 4. Let creatorBaseURL be null. |
150 | 0 | Optional<URL::URL> creator_base_url = {}; |
151 | | |
152 | | // 5. If creator is non-null, then: |
153 | 0 | if (creator) { |
154 | | // 1. Set creatorOrigin to creator's origin. |
155 | 0 | creator_origin = creator->origin(); |
156 | | |
157 | | // 2. Set creatorBaseURL to creator's document base URL. |
158 | 0 | creator_base_url = creator->base_url(); |
159 | | |
160 | | // 3. Set browsingContext's virtual browsing context group ID to creator's browsing context's top-level browsing context's virtual browsing context group ID. |
161 | 0 | VERIFY(creator->browsing_context()); |
162 | 0 | browsing_context->m_virtual_browsing_context_group_id = creator->browsing_context()->top_level_browsing_context()->m_virtual_browsing_context_group_id; |
163 | 0 | } |
164 | | |
165 | | // FIXME: 6. Let sandboxFlags be the result of determining the creation sandboxing flags given browsingContext and embedder. |
166 | 0 | SandboxingFlagSet sandbox_flags = {}; |
167 | | |
168 | | // 7. Let origin be the result of determining the origin given about:blank, sandboxFlags, and creatorOrigin. |
169 | 0 | auto origin = determine_the_origin(URL::URL("about:blank"sv), sandbox_flags, creator_origin); |
170 | | |
171 | | // FIXME: 8. Let permissionsPolicy be the result of creating a permissions policy given embedder and origin. [PERMISSIONSPOLICY] |
172 | | |
173 | | // FIXME: 9. Let agent be the result of obtaining a similar-origin window agent given origin, group, and false. |
174 | |
|
175 | 0 | JS::GCPtr<Window> window; |
176 | | |
177 | | // 10. Let realm execution context be the result of creating a new JavaScript realm given agent and the following customizations: |
178 | 0 | auto realm_execution_context = Bindings::create_a_new_javascript_realm( |
179 | 0 | Bindings::main_thread_vm(), |
180 | 0 | [&](JS::Realm& realm) -> JS::Object* { |
181 | 0 | auto window_proxy = realm.heap().allocate<WindowProxy>(realm, realm); |
182 | 0 | browsing_context->set_window_proxy(window_proxy); |
183 | | |
184 | | // - For the global object, create a new Window object. |
185 | 0 | window = Window::create(realm); |
186 | 0 | return window.ptr(); |
187 | 0 | }, |
188 | 0 | [&](JS::Realm&) -> JS::Object* { |
189 | | // - For the global this binding, use browsingContext's WindowProxy object. |
190 | 0 | return browsing_context->window_proxy(); |
191 | 0 | }); |
192 | | |
193 | | // 11. Let topLevelCreationURL be about:blank if embedder is null; otherwise embedder's relevant settings object's top-level creation URL. |
194 | 0 | auto top_level_creation_url = !embedder ? URL::URL("about:blank") : relevant_settings_object(*embedder).top_level_creation_url; |
195 | | |
196 | | // 12. Let topLevelOrigin be origin if embedder is null; otherwise embedder's relevant settings object's top-level origin. |
197 | 0 | auto top_level_origin = !embedder ? origin : relevant_settings_object(*embedder).origin(); |
198 | | |
199 | | // 13. Set up a window environment settings object with about:blank, realm execution context, null, topLevelCreationURL, and topLevelOrigin. |
200 | 0 | WindowEnvironmentSettingsObject::setup( |
201 | 0 | page, |
202 | 0 | URL::URL("about:blank"), |
203 | 0 | move(realm_execution_context), |
204 | 0 | {}, |
205 | 0 | top_level_creation_url, |
206 | 0 | top_level_origin); |
207 | | |
208 | | // 14. Let loadTimingInfo be a new document load timing info with its navigation start time set to the result of calling |
209 | | // coarsen time with unsafeContextCreationTime and the new environment settings object's cross-origin isolated capability. |
210 | 0 | auto load_timing_info = DOM::DocumentLoadTimingInfo(); |
211 | 0 | load_timing_info.navigation_start_time = HighResolutionTime::coarsen_time( |
212 | 0 | unsafe_context_creation_time, |
213 | 0 | verify_cast<WindowEnvironmentSettingsObject>(Bindings::host_defined_environment_settings_object(window->realm())).cross_origin_isolated_capability() == CanUseCrossOriginIsolatedAPIs::Yes); |
214 | | |
215 | | // 15. Let document be a new Document, with: |
216 | 0 | auto document = HTML::HTMLDocument::create(window->realm()); |
217 | | |
218 | | // Non-standard |
219 | 0 | window->set_associated_document(*document); |
220 | | |
221 | | // type: "html" |
222 | 0 | document->set_document_type(DOM::Document::Type::HTML); |
223 | | |
224 | | // content type: "text/html" |
225 | 0 | document->set_content_type("text/html"_string); |
226 | | |
227 | | // mode: "quirks" |
228 | 0 | document->set_quirks_mode(DOM::QuirksMode::Yes); |
229 | | |
230 | | // origin: origin |
231 | 0 | document->set_origin(origin); |
232 | | |
233 | | // browsing context: browsingContext |
234 | 0 | document->set_browsing_context(browsing_context); |
235 | | |
236 | | // FIXME: permissions policy: permissionsPolicy |
237 | | |
238 | | // active sandboxing flag set: sandboxFlags |
239 | 0 | document->set_active_sandboxing_flag_set(sandbox_flags); |
240 | | |
241 | | // load timing info: loadTimingInfo |
242 | 0 | document->set_load_timing_info(load_timing_info); |
243 | | |
244 | | // is initial about:blank: true |
245 | 0 | document->set_is_initial_about_blank(true); |
246 | | // Spec issue: https://github.com/whatwg/html/issues/10261 |
247 | 0 | document->set_ready_to_run_scripts(); |
248 | | |
249 | | // about base URL: creatorBaseURL |
250 | 0 | document->set_about_base_url(creator_base_url); |
251 | | |
252 | | // allow declarative shadow roots: true |
253 | 0 | document->set_allow_declarative_shadow_roots(true); |
254 | | |
255 | | // 16. If creator is non-null, then: |
256 | 0 | if (creator) { |
257 | | // 1. Set document's referrer to the serialization of creator's URL. |
258 | 0 | document->set_referrer(MUST(String::from_byte_string(creator->url().serialize()))); |
259 | | |
260 | | // 2. Set document's policy container to a clone of creator's policy container. |
261 | 0 | document->set_policy_container(creator->policy_container()); |
262 | | |
263 | | // 3. If creator's origin is same origin with creator's relevant settings object's top-level origin, |
264 | 0 | if (creator->origin().is_same_origin(creator->relevant_settings_object().top_level_origin)) { |
265 | | // then set document's opener policy to creator's browsing context's top-level browsing context's active document's opener policy. |
266 | 0 | VERIFY(creator->browsing_context()); |
267 | 0 | VERIFY(creator->browsing_context()->top_level_browsing_context()->active_document()); |
268 | 0 | document->set_opener_policy(creator->browsing_context()->top_level_browsing_context()->active_document()->opener_policy()); |
269 | 0 | } |
270 | 0 | } |
271 | | |
272 | | // 17. Assert: document's URL and document's relevant settings object's creation URL are about:blank. |
273 | 0 | VERIFY(document->url() == "about:blank"sv); |
274 | 0 | VERIFY(document->relevant_settings_object().creation_url == "about:blank"sv); |
275 | | |
276 | | // 18. Mark document as ready for post-load tasks. |
277 | 0 | document->set_ready_for_post_load_tasks(true); |
278 | | |
279 | | // 19. Populate with html/head/body given document. |
280 | 0 | populate_with_html_head_body(*document); |
281 | | |
282 | | // 20. Make active document. |
283 | 0 | document->make_active(); |
284 | | |
285 | | // 21. Completely finish loading document. |
286 | 0 | document->completely_finish_loading(); |
287 | | |
288 | | // 22. Return browsingContext and document. |
289 | 0 | return BrowsingContext::BrowsingContextAndDocument { browsing_context, document }; |
290 | 0 | } |
291 | | |
292 | | BrowsingContext::BrowsingContext(JS::NonnullGCPtr<Page> page) |
293 | 0 | : m_page(page) |
294 | 0 | { |
295 | 0 | } |
296 | | |
297 | 0 | BrowsingContext::~BrowsingContext() = default; |
298 | | |
299 | | void BrowsingContext::visit_edges(Cell::Visitor& visitor) |
300 | 0 | { |
301 | 0 | Base::visit_edges(visitor); |
302 | |
|
303 | 0 | visitor.visit(m_page); |
304 | 0 | visitor.visit(m_window_proxy); |
305 | 0 | visitor.visit(m_group); |
306 | 0 | visitor.visit(m_first_child); |
307 | 0 | visitor.visit(m_last_child); |
308 | 0 | visitor.visit(m_next_sibling); |
309 | 0 | visitor.visit(m_previous_sibling); |
310 | 0 | visitor.visit(m_opener_browsing_context); |
311 | 0 | } |
312 | | |
313 | | // https://html.spec.whatwg.org/multipage/document-sequences.html#bc-traversable |
314 | | JS::NonnullGCPtr<HTML::TraversableNavigable> BrowsingContext::top_level_traversable() const |
315 | 0 | { |
316 | | // A browsing context's top-level traversable is its active document's node navigable's top-level traversable. |
317 | 0 | auto traversable = active_document()->navigable()->top_level_traversable(); |
318 | 0 | VERIFY(traversable); |
319 | 0 | VERIFY(traversable->is_top_level_traversable()); |
320 | 0 | return *traversable; |
321 | 0 | } |
322 | | |
323 | | // https://html.spec.whatwg.org/multipage/browsers.html#top-level-browsing-context |
324 | | bool BrowsingContext::is_top_level() const |
325 | 0 | { |
326 | | // FIXME: Remove this. The active document's navigable is sometimes null when it shouldn't be, failing assertions. |
327 | 0 | return true; |
328 | | // A top-level browsing context is a browsing context whose active document's node navigable is a traversable navigable. |
329 | 0 | return active_document() != nullptr && active_document()->navigable() != nullptr && active_document()->navigable()->is_traversable(); |
330 | 0 | } |
331 | | |
332 | | JS::GCPtr<BrowsingContext> BrowsingContext::top_level_browsing_context() const |
333 | 0 | { |
334 | 0 | auto const* start = this; |
335 | | |
336 | | // 1. If start's active document is not fully active, then return null. |
337 | 0 | if (!start->active_document()->is_fully_active()) { |
338 | 0 | return nullptr; |
339 | 0 | } |
340 | | |
341 | | // 2. Let navigable be start's active document's node navigable. |
342 | 0 | auto navigable = start->active_document()->navigable(); |
343 | | |
344 | | // 3. While navigable's parent is not null, set navigable to navigable's parent. |
345 | 0 | while (navigable->parent()) { |
346 | 0 | navigable = navigable->parent(); |
347 | 0 | } |
348 | | |
349 | | // 4. Return navigable's active browsing context. |
350 | 0 | return navigable->active_browsing_context(); |
351 | 0 | } |
352 | | |
353 | | DOM::Document const* BrowsingContext::active_document() const |
354 | 0 | { |
355 | 0 | auto* window = active_window(); |
356 | 0 | if (!window) |
357 | 0 | return nullptr; |
358 | 0 | return &window->associated_document(); |
359 | 0 | } |
360 | | |
361 | | DOM::Document* BrowsingContext::active_document() |
362 | 0 | { |
363 | 0 | auto* window = active_window(); |
364 | 0 | if (!window) |
365 | 0 | return nullptr; |
366 | 0 | return &window->associated_document(); |
367 | 0 | } |
368 | | |
369 | | // https://html.spec.whatwg.org/multipage/browsers.html#active-window |
370 | | HTML::Window* BrowsingContext::active_window() |
371 | 0 | { |
372 | 0 | return m_window_proxy->window(); |
373 | 0 | } |
374 | | |
375 | | // https://html.spec.whatwg.org/multipage/browsers.html#active-window |
376 | | HTML::Window const* BrowsingContext::active_window() const |
377 | 0 | { |
378 | 0 | return m_window_proxy->window(); |
379 | 0 | } |
380 | | |
381 | | HTML::WindowProxy* BrowsingContext::window_proxy() |
382 | 0 | { |
383 | 0 | return m_window_proxy.ptr(); |
384 | 0 | } |
385 | | |
386 | | HTML::WindowProxy const* BrowsingContext::window_proxy() const |
387 | 0 | { |
388 | 0 | return m_window_proxy.ptr(); |
389 | 0 | } |
390 | | |
391 | | void BrowsingContext::set_window_proxy(JS::GCPtr<WindowProxy> window_proxy) |
392 | 0 | { |
393 | 0 | m_window_proxy = move(window_proxy); |
394 | 0 | } |
395 | | |
396 | | BrowsingContextGroup* BrowsingContext::group() |
397 | 0 | { |
398 | 0 | return m_group; |
399 | 0 | } |
400 | | |
401 | | void BrowsingContext::set_group(BrowsingContextGroup* group) |
402 | 0 | { |
403 | 0 | m_group = group; |
404 | 0 | } |
405 | | |
406 | | // https://html.spec.whatwg.org/multipage/browsers.html#bcg-remove |
407 | | void BrowsingContext::remove() |
408 | 0 | { |
409 | | // 1. Assert: browsingContext's group is non-null, because a browsing context only gets discarded once. |
410 | 0 | VERIFY(group()); |
411 | | |
412 | | // 2. Let group be browsingContext's group. |
413 | 0 | JS::NonnullGCPtr<BrowsingContextGroup> group = *this->group(); |
414 | | |
415 | | // 3. Set browsingContext's group to null. |
416 | 0 | set_group(nullptr); |
417 | | |
418 | | // 4. Remove browsingContext from group's browsing context set. |
419 | 0 | group->browsing_context_set().remove(*this); |
420 | | |
421 | | // 5. If group's browsing context set is empty, then remove group from the user agent's browsing context group set. |
422 | | // NOTE: This is done by ~BrowsingContextGroup() when the refcount reaches 0. |
423 | 0 | } |
424 | | |
425 | | // https://html.spec.whatwg.org/multipage/origin.html#one-permitted-sandboxed-navigator |
426 | | BrowsingContext const* BrowsingContext::the_one_permitted_sandboxed_navigator() const |
427 | 0 | { |
428 | | // FIXME: Implement this. |
429 | 0 | return nullptr; |
430 | 0 | } |
431 | | |
432 | | JS::GCPtr<BrowsingContext> BrowsingContext::first_child() const |
433 | 0 | { |
434 | 0 | return m_first_child; |
435 | 0 | } |
436 | | JS::GCPtr<BrowsingContext> BrowsingContext::next_sibling() const |
437 | 0 | { |
438 | 0 | return m_next_sibling; |
439 | 0 | } |
440 | | |
441 | | // https://html.spec.whatwg.org/multipage/document-sequences.html#ancestor-browsing-context |
442 | | bool BrowsingContext::is_ancestor_of(BrowsingContext const& potential_descendant) const |
443 | 0 | { |
444 | | // A browsing context potentialDescendant is said to be an ancestor of a browsing context potentialAncestor if the following algorithm returns true: |
445 | | |
446 | | // 1. Let potentialDescendantDocument be potentialDescendant's active document. |
447 | 0 | auto const* potential_descendant_document = potential_descendant.active_document(); |
448 | | |
449 | | // 2. If potentialDescendantDocument is not fully active, then return false. |
450 | 0 | if (!potential_descendant_document->is_fully_active()) |
451 | 0 | return false; |
452 | | |
453 | | // 3. Let ancestorBCs be the list obtained by taking the browsing context of the active document of each member of potentialDescendantDocument's ancestor navigables. |
454 | 0 | for (auto const& ancestor : potential_descendant_document->ancestor_navigables()) { |
455 | 0 | auto ancestor_browsing_context = ancestor->active_browsing_context(); |
456 | | |
457 | | // 4. If ancestorBCs contains potentialAncestor, then return true. |
458 | 0 | if (ancestor_browsing_context == this) |
459 | 0 | return true; |
460 | 0 | } |
461 | | |
462 | | // 5. Return false. |
463 | 0 | return false; |
464 | 0 | } |
465 | | |
466 | | // https://html.spec.whatwg.org/multipage/document-sequences.html#familiar-with |
467 | | bool BrowsingContext::is_familiar_with(BrowsingContext const& other) const |
468 | 0 | { |
469 | | // A browsing context A is familiar with a second browsing context B if the following algorithm returns true: |
470 | 0 | auto const& A = *this; |
471 | 0 | auto const& B = other; |
472 | | |
473 | | // 1. If A's active document's origin is same origin with B's active document's origin, then return true. |
474 | 0 | if (A.active_document()->origin().is_same_origin(B.active_document()->origin())) |
475 | 0 | return true; |
476 | | |
477 | | // 2. If A's top-level browsing context is B, then return true. |
478 | 0 | if (A.top_level_browsing_context() == &B) |
479 | 0 | return true; |
480 | | |
481 | | // 3. If B is an auxiliary browsing context and A is familiar with B's opener browsing context, then return true. |
482 | 0 | if (B.opener_browsing_context() != nullptr && A.is_familiar_with(*B.opener_browsing_context())) |
483 | 0 | return true; |
484 | | |
485 | | // 4. If there exists an ancestor browsing context of B whose active document has the same origin as the active document of A, then return true. |
486 | | // NOTE: This includes the case where A is an ancestor browsing context of B. |
487 | | |
488 | | // If B's active document is not fully active then it cannot have ancestor browsing context |
489 | 0 | if (!B.active_document()->is_fully_active()) |
490 | 0 | return false; |
491 | | |
492 | 0 | for (auto const& ancestor : B.active_document()->ancestor_navigables()) { |
493 | 0 | if (ancestor->active_document()->origin().is_same_origin(A.active_document()->origin())) |
494 | 0 | return true; |
495 | 0 | } |
496 | | |
497 | | // 5. Return false. |
498 | 0 | return false; |
499 | 0 | } |
500 | | |
501 | | // https://html.spec.whatwg.org/multipage/browsing-the-web.html#snapshotting-target-snapshot-params |
502 | | SandboxingFlagSet determine_the_creation_sandboxing_flags(BrowsingContext const&, JS::GCPtr<DOM::Element>) |
503 | 0 | { |
504 | | // FIXME: Populate this once we have the proper flag sets on BrowsingContext |
505 | 0 | return {}; |
506 | 0 | } |
507 | | |
508 | | bool BrowsingContext::has_navigable_been_destroyed() const |
509 | 0 | { |
510 | 0 | auto navigable = active_document()->navigable(); |
511 | 0 | return !navigable || navigable->has_been_destroyed(); |
512 | 0 | } |
513 | | |
514 | | } |