summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp186
-rw-r--r--Userland/Libraries/LibWeb/HTML/BrowsingContext.h13
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLHyperlinkElementUtils.cpp4
3 files changed, 112 insertions, 91 deletions
diff --git a/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp b/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp
index 67cb6e1eca..d2e9306306 100644
--- a/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp
+++ b/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp
@@ -651,118 +651,128 @@ JS::GCPtr<DOM::Node> BrowsingContext::currently_focused_area()
return candidate;
}
-BrowsingContext* BrowsingContext::choose_a_browsing_context(StringView name, bool)
+// https://html.spec.whatwg.org/#the-rules-for-choosing-a-browsing-context-given-a-browsing-context-name
+BrowsingContext::ChosenBrowsingContext BrowsingContext::choose_a_browsing_context(StringView name, bool no_opener)
{
- // The rules for choosing a browsing context, given a browsing context name
- // name, a browsing context current, and a boolean noopener are as follows:
+ // The rules for choosing a browsing context, given a browsing context name name, a browsing context current, and
+ // a boolean noopener are as follows:
// 1. Let chosen be null.
JS::GCPtr<BrowsingContext> chosen = nullptr;
- // FIXME: 2. Let windowType be "existing or none".
+ // 2. Let windowType be "existing or none".
+ auto window_type = WindowType::ExistingOrNone;
- // FIXME: 3. Let sandboxingFlagSet be current's active document's active
- // sandboxing flag set.
+ // 3. Let sandboxingFlagSet be current's active document's active sandboxing flag set.
+ auto sandboxing_flag_set = active_document()->active_sandboxing_flag_set();
// 4. If name is the empty string or an ASCII case-insensitive match for "_self", then set chosen to current.
- if (name.is_empty() || name.equals_ignoring_case("_self"sv))
+ if (name.is_empty() || name.equals_ignoring_case("_self"sv)) {
chosen = this;
+ }
- // 5. Otherwise, if name is an ASCII case-insensitive match for "_parent",
- // set chosen to current's parent browsing context, if any, and current
- // otherwise.
- if (name.equals_ignoring_case("_parent"sv)) {
+ // 5. Otherwise, if name is an ASCII case-insensitive match for "_parent", set chosen to current's parent browsing
+ // context, if any, and current otherwise.
+ else if (name.equals_ignoring_case("_parent"sv)) {
if (auto parent = this->parent())
chosen = parent;
else
chosen = this;
}
- // 6. Otherwise, if name is an ASCII case-insensitive match for "_top", set
- // chosen to current's top-level browsing context, if any, and current
- // otherwise.
- if (name.equals_ignoring_case("_top"sv)) {
+ // 6. Otherwise, if name is an ASCII case-insensitive match for "_top", set chosen to current's top-level browsing
+ // context, if any, and current otherwise.
+ else if (name.equals_ignoring_case("_top"sv)) {
chosen = &top_level_browsing_context();
}
- // FIXME: 7. Otherwise, if name is not an ASCII case-insensitive match for
- // "_blank", there exists a browsing context whose name is the same as name,
- // current is familiar with that browsing context, and the user agent
- // determines that the two browsing contexts are related enough that it is
- // ok if they reach each other, set chosen to that browsing context. If
- // there are multiple matching browsing contexts, the user agent should set
- // chosen to one in some arbitrary consistent manner, such as the most
- // recently opened, most recently focused, or more closely related.
- if (!name.equals_ignoring_case("_blank"sv)) {
+ // FIXME: 7. Otherwise, if name is not an ASCII case-insensitive match for "_blank", there exists a browsing context
+ // whose name is the same as name, current is familiar with that browsing context, and the user agent
+ // determines that the two browsing contexts are related enough that it is ok if they reach each other,
+ // set chosen to that browsing context. If there are multiple matching browsing contexts, the user agent
+ // should set chosen to one in some arbitrary consistent manner, such as the most recently opened, most
+ // recently focused, or more closely related.
+ else if (!name.equals_ignoring_case("_blank"sv)) {
+ dbgln("FIXME: Find matching browser context for name {}", name);
chosen = this;
} else {
- // 8. Otherwise, a new browsing context is being requested, and what
- // happens depends on the user agent's configuration and abilities — it
- // is determined by the rules given for the first applicable option from
- // the following list:
- dbgln("FIXME: Create a new browsing context!");
-
- // --> If current's active window does not have transient activation and
- // the user agent has been configured to not show popups (i.e., the
- // user agent has a "popup blocker" enabled)
- //
- // The user agent may inform the user that a popup has been blocked.
-
- // --> If sandboxingFlagSet has the sandboxed auxiliary navigation
- // browsing context flag set
- //
- // The user agent may report to a developer console that a popup has
- // been blocked.
-
- // --> If the user agent has been configured such that in this instance
- // it will create a new browsing context
- //
- // 1. Set windowType to "new and unrestricted".
-
- // 2. If current's top-level browsing context's active document's
- // cross-origin opener policy's value is "same-origin" or
- // "same-origin-plus-COEP", then:
-
- // 2.1. Let currentDocument be current's active document.
-
- // 2.2. If currentDocument's origin is not same origin with
- // currentDocument's relevant settings object's top-level
- // origin, then set noopener to true, name to "_blank", and
- // windowType to "new with no opener".
-
- // 3. If noopener is true, then set chosen to the result of creating
- // a new top-level browsing context.
-
- // 4. Otherwise:
-
- // 4.1. Set chosen to the result of creating a new auxiliary
- // browsing context with current.
-
- // 4.2. If sandboxingFlagSet's sandboxed navigation browsing
- // context flag is set, then current must be set as chosen's one
- // permitted sandboxed navigator.
-
- // 5. If sandboxingFlagSet's sandbox propagates to auxiliary
- // browsing contexts flag is set, then all the flags that are set in
- // sandboxingFlagSet must be set in chosen's popup sandboxing flag
- // set.
-
- // 6. If name is not an ASCII case-insensitive match for "_blank",
- // then set chosen's name to name.
-
- // --> If the user agent has been configured such that in this instance
- // it will reuse current
- //
- // Set chosen to current.
-
- // --> If the user agent has been configured such that in this instance
- // it will not find a browsing context
- //
- // Do nothing.
+ // 8. Otherwise, a new browsing context is being requested, and what happens depends on the user agent's
+ // configuration and abilities — it is determined by the rules given for the first applicable option from
+ // the following list:
+
+ // --> If current's active window does not have transient activation and the user agent has been configured to
+ // not show popups (i.e., the user agent has a "popup blocker" enabled)
+ VERIFY(m_page);
+ if (!active_window()->has_transient_activation() && m_page->should_block_pop_ups()) {
+ // FIXME: The user agent may inform the user that a popup has been blocked.
+ dbgln("Pop-up blocked!");
+ }
+
+ // --> If sandboxingFlagSet has the sandboxed auxiliary navigation browsing context flag set
+ else if (sandboxing_flag_set.flags & SandboxingFlagSet::SandboxedAuxiliaryNavigation) {
+ // FIXME: The user agent may report to a developer console that a popup has been blocked.
+ dbgln("Pop-up blocked!");
+ }
+
+ // --> If the user agent has been configured such that in this instance it will create a new browsing context
+ else if (true) { // FIXME: When is this the case?
+ // 1. Set windowType to "new and unrestricted".
+ window_type = WindowType::NewAndUnrestricted;
+
+ // 2. If current's top-level browsing context's active document's cross-origin opener policy's value is
+ // "same-origin" or "same-origin-plus-COEP", then:
+ if (top_level_browsing_context().active_document()->cross_origin_opener_policy().value == CrossOriginOpenerPolicyValue::SameOrigin || top_level_browsing_context().active_document()->cross_origin_opener_policy().value == CrossOriginOpenerPolicyValue::SameOriginPlusCOEP) {
+ // 1. Let currentDocument be current's active document.
+ auto* current_document = top_level_browsing_context().active_document();
+
+ // 2. If currentDocument's origin is not same origin with currentDocument's relevant settings object's
+ // top-level origin, then set noopener to true, name to "_blank", and windowType to "new with no opener".
+ if (!current_document->origin().is_same_origin(current_document->relevant_settings_object().top_level_origin)) {
+ no_opener = true;
+ name = "_blank"sv;
+ window_type = WindowType::NewWithNoOpener;
+ }
+ }
+
+ // 3. If noopener is true, then set chosen to the result of creating a new top-level browsing context.
+ if (no_opener) {
+ chosen = HTML::BrowsingContext::create_a_new_top_level_browsing_context(*m_page);
+ }
+
+ // 4. Otherwise:
+ else {
+ // 1. Set chosen to the result of creating a new auxiliary browsing context with current.
+ // FIXME: We have no concept of auxiliary browsing context
+ chosen = HTML::BrowsingContext::create_a_new_top_level_browsing_context(*m_page);
+
+ // 2. If sandboxingFlagSet's sandboxed navigation browsing context flag is set, then current must be
+ // set as chosen's one permitted sandboxed navigator.
+ // FIXME: We have no concept of one permitted sandboxed navigator
+ }
+
+ // 5. If sandboxingFlagSet's sandbox propagates to auxiliary browsing contexts flag is set, then all the
+ // flags that are set in sandboxingFlagSet must be set in chosen's popup sandboxing flag set.
+ // FIXME: Our BrowsingContexts do not have SandboxingFlagSets yet, only documents do
+
+ // 6. If name is not an ASCII case-insensitive match for "_blank", then set chosen's name to name.
+ if (!name.equals_ignoring_case("_blank"sv))
+ chosen->set_name(name);
+ }
+
+ // --> If the user agent has been configured such that in this instance t will reuse current
+ else if (false) { // FIXME: When is this the case?
+ // Set chosen to current.
+ chosen = *this;
+ }
+
+ // --> If the user agent has been configured such that in this instance it will not find a browsing context
+ else if (false) { // FIXME: When is this the case?
+ // Do nothing.
+ }
}
// 9. Return chosen and windowType.
- return chosen;
+ return { chosen, window_type };
}
// https://html.spec.whatwg.org/multipage/browsers.html#document-tree-child-browsing-context
diff --git a/Userland/Libraries/LibWeb/HTML/BrowsingContext.h b/Userland/Libraries/LibWeb/HTML/BrowsingContext.h
index 64953a5638..32a7bfd6fb 100644
--- a/Userland/Libraries/LibWeb/HTML/BrowsingContext.h
+++ b/Userland/Libraries/LibWeb/HTML/BrowsingContext.h
@@ -163,7 +163,18 @@ public:
BrowsingContext const& top_level_browsing_context() const { return const_cast<BrowsingContext*>(this)->top_level_browsing_context(); }
- BrowsingContext* choose_a_browsing_context(StringView name, bool noopener);
+ enum class WindowType {
+ ExistingOrNone,
+ NewAndUnrestricted,
+ NewWithNoOpener,
+ };
+
+ struct ChosenBrowsingContext {
+ JS::GCPtr<BrowsingContext> browsing_context;
+ WindowType window_type;
+ };
+
+ ChosenBrowsingContext choose_a_browsing_context(StringView name, bool no_opener);
size_t document_tree_child_browsing_context_count() const;
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLHyperlinkElementUtils.cpp b/Userland/Libraries/LibWeb/HTML/HTMLHyperlinkElementUtils.cpp
index 794cb51453..43858ad2b4 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLHyperlinkElementUtils.cpp
+++ b/Userland/Libraries/LibWeb/HTML/HTMLHyperlinkElementUtils.cpp
@@ -493,7 +493,7 @@ void HTMLHyperlinkElementUtils::follow_the_hyperlink(Optional<String> hyperlink_
// 7. Let target be the first return value of applying the rules for
// choosing a browsing context given targetAttributeValue, source, and
// noopener.
- auto* target = source->choose_a_browsing_context(target_attribute_value, noopener);
+ auto target = source->choose_a_browsing_context(target_attribute_value, noopener).browsing_context;
// 8. If target is null, then return.
if (!target)
@@ -534,7 +534,7 @@ void HTMLHyperlinkElementUtils::follow_the_hyperlink(Optional<String> hyperlink_
// set to source.
// FIXME: "navigate" means implementing the navigation algorithm here:
// https://html.spec.whatwg.org/multipage/browsing-the-web.html#navigate
- hyperlink_element_utils_queue_an_element_task(Task::Source::DOMManipulation, [url_string, target] {
+ hyperlink_element_utils_queue_an_element_task(Task::Source::DOMManipulation, [url_string, &target] {
target->loader().load(url_string, FrameLoader::Type::Navigation);
});
}