Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/fetch/BodyExtractor.cpp
Line
Count
Source (jump to first uncovered line)
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 "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"
21
22
namespace mozilla {
23
namespace dom {
24
25
static nsresult
26
GetBufferDataAsStream(const uint8_t* aData, uint32_t aDataLength,
27
                      nsIInputStream** aResult, uint64_t* aContentLength,
28
                      nsACString& aContentType, nsACString& aCharset)
29
0
{
30
0
  aContentType.SetIsVoid(true);
31
0
  aCharset.Truncate();
32
0
33
0
  *aContentLength = aDataLength;
34
0
  const char* data = reinterpret_cast<const char*>(aData);
35
0
36
0
  nsCOMPtr<nsIInputStream> stream;
37
0
  nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream), data, aDataLength,
38
0
                                      NS_ASSIGNMENT_COPY);
39
0
  NS_ENSURE_SUCCESS(rv, rv);
40
0
41
0
  stream.forget(aResult);
42
0
43
0
  return NS_OK;
44
0
}
45
46
template<> nsresult
47
BodyExtractor<const ArrayBuffer>::GetAsStream(nsIInputStream** aResult,
48
                                              uint64_t* aContentLength,
49
                                              nsACString& aContentTypeWithCharset,
50
                                              nsACString& aCharset) const
51
0
{
52
0
  mBody->ComputeLengthAndData();
53
0
  return GetBufferDataAsStream(mBody->Data(), mBody->Length(),
54
0
                               aResult, aContentLength, aContentTypeWithCharset,
55
0
                               aCharset);
56
0
}
57
58
template<> nsresult
59
BodyExtractor<const ArrayBufferView>::GetAsStream(nsIInputStream** aResult,
60
                                                  uint64_t* aContentLength,
61
                                                  nsACString& aContentTypeWithCharset,
62
                                                  nsACString& aCharset) const
63
0
{
64
0
  mBody->ComputeLengthAndData();
65
0
  return GetBufferDataAsStream(mBody->Data(), mBody->Length(),
66
0
                               aResult, aContentLength, aContentTypeWithCharset,
67
0
                               aCharset);
68
0
}
69
70
template<> nsresult
71
BodyExtractor<nsIDocument>::GetAsStream(nsIInputStream** aResult,
72
                                        uint64_t* aContentLength,
73
                                        nsACString& aContentTypeWithCharset,
74
                                        nsACString& aCharset) const
75
0
{
76
0
  NS_ENSURE_STATE(mBody);
77
0
  aCharset.AssignLiteral("UTF-8");
78
0
79
0
  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
0
84
0
  nsCOMPtr<nsIOutputStream> output;
85
0
  rv = storStream->GetOutputStream(0, getter_AddRefs(output));
86
0
  NS_ENSURE_SUCCESS(rv, rv);
87
0
88
0
  if (mBody->IsHTMLDocument()) {
89
0
    aContentTypeWithCharset.AssignLiteral("text/html;charset=UTF-8");
90
0
91
0
    nsString serialized;
92
0
    if (!nsContentUtils::SerializeNodeToMarkup(mBody, true, serialized)) {
93
0
      return NS_ERROR_OUT_OF_MEMORY;
94
0
    }
95
0
96
0
    nsAutoCString utf8Serialized;
97
0
    if (!AppendUTF16toUTF8(serialized, utf8Serialized, fallible)) {
98
0
      return NS_ERROR_OUT_OF_MEMORY;
99
0
    }
100
0
101
0
    uint32_t written;
102
0
    rv = output->Write(utf8Serialized.get(), utf8Serialized.Length(), &written);
103
0
    NS_ENSURE_SUCCESS(rv, rv);
104
0
105
0
    MOZ_ASSERT(written == utf8Serialized.Length());
106
0
  } else {
107
0
    aContentTypeWithCharset.AssignLiteral("application/xml;charset=UTF-8");
108
0
109
0
    auto serializer = MakeUnique<nsDOMSerializer>();
110
0
111
0
    // Make sure to use the encoding we'll send
112
0
    ErrorResult res;
113
0
    serializer->SerializeToStream(*mBody, output, NS_LITERAL_STRING("UTF-8"),
114
0
                                  res);
115
0
    if (NS_WARN_IF(res.Failed())) {
116
0
      return res.StealNSResult();
117
0
    }
118
0
  }
119
0
120
0
  output->Close();
121
0
122
0
  uint32_t length;
123
0
  rv = storStream->GetLength(&length);
124
0
  NS_ENSURE_SUCCESS(rv, rv);
125
0
  *aContentLength = length;
126
0
127
0
  rv = storStream->NewInputStream(0, aResult);
128
0
  NS_ENSURE_SUCCESS(rv, rv);
129
0
  return NS_OK;
130
0
}
131
132
template<> nsresult
133
BodyExtractor<const nsAString>::GetAsStream(nsIInputStream** aResult,
134
                                            uint64_t* aContentLength,
135
                                            nsACString& aContentTypeWithCharset,
136
                                            nsACString& aCharset) const
137
0
{
138
0
  nsCString encoded;
139
0
  if (!CopyUTF16toUTF8(*mBody, encoded, fallible)) {
140
0
    return NS_ERROR_OUT_OF_MEMORY;
141
0
  }
142
0
143
0
  uint32_t encodedLength = encoded.Length();
144
0
  nsresult rv = NS_NewCStringInputStream(aResult, std::move(encoded));
145
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
146
0
    return rv;
147
0
  }
148
0
149
0
  *aContentLength = encodedLength;
150
0
  aContentTypeWithCharset.AssignLiteral("text/plain;charset=UTF-8");
151
0
  aCharset.AssignLiteral("UTF-8");
152
0
  return NS_OK;
153
0
}
154
155
template<> nsresult
156
BodyExtractor<nsIInputStream>::GetAsStream(nsIInputStream** aResult,
157
                                           uint64_t* aContentLength,
158
                                           nsACString& aContentTypeWithCharset,
159
                                           nsACString& aCharset) const
160
0
{
161
0
  aContentTypeWithCharset.AssignLiteral("text/plain");
162
0
  aCharset.Truncate();
163
0
164
0
  nsresult rv = mBody->Available(aContentLength);
165
0
  NS_ENSURE_SUCCESS(rv, rv);
166
0
167
0
  nsCOMPtr<nsIInputStream> stream(mBody);
168
0
  stream.forget(aResult);
169
0
  return NS_OK;
170
0
}
171
172
template<> nsresult
173
BodyExtractor<const Blob>::GetAsStream(nsIInputStream** aResult,
174
                                       uint64_t* aContentLength,
175
                                       nsACString& aContentTypeWithCharset,
176
                                       nsACString& aCharset) const
177
0
{
178
0
  return mBody->GetSendInfo(aResult, aContentLength, aContentTypeWithCharset,
179
0
                            aCharset);
180
0
}
181
182
template<> nsresult
183
BodyExtractor<const FormData>::GetAsStream(nsIInputStream** aResult,
184
                                           uint64_t* aContentLength,
185
                                           nsACString& aContentTypeWithCharset,
186
                                           nsACString& aCharset) const
187
0
{
188
0
  return mBody->GetSendInfo(aResult, aContentLength, aContentTypeWithCharset,
189
0
                            aCharset);
190
0
}
191
192
template<> nsresult
193
BodyExtractor<const URLSearchParams>::GetAsStream(nsIInputStream** aResult,
194
                                                  uint64_t* aContentLength,
195
                                                  nsACString& aContentTypeWithCharset,
196
                                                  nsACString& aCharset) const
197
0
{
198
0
  return mBody->GetSendInfo(aResult, aContentLength, aContentTypeWithCharset,
199
0
                            aCharset);
200
0
}
201
202
} // dom namespace
203
} // mozilla namespace