This commit is contained in:
Chase Knowlden 2024-11-20 20:01:46 -05:00 committed by GitHub
commit b4e7e27dae
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 57 additions and 8 deletions

View file

@ -122,22 +122,18 @@ void HTMLAnchorElement::activation_behavior(Web::DOM::Event const& event)
// 5. If the user has expressed a preference to download the hyperlink, then set userInvolvement to "browser UI". // 5. If the user has expressed a preference to download the hyperlink, then set userInvolvement to "browser UI".
// NOTE: That is, if the user has expressed a specific preference for downloading, this no longer counts as merely "activation". // NOTE: That is, if the user has expressed a specific preference for downloading, this no longer counts as merely "activation".
if (has_download_preference()) if (has_attribute(HTML::AttributeNames::download))
user_involvement = UserNavigationInvolvement::BrowserUI; user_involvement = UserNavigationInvolvement::BrowserUI;
// FIXME: 6. If element has a download attribute, or if the user has expressed a preference to download the // 6. If element has a download attribute, or if the user has expressed a preference to download the
// hyperlink, then download the hyperlink created by element with hyperlinkSuffix set to hyperlinkSuffix and // hyperlink, then download the hyperlink created by element with hyperlinkSuffix set to hyperlinkSuffix and
// userInvolvement set to userInvolvement. // userInvolvement set to userInvolvement.
download_hyperlink(hyperlink_suffix, user_involvement);
// 7. Otherwise, follow the hyperlink created by element with hyperlinkSuffix set to hyperlinkSuffix and userInvolvement set to userInvolvement. // 7. Otherwise, follow the hyperlink created by element with hyperlinkSuffix set to hyperlinkSuffix and userInvolvement set to userInvolvement.
follow_the_hyperlink(hyperlink_suffix, user_involvement); follow_the_hyperlink(hyperlink_suffix, user_involvement);
} }
bool HTMLAnchorElement::has_download_preference() const
{
return has_attribute(HTML::AttributeNames::download);
}
// https://html.spec.whatwg.org/multipage/interaction.html#dom-tabindex // https://html.spec.whatwg.org/multipage/interaction.html#dom-tabindex
i32 HTMLAnchorElement::default_tab_index_value() const i32 HTMLAnchorElement::default_tab_index_value() const
{ {

View file

@ -43,7 +43,6 @@ private:
virtual bool has_activation_behavior() const override; virtual bool has_activation_behavior() const override;
virtual void activation_behavior(Web::DOM::Event const&) override; virtual void activation_behavior(Web::DOM::Event const&) override;
virtual bool has_download_preference() const;
// ^DOM::Element // ^DOM::Element
virtual void attribute_changed(FlyString const& name, Optional<String> const& old_value, Optional<String> const& value, Optional<FlyString> const& namespace_) override; virtual void attribute_changed(FlyString const& name, Optional<String> const& old_value, Optional<String> const& value, Optional<FlyString> const& namespace_) override;

View file

@ -8,6 +8,9 @@
#include <LibWeb/DOM/Document.h> #include <LibWeb/DOM/Document.h>
#include <LibWeb/HTML/HTMLHyperlinkElementUtils.h> #include <LibWeb/HTML/HTMLHyperlinkElementUtils.h>
#include <LibWeb/HTML/Navigable.h> #include <LibWeb/HTML/Navigable.h>
#include <LibWeb/HTML/Navigation.h>
#include <LibWeb/HTML/Window.h>
#include <LibWeb/Platform/EventLoopPlugin.h>
namespace Web::HTML { namespace Web::HTML {
@ -509,4 +512,54 @@ void HTMLHyperlinkElementUtils::follow_the_hyperlink(Optional<String> hyperlink_
MUST(target_navigable->navigate({ .url = url_string, .source_document = hyperlink_element_utils_document(), .referrer_policy = referrer_policy, .user_involvement = user_involvement })); MUST(target_navigable->navigate({ .url = url_string, .source_document = hyperlink_element_utils_document(), .referrer_policy = referrer_policy, .user_involvement = user_involvement }));
} }
void HTMLHyperlinkElementUtils::download_hyperlink(Optional<String> hyperlink_suffix, UserNavigationInvolvement user_involvement)
{
// 1. If subject cannot navigate, then return.
if (cannot_navigate())
return;
// 2. If subject's node document's active sandboxing flag set has the sandboxed downloads browsing context flag set, then return.
if (has_flag(hyperlink_element_utils_document().active_sandboxing_flag_set(), SandboxingFlagSet::SandboxedDownloads))
return;
// 3. Let urlString be the result of encoding-parsing-and-serializing a URL given subject's href attribute value, relative to subject's node document.
auto url = hyperlink_element_utils_document().parse_url(href());
// 4. If urlString is failure, then return.
if (!url.is_valid())
return;
auto url_string = MUST(url.to_string());
// 5. If hyperlinkSuffix is non-null, then append it to urlString.
if (hyperlink_suffix.has_value()) {
StringBuilder url_builder;
url_builder.append(url_string);
url_builder.append(*hyperlink_suffix);
url_string = MUST(url_builder.to_string());
}
// 6. If userInvolvement is not "browser UI", then:
if (user_involvement != UserNavigationInvolvement::BrowserUI) {
// 1. Assert: subject has a download attribute.
VERIFY(hyperlink_element_utils_element().has_attribute(HTML::AttributeNames::download));
// 2. Let navigation be subject's relevant global object's navigation API.
auto navigation = verify_cast<Window>(relevant_global_object(hyperlink_element_utils_element())).navigation();
// 3. Let filename be the value of subject's download attribute.
auto filename = hyperlink_element_utils_element().attribute(HTML::AttributeNames::download).value_or(String {});
// 4. Let continue be the result of firing a download request navigate event at navigation with destinationURL set to urlString, userInvolvement set to userInvolvement, and filename set to filename.
bool continue_ = navigation->fire_a_download_request_navigate_event(url_string, user_involvement, filename);
// 5. If continue is false, then return.
if (!continue_)
return;
}
// FIXME: 7. Run these steps in parallel:
}
} }

View file

@ -65,6 +65,7 @@ protected:
void set_the_url(); void set_the_url();
void follow_the_hyperlink(Optional<String> hyperlink_suffix, UserNavigationInvolvement = UserNavigationInvolvement::None); void follow_the_hyperlink(Optional<String> hyperlink_suffix, UserNavigationInvolvement = UserNavigationInvolvement::None);
void download_hyperlink(Optional<String> hyperlink_suffix, UserNavigationInvolvement = UserNavigationInvolvement::None);
private: private:
void reinitialize_url() const; void reinitialize_url() const;