Line data Source code
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/. */
6 :
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 "nsContentUtils.h"
14 : #include "nsIDOMDocument.h"
15 : #include "nsIDOMSerializer.h"
16 : #include "nsIInputStream.h"
17 : #include "nsIOutputStream.h"
18 : #include "nsIStorageStream.h"
19 : #include "nsStringStream.h"
20 :
21 : namespace mozilla {
22 : namespace dom {
23 :
24 : static nsresult
25 0 : GetBufferDataAsStream(const uint8_t* aData, uint32_t aDataLength,
26 : nsIInputStream** aResult, uint64_t* aContentLength,
27 : nsACString& aContentType, nsACString& aCharset)
28 : {
29 0 : aContentType.SetIsVoid(true);
30 0 : aCharset.Truncate();
31 :
32 0 : *aContentLength = aDataLength;
33 0 : const char* data = reinterpret_cast<const char*>(aData);
34 :
35 0 : nsCOMPtr<nsIInputStream> stream;
36 0 : nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream), data, aDataLength,
37 0 : NS_ASSIGNMENT_COPY);
38 0 : NS_ENSURE_SUCCESS(rv, rv);
39 :
40 0 : stream.forget(aResult);
41 :
42 0 : return NS_OK;
43 : }
44 :
45 : template<> nsresult
46 0 : BodyExtractor<const ArrayBuffer>::GetAsStream(nsIInputStream** aResult,
47 : uint64_t* aContentLength,
48 : nsACString& aContentTypeWithCharset,
49 : nsACString& aCharset) const
50 : {
51 0 : mBody->ComputeLengthAndData();
52 0 : return GetBufferDataAsStream(mBody->Data(), mBody->Length(),
53 : aResult, aContentLength, aContentTypeWithCharset,
54 0 : aCharset);
55 : }
56 :
57 : template<> nsresult
58 0 : BodyExtractor<const ArrayBufferView>::GetAsStream(nsIInputStream** aResult,
59 : uint64_t* aContentLength,
60 : nsACString& aContentTypeWithCharset,
61 : nsACString& aCharset) const
62 : {
63 0 : mBody->ComputeLengthAndData();
64 0 : return GetBufferDataAsStream(mBody->Data(), mBody->Length(),
65 : aResult, aContentLength, aContentTypeWithCharset,
66 0 : aCharset);
67 : }
68 :
69 : template<> nsresult
70 0 : BodyExtractor<nsIDocument>::GetAsStream(nsIInputStream** aResult,
71 : uint64_t* aContentLength,
72 : nsACString& aContentTypeWithCharset,
73 : nsACString& aCharset) const
74 : {
75 0 : nsCOMPtr<nsIDOMDocument> domdoc(do_QueryInterface(mBody));
76 0 : NS_ENSURE_STATE(domdoc);
77 0 : aCharset.AssignLiteral("UTF-8");
78 :
79 : nsresult rv;
80 0 : nsCOMPtr<nsIStorageStream> storStream;
81 0 : rv = NS_NewStorageStream(4096, UINT32_MAX, getter_AddRefs(storStream));
82 0 : NS_ENSURE_SUCCESS(rv, rv);
83 :
84 0 : nsCOMPtr<nsIOutputStream> output;
85 0 : rv = storStream->GetOutputStream(0, getter_AddRefs(output));
86 0 : NS_ENSURE_SUCCESS(rv, rv);
87 :
88 0 : if (mBody->IsHTMLDocument()) {
89 0 : aContentTypeWithCharset.AssignLiteral("text/html;charset=UTF-8");
90 :
91 0 : nsString serialized;
92 0 : if (!nsContentUtils::SerializeNodeToMarkup(mBody, true, serialized)) {
93 0 : return NS_ERROR_OUT_OF_MEMORY;
94 : }
95 :
96 0 : nsAutoCString utf8Serialized;
97 0 : if (!AppendUTF16toUTF8(serialized, utf8Serialized, fallible)) {
98 0 : return NS_ERROR_OUT_OF_MEMORY;
99 : }
100 :
101 : uint32_t written;
102 0 : rv = output->Write(utf8Serialized.get(), utf8Serialized.Length(), &written);
103 0 : NS_ENSURE_SUCCESS(rv, rv);
104 :
105 0 : MOZ_ASSERT(written == utf8Serialized.Length());
106 : } else {
107 0 : aContentTypeWithCharset.AssignLiteral("application/xml;charset=UTF-8");
108 :
109 : nsCOMPtr<nsIDOMSerializer> serializer =
110 0 : do_CreateInstance(NS_XMLSERIALIZER_CONTRACTID, &rv);
111 0 : NS_ENSURE_SUCCESS(rv, rv);
112 :
113 : // Make sure to use the encoding we'll send
114 0 : rv = serializer->SerializeToStream(domdoc, output, aCharset);
115 0 : NS_ENSURE_SUCCESS(rv, rv);
116 : }
117 :
118 0 : output->Close();
119 :
120 : uint32_t length;
121 0 : rv = storStream->GetLength(&length);
122 0 : NS_ENSURE_SUCCESS(rv, rv);
123 0 : *aContentLength = length;
124 :
125 0 : rv = storStream->NewInputStream(0, aResult);
126 0 : NS_ENSURE_SUCCESS(rv, rv);
127 0 : return NS_OK;
128 : }
129 :
130 : template<> nsresult
131 0 : BodyExtractor<const nsAString>::GetAsStream(nsIInputStream** aResult,
132 : uint64_t* aContentLength,
133 : nsACString& aContentTypeWithCharset,
134 : nsACString& aCharset) const
135 : {
136 0 : nsCString encoded;
137 0 : CopyUTF16toUTF8(*mBody, encoded);
138 :
139 0 : nsresult rv = NS_NewCStringInputStream(aResult, encoded);
140 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
141 0 : return rv;
142 : }
143 :
144 0 : *aContentLength = encoded.Length();
145 0 : aContentTypeWithCharset.AssignLiteral("text/plain;charset=UTF-8");
146 0 : aCharset.AssignLiteral("UTF-8");
147 0 : return NS_OK;
148 : }
149 :
150 : template<> nsresult
151 0 : BodyExtractor<nsIInputStream>::GetAsStream(nsIInputStream** aResult,
152 : uint64_t* aContentLength,
153 : nsACString& aContentTypeWithCharset,
154 : nsACString& aCharset) const
155 : {
156 0 : aContentTypeWithCharset.AssignLiteral("text/plain");
157 0 : aCharset.Truncate();
158 :
159 0 : nsresult rv = mBody->Available(aContentLength);
160 0 : NS_ENSURE_SUCCESS(rv, rv);
161 :
162 0 : nsCOMPtr<nsIInputStream> stream(mBody);
163 0 : stream.forget(aResult);
164 0 : return NS_OK;
165 : }
166 :
167 : template<> nsresult
168 0 : BodyExtractor<nsIXHRSendable>::GetAsStream(nsIInputStream** aResult,
169 : uint64_t* aContentLength,
170 : nsACString& aContentTypeWithCharset,
171 : nsACString& aCharset) const
172 : {
173 0 : return mBody->GetSendInfo(aResult, aContentLength, aContentTypeWithCharset,
174 0 : aCharset);
175 : }
176 :
177 : } // dom namespace
178 : } // mozilla namespace
|