1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is mozila.org code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Mozilla Corporation
19 : * Portions created by the Initial Developer are Copyright (C) 2007
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Dave Camp <dcamp@mozilla.com>
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either the GNU General Public License Version 2 or later (the "GPL"), or
27 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : #ifndef nsDOMFile_h__
40 : #define nsDOMFile_h__
41 :
42 : #include "nsICharsetDetectionObserver.h"
43 : #include "nsIFile.h"
44 : #include "nsIDOMFile.h"
45 : #include "nsIDOMFileList.h"
46 : #include "nsIInputStream.h"
47 : #include "nsIJSNativeInitializer.h"
48 : #include "nsIMutable.h"
49 : #include "nsCOMArray.h"
50 : #include "nsCOMPtr.h"
51 : #include "nsString.h"
52 : #include "nsIXMLHttpRequest.h"
53 : #include "prmem.h"
54 : #include "nsAutoPtr.h"
55 :
56 : #include "mozilla/GuardObjects.h"
57 : #include "mozilla/StandardInteger.h"
58 : #include "mozilla/dom/DOMError.h"
59 : #include "mozilla/dom/indexedDB/FileInfo.h"
60 : #include "mozilla/dom/indexedDB/FileManager.h"
61 : #include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
62 : #include "nsWrapperCache.h"
63 : #include "nsCycleCollectionParticipant.h"
64 :
65 : class nsIFile;
66 : class nsIInputStream;
67 : class nsIClassInfo;
68 : class nsIBlobBuilder;
69 :
70 : nsresult NS_NewBlobBuilder(nsISupports* *aSupports);
71 :
72 : class nsDOMFileBase : public nsIDOMFile,
73 : public nsIDOMBlob_GECKO_13,
74 : public nsIXHRSendable,
75 : public nsIMutable
76 : {
77 : public:
78 : typedef mozilla::dom::indexedDB::FileInfo FileInfo;
79 :
80 10 : nsDOMFileBase(const nsAString& aName, const nsAString& aContentType,
81 : PRUint64 aLength)
82 : : mIsFile(true), mImmutable(false), mContentType(aContentType),
83 10 : mName(aName), mStart(0), mLength(aLength)
84 : {
85 : // Ensure non-null mContentType by default
86 10 : mContentType.SetIsVoid(false);
87 10 : }
88 :
89 0 : nsDOMFileBase(const nsAString& aContentType, PRUint64 aLength)
90 : : mIsFile(false), mImmutable(false), mContentType(aContentType),
91 0 : mStart(0), mLength(aLength)
92 : {
93 : // Ensure non-null mContentType by default
94 0 : mContentType.SetIsVoid(false);
95 0 : }
96 :
97 0 : nsDOMFileBase(const nsAString& aContentType,
98 : PRUint64 aStart, PRUint64 aLength)
99 : : mIsFile(false), mImmutable(false), mContentType(aContentType),
100 0 : mStart(aStart), mLength(aLength)
101 : {
102 0 : NS_ASSERTION(aLength != UINT64_MAX,
103 : "Must know length when creating slice");
104 : // Ensure non-null mContentType by default
105 0 : mContentType.SetIsVoid(false);
106 0 : }
107 :
108 20 : virtual ~nsDOMFileBase() {}
109 :
110 : virtual already_AddRefed<nsIDOMBlob>
111 : CreateSlice(PRUint64 aStart, PRUint64 aLength,
112 : const nsAString& aContentType) = 0;
113 :
114 : virtual const nsTArray<nsCOMPtr<nsIDOMBlob> >*
115 0 : GetSubBlobs() const { return nsnull; }
116 :
117 : NS_DECL_ISUPPORTS
118 : NS_DECL_NSIDOMBLOB
119 : NS_DECL_NSIDOMFILE
120 : NS_DECL_NSIDOMBLOB_GECKO_13
121 : NS_DECL_NSIXHRSENDABLE
122 : NS_DECL_NSIMUTABLE
123 :
124 : protected:
125 2 : bool IsSizeUnknown()
126 : {
127 2 : return mLength == UINT64_MAX;
128 : }
129 :
130 0 : virtual bool IsStoredFile()
131 : {
132 0 : return false;
133 : }
134 :
135 0 : virtual bool IsWholeFile()
136 : {
137 0 : NS_NOTREACHED("Should only be called on dom blobs backed by files!");
138 0 : return false;
139 : }
140 :
141 : bool mIsFile;
142 : bool mImmutable;
143 : nsString mContentType;
144 : nsString mName;
145 :
146 : PRUint64 mStart;
147 : PRUint64 mLength;
148 :
149 : // Protected by IndexedDatabaseManager::FileMutex()
150 : nsTArray<nsRefPtr<FileInfo> > mFileInfos;
151 : };
152 :
153 : class nsDOMFileFile : public nsDOMFileBase,
154 : public nsIJSNativeInitializer
155 40 : {
156 : public:
157 : // Create as a file
158 0 : nsDOMFileFile(nsIFile *aFile)
159 0 : : nsDOMFileBase(EmptyString(), EmptyString(), UINT64_MAX),
160 0 : mFile(aFile), mWholeFile(true), mStoredFile(false)
161 : {
162 0 : NS_ASSERTION(mFile, "must have file");
163 : // Lazily get the content type and size
164 0 : mContentType.SetIsVoid(true);
165 0 : mFile->GetLeafName(mName);
166 0 : }
167 :
168 : // Create as a blob
169 0 : nsDOMFileFile(nsIFile *aFile, const nsAString& aContentType,
170 : nsISupports *aCacheToken = nsnull)
171 : : nsDOMFileBase(aContentType, UINT64_MAX),
172 : mFile(aFile), mWholeFile(true), mStoredFile(false),
173 0 : mCacheToken(aCacheToken)
174 : {
175 0 : NS_ASSERTION(mFile, "must have file");
176 0 : }
177 :
178 : // Create as a stored file
179 0 : nsDOMFileFile(const nsAString& aName, const nsAString& aContentType,
180 : PRUint64 aLength, nsIFile* aFile,
181 : FileInfo* aFileInfo)
182 : : nsDOMFileBase(aName, aContentType, aLength),
183 0 : mFile(aFile), mWholeFile(true), mStoredFile(true)
184 : {
185 0 : NS_ASSERTION(mFile, "must have file");
186 0 : mFileInfos.AppendElement(aFileInfo);
187 0 : }
188 :
189 : // Create as a stored blob
190 0 : nsDOMFileFile(const nsAString& aContentType, PRUint64 aLength,
191 : nsIFile* aFile, FileInfo* aFileInfo)
192 : : nsDOMFileBase(aContentType, aLength),
193 0 : mFile(aFile), mWholeFile(true), mStoredFile(true)
194 : {
195 0 : NS_ASSERTION(mFile, "must have file");
196 0 : mFileInfos.AppendElement(aFileInfo);
197 0 : }
198 :
199 : // Create as a file to be later initialized
200 10 : nsDOMFileFile()
201 20 : : nsDOMFileBase(EmptyString(), EmptyString(), UINT64_MAX),
202 20 : mWholeFile(true), mStoredFile(false)
203 : {
204 : // Lazily get the content type and size
205 10 : mContentType.SetIsVoid(true);
206 10 : mName.SetIsVoid(true);
207 10 : }
208 :
209 : NS_DECL_ISUPPORTS_INHERITED
210 :
211 : // nsIJSNativeInitializer
212 : NS_IMETHOD Initialize(nsISupports* aOwner,
213 : JSContext* aCx,
214 : JSObject* aObj,
215 : PRUint32 aArgc,
216 : jsval* aArgv);
217 :
218 : // Overrides
219 : NS_IMETHOD GetSize(PRUint64* aSize);
220 : NS_IMETHOD GetType(nsAString& aType);
221 : NS_IMETHOD GetMozFullPathInternal(nsAString& aFullPath);
222 : NS_IMETHOD GetInternalStream(nsIInputStream**);
223 :
224 : // DOMClassInfo constructor (for File("foo"))
225 : static nsresult
226 : NewFile(nsISupports* *aNewObject);
227 :
228 : protected:
229 : // Create slice
230 0 : nsDOMFileFile(const nsDOMFileFile* aOther, PRUint64 aStart, PRUint64 aLength,
231 : const nsAString& aContentType)
232 : : nsDOMFileBase(aContentType, aOther->mStart + aStart, aLength),
233 : mFile(aOther->mFile), mWholeFile(false),
234 0 : mStoredFile(aOther->mStoredFile), mCacheToken(aOther->mCacheToken)
235 : {
236 0 : NS_ASSERTION(mFile, "must have file");
237 0 : mImmutable = aOther->mImmutable;
238 :
239 0 : if (mStoredFile) {
240 : FileInfo* fileInfo;
241 :
242 0 : if (!mozilla::dom::indexedDB::IndexedDatabaseManager::IsClosed()) {
243 0 : mozilla::dom::indexedDB::IndexedDatabaseManager::FileMutex().Lock();
244 : }
245 :
246 0 : NS_ASSERTION(!aOther->mFileInfos.IsEmpty(),
247 : "A stored file must have at least one file info!");
248 :
249 0 : fileInfo = aOther->mFileInfos.ElementAt(0);
250 :
251 0 : if (!mozilla::dom::indexedDB::IndexedDatabaseManager::IsClosed()) {
252 0 : mozilla::dom::indexedDB::IndexedDatabaseManager::FileMutex().Unlock();
253 : }
254 :
255 0 : mFileInfos.AppendElement(fileInfo);
256 : }
257 0 : }
258 : virtual already_AddRefed<nsIDOMBlob>
259 : CreateSlice(PRUint64 aStart, PRUint64 aLength,
260 : const nsAString& aContentType);
261 :
262 0 : virtual bool IsStoredFile()
263 : {
264 0 : return mStoredFile;
265 : }
266 :
267 0 : virtual bool IsWholeFile()
268 : {
269 0 : return mWholeFile;
270 : }
271 :
272 : nsCOMPtr<nsIFile> mFile;
273 : bool mWholeFile;
274 : bool mStoredFile;
275 : nsCOMPtr<nsISupports> mCacheToken;
276 : };
277 :
278 : class nsDOMMemoryFile : public nsDOMFileBase
279 0 : {
280 : public:
281 : // Create as file
282 0 : nsDOMMemoryFile(void *aMemoryBuffer,
283 : PRUint64 aLength,
284 : const nsAString& aName,
285 : const nsAString& aContentType)
286 : : nsDOMFileBase(aName, aContentType, aLength),
287 0 : mDataOwner(new DataOwner(aMemoryBuffer))
288 : {
289 0 : NS_ASSERTION(mDataOwner && mDataOwner->mData, "must have data");
290 0 : }
291 :
292 : // Create as blob
293 0 : nsDOMMemoryFile(void *aMemoryBuffer,
294 : PRUint64 aLength,
295 : const nsAString& aContentType)
296 : : nsDOMFileBase(aContentType, aLength),
297 0 : mDataOwner(new DataOwner(aMemoryBuffer))
298 : {
299 0 : NS_ASSERTION(mDataOwner && mDataOwner->mData, "must have data");
300 0 : }
301 :
302 : NS_IMETHOD GetInternalStream(nsIInputStream**);
303 :
304 : protected:
305 : // Create slice
306 0 : nsDOMMemoryFile(const nsDOMMemoryFile* aOther, PRUint64 aStart,
307 : PRUint64 aLength, const nsAString& aContentType)
308 : : nsDOMFileBase(aContentType, aOther->mStart + aStart, aLength),
309 0 : mDataOwner(aOther->mDataOwner)
310 : {
311 0 : NS_ASSERTION(mDataOwner && mDataOwner->mData, "must have data");
312 0 : mImmutable = aOther->mImmutable;
313 0 : }
314 : virtual already_AddRefed<nsIDOMBlob>
315 : CreateSlice(PRUint64 aStart, PRUint64 aLength,
316 : const nsAString& aContentType);
317 :
318 : friend class DataOwnerAdapter; // Needs to see DataOwner
319 : class DataOwner {
320 : public:
321 0 : NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DataOwner)
322 0 : DataOwner(void* aMemoryBuffer)
323 0 : : mData(aMemoryBuffer)
324 : {
325 0 : }
326 0 : ~DataOwner() {
327 0 : PR_Free(mData);
328 0 : }
329 : void* mData;
330 : };
331 :
332 : // Used when backed by a memory store
333 : nsRefPtr<DataOwner> mDataOwner;
334 : };
335 :
336 : class nsDOMFileList MOZ_FINAL : public nsIDOMFileList,
337 : public nsWrapperCache
338 0 : {
339 : public:
340 0 : nsDOMFileList(nsISupports *aParent) : mParent(aParent)
341 : {
342 0 : SetIsProxy();
343 0 : }
344 :
345 0 : NS_DECL_CYCLE_COLLECTING_ISUPPORTS
346 1464 : NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsDOMFileList)
347 :
348 : NS_DECL_NSIDOMFILELIST
349 :
350 : virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
351 : bool *triedToWrap);
352 :
353 0 : nsISupports* GetParentObject()
354 : {
355 0 : return mParent;
356 : }
357 :
358 0 : void Disconnect()
359 : {
360 0 : mParent = nsnull;
361 0 : }
362 :
363 0 : bool Append(nsIDOMFile *aFile) { return mFiles.AppendObject(aFile); }
364 :
365 : bool Remove(PRUint32 aIndex) { return mFiles.RemoveObjectAt(aIndex); }
366 0 : void Clear() { return mFiles.Clear(); }
367 :
368 0 : static nsDOMFileList* FromSupports(nsISupports* aSupports)
369 : {
370 : #ifdef DEBUG
371 : {
372 0 : nsCOMPtr<nsIDOMFileList> list_qi = do_QueryInterface(aSupports);
373 :
374 : // If this assertion fires the QI implementation for the object in
375 : // question doesn't use the nsIDOMFileList pointer as the nsISupports
376 : // pointer. That must be fixed, or we'll crash...
377 0 : NS_ASSERTION(list_qi == static_cast<nsIDOMFileList*>(aSupports),
378 : "Uh, fix QI!");
379 : }
380 : #endif
381 :
382 0 : return static_cast<nsDOMFileList*>(aSupports);
383 : }
384 :
385 : private:
386 : nsCOMArray<nsIDOMFile> mFiles;
387 : nsISupports *mParent;
388 : };
389 :
390 : class NS_STACK_CLASS nsDOMFileInternalUrlHolder {
391 : public:
392 : nsDOMFileInternalUrlHolder(nsIDOMBlob* aFile, nsIPrincipal* aPrincipal
393 : MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
394 : ~nsDOMFileInternalUrlHolder();
395 : nsAutoString mUrl;
396 : private:
397 : MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
398 : };
399 :
400 : #endif
|