mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 23:57:43 +00:00
LibWeb+WebContent: Change the "noopener" storage type to a named enum
This commit is contained in:
parent
496b7ffb2b
commit
1b811191cd
7 changed files with 65 additions and 16 deletions
|
@ -615,7 +615,7 @@ JS::GCPtr<DOM::Node> BrowsingContext::currently_focused_area()
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/#the-rules-for-choosing-a-browsing-context-given-a-browsing-context-name
|
// 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, ActivateTab activate_tab)
|
BrowsingContext::ChosenBrowsingContext BrowsingContext::choose_a_browsing_context(StringView name, TokenizedFeature::NoOpener no_opener, ActivateTab activate_tab)
|
||||||
{
|
{
|
||||||
// The rules for choosing a browsing context, given a browsing context name name, a browsing context current, and
|
// The rules for choosing a browsing context, given a browsing context name name, a browsing context current, and
|
||||||
// a boolean noopener are as follows:
|
// a boolean noopener are as follows:
|
||||||
|
@ -691,14 +691,14 @@ BrowsingContext::ChosenBrowsingContext BrowsingContext::choose_a_browsing_contex
|
||||||
// 2. If currentDocument's origin is not same origin with currentDocument's relevant settings object's
|
// 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".
|
// 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)) {
|
if (!current_document->origin().is_same_origin(current_document->relevant_settings_object().top_level_origin)) {
|
||||||
no_opener = true;
|
no_opener = TokenizedFeature::NoOpener::Yes;
|
||||||
name = "_blank"sv;
|
name = "_blank"sv;
|
||||||
window_type = WindowType::NewWithNoOpener;
|
window_type = WindowType::NewWithNoOpener;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. If noopener is true, then set chosen to the result of creating a new top-level browsing context.
|
// 3. If noopener is true, then set chosen to the result of creating a new top-level browsing context.
|
||||||
if (no_opener) {
|
if (no_opener == TokenizedFeature::NoOpener::Yes) {
|
||||||
auto handle = m_page->client().page_did_request_new_tab(activate_tab);
|
auto handle = m_page->client().page_did_request_new_tab(activate_tab);
|
||||||
chosen = RemoteBrowsingContext::create_a_new_remote_browsing_context(handle);
|
chosen = RemoteBrowsingContext::create_a_new_remote_browsing_context(handle);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include <LibWeb/HTML/HistoryHandlingBehavior.h>
|
#include <LibWeb/HTML/HistoryHandlingBehavior.h>
|
||||||
#include <LibWeb/HTML/Origin.h>
|
#include <LibWeb/HTML/Origin.h>
|
||||||
#include <LibWeb/HTML/SessionHistoryEntry.h>
|
#include <LibWeb/HTML/SessionHistoryEntry.h>
|
||||||
|
#include <LibWeb/HTML/TokenizedFeatures.h>
|
||||||
#include <LibWeb/HTML/VisibilityState.h>
|
#include <LibWeb/HTML/VisibilityState.h>
|
||||||
#include <LibWeb/Loader/FrameLoader.h>
|
#include <LibWeb/Loader/FrameLoader.h>
|
||||||
#include <LibWeb/Page/EventHandler.h>
|
#include <LibWeb/Page/EventHandler.h>
|
||||||
|
@ -172,7 +173,7 @@ public:
|
||||||
WindowType window_type;
|
WindowType window_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
ChosenBrowsingContext choose_a_browsing_context(StringView name, bool no_opener, ActivateTab = ActivateTab::Yes);
|
ChosenBrowsingContext choose_a_browsing_context(StringView name, TokenizedFeature::NoOpener no_opener, ActivateTab = ActivateTab::Yes);
|
||||||
|
|
||||||
size_t document_tree_child_browsing_context_count() const;
|
size_t document_tree_child_browsing_context_count() const;
|
||||||
|
|
||||||
|
|
|
@ -490,7 +490,7 @@ void HTMLHyperlinkElementUtils::follow_the_hyperlink(Optional<DeprecatedString>
|
||||||
DeprecatedString target_attribute_value = get_an_elements_target();
|
DeprecatedString target_attribute_value = get_an_elements_target();
|
||||||
|
|
||||||
// 6. Let noopener be the result of getting an element's noopener with subject and targetAttributeValue.
|
// 6. Let noopener be the result of getting an element's noopener with subject and targetAttributeValue.
|
||||||
bool noopener = get_an_elements_noopener(target_attribute_value);
|
auto noopener = get_an_elements_noopener(target_attribute_value);
|
||||||
|
|
||||||
// 7. Let target be the first return value of applying the rules for
|
// 7. Let target be the first return value of applying the rules for
|
||||||
// choosing a browsing context given targetAttributeValue, source, and
|
// choosing a browsing context given targetAttributeValue, source, and
|
||||||
|
@ -558,7 +558,7 @@ DeprecatedString HTMLHyperlinkElementUtils::get_an_elements_target() const
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/links.html#get-an-element's-noopener
|
// https://html.spec.whatwg.org/multipage/links.html#get-an-element's-noopener
|
||||||
bool HTMLHyperlinkElementUtils::get_an_elements_noopener(StringView target) const
|
TokenizedFeature::NoOpener HTMLHyperlinkElementUtils::get_an_elements_noopener(StringView target) const
|
||||||
{
|
{
|
||||||
// To get an element's noopener, given an a, area, or form element element and a string target:
|
// To get an element's noopener, given an a, area, or form element element and a string target:
|
||||||
auto rel = hyperlink_element_utils_rel().to_lowercase();
|
auto rel = hyperlink_element_utils_rel().to_lowercase();
|
||||||
|
@ -566,15 +566,15 @@ bool HTMLHyperlinkElementUtils::get_an_elements_noopener(StringView target) cons
|
||||||
|
|
||||||
// 1. If element's link types include the noopener or noreferrer keyword, then return true.
|
// 1. If element's link types include the noopener or noreferrer keyword, then return true.
|
||||||
if (link_types.contains_slow("noopener"sv) || link_types.contains_slow("noreferrer"sv))
|
if (link_types.contains_slow("noopener"sv) || link_types.contains_slow("noreferrer"sv))
|
||||||
return true;
|
return TokenizedFeature::NoOpener::Yes;
|
||||||
|
|
||||||
// 2. If element's link types do not include the opener keyword and
|
// 2. If element's link types do not include the opener keyword and
|
||||||
// target is an ASCII case-insensitive match for "_blank", then return true.
|
// target is an ASCII case-insensitive match for "_blank", then return true.
|
||||||
if (!link_types.contains_slow("opener"sv) && Infra::is_ascii_case_insensitive_match(target, "_blank"sv))
|
if (!link_types.contains_slow("opener"sv) && Infra::is_ascii_case_insensitive_match(target, "_blank"sv))
|
||||||
return true;
|
return TokenizedFeature::NoOpener::Yes;
|
||||||
|
|
||||||
// 3. Return false.
|
// 3. Return false.
|
||||||
return false;
|
return TokenizedFeature::NoOpener::No;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <AK/URL.h>
|
#include <AK/URL.h>
|
||||||
#include <LibWeb/Forward.h>
|
#include <LibWeb/Forward.h>
|
||||||
#include <LibWeb/HTML/EventLoop/Task.h>
|
#include <LibWeb/HTML/EventLoop/Task.h>
|
||||||
|
#include <LibWeb/HTML/TokenizedFeatures.h>
|
||||||
|
|
||||||
namespace Web::HTML {
|
namespace Web::HTML {
|
||||||
|
|
||||||
|
@ -66,7 +67,7 @@ private:
|
||||||
void update_href();
|
void update_href();
|
||||||
bool cannot_navigate() const;
|
bool cannot_navigate() const;
|
||||||
DeprecatedString get_an_elements_target() const;
|
DeprecatedString get_an_elements_target() const;
|
||||||
bool get_an_elements_noopener(StringView target) const;
|
TokenizedFeature::NoOpener get_an_elements_noopener(StringView target) const;
|
||||||
|
|
||||||
Optional<AK::URL> m_url;
|
Optional<AK::URL> m_url;
|
||||||
};
|
};
|
||||||
|
|
19
Userland/Libraries/LibWeb/HTML/TokenizedFeatures.h
Normal file
19
Userland/Libraries/LibWeb/HTML/TokenizedFeatures.h
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023, Tim Flynn <trflynn89@serenityos.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace Web::HTML::TokenizedFeature {
|
||||||
|
|
||||||
|
#define TOKENIZED_FEATURE(Feature) \
|
||||||
|
enum class Feature { \
|
||||||
|
Yes, \
|
||||||
|
No, \
|
||||||
|
}
|
||||||
|
|
||||||
|
TOKENIZED_FEATURE(NoOpener);
|
||||||
|
|
||||||
|
}
|
|
@ -43,6 +43,7 @@
|
||||||
#include <LibWeb/HTML/Scripting/Environments.h>
|
#include <LibWeb/HTML/Scripting/Environments.h>
|
||||||
#include <LibWeb/HTML/Scripting/ExceptionReporter.h>
|
#include <LibWeb/HTML/Scripting/ExceptionReporter.h>
|
||||||
#include <LibWeb/HTML/Storage.h>
|
#include <LibWeb/HTML/Storage.h>
|
||||||
|
#include <LibWeb/HTML/TokenizedFeatures.h>
|
||||||
#include <LibWeb/HTML/Window.h>
|
#include <LibWeb/HTML/Window.h>
|
||||||
#include <LibWeb/HTML/WindowProxy.h>
|
#include <LibWeb/HTML/WindowProxy.h>
|
||||||
#include <LibWeb/HighResolutionTime/Performance.h>
|
#include <LibWeb/HighResolutionTime/Performance.h>
|
||||||
|
@ -223,6 +224,33 @@ static bool parse_boolean_feature(StringView value)
|
||||||
return *parsed != 0;
|
return *parsed != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#concept-window-open-features-parse-boolean
|
||||||
|
template<Enum T>
|
||||||
|
static T parse_boolean_feature(StringView value)
|
||||||
|
{
|
||||||
|
// 1. If value is the empty string, then return true.
|
||||||
|
if (value.is_empty())
|
||||||
|
return T::Yes;
|
||||||
|
|
||||||
|
// 2. If value is "yes", then return true.
|
||||||
|
if (value == "yes"sv)
|
||||||
|
return T::Yes;
|
||||||
|
|
||||||
|
// 3. If value is "true", then return true.
|
||||||
|
if (value == "true"sv)
|
||||||
|
return T::Yes;
|
||||||
|
|
||||||
|
// 4. Let parsed be the result of parsing value as an integer.
|
||||||
|
auto parsed = value.to_int<i64>();
|
||||||
|
|
||||||
|
// 5. If parsed is an error, then set it to 0.
|
||||||
|
if (!parsed.has_value())
|
||||||
|
parsed = 0;
|
||||||
|
|
||||||
|
// 6. Return false if parsed is 0, and true otherwise.
|
||||||
|
return parsed == 0 ? T::No : T::Yes;
|
||||||
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/window-object.html#popup-window-is-requested
|
// https://html.spec.whatwg.org/multipage/window-object.html#popup-window-is-requested
|
||||||
static bool check_if_a_popup_window_is_requested(OrderedHashMap<DeprecatedString, DeprecatedString> const& tokenized_features)
|
static bool check_if_a_popup_window_is_requested(OrderedHashMap<DeprecatedString, DeprecatedString> const& tokenized_features)
|
||||||
{
|
{
|
||||||
|
@ -307,13 +335,13 @@ WebIDL::ExceptionOr<JS::GCPtr<WindowProxy>> Window::open_impl(StringView url, St
|
||||||
auto tokenized_features = tokenize_open_features(features);
|
auto tokenized_features = tokenize_open_features(features);
|
||||||
|
|
||||||
// 5. Let noopener and noreferrer be false.
|
// 5. Let noopener and noreferrer be false.
|
||||||
auto no_opener = false;
|
auto no_opener = TokenizedFeature::NoOpener::No;
|
||||||
auto no_referrer = false;
|
auto no_referrer = false;
|
||||||
|
|
||||||
// 6. If tokenizedFeatures["noopener"] exists, then:
|
// 6. If tokenizedFeatures["noopener"] exists, then:
|
||||||
if (auto no_opener_feature = tokenized_features.get("noopener"sv); no_opener_feature.has_value()) {
|
if (auto no_opener_feature = tokenized_features.get("noopener"sv); no_opener_feature.has_value()) {
|
||||||
// 1. Set noopener to the result of parsing tokenizedFeatures["noopener"] as a boolean feature.
|
// 1. Set noopener to the result of parsing tokenizedFeatures["noopener"] as a boolean feature.
|
||||||
no_opener = parse_boolean_feature(*no_opener_feature);
|
no_opener = parse_boolean_feature<TokenizedFeature::NoOpener>(*no_opener_feature);
|
||||||
|
|
||||||
// 2. Remove tokenizedFeatures["noopener"].
|
// 2. Remove tokenizedFeatures["noopener"].
|
||||||
tokenized_features.remove("noopener"sv);
|
tokenized_features.remove("noopener"sv);
|
||||||
|
@ -330,7 +358,7 @@ WebIDL::ExceptionOr<JS::GCPtr<WindowProxy>> Window::open_impl(StringView url, St
|
||||||
|
|
||||||
// 8. If noreferrer is true, then set noopener to true.
|
// 8. If noreferrer is true, then set noopener to true.
|
||||||
if (no_referrer)
|
if (no_referrer)
|
||||||
no_opener = true;
|
no_opener = TokenizedFeature::NoOpener::Yes;
|
||||||
|
|
||||||
// 9. Let target browsing context and windowType be the result of applying the rules for choosing a browsing context given target, source browsing context, and noopener.
|
// 9. Let target browsing context and windowType be the result of applying the rules for choosing a browsing context given target, source browsing context, and noopener.
|
||||||
auto [target_browsing_context, window_type] = source_browsing_context->choose_a_browsing_context(target, no_opener);
|
auto [target_browsing_context, window_type] = source_browsing_context->choose_a_browsing_context(target, no_opener);
|
||||||
|
@ -399,12 +427,12 @@ WebIDL::ExceptionOr<JS::GCPtr<WindowProxy>> Window::open_impl(StringView url, St
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. If noopener is false, then set target browsing context's opener browsing context to source browsing context.
|
// 2. If noopener is false, then set target browsing context's opener browsing context to source browsing context.
|
||||||
if (!no_opener)
|
if (no_opener == TokenizedFeature::NoOpener::No)
|
||||||
target_browsing_context->set_opener_browsing_context(source_browsing_context);
|
target_browsing_context->set_opener_browsing_context(source_browsing_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 13. If noopener is true or windowType is "new with no opener", then return null.
|
// 13. If noopener is true or windowType is "new with no opener", then return null.
|
||||||
if (no_opener || window_type == BrowsingContext::WindowType::NewWithNoOpener)
|
if (no_opener == TokenizedFeature::NoOpener::Yes || window_type == BrowsingContext::WindowType::NewWithNoOpener)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
// 14. Return target browsing context's WindowProxy object.
|
// 14. Return target browsing context's WindowProxy object.
|
||||||
|
|
|
@ -577,7 +577,7 @@ Messages::WebDriverClient::NewWindowResponse WebDriverConnection::new_window(Jso
|
||||||
// created browsing context should be in a new OS window. In all other cases the details of how the browsing
|
// created browsing context should be in a new OS window. In all other cases the details of how the browsing
|
||||||
// context is presented to the user are implementation defined.
|
// context is presented to the user are implementation defined.
|
||||||
// FIXME: Reuse code of window.open() instead of calling choose_a_browsing_context
|
// FIXME: Reuse code of window.open() instead of calling choose_a_browsing_context
|
||||||
auto [browsing_context, window_type] = m_page_client.page().top_level_browsing_context().choose_a_browsing_context("_blank"sv, true, Web::HTML::ActivateTab::No);
|
auto [browsing_context, window_type] = m_page_client.page().top_level_browsing_context().choose_a_browsing_context("_blank"sv, Web::HTML::TokenizedFeature::NoOpener::Yes, Web::HTML::ActivateTab::No);
|
||||||
|
|
||||||
// 6. Let handle be the associated window handle of the newly created window.
|
// 6. Let handle be the associated window handle of the newly created window.
|
||||||
auto handle = browsing_context->window_handle();
|
auto handle = browsing_context->window_handle();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue