LibWeb: Update HTMLFormElement to use navigables

This commit is contained in:
Aliaksandr Kalenik 2023-06-23 00:32:10 +03:00 committed by Andreas Kling
parent 4a6ac18cd4
commit 857537f90c
Notes: sideshowbarker 2024-07-17 14:33:07 +09:00
2 changed files with 41 additions and 68 deletions

View file

@ -69,10 +69,6 @@ WebIDL::ExceptionOr<void> HTMLFormElement::submit_form(JS::NonnullGCPtr<HTMLElem
// 3. Let form document be form's node document.
JS::NonnullGCPtr<DOM::Document> form_document = this->document();
// FIXME: This is not in the navigable version.
// Let form browsing context be the browsing context of form document.
auto* form_browsing_context = form_document->browsing_context();
// 4. If form document's active sandboxing flag set has its sandboxed forms browsing context flag set, then return.
if (has_flag(form_document->active_sandboxing_flag_set(), HTML::SandboxingFlagSet::SandboxedForms))
return {};
@ -192,9 +188,8 @@ WebIDL::ExceptionOr<void> HTMLFormElement::submit_form(JS::NonnullGCPtr<HTMLElem
// 19. Let noopener be the result of getting an element's noopener with form and target.
auto no_opener = get_an_elements_noopener(target);
// FIXME: Update these steps for navigables.
// 20. Let targetNavigable be the first return value of applying the rules for choosing a navigable given target, form's node navigable, and noopener.
auto target_navigable = form_browsing_context->choose_a_browsing_context(target, no_opener).browsing_context;
auto target_navigable = form_document->navigable()->choose_a_navigable(target, no_opener).navigable;
// 21. If targetNavigable is null, then return.
if (!target_navigable) {
@ -608,7 +603,7 @@ static ErrorOr<String> plain_text_encode(Vector<URL::QueryParam> const& pairs)
}
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#submit-mutate-action
ErrorOr<void> HTMLFormElement::mutate_action_url(AK::URL parsed_action, Vector<XHR::FormDataEntry> entry_list, String encoding, JS::NonnullGCPtr<AbstractBrowsingContext> target_navigable, HistoryHandlingBehavior history_handling)
ErrorOr<void> HTMLFormElement::mutate_action_url(AK::URL parsed_action, Vector<XHR::FormDataEntry> entry_list, String encoding, JS::NonnullGCPtr<Navigable> target_navigable, HistoryHandlingBehavior history_handling)
{
// 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));
@ -620,16 +615,16 @@ ErrorOr<void> HTMLFormElement::mutate_action_url(AK::URL parsed_action, Vector<X
parsed_action.set_query(query);
// 4. Plan to navigate to parsed action.
plan_to_navigate_to(move(parsed_action), target_navigable, history_handling);
plan_to_navigate_to(move(parsed_action), Empty {}, target_navigable, history_handling);
return {};
}
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#submit-body
ErrorOr<void> HTMLFormElement::submit_as_entity_body(AK::URL parsed_action, Vector<XHR::FormDataEntry> entry_list, EncodingTypeAttributeState encoding_type, [[maybe_unused]] String encoding, JS::NonnullGCPtr<AbstractBrowsingContext> target_navigable, HistoryHandlingBehavior history_handling)
ErrorOr<void> HTMLFormElement::submit_as_entity_body(AK::URL parsed_action, Vector<XHR::FormDataEntry> entry_list, EncodingTypeAttributeState encoding_type, [[maybe_unused]] String encoding, JS::NonnullGCPtr<Navigable> target_navigable, HistoryHandlingBehavior history_handling)
{
// 1. Assert: method is POST.
ByteBuffer mime_type;
POSTResource::RequestContentType mime_type {};
ByteBuffer body;
// 2. Switch on enctype:
@ -646,7 +641,7 @@ ErrorOr<void> HTMLFormElement::submit_as_entity_body(AK::URL parsed_action, Vect
// NOTE: `encoding` refers to `UTF-8 encode`, which body already is encoded as because it uses AK::String.
// 4. Let mimeType be `application/x-www-form-urlencoded`.
mime_type = TRY(ByteBuffer::copy("application/x-www-form-urlencoded"sv.bytes()));
mime_type = POSTResource::RequestContentType::ApplicationXWWWFormUrlencoded;
break;
}
case EncodingTypeAttributeState::FormData: {
@ -657,7 +652,7 @@ ErrorOr<void> HTMLFormElement::submit_as_entity_body(AK::URL parsed_action, Vect
// 2. Let mimeType be the isomorphic encoding of the concatenation of "multipart/form-data; boundary=" and the multipart/form-data
// boundary string generated by the multipart/form-data encoding algorithm.
mime_type = TRY(ByteBuffer::copy(TRY(String::formatted("multipart/form-data; boundary={}", body_and_mime_type.boundary)).bytes()));
mime_type = POSTResource::RequestContentType::MultipartFormData;
return {};
}
case EncodingTypeAttributeState::PlainText: {
@ -671,40 +666,28 @@ ErrorOr<void> HTMLFormElement::submit_as_entity_body(AK::URL parsed_action, Vect
// FIXME: 3. Set body to the result of encoding body using encoding.
// 4. Let mimeType be `text/plain`.
mime_type = TRY(ByteBuffer::copy("text/plain"sv.bytes()));
mime_type = POSTResource::RequestContentType::TextPlain;
break;
}
default:
VERIFY_NOT_REACHED();
}
// FIXME: Update this to the navigable version.
// 3. Plan to navigate to a new request whose url is parsed action, method is method, header list consists of `Content-Type`/MIME type,
// and body is body.
auto request = Fetch::Infrastructure::Request::create(vm());
request->set_url(move(parsed_action));
request->set_method(TRY(ByteBuffer::copy("POST"sv.bytes())));
request->set_body(move(body));
auto temp_header = Fetch::Infrastructure::Header {
.name = TRY(ByteBuffer::copy("Content-Type"sv.bytes())),
.value = move(mime_type),
};
TRY(request->header_list()->append(move(temp_header)));
plan_to_navigate_to(request, target_navigable, history_handling);
// 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);
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<AbstractBrowsingContext> target_navigable, Web::HTML::HistoryHandlingBehavior history_handling)
void HTMLFormElement::get_action_url(AK::URL parsed_action, JS::NonnullGCPtr<Navigable> target_navigable, Web::HTML::HistoryHandlingBehavior history_handling)
{
// 1. Plan to navigate to parsed action.
// Spec Note: entry list is discarded.
plan_to_navigate_to(move(parsed_action), target_navigable, history_handling);
plan_to_navigate_to(move(parsed_action), Empty {}, target_navigable, history_handling);
}
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#submit-mailto-headers
ErrorOr<void> HTMLFormElement::mail_with_headers(AK::URL parsed_action, Vector<XHR::FormDataEntry> entry_list, [[maybe_unused]] String encoding, JS::NonnullGCPtr<AbstractBrowsingContext> target_navigable, HistoryHandlingBehavior history_handling)
ErrorOr<void> HTMLFormElement::mail_with_headers(AK::URL parsed_action, Vector<XHR::FormDataEntry> entry_list, [[maybe_unused]] String encoding, JS::NonnullGCPtr<Navigable> target_navigable, HistoryHandlingBehavior history_handling)
{
// 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));
@ -719,11 +702,11 @@ ErrorOr<void> HTMLFormElement::mail_with_headers(AK::URL parsed_action, Vector<X
parsed_action.set_query(headers);
// 5. Plan to navigate to parsed action.
plan_to_navigate_to(move(parsed_action), target_navigable, history_handling);
plan_to_navigate_to(move(parsed_action), Empty {}, target_navigable, history_handling);
return {};
}
ErrorOr<void> HTMLFormElement::mail_as_body(AK::URL parsed_action, Vector<XHR::FormDataEntry> entry_list, EncodingTypeAttributeState encoding_type, [[maybe_unused]] String encoding, JS::NonnullGCPtr<AbstractBrowsingContext> target_navigable, HistoryHandlingBehavior history_handling)
ErrorOr<void> HTMLFormElement::mail_as_body(AK::URL parsed_action, Vector<XHR::FormDataEntry> entry_list, EncodingTypeAttributeState encoding_type, [[maybe_unused]] String encoding, JS::NonnullGCPtr<Navigable> target_navigable, HistoryHandlingBehavior history_handling)
{
// 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));
@ -772,17 +755,28 @@ ErrorOr<void> HTMLFormElement::mail_as_body(AK::URL parsed_action, Vector<XHR::F
parsed_action.set_query(MUST(query_builder.to_string()));
// 7. Plan to navigate to parsed action.
plan_to_navigate_to(move(parsed_action), target_navigable, history_handling);
plan_to_navigate_to(move(parsed_action), Empty {}, target_navigable, history_handling);
return {};
}
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#plan-to-navigate
void HTMLFormElement::plan_to_navigate_to(Variant<AK::URL, JS::NonnullGCPtr<Fetch::Infrastructure::Request>> resource, JS::NonnullGCPtr<AbstractBrowsingContext> target_navigable, HistoryHandlingBehavior history_handling)
// FIXME:
static Bindings::NavigationHistoryBehavior to_navigation_history_behavior(HistoryHandlingBehavior b)
{
// FIXME: Update this to the navigable version.
switch (b) {
case HistoryHandlingBehavior::Push:
return Bindings::NavigationHistoryBehavior::Push;
case HistoryHandlingBehavior::Replace:
return Bindings::NavigationHistoryBehavior::Replace;
default:
return Bindings::NavigationHistoryBehavior::Auto;
}
}
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#plan-to-navigate
void HTMLFormElement::plan_to_navigate_to(AK::URL url, Variant<Empty, String, POSTResource> post_resource, JS::NonnullGCPtr<Navigable> target_navigable, HistoryHandlingBehavior history_handling)
{
// 1. Let referrerPolicy be the empty string.
Optional<ReferrerPolicy::ReferrerPolicy> referrer_policy;
ReferrerPolicy::ReferrerPolicy referrer_policy = ReferrerPolicy::ReferrerPolicy::EmptyString;
// 2. If the form element's link types include the noreferrer keyword, then set referrerPolicy to "no-referrer".
auto rel = deprecated_attribute(HTML::AttributeNames::rel).to_lowercase();
@ -797,36 +791,15 @@ void HTMLFormElement::plan_to_navigate_to(Variant<AK::URL, JS::NonnullGCPtr<Fetc
});
}
auto actual_resource = resource.visit(
[this](AK::URL url) {
// NOTE: BrowsingContext::navigate is supposed to do this for us, however it currently doesn't.
// This will eventually be replaced with URL + POST-resource when updated to the navigable version however,
// so it's not worth changing BrowsingContext::navigate.
auto request = Fetch::Infrastructure::Request::create(vm());
request->set_url(url);
return request;
},
[](JS::NonnullGCPtr<Fetch::Infrastructure::Request> request) {
return request;
});
actual_resource->set_referrer_policy(move(referrer_policy));
// 4. Queue an element task on the DOM manipulation task source given the form element and the following steps:
// NOTE: `this`, `actual_resource` and `target_navigable` are protected by JS::SafeFunction.
queue_an_element_task(Task::Source::DOMManipulation, [this, actual_resource, target_navigable, history_handling]() {
queue_an_element_task(Task::Source::DOMManipulation, [this, url, post_resource, target_navigable, history_handling, referrer_policy]() {
// 1. Set the form's planned navigation to null.
m_planned_navigation = nullptr;
// FIXME: 2. Navigate targetNavigable to url using the form element's node document, with historyHandling set to historyHandling,
// referrerPolicy set to referrerPolicy, documentResource set to postResource, and cspNavigationType set to "form-submission".
// Browsing Context version:
// Navigate target browsing context to destination. If replace is true, then target browsing context must be navigated with
// replacement enabled.
// NOTE: This uses the current node document's browsing context, as the submission events or any code run after planning the navigation
// could have adopted the node to a different document.
VERIFY(document().browsing_context());
MUST(target_navigable->navigate(actual_resource, *document().browsing_context(), false, history_handling));
// 2. Navigate targetNavigable to url using the form element's node document, with historyHandling set to historyHandling,
// referrerPolicy set to referrerPolicy, documentResource set to postResource, and cspNavigationType set to "form-submission".
MUST(target_navigable->navigate(url, this->document(), post_resource, nullptr, false, to_navigation_history_behavior(history_handling), {}, {}, referrer_policy));
});
// 5. Set the form's planned navigation to the just-queued task.