summaryrefslogtreecommitdiffstats
path: root/dom/file/Blob.h
blob: 2314df32b3d3ff072e1c71599912420dcddd97db (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef mozilla_dom_Blob_h
#define mozilla_dom_Blob_h

#include "mozilla/dom/BodyConsumer.h"
#include "nsCycleCollectionParticipant.h"
#include "nsCOMPtr.h"
#include "nsWrapperCache.h"
#include "nsWeakReference.h"

class nsIGlobalObject;
class nsIInputStream;

namespace mozilla {
class ErrorResult;

namespace dom {

struct BlobPropertyBag;
class BlobImpl;
class File;
class GlobalObject;
class OwningArrayBufferViewOrArrayBufferOrBlobOrUTF8String;
class Promise;

class ReadableStream;

#define NS_DOM_BLOB_IID                              \
  {                                                  \
    0x648c2a83, 0xbdb1, 0x4a7d, {                    \
      0xb5, 0x0a, 0xca, 0xcd, 0x92, 0x87, 0x45, 0xc2 \
    }                                                \
  }

class Blob : public nsSupportsWeakReference, public nsWrapperCache {
 public:
  NS_DECL_CYCLE_COLLECTING_ISUPPORTS_FINAL
  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Blob)
  NS_DECLARE_STATIC_IID_ACCESSOR(NS_DOM_BLOB_IID)

  using BlobPart = OwningArrayBufferViewOrArrayBufferOrBlobOrUTF8String;

  // This creates a Blob or a File based on the type of BlobImpl.
  static Blob* Create(nsIGlobalObject* aGlobal, BlobImpl* aImpl);

  static already_AddRefed<Blob> CreateStringBlob(nsIGlobalObject* aGlobal,
                                                 const nsACString& aData,
                                                 const nsAString& aContentType);

  // The returned Blob takes ownership of aMemoryBuffer. aMemoryBuffer will be
  // freed by free so it must be allocated by malloc or something
  // compatible with it.
  static already_AddRefed<Blob> CreateMemoryBlob(nsIGlobalObject* aGlobal,
                                                 void* aMemoryBuffer,
                                                 uint64_t aLength,
                                                 const nsAString& aContentType);

  BlobImpl* Impl() const { return mImpl; }

  bool IsFile() const;

  const nsTArray<RefPtr<BlobImpl>>* GetSubBlobImpls() const;

  // This method returns null if this Blob is not a File; it returns
  // the same object in case this Blob already implements the File interface;
  // otherwise it returns a new File object with the same BlobImpl.
  already_AddRefed<File> ToFile();

  // This method creates a new File object with the given name and the same
  // BlobImpl.
  already_AddRefed<File> ToFile(const nsAString& aName, ErrorResult& aRv) const;

  already_AddRefed<Blob> CreateSlice(uint64_t aStart, uint64_t aLength,
                                     const nsAString& aContentType,
                                     ErrorResult& aRv) const;

  void CreateInputStream(nsIInputStream** aStream, ErrorResult& aRv) const;

  int64_t GetFileId() const;

  // A utility function that enforces the spec constraints on the type of a
  // blob: no codepoints outside the ASCII range (otherwise type becomes empty)
  // and lowercase ASCII only.  We can't just use our existing nsContentUtils
  // ASCII-related helpers because we need the "outside ASCII range" check, and
  // we can't use NS_IsAscii because its definition of "ASCII" (chars all <=
  // 0x7E) differs from the file API definition (which excludes control chars).
  static void MakeValidBlobType(nsAString& aType);

  // WebIDL methods
  nsIGlobalObject* GetParentObject() const { return mGlobal; }

  bool IsMemoryFile() const;

  // Blob constructor
  static already_AddRefed<Blob> Constructor(
      const GlobalObject& aGlobal, const Optional<Sequence<BlobPart>>& aData,
      const BlobPropertyBag& aBag, ErrorResult& aRv);

  JSObject* WrapObject(JSContext* aCx,
                       JS::Handle<JSObject*> aGivenProto) override;

  uint64_t GetSize(ErrorResult& aRv);

  void GetType(nsAString& aType);

  void GetBlobImplType(nsAString& aBlobImplType);

  already_AddRefed<Blob> Slice(const Optional<int64_t>& aStart,
                               const Optional<int64_t>& aEnd,
                               const Optional<nsAString>& aContentType,
                               ErrorResult& aRv);

  size_t GetAllocationSize() const;

  nsresult GetSendInfo(nsIInputStream** aBody, uint64_t* aContentLength,
                       nsACString& aContentType, nsACString& aCharset) const;

  already_AddRefed<ReadableStream> Stream(JSContext* aCx,
                                          ErrorResult& aRv) const;
  already_AddRefed<Promise> Text(ErrorResult& aRv) const;
  already_AddRefed<Promise> ArrayBuffer(ErrorResult& aRv) const;

 protected:
  // File constructor should never be used directly. Use Blob::Create instead.
  Blob(nsIGlobalObject* aGlobal, BlobImpl* aImpl);
  virtual ~Blob();

  virtual bool HasFileInterface() const { return false; }

  already_AddRefed<Promise> ConsumeBody(BodyConsumer::ConsumeType aConsumeType,
                                        ErrorResult& aRv) const;

  // The member is the real backend implementation of this File/Blob.
  // It's thread-safe and not CC-able and it's the only element that is moved
  // between threads.
  // Note: we should not store any other state in this class!
  RefPtr<BlobImpl> mImpl;

 private:
  nsCOMPtr<nsIGlobalObject> mGlobal;
};

NS_DEFINE_STATIC_IID_ACCESSOR(Blob, NS_DOM_BLOB_IID)

// Override BindingJSObjectMallocBytes for blobs to tell the JS GC how much
// memory is held live by the binding object.
size_t BindingJSObjectMallocBytes(Blob* aBlob);

}  // namespace dom
}  // namespace mozilla

inline nsISupports* ToSupports(mozilla::dom::Blob* aBlob) {
  return static_cast<nsISupportsWeakReference*>(aBlob);
}

#endif  // mozilla_dom_Blob_h