Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/file/Blob.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 "Blob.h"
8
#include "File.h"
9
#include "MemoryBlobImpl.h"
10
#include "mozilla/dom/BlobBinding.h"
11
#include "MultipartBlobImpl.h"
12
#include "nsIInputStream.h"
13
#include "nsPIDOMWindow.h"
14
#include "StreamBlobImpl.h"
15
#include "StringBlobImpl.h"
16
17
namespace mozilla {
18
namespace dom {
19
20
NS_IMPL_CYCLE_COLLECTION_CLASS(Blob)
21
22
0
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Blob)
23
0
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)
24
0
  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
25
0
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
26
27
0
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Blob)
28
0
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)
29
0
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
30
31
0
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Blob)
32
0
  NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
33
0
NS_IMPL_CYCLE_COLLECTION_TRACE_END
34
35
0
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Blob)
36
0
  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
37
0
  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIMutable)
38
0
  NS_INTERFACE_MAP_ENTRY_CONCRETE(Blob)
39
0
  NS_INTERFACE_MAP_ENTRY(nsIMutable)
40
0
  NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
41
0
NS_INTERFACE_MAP_END
42
43
NS_IMPL_CYCLE_COLLECTING_ADDREF(Blob)
44
NS_IMPL_CYCLE_COLLECTING_RELEASE(Blob)
45
46
void
47
Blob::MakeValidBlobType(nsAString& aType)
48
0
{
49
0
  char16_t* iter = aType.BeginWriting();
50
0
  char16_t* end = aType.EndWriting();
51
0
52
0
  for ( ; iter != end; ++iter) {
53
0
    char16_t c = *iter;
54
0
    if (c < 0x20 || c > 0x7E) {
55
0
      // Non-ASCII char, bail out.
56
0
      aType.Truncate();
57
0
      return;
58
0
    }
59
0
60
0
    if (c >= 'A' && c <= 'Z') {
61
0
      *iter = c + ('a' - 'A');
62
0
    }
63
0
  }
64
0
}
65
66
/* static */ Blob*
67
Blob::Create(nsISupports* aParent, BlobImpl* aImpl)
68
0
{
69
0
  MOZ_ASSERT(aImpl);
70
0
71
0
  return aImpl->IsFile() ? new File(aParent, aImpl)
72
0
                         : new Blob(aParent, aImpl);
73
0
}
74
75
/* static */ already_AddRefed<Blob>
76
Blob::CreateStringBlob(nsISupports* aParent, const nsACString& aData,
77
                       const nsAString& aContentType)
78
0
{
79
0
  RefPtr<BlobImpl> blobImpl = StringBlobImpl::Create(aData, aContentType);
80
0
  RefPtr<Blob> blob = Blob::Create(aParent, blobImpl);
81
0
  MOZ_ASSERT(!blob->mImpl->IsFile());
82
0
  return blob.forget();
83
0
}
84
85
/* static */ already_AddRefed<Blob>
86
Blob::CreateMemoryBlob(nsISupports* aParent, void* aMemoryBuffer,
87
                       uint64_t aLength, const nsAString& aContentType)
88
0
{
89
0
  RefPtr<Blob> blob = Blob::Create(aParent,
90
0
    new MemoryBlobImpl(aMemoryBuffer, aLength, aContentType));
91
0
  MOZ_ASSERT(!blob->mImpl->IsFile());
92
0
  return blob.forget();
93
0
}
94
95
Blob::Blob(nsISupports* aParent, BlobImpl* aImpl)
96
  : mImpl(aImpl)
97
  , mParent(aParent)
98
0
{
99
0
  MOZ_ASSERT(mImpl);
100
0
}
101
102
Blob::~Blob()
103
0
{}
104
105
bool
106
Blob::IsFile() const
107
0
{
108
0
  return mImpl->IsFile();
109
0
}
110
111
const nsTArray<RefPtr<BlobImpl>>*
112
Blob::GetSubBlobImpls() const
113
0
{
114
0
  return mImpl->GetSubBlobImpls();
115
0
}
116
117
already_AddRefed<File>
118
Blob::ToFile()
119
0
{
120
0
  if (!mImpl->IsFile()) {
121
0
    return nullptr;
122
0
  }
123
0
124
0
  RefPtr<File> file;
125
0
  if (HasFileInterface()) {
126
0
    file = static_cast<File*>(this);
127
0
  } else {
128
0
    file = new File(mParent, mImpl);
129
0
  }
130
0
131
0
  return file.forget();
132
0
}
133
134
already_AddRefed<File>
135
Blob::ToFile(const nsAString& aName, ErrorResult& aRv) const
136
0
{
137
0
  AutoTArray<RefPtr<BlobImpl>, 1> blobImpls({mImpl});
138
0
139
0
  nsAutoString contentType;
140
0
  mImpl->GetType(contentType);
141
0
142
0
  RefPtr<MultipartBlobImpl> impl =
143
0
    MultipartBlobImpl::Create(std::move(blobImpls), aName, contentType, aRv);
144
0
  if (NS_WARN_IF(aRv.Failed())) {
145
0
    return nullptr;
146
0
  }
147
0
148
0
  RefPtr<File> file = new File(mParent, impl);
149
0
  return file.forget();
150
0
}
151
152
already_AddRefed<Blob>
153
Blob::CreateSlice(uint64_t aStart, uint64_t aLength,
154
                  const nsAString& aContentType,
155
                  ErrorResult& aRv)
156
0
{
157
0
  RefPtr<BlobImpl> impl = mImpl->CreateSlice(aStart, aLength,
158
0
                                             aContentType, aRv);
159
0
  if (aRv.Failed()) {
160
0
    return nullptr;
161
0
  }
162
0
163
0
  RefPtr<Blob> blob = Blob::Create(mParent, impl);
164
0
  return blob.forget();
165
0
}
166
167
uint64_t
168
Blob::GetSize(ErrorResult& aRv)
169
0
{
170
0
  return mImpl->GetSize(aRv);
171
0
}
172
173
void
174
Blob::GetType(nsAString &aType)
175
0
{
176
0
  mImpl->GetType(aType);
177
0
}
178
179
already_AddRefed<Blob>
180
Blob::Slice(const Optional<int64_t>& aStart,
181
            const Optional<int64_t>& aEnd,
182
            const Optional<nsAString>& aContentType,
183
            ErrorResult& aRv)
184
0
{
185
0
  nsAutoString contentType;
186
0
  if (aContentType.WasPassed()) {
187
0
    contentType = aContentType.Value();
188
0
  }
189
0
190
0
  RefPtr<BlobImpl> impl =
191
0
    mImpl->Slice(aStart, aEnd, contentType, aRv);
192
0
  if (aRv.Failed()) {
193
0
    return nullptr;
194
0
  }
195
0
196
0
  RefPtr<Blob> blob = Blob::Create(mParent, impl);
197
0
  return blob.forget();
198
0
}
199
200
size_t
201
Blob::GetAllocationSize() const
202
0
{
203
0
  return mImpl->GetAllocationSize();
204
0
}
205
206
// contentTypeWithCharset can be set to the contentType or
207
// contentType+charset based on what the spec says.
208
// See: https://fetch.spec.whatwg.org/#concept-bodyinit-extract
209
nsresult
210
Blob::GetSendInfo(nsIInputStream** aBody,
211
                  uint64_t* aContentLength,
212
                  nsACString& aContentType,
213
                  nsACString& aCharset) const
214
0
{
215
0
  return mImpl->GetSendInfo(aBody, aContentLength, aContentType, aCharset);
216
0
}
217
218
NS_IMETHODIMP
219
Blob::GetMutable(bool* aMutable)
220
0
{
221
0
  return mImpl->GetMutable(aMutable);
222
0
}
223
224
NS_IMETHODIMP
225
Blob::SetMutable(bool aMutable)
226
0
{
227
0
  return mImpl->SetMutable(aMutable);
228
0
}
229
230
JSObject*
231
Blob::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
232
0
{
233
0
  return Blob_Binding::Wrap(aCx, this, aGivenProto);
234
0
}
235
236
/* static */ already_AddRefed<Blob>
237
Blob::Constructor(const GlobalObject& aGlobal,
238
                  const Optional<Sequence<BlobPart>>& aData,
239
                  const BlobPropertyBag& aBag,
240
                  ErrorResult& aRv)
241
0
{
242
0
  RefPtr<MultipartBlobImpl> impl = new MultipartBlobImpl();
243
0
244
0
  if (aData.WasPassed()) {
245
0
    nsAutoString type(aBag.mType);
246
0
    MakeValidBlobType(type);
247
0
    impl->InitializeBlob(aData.Value(), type,
248
0
                         aBag.mEndings == EndingTypes::Native, aRv);
249
0
  } else {
250
0
    impl->InitializeBlob(aRv);
251
0
  }
252
0
253
0
  if (NS_WARN_IF(aRv.Failed())) {
254
0
    return nullptr;
255
0
  }
256
0
257
0
  MOZ_ASSERT(!impl->IsFile());
258
0
259
0
  RefPtr<Blob> blob = Blob::Create(aGlobal.GetAsSupports(), impl);
260
0
  return blob.forget();
261
0
}
262
263
int64_t
264
Blob::GetFileId()
265
0
{
266
0
  return mImpl->GetFileId();
267
0
}
268
269
bool
270
Blob::IsMemoryFile() const
271
0
{
272
0
  return mImpl->IsMemoryFile();
273
0
}
274
275
void
276
Blob::CreateInputStream(nsIInputStream** aStream, ErrorResult& aRv)
277
0
{
278
0
  mImpl->CreateInputStream(aStream, aRv);
279
0
}
280
281
size_t
282
BindingJSObjectMallocBytes(Blob* aBlob)
283
0
{
284
0
  MOZ_ASSERT(aBlob);
285
0
  return aBlob->GetAllocationSize();
286
0
}
287
288
} // namespace dom
289
} // namespace mozilla