Browse Source

LibWeb: Update HTMLFormElement to use navigables

Aliaksandr Kalenik 2 years ago
parent
commit
857537f90c

+ 35 - 62
Userland/Libraries/LibWeb/HTML/HTMLFormElement.cpp

@@ -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.

+ 6 - 6
Userland/Libraries/LibWeb/HTML/HTMLFormElement.h

@@ -96,12 +96,12 @@ private:
 
     ErrorOr<String> pick_an_encoding() const;
 
-    ErrorOr<void> mutate_action_url(AK::URL parsed_action, Vector<XHR::FormDataEntry> entry_list, String encoding, JS::NonnullGCPtr<AbstractBrowsingContext> target_navigable, HistoryHandlingBehavior history_handling);
-    ErrorOr<void> submit_as_entity_body(AK::URL parsed_action, Vector<XHR::FormDataEntry> entry_list, EncodingTypeAttributeState encoding_type, String encoding, JS::NonnullGCPtr<AbstractBrowsingContext> target_navigable, HistoryHandlingBehavior history_handling);
-    void get_action_url(AK::URL parsed_action, JS::NonnullGCPtr<AbstractBrowsingContext> target_navigable, HistoryHandlingBehavior history_handling);
-    ErrorOr<void> mail_with_headers(AK::URL parsed_action, Vector<XHR::FormDataEntry> entry_list, String encoding, JS::NonnullGCPtr<AbstractBrowsingContext> target_navigable, HistoryHandlingBehavior history_handling);
-    ErrorOr<void> mail_as_body(AK::URL parsed_action, Vector<XHR::FormDataEntry> entry_list, EncodingTypeAttributeState encoding_type, String encoding, JS::NonnullGCPtr<AbstractBrowsingContext> target_navigable, HistoryHandlingBehavior history_handling);
-    void plan_to_navigate_to(Variant<AK::URL, JS::NonnullGCPtr<Fetch::Infrastructure::Request>> resource, JS::NonnullGCPtr<AbstractBrowsingContext> target_navigable, HistoryHandlingBehavior history_handling);
+    ErrorOr<void> mutate_action_url(AK::URL parsed_action, Vector<XHR::FormDataEntry> entry_list, String encoding, JS::NonnullGCPtr<Navigable> target_navigable, HistoryHandlingBehavior history_handling);
+    ErrorOr<void> submit_as_entity_body(AK::URL parsed_action, Vector<XHR::FormDataEntry> entry_list, EncodingTypeAttributeState encoding_type, String encoding, JS::NonnullGCPtr<Navigable> target_navigable, HistoryHandlingBehavior history_handling);
+    void get_action_url(AK::URL parsed_action, JS::NonnullGCPtr<Navigable> target_navigable, HistoryHandlingBehavior history_handling);
+    ErrorOr<void> mail_with_headers(AK::URL parsed_action, Vector<XHR::FormDataEntry> entry_list, String encoding, JS::NonnullGCPtr<Navigable> target_navigable, HistoryHandlingBehavior history_handling);
+    ErrorOr<void> mail_as_body(AK::URL parsed_action, Vector<XHR::FormDataEntry> entry_list, EncodingTypeAttributeState encoding_type, String encoding, JS::NonnullGCPtr<Navigable> target_navigable, HistoryHandlingBehavior history_handling);
+    void plan_to_navigate_to(AK::URL url, Variant<Empty, String, POSTResource> post_resource, JS::NonnullGCPtr<Navigable> target_navigable, HistoryHandlingBehavior history_handling);
 
     bool m_firing_submission_events { false };