diff --git a/Userland/Libraries/LibWeb/HTML/HTMLButtonElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLButtonElement.cpp index 84e96248f06..508c568967a 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLButtonElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLButtonElement.cpp @@ -70,40 +70,40 @@ bool HTMLButtonElement::has_activation_behavior() const return true; } -void HTMLButtonElement::activation_behavior(DOM::Event const&) +void HTMLButtonElement::activation_behavior(DOM::Event const& event) { // https://html.spec.whatwg.org/multipage/form-elements.html#the-button-element:activation-behaviour // 1. If element is disabled, then return. if (!enabled()) return; - // 2. If element does not have a form owner, then return. - if (!form()) - return; - - // 3. If element's node document is not fully active, then return. + // 2. If element's node document is not fully active, then return. if (!this->document().is_fully_active()) return; - // 4. Switch on element's type attribute's state: - switch (type_state()) { - case TypeAttributeState::Submit: - // Submit Button - // Submit element's form owner from element. - form()->submit_form(*this).release_value_but_fixme_should_propagate_errors(); - break; - case TypeAttributeState::Reset: - // Reset Button - // Reset element's form owner. - form()->reset_form(); - break; - case TypeAttributeState::Button: - // Button - // Do nothing. - break; - default: - VERIFY_NOT_REACHED(); + // 3. If element has a form owner then switch on element's type attribute's state, then: + if (form() != nullptr) { + switch (type_state()) { + case TypeAttributeState::Submit: + // Submit Button + // Submit element's form owner from element with userInvolvement set to event's user navigation involvement. + form()->submit_form(*this, { .user_involvement = user_navigation_involvement(event) }).release_value_but_fixme_should_propagate_errors(); + break; + case TypeAttributeState::Reset: + // Reset Button + // Reset element's form owner. + form()->reset_form(); + break; + case TypeAttributeState::Button: + // Button + // Do nothing. + break; + default: + VERIFY_NOT_REACHED(); + } } + + // 4. FIXME: Run the popover target attribute activation behavior given element. } } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLFormElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLFormElement.cpp index fc4803d04eb..e86d00f1496 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLFormElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLFormElement.cpp @@ -63,7 +63,7 @@ void HTMLFormElement::visit_edges(Cell::Visitor& visitor) } // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#concept-form-submit -WebIDL::ExceptionOr HTMLFormElement::submit_form(JS::NonnullGCPtr submitter, bool from_submit_binding) +WebIDL::ExceptionOr HTMLFormElement::submit_form(JS::NonnullGCPtr submitter, SubmitFormOptions options) { auto& vm = this->vm(); auto& realm = this->realm(); @@ -84,7 +84,7 @@ WebIDL::ExceptionOr HTMLFormElement::submit_form(JS::NonnullGCPtr HTMLFormElement::submit_form(JS::NonnullGCPtris_completely_loaded()) - history_handling = HistoryHandlingBehavior::Replace; + history_handling = Bindings::NavigationHistoryBehavior::Replace; // 24. Select the appropriate row in the table below based on scheme as given by the first cell of each row. // Then, select the appropriate cell on that row based on method as given in the first cell of each column. @@ -233,21 +232,21 @@ WebIDL::ExceptionOr HTMLFormElement::submit_form(JS::NonnullGCPtr HTMLFormElement::submit() { - return submit_form(*this, true); + return submit_form(*this, { .from_submit_binding = true }); } // https://html.spec.whatwg.org/multipage/forms.html#dom-form-reset @@ -645,7 +644,7 @@ static ErrorOr plain_text_encode(Vector const& pairs) } // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#submit-mutate-action -ErrorOr HTMLFormElement::mutate_action_url(AK::URL parsed_action, Vector entry_list, String encoding, JS::NonnullGCPtr target_navigable, HistoryHandlingBehavior history_handling) +ErrorOr HTMLFormElement::mutate_action_url(AK::URL parsed_action, Vector entry_list, String encoding, JS::NonnullGCPtr target_navigable, Bindings::NavigationHistoryBehavior history_handling, UserNavigationInvolvement user_involvement) { // 1. Let pairs be the result of converting to a list of name-value pairs with entry list. auto pairs = TRY(convert_to_list_of_name_value_pairs(entry_list)); @@ -657,12 +656,12 @@ ErrorOr HTMLFormElement::mutate_action_url(AK::URL parsed_action, Vector HTMLFormElement::submit_as_entity_body(AK::URL parsed_action, Vector entry_list, EncodingTypeAttributeState encoding_type, [[maybe_unused]] String encoding, JS::NonnullGCPtr target_navigable, HistoryHandlingBehavior history_handling) +ErrorOr HTMLFormElement::submit_as_entity_body(AK::URL parsed_action, Vector entry_list, EncodingTypeAttributeState encoding_type, [[maybe_unused]] String encoding, JS::NonnullGCPtr target_navigable, Bindings::NavigationHistoryBehavior history_handling, UserNavigationInvolvement user_involvement) { // 1. Assert: method is POST. @@ -716,20 +715,20 @@ ErrorOr HTMLFormElement::submit_as_entity_body(AK::URL parsed_action, Vect } // 3. Plan to navigate to parsed action given a POST resource whose request body is body and request content-type is mimeType. - plan_to_navigate_to(parsed_action, POSTResource { .request_body = move(body), .request_content_type = mime_type }, target_navigable, history_handling); + plan_to_navigate_to(parsed_action, POSTResource { .request_body = move(body), .request_content_type = mime_type }, target_navigable, history_handling, user_involvement); return {}; } // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#submit-get-action -void HTMLFormElement::get_action_url(AK::URL parsed_action, JS::NonnullGCPtr target_navigable, Web::HTML::HistoryHandlingBehavior history_handling) +void HTMLFormElement::get_action_url(AK::URL parsed_action, JS::NonnullGCPtr target_navigable, Bindings::NavigationHistoryBehavior history_handling, UserNavigationInvolvement user_involvement) { // 1. Plan to navigate to parsed action. // Spec Note: entry list is discarded. - plan_to_navigate_to(move(parsed_action), Empty {}, target_navigable, history_handling); + plan_to_navigate_to(move(parsed_action), Empty {}, target_navigable, history_handling, user_involvement); } // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#submit-mailto-headers -ErrorOr HTMLFormElement::mail_with_headers(AK::URL parsed_action, Vector entry_list, [[maybe_unused]] String encoding, JS::NonnullGCPtr target_navigable, HistoryHandlingBehavior history_handling) +ErrorOr HTMLFormElement::mail_with_headers(AK::URL parsed_action, Vector entry_list, [[maybe_unused]] String encoding, JS::NonnullGCPtr target_navigable, Bindings::NavigationHistoryBehavior history_handling, UserNavigationInvolvement user_involvement) { // 1. Let pairs be the result of converting to a list of name-value pairs with entry list. auto pairs = TRY(convert_to_list_of_name_value_pairs(entry_list)); @@ -744,11 +743,11 @@ ErrorOr HTMLFormElement::mail_with_headers(AK::URL parsed_action, Vector HTMLFormElement::mail_as_body(AK::URL parsed_action, Vector entry_list, EncodingTypeAttributeState encoding_type, [[maybe_unused]] String encoding, JS::NonnullGCPtr target_navigable, HistoryHandlingBehavior history_handling) +ErrorOr HTMLFormElement::mail_as_body(AK::URL parsed_action, Vector entry_list, EncodingTypeAttributeState encoding_type, [[maybe_unused]] String encoding, JS::NonnullGCPtr target_navigable, Bindings::NavigationHistoryBehavior history_handling, UserNavigationInvolvement user_involvement) { // 1. Let pairs be the result of converting to a list of name-value pairs with entry list. auto pairs = TRY(convert_to_list_of_name_value_pairs(entry_list)); @@ -797,25 +796,12 @@ ErrorOr HTMLFormElement::mail_as_body(AK::URL parsed_action, Vector post_resource, JS::NonnullGCPtr target_navigable, HistoryHandlingBehavior history_handling) +void HTMLFormElement::plan_to_navigate_to(AK::URL url, Variant post_resource, JS::NonnullGCPtr target_navigable, Bindings::NavigationHistoryBehavior history_handling, UserNavigationInvolvement user_involvement) { // 1. Let referrerPolicy be the empty string. ReferrerPolicy::ReferrerPolicy referrer_policy = ReferrerPolicy::ReferrerPolicy::EmptyString; @@ -835,7 +821,7 @@ void HTMLFormElement::plan_to_navigate_to(AK::URL url, Variant #include #include -#include +#include namespace Web::HTML { @@ -54,7 +54,11 @@ public: EncodingTypeAttributeState encoding_type_state_from_form_element(JS::NonnullGCPtr element) const; - WebIDL::ExceptionOr submit_form(JS::NonnullGCPtr submitter, bool from_submit_binding = false); + struct SubmitFormOptions { + bool from_submit_binding = { false }; + UserNavigationInvolvement user_involvement = { UserNavigationInvolvement::None }; + }; + WebIDL::ExceptionOr submit_form(JS::NonnullGCPtr submitter, SubmitFormOptions); void reset_form(); @@ -106,12 +110,12 @@ private: ErrorOr pick_an_encoding() const; - ErrorOr mutate_action_url(AK::URL parsed_action, Vector entry_list, String encoding, JS::NonnullGCPtr target_navigable, HistoryHandlingBehavior history_handling); - ErrorOr submit_as_entity_body(AK::URL parsed_action, Vector entry_list, EncodingTypeAttributeState encoding_type, String encoding, JS::NonnullGCPtr target_navigable, HistoryHandlingBehavior history_handling); - void get_action_url(AK::URL parsed_action, JS::NonnullGCPtr target_navigable, HistoryHandlingBehavior history_handling); - ErrorOr mail_with_headers(AK::URL parsed_action, Vector entry_list, String encoding, JS::NonnullGCPtr target_navigable, HistoryHandlingBehavior history_handling); - ErrorOr mail_as_body(AK::URL parsed_action, Vector entry_list, EncodingTypeAttributeState encoding_type, String encoding, JS::NonnullGCPtr target_navigable, HistoryHandlingBehavior history_handling); - void plan_to_navigate_to(AK::URL url, Variant post_resource, JS::NonnullGCPtr target_navigable, HistoryHandlingBehavior history_handling); + ErrorOr mutate_action_url(AK::URL parsed_action, Vector entry_list, String encoding, JS::NonnullGCPtr target_navigable, Bindings::NavigationHistoryBehavior history_handling, UserNavigationInvolvement user_involvement); + ErrorOr submit_as_entity_body(AK::URL parsed_action, Vector entry_list, EncodingTypeAttributeState encoding_type, String encoding, JS::NonnullGCPtr target_navigable, Bindings::NavigationHistoryBehavior history_handling, UserNavigationInvolvement user_involvement); + void get_action_url(AK::URL parsed_action, JS::NonnullGCPtr target_navigable, Bindings::NavigationHistoryBehavior history_handling, UserNavigationInvolvement user_involvement); + ErrorOr mail_with_headers(AK::URL parsed_action, Vector entry_list, String encoding, JS::NonnullGCPtr target_navigable, Bindings::NavigationHistoryBehavior history_handling, UserNavigationInvolvement user_involvement); + ErrorOr mail_as_body(AK::URL parsed_action, Vector entry_list, EncodingTypeAttributeState encoding_type, String encoding, JS::NonnullGCPtr target_navigable, Bindings::NavigationHistoryBehavior history_handling, UserNavigationInvolvement user_involvement); + void plan_to_navigate_to(AK::URL url, Variant post_resource, JS::NonnullGCPtr target_navigable, Bindings::NavigationHistoryBehavior history_handling, UserNavigationInvolvement user_involvement); bool m_firing_submission_events { false }; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp index 25763fe1eb1..9085261bf9e 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp @@ -252,7 +252,7 @@ WebIDL::ExceptionOr HTMLInputElement::show_picker() } // https://html.spec.whatwg.org/multipage/input.html#input-activation-behavior -WebIDL::ExceptionOr HTMLInputElement::run_input_activation_behavior() +WebIDL::ExceptionOr HTMLInputElement::run_input_activation_behavior(DOM::Event const& event) { if (type_state() == TypeAttributeState::Checkbox || type_state() == TypeAttributeState::RadioButton) { // 1. If the element is not connected, then return. @@ -279,8 +279,8 @@ WebIDL::ExceptionOr HTMLInputElement::run_input_activation_behavior() if (!document().is_fully_active()) return {}; - // 3. Submit the form owner from the element. - TRY(form->submit_form(*this)); + // 3. Submit the element's form owner from the element with userInvolvement set to event's user navigation involvement. + TRY(form->submit_form(*this, { .user_involvement = user_navigation_involvement(event) })); } else if (type_state() == TypeAttributeState::FileUpload || type_state() == TypeAttributeState::Color) { show_the_picker_if_applicable(*this); } @@ -1581,14 +1581,14 @@ bool HTMLInputElement::has_activation_behavior() const return true; } -void HTMLInputElement::activation_behavior(DOM::Event const&) +void HTMLInputElement::activation_behavior(DOM::Event const& event) { // The activation behavior for input elements are these steps: // FIXME: 1. If this element is not mutable and is not in the Checkbox state and is not in the Radio state, then return. // 2. Run this element's input activation behavior, if any, and do nothing otherwise. - run_input_activation_behavior().release_value_but_fixme_should_propagate_errors(); + run_input_activation_behavior(event).release_value_but_fixme_should_propagate_errors(); } bool HTMLInputElement::has_input_activation_behavior() const diff --git a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h index b9d184b3252..9ee995db3f4 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h @@ -210,7 +210,7 @@ private: void create_text_input_shadow_tree(); void create_color_input_shadow_tree(); void create_range_input_shadow_tree(); - WebIDL::ExceptionOr run_input_activation_behavior(); + WebIDL::ExceptionOr run_input_activation_behavior(DOM::Event const&); void set_checked_within_group(); void handle_readonly_attribute(Optional const& value);