Bug 1686668 [wpt PR 27185] - Update wpt metadata, a=testonly
[gecko.git] / dom / fetch / BodyExtractor.cpp
blobc4a6e3a3990aabe47d75253f85db8e5290a45fd8
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "BodyExtractor.h"
8 #include "mozilla/dom/File.h"
9 #include "mozilla/dom/FormData.h"
10 #include "mozilla/dom/TypedArray.h"
11 #include "mozilla/dom/URLSearchParams.h"
12 #include "mozilla/dom/XMLHttpRequest.h"
13 #include "mozilla/UniquePtr.h"
14 #include "nsContentUtils.h"
15 #include "nsDOMSerializer.h"
16 #include "nsIGlobalObject.h"
17 #include "nsIInputStream.h"
18 #include "nsIOutputStream.h"
19 #include "nsIStorageStream.h"
20 #include "nsStringStream.h"
22 namespace mozilla::dom {
24 static nsresult GetBufferDataAsStream(
25 const uint8_t* aData, uint32_t aDataLength, nsIInputStream** aResult,
26 uint64_t* aContentLength, nsACString& aContentType, nsACString& aCharset) {
27 aContentType.SetIsVoid(true);
28 aCharset.Truncate();
30 *aContentLength = aDataLength;
31 const char* data = reinterpret_cast<const char*>(aData);
33 nsCOMPtr<nsIInputStream> stream;
34 nsresult rv = NS_NewByteInputStream(
35 getter_AddRefs(stream), Span(data, aDataLength), NS_ASSIGNMENT_COPY);
36 NS_ENSURE_SUCCESS(rv, rv);
38 stream.forget(aResult);
40 return NS_OK;
43 template <>
44 nsresult BodyExtractor<const ArrayBuffer>::GetAsStream(
45 nsIInputStream** aResult, uint64_t* aContentLength,
46 nsACString& aContentTypeWithCharset, nsACString& aCharset) const {
47 mBody->ComputeState();
48 return GetBufferDataAsStream(mBody->Data(), mBody->Length(), aResult,
49 aContentLength, aContentTypeWithCharset,
50 aCharset);
53 template <>
54 nsresult BodyExtractor<const ArrayBufferView>::GetAsStream(
55 nsIInputStream** aResult, uint64_t* aContentLength,
56 nsACString& aContentTypeWithCharset, nsACString& aCharset) const {
57 mBody->ComputeState();
58 return GetBufferDataAsStream(mBody->Data(), mBody->Length(), aResult,
59 aContentLength, aContentTypeWithCharset,
60 aCharset);
63 template <>
64 nsresult BodyExtractor<Document>::GetAsStream(
65 nsIInputStream** aResult, uint64_t* aContentLength,
66 nsACString& aContentTypeWithCharset, nsACString& aCharset) const {
67 NS_ENSURE_STATE(mBody);
68 aCharset.AssignLiteral("UTF-8");
70 nsresult rv;
71 nsCOMPtr<nsIStorageStream> storStream;
72 rv = NS_NewStorageStream(4096, UINT32_MAX, getter_AddRefs(storStream));
73 NS_ENSURE_SUCCESS(rv, rv);
75 nsCOMPtr<nsIOutputStream> output;
76 rv = storStream->GetOutputStream(0, getter_AddRefs(output));
77 NS_ENSURE_SUCCESS(rv, rv);
79 if (mBody->IsHTMLDocument()) {
80 aContentTypeWithCharset.AssignLiteral("text/html;charset=UTF-8");
82 nsString serialized;
83 if (!nsContentUtils::SerializeNodeToMarkup(mBody, true, serialized)) {
84 return NS_ERROR_OUT_OF_MEMORY;
87 nsAutoCString utf8Serialized;
88 if (!AppendUTF16toUTF8(serialized, utf8Serialized, fallible)) {
89 return NS_ERROR_OUT_OF_MEMORY;
92 uint32_t written;
93 rv = output->Write(utf8Serialized.get(), utf8Serialized.Length(), &written);
94 NS_ENSURE_SUCCESS(rv, rv);
96 MOZ_ASSERT(written == utf8Serialized.Length());
97 } else {
98 aContentTypeWithCharset.AssignLiteral("application/xml;charset=UTF-8");
100 auto serializer = MakeUnique<nsDOMSerializer>();
102 // Make sure to use the encoding we'll send
103 ErrorResult res;
104 serializer->SerializeToStream(*mBody, output, u"UTF-8"_ns, res);
105 if (NS_WARN_IF(res.Failed())) {
106 return res.StealNSResult();
110 output->Close();
112 uint32_t length;
113 rv = storStream->GetLength(&length);
114 NS_ENSURE_SUCCESS(rv, rv);
115 *aContentLength = length;
117 rv = storStream->NewInputStream(0, aResult);
118 NS_ENSURE_SUCCESS(rv, rv);
119 return NS_OK;
122 template <>
123 nsresult BodyExtractor<const nsAString>::GetAsStream(
124 nsIInputStream** aResult, uint64_t* aContentLength,
125 nsACString& aContentTypeWithCharset, nsACString& aCharset) const {
126 nsCString encoded;
127 if (!CopyUTF16toUTF8(*mBody, encoded, fallible)) {
128 return NS_ERROR_OUT_OF_MEMORY;
131 uint32_t encodedLength = encoded.Length();
132 nsresult rv = NS_NewCStringInputStream(aResult, std::move(encoded));
133 if (NS_WARN_IF(NS_FAILED(rv))) {
134 return rv;
137 *aContentLength = encodedLength;
138 aContentTypeWithCharset.AssignLiteral("text/plain;charset=UTF-8");
139 aCharset.AssignLiteral("UTF-8");
140 return NS_OK;
143 template <>
144 nsresult BodyExtractor<nsIInputStream>::GetAsStream(
145 nsIInputStream** aResult, uint64_t* aContentLength,
146 nsACString& aContentTypeWithCharset, nsACString& aCharset) const {
147 aContentTypeWithCharset.AssignLiteral("text/plain");
148 aCharset.Truncate();
150 nsresult rv = mBody->Available(aContentLength);
151 NS_ENSURE_SUCCESS(rv, rv);
153 nsCOMPtr<nsIInputStream> stream(mBody);
154 stream.forget(aResult);
155 return NS_OK;
158 template <>
159 nsresult BodyExtractor<const Blob>::GetAsStream(
160 nsIInputStream** aResult, uint64_t* aContentLength,
161 nsACString& aContentTypeWithCharset, nsACString& aCharset) const {
162 return mBody->GetSendInfo(aResult, aContentLength, aContentTypeWithCharset,
163 aCharset);
166 template <>
167 nsresult BodyExtractor<const FormData>::GetAsStream(
168 nsIInputStream** aResult, uint64_t* aContentLength,
169 nsACString& aContentTypeWithCharset, nsACString& aCharset) const {
170 return mBody->GetSendInfo(aResult, aContentLength, aContentTypeWithCharset,
171 aCharset);
174 template <>
175 nsresult BodyExtractor<const URLSearchParams>::GetAsStream(
176 nsIInputStream** aResult, uint64_t* aContentLength,
177 nsACString& aContentTypeWithCharset, nsACString& aCharset) const {
178 return mBody->GetSendInfo(aResult, aContentLength, aContentTypeWithCharset,
179 aCharset);
182 } // namespace mozilla::dom