|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #ifndef nsDOMBlobBuilder_h |
|
7 #define nsDOMBlobBuilder_h |
|
8 |
|
9 #include "nsDOMFile.h" |
|
10 |
|
11 #include "mozilla/CheckedInt.h" |
|
12 #include "mozilla/Attributes.h" |
|
13 #include <algorithm> |
|
14 |
|
15 #define NS_DOMMULTIPARTBLOB_CID { 0x47bf0b43, 0xf37e, 0x49ef, \ |
|
16 { 0x81, 0xa0, 0x18, 0xba, 0xc0, 0x57, 0xb5, 0xcc } } |
|
17 #define NS_DOMMULTIPARTBLOB_CONTRACTID "@mozilla.org/dom/multipart-blob;1" |
|
18 |
|
19 #define NS_DOMMULTIPARTFILE_CID { 0xc3361f77, 0x60d1, 0x4ea9, \ |
|
20 { 0x94, 0x96, 0xdf, 0x5d, 0x6f, 0xcd, 0xd7, 0x8f } } |
|
21 #define NS_DOMMULTIPARTFILE_CONTRACTID "@mozilla.org/dom/multipart-file;1" |
|
22 |
|
23 class nsDOMMultipartFile : public nsDOMFile, |
|
24 public nsIJSNativeInitializer |
|
25 { |
|
26 public: |
|
27 // Create as a file |
|
28 nsDOMMultipartFile(nsTArray<nsCOMPtr<nsIDOMBlob> > aBlobs, |
|
29 const nsAString& aName, |
|
30 const nsAString& aContentType) |
|
31 : nsDOMFile(aName, aContentType, UINT64_MAX), |
|
32 mBlobs(aBlobs), |
|
33 mIsFromNsiFile(false) |
|
34 { |
|
35 } |
|
36 |
|
37 // Create as a blob |
|
38 nsDOMMultipartFile(nsTArray<nsCOMPtr<nsIDOMBlob> >& aBlobs, |
|
39 const nsAString& aContentType) |
|
40 : nsDOMFile(aContentType, UINT64_MAX), |
|
41 mBlobs(aBlobs), |
|
42 mIsFromNsiFile(false) |
|
43 { |
|
44 } |
|
45 |
|
46 // Create as a file to be later initialized |
|
47 nsDOMMultipartFile(const nsAString& aName) |
|
48 : nsDOMFile(aName, EmptyString(), UINT64_MAX), |
|
49 mIsFromNsiFile(false) |
|
50 { |
|
51 } |
|
52 |
|
53 // Create as a blob to be later initialized |
|
54 nsDOMMultipartFile() |
|
55 : nsDOMFile(EmptyString(), UINT64_MAX), |
|
56 mIsFromNsiFile(false) |
|
57 { |
|
58 } |
|
59 |
|
60 NS_DECL_ISUPPORTS_INHERITED |
|
61 |
|
62 // nsIJSNativeInitializer |
|
63 NS_IMETHOD Initialize(nsISupports* aOwner, |
|
64 JSContext* aCx, |
|
65 JSObject* aObj, |
|
66 const JS::CallArgs& aArgs) MOZ_OVERRIDE; |
|
67 |
|
68 typedef nsIDOMBlob* (*UnwrapFuncPtr)(JSContext*, JSObject*); |
|
69 nsresult InitBlob(JSContext* aCx, |
|
70 uint32_t aArgc, |
|
71 JS::Value* aArgv, |
|
72 UnwrapFuncPtr aUnwrapFunc); |
|
73 nsresult InitFile(JSContext* aCx, |
|
74 uint32_t aArgc, |
|
75 JS::Value* aArgv); |
|
76 nsresult InitChromeFile(JSContext* aCx, |
|
77 uint32_t aArgc, |
|
78 JS::Value* aArgv); |
|
79 |
|
80 already_AddRefed<nsIDOMBlob> |
|
81 CreateSlice(uint64_t aStart, uint64_t aLength, const nsAString& aContentType) MOZ_OVERRIDE; |
|
82 |
|
83 NS_IMETHOD GetSize(uint64_t*) MOZ_OVERRIDE; |
|
84 NS_IMETHOD GetInternalStream(nsIInputStream**) MOZ_OVERRIDE; |
|
85 |
|
86 static nsresult |
|
87 NewFile(const nsAString& aName, nsISupports* *aNewObject); |
|
88 |
|
89 // DOMClassInfo constructor (for Blob([b1, "foo"], { type: "image/png" })) |
|
90 static nsresult |
|
91 NewBlob(nsISupports* *aNewObject); |
|
92 |
|
93 // DOMClassInfo constructor (for File([b1, "foo"], { type: "image/png", |
|
94 // name: "foo.png" })) |
|
95 inline static nsresult |
|
96 NewFile(nsISupports* *aNewObject) |
|
97 { |
|
98 // Initialization will set the filename, so we can pass in an empty string |
|
99 // for now. |
|
100 return NewFile(EmptyString(), aNewObject); |
|
101 } |
|
102 |
|
103 virtual const nsTArray<nsCOMPtr<nsIDOMBlob> >* |
|
104 GetSubBlobs() const MOZ_OVERRIDE { return &mBlobs; } |
|
105 |
|
106 NS_IMETHOD GetMozFullPathInternal(nsAString& aFullPath) MOZ_OVERRIDE; |
|
107 |
|
108 protected: |
|
109 nsresult ParseBlobArrayArgument(JSContext* aCx, JS::Value& aValue, |
|
110 bool aNativeEOL, UnwrapFuncPtr aUnwrapFunc); |
|
111 |
|
112 nsTArray<nsCOMPtr<nsIDOMBlob> > mBlobs; |
|
113 bool mIsFromNsiFile; |
|
114 }; |
|
115 |
|
116 class BlobSet { |
|
117 public: |
|
118 BlobSet() |
|
119 : mData(nullptr), mDataLen(0), mDataBufferLen(0) |
|
120 {} |
|
121 |
|
122 nsresult AppendVoidPtr(const void* aData, uint32_t aLength); |
|
123 nsresult AppendString(JSString* aString, bool nativeEOL, JSContext* aCx); |
|
124 nsresult AppendBlob(nsIDOMBlob* aBlob); |
|
125 nsresult AppendArrayBuffer(JSObject* aBuffer); |
|
126 nsresult AppendBlobs(const nsTArray<nsCOMPtr<nsIDOMBlob> >& aBlob); |
|
127 |
|
128 nsTArray<nsCOMPtr<nsIDOMBlob> >& GetBlobs() { Flush(); return mBlobs; } |
|
129 |
|
130 already_AddRefed<nsIDOMBlob> |
|
131 GetBlobInternal(const nsACString& aContentType) |
|
132 { |
|
133 nsCOMPtr<nsIDOMBlob> blob = |
|
134 new nsDOMMultipartFile(GetBlobs(), NS_ConvertASCIItoUTF16(aContentType)); |
|
135 return blob.forget(); |
|
136 } |
|
137 |
|
138 protected: |
|
139 bool ExpandBufferSize(uint64_t aSize) |
|
140 { |
|
141 using mozilla::CheckedUint32; |
|
142 |
|
143 if (mDataBufferLen >= mDataLen + aSize) { |
|
144 mDataLen += aSize; |
|
145 return true; |
|
146 } |
|
147 |
|
148 // Start at 1 or we'll loop forever. |
|
149 CheckedUint32 bufferLen = |
|
150 std::max<uint32_t>(static_cast<uint32_t>(mDataBufferLen), 1); |
|
151 while (bufferLen.isValid() && bufferLen.value() < mDataLen + aSize) |
|
152 bufferLen *= 2; |
|
153 |
|
154 if (!bufferLen.isValid()) |
|
155 return false; |
|
156 |
|
157 void* data = moz_realloc(mData, bufferLen.value()); |
|
158 if (!data) |
|
159 return false; |
|
160 |
|
161 mData = data; |
|
162 mDataBufferLen = bufferLen.value(); |
|
163 mDataLen += aSize; |
|
164 return true; |
|
165 } |
|
166 |
|
167 void Flush() { |
|
168 if (mData) { |
|
169 // If we have some data, create a blob for it |
|
170 // and put it on the stack |
|
171 |
|
172 nsCOMPtr<nsIDOMBlob> blob = |
|
173 new nsDOMMemoryFile(mData, mDataLen, EmptyString(), EmptyString()); |
|
174 mBlobs.AppendElement(blob); |
|
175 mData = nullptr; // The nsDOMMemoryFile takes ownership of the buffer |
|
176 mDataLen = 0; |
|
177 mDataBufferLen = 0; |
|
178 } |
|
179 } |
|
180 |
|
181 nsTArray<nsCOMPtr<nsIDOMBlob> > mBlobs; |
|
182 void* mData; |
|
183 uint64_t mDataLen; |
|
184 uint64_t mDataBufferLen; |
|
185 }; |
|
186 |
|
187 #endif |