diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator/IDLGenerators.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator/IDLGenerators.cpp index d8b6967579..994f9a0622 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator/IDLGenerators.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator/IDLGenerators.cpp @@ -52,6 +52,8 @@ static bool is_wrappable_type(Type const& type) return true; if (type.name == "WebGLRenderingContext") return true; + if (type.name == "URLSearchParams") + return true; return false; } diff --git a/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp b/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp index 06a69c5666..62dbc8d64b 100644 --- a/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp +++ b/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp @@ -3,6 +3,7 @@ * Copyright (c) 2021, Linus Groh * Copyright (c) 2022, Luke Wilde * Copyright (c) 2022, Ali Mohammad Pur + * Copyright (c) 2022, Kenneth Myhra * * SPDX-License-Identifier: BSD-2-Clause */ @@ -426,6 +427,21 @@ static bool is_header_value(String const& header_value) return true; } +static XMLHttpRequest::BodyWithType safely_extract_body(XMLHttpRequestBodyInit& body) +{ + if (body.has>()) { + return { + body.get>()->to_string().to_byte_buffer(), + "application/x-www-form-urlencoded;charset=UTF-8" + }; + } + VERIFY(body.has()); + return { + body.get().to_byte_buffer(), + "text/plain;charset=UTF-8" + }; +} + // https://xhr.spec.whatwg.org/#dom-xmlhttprequest-setrequestheader DOM::ExceptionOr XMLHttpRequest::set_request_header(String const& name, String const& value) { @@ -547,7 +563,7 @@ DOM::ExceptionOr XMLHttpRequest::open(String const& method, String const& } // https://xhr.spec.whatwg.org/#dom-xmlhttprequest-send -DOM::ExceptionOr XMLHttpRequest::send(String body) +DOM::ExceptionOr XMLHttpRequest::send(Optional body) { if (m_ready_state != ReadyState::Opened) return DOM::InvalidStateError::create("XHR readyState is not OPENED"); @@ -559,6 +575,8 @@ DOM::ExceptionOr XMLHttpRequest::send(String body) if (m_method.is_one_of("GET"sv, "HEAD"sv)) body = {}; + auto body_with_type = body.has_value() ? safely_extract_body(body.value()) : XMLHttpRequest::BodyWithType {}; + AK::URL request_url = m_window->associated_document().parse_url(m_url.to_string()); dbgln("XHR send from {} to {}", m_window->associated_document().url(), request_url); @@ -578,8 +596,11 @@ DOM::ExceptionOr XMLHttpRequest::send(String body) auto request = LoadRequest::create_for_url_on_page(request_url, m_window->page()); request.set_method(m_method); - if (!body.is_null()) - request.set_body(body.to_byte_buffer()); + if (!body_with_type.body.is_empty()) { + request.set_body(body_with_type.body); + if (!body_with_type.type.is_empty()) + request.set_header("Content-Type", body_with_type.type); + } for (auto& it : m_request_headers) request.set_header(it.key, it.value); diff --git a/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.h b/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.h index 678e83ce8a..78197897c1 100644 --- a/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.h +++ b/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2020-2021, Andreas Kling + * Copyright (c) 2022, Kenneth Myhra * * SPDX-License-Identifier: BSD-2-Clause */ @@ -15,12 +16,15 @@ #include #include #include +#include #include namespace Web::XHR { static constexpr Array http_whitespace_bytes = { '\t', '\n', '\r', ' ' }; +using XMLHttpRequestBodyInit = Variant, String>; + class XMLHttpRequest final : public RefCounted , public Weakable @@ -34,6 +38,11 @@ public: Done = 4, }; + struct BodyWithType { + ByteBuffer body; + String type; + }; + using WrapperType = Bindings::XMLHttpRequestWrapper; static NonnullRefPtr create(HTML::Window& window) @@ -58,7 +67,7 @@ public: DOM::ExceptionOr open(String const& method, String const& url); DOM::ExceptionOr open(String const& method, String const& url, bool async, String const& username = {}, String const& password = {}); - DOM::ExceptionOr send(String body); + DOM::ExceptionOr send(Optional body); DOM::ExceptionOr set_request_header(String const& header, String const& value); void set_response_type(Bindings::XMLHttpRequestResponseType type) { m_response_type = type; } diff --git a/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.idl b/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.idl index 56d1c9d1f7..c712fd9aa2 100644 --- a/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.idl +++ b/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.idl @@ -1,5 +1,8 @@ #import #import +#import + +typedef (URLSearchParams or USVString) XMLHttpRequestBodyInit; enum XMLHttpRequestResponseType { "", @@ -30,7 +33,7 @@ interface XMLHttpRequest : XMLHttpRequestEventTarget { undefined open(DOMString method, DOMString url); undefined open(ByteString method, USVString url, boolean async, optional USVString? username = {}, optional USVString? password = {}); undefined setRequestHeader(DOMString name, DOMString value); - undefined send(optional USVString body = {}); + undefined send(optional XMLHttpRequestBodyInit? body = null); ByteString? getResponseHeader(ByteString name); ByteString getAllResponseHeaders();