1 /* -*- Mode: C++; tab-width: 2; 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/. */
9 #include "nsCExternalHandlerService.h"
10 #include "nsContentCID.h"
11 #include "nsContentUtils.h"
12 #include "nsDOMClassInfoID.h"
14 #include "nsICharsetDetector.h"
15 #include "nsIClassInfo.h"
16 #include "nsIConverterInputStream.h"
17 #include "nsIDocument.h"
18 #include "nsIFileStreams.h"
19 #include "nsIInputStream.h"
20 #include "nsIIPCSerializableInputStream.h"
21 #include "nsIMemoryReporter.h"
22 #include "nsIMIMEService.h"
23 #include "nsIPlatformCharset.h"
24 #include "nsISeekableStream.h"
25 #include "nsIUnicharInputStream.h"
26 #include "nsIUnicodeDecoder.h"
28 #include "nsNetUtil.h"
29 #include "nsIUUIDGenerator.h"
30 #include "nsHostObjectProtocolHandler.h"
31 #include "nsStringStream.h"
32 #include "nsJSUtils.h"
33 #include "nsPrintfCString.h"
34 #include "mozilla/SHA1.h"
35 #include "mozilla/CheckedInt.h"
36 #include "mozilla/Preferences.h"
37 #include "mozilla/Attributes.h"
38 #include "nsThreadUtils.h"
40 #include "mozilla/dom/FileListBinding.h"
41 using namespace mozilla
;
42 using namespace mozilla::dom
;
44 // XXXkhuey the input stream that we pass out of a DOMFile
45 // can outlive the actual DOMFile object. Thus, we must
46 // ensure that the buffer underlying the stream we get
47 // from NS_NewByteInputStream is held alive as long as the
48 // stream is. We do that by passing back this class instead.
49 class DataOwnerAdapter MOZ_FINAL
: public nsIInputStream
,
50 public nsISeekableStream
,
51 public nsIIPCSerializableInputStream
53 typedef nsDOMMemoryFile::DataOwner DataOwner
;
55 static nsresult
Create(DataOwner
* aDataOwner
,
58 nsIInputStream
** _retval
);
60 NS_DECL_THREADSAFE_ISUPPORTS
62 // These are mandatory.
63 NS_FORWARD_NSIINPUTSTREAM(mStream
->)
64 NS_FORWARD_NSISEEKABLESTREAM(mSeekableStream
->)
66 // This is optional. We use a conditional QI to keep it from being called
67 // if the underlying stream doesn't support it.
68 NS_FORWARD_NSIIPCSERIALIZABLEINPUTSTREAM(mSerializableInputStream
->)
71 DataOwnerAdapter(DataOwner
* aDataOwner
,
72 nsIInputStream
* aStream
)
73 : mDataOwner(aDataOwner
), mStream(aStream
),
74 mSeekableStream(do_QueryInterface(aStream
)),
75 mSerializableInputStream(do_QueryInterface(aStream
))
77 NS_ASSERTION(mSeekableStream
, "Somebody gave us the wrong stream!");
80 nsRefPtr
<DataOwner
> mDataOwner
;
81 nsCOMPtr
<nsIInputStream
> mStream
;
82 nsCOMPtr
<nsISeekableStream
> mSeekableStream
;
83 nsCOMPtr
<nsIIPCSerializableInputStream
> mSerializableInputStream
;
86 NS_IMPL_ADDREF(DataOwnerAdapter
)
87 NS_IMPL_RELEASE(DataOwnerAdapter
)
89 NS_INTERFACE_MAP_BEGIN(DataOwnerAdapter
)
90 NS_INTERFACE_MAP_ENTRY(nsIInputStream
)
91 NS_INTERFACE_MAP_ENTRY(nsISeekableStream
)
92 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableInputStream
,
93 mSerializableInputStream
)
94 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIInputStream
)
97 nsresult
DataOwnerAdapter::Create(DataOwner
* aDataOwner
,
100 nsIInputStream
** _retval
)
103 NS_ASSERTION(aDataOwner
, "Uh ...");
105 nsCOMPtr
<nsIInputStream
> stream
;
107 rv
= NS_NewByteInputStream(getter_AddRefs(stream
),
108 static_cast<const char*>(aDataOwner
->mData
) +
111 NS_ASSIGNMENT_DEPEND
);
112 NS_ENSURE_SUCCESS(rv
, rv
);
114 NS_ADDREF(*_retval
= new DataOwnerAdapter(aDataOwner
, stream
));
119 ////////////////////////////////////////////////////////////////////////////
120 // nsDOMFileBase implementation
123 nsDOMFileBase::GetName(nsAString
&aFileName
)
125 NS_ASSERTION(mIsFile
, "Should only be called on files");
131 nsDOMFileBase::GetPath(nsAString
&aPath
)
133 NS_ASSERTION(mIsFile
, "Should only be called on files");
139 nsDOMFileBase::GetLastModifiedDate(JSContext
* cx
, JS::Value
*aLastModifiedDate
)
141 JSObject
* date
= JS_NewDateObjectMsec(cx
, JS_Now() / PR_USEC_PER_MSEC
);
142 aLastModifiedDate
->setObject(*date
);
147 nsDOMFileBase::GetMozFullPath(nsAString
&aFileName
)
149 NS_ASSERTION(mIsFile
, "Should only be called on files");
151 // It is unsafe to call IsCallerChrome on a non-main thread. If
152 // you hit the following assertion you need to figure out some other way to
153 // determine privileges and call GetMozFullPathInternal.
154 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
156 if (nsContentUtils::IsCallerChrome()) {
157 return GetMozFullPathInternal(aFileName
);
159 aFileName
.Truncate();
164 nsDOMFileBase::GetMozFullPathInternal(nsAString
&aFileName
)
167 return NS_ERROR_FAILURE
;
170 aFileName
.Truncate();
175 nsDOMFileBase::GetSize(uint64_t *aSize
)
182 nsDOMFileBase::GetType(nsAString
&aType
)
184 aType
= mContentType
;
189 nsDOMFileBase::GetMozLastModifiedDate(uint64_t* aLastModifiedDate
)
191 NS_ASSERTION(mIsFile
, "Should only be called on files");
192 if (IsDateUnknown()) {
193 mLastModificationDate
= PR_Now();
195 *aLastModifiedDate
= mLastModificationDate
;
199 // Makes sure that aStart and aEnd is less then or equal to aSize and greater
202 ParseSize(int64_t aSize
, int64_t& aStart
, int64_t& aEnd
)
204 CheckedInt64 newStartOffset
= aStart
;
205 if (aStart
< -aSize
) {
208 else if (aStart
< 0) {
209 newStartOffset
+= aSize
;
211 else if (aStart
> aSize
) {
212 newStartOffset
= aSize
;
215 CheckedInt64 newEndOffset
= aEnd
;
220 newEndOffset
+= aSize
;
222 else if (aEnd
> aSize
) {
223 newEndOffset
= aSize
;
226 if (!newStartOffset
.isValid() || !newEndOffset
.isValid() ||
227 newStartOffset
.value() >= newEndOffset
.value()) {
231 aStart
= newStartOffset
.value();
232 aEnd
= newEndOffset
.value();
237 nsDOMFileBase::Slice(int64_t aStart
, int64_t aEnd
,
238 const nsAString
& aContentType
, uint8_t optional_argc
,
243 // Truncate aStart and aEnd so that we stay within this file.
245 nsresult rv
= GetSize(&thisLength
);
246 NS_ENSURE_SUCCESS(rv
, rv
);
248 if (optional_argc
< 2) {
249 aEnd
= (int64_t)thisLength
;
252 ParseSize((int64_t)thisLength
, aStart
, aEnd
);
254 // Create the new file
255 *aBlob
= CreateSlice((uint64_t)aStart
, (uint64_t)(aEnd
- aStart
),
258 return *aBlob
? NS_OK
: NS_ERROR_UNEXPECTED
;
262 nsDOMFileBase::MozSlice(int64_t aStart
, int64_t aEnd
,
263 const nsAString
& aContentType
,
265 uint8_t optional_argc
,
268 MOZ_ASSERT(NS_IsMainThread());
270 nsIScriptGlobalObject
* sgo
= nsJSUtils::GetDynamicScriptGlobal(aCx
);
272 nsCOMPtr
<nsPIDOMWindow
> window
= do_QueryInterface(sgo
);
274 nsCOMPtr
<nsIDocument
> document
= window
->GetExtantDoc();
276 document
->WarnOnceAbout(nsIDocument::eMozSlice
);
281 return Slice(aStart
, aEnd
, aContentType
, optional_argc
, aBlob
);
285 nsDOMFileBase::GetInternalStream(nsIInputStream
**aStream
)
287 // Must be overridden
288 NS_NOTREACHED("Must override GetInternalStream");
290 return NS_ERROR_NOT_IMPLEMENTED
;
294 nsDOMFileBase::GetInternalUrl(nsIPrincipal
* aPrincipal
, nsAString
& aURL
)
296 NS_ENSURE_STATE(aPrincipal
);
299 nsresult rv
= nsBlobProtocolHandler::AddDataEntry(
300 NS_LITERAL_CSTRING(BLOBURI_SCHEME
),
301 static_cast<nsIDOMBlob
*>(this), aPrincipal
, url
);
306 CopyASCIItoUTF16(url
, aURL
);
310 NS_IMETHODIMP_(int64_t)
311 nsDOMFileBase::GetFileId()
315 if (IsStoredFile() && IsWholeFile() && !IsSnapshot()) {
316 if (!indexedDB::IndexedDatabaseManager::IsClosed()) {
317 indexedDB::IndexedDatabaseManager::FileMutex().Lock();
320 NS_ASSERTION(!mFileInfos
.IsEmpty(),
321 "A stored file must have at least one file info!");
323 nsRefPtr
<indexedDB::FileInfo
>& fileInfo
= mFileInfos
.ElementAt(0);
328 if (!indexedDB::IndexedDatabaseManager::IsClosed()) {
329 indexedDB::IndexedDatabaseManager::FileMutex().Unlock();
337 nsDOMFileBase::AddFileInfo(indexedDB::FileInfo
* aFileInfo
)
339 if (indexedDB::IndexedDatabaseManager::IsClosed()) {
340 NS_ERROR("Shouldn't be called after shutdown!");
344 nsRefPtr
<indexedDB::FileInfo
> fileInfo
= aFileInfo
;
346 MutexAutoLock
lock(indexedDB::IndexedDatabaseManager::FileMutex());
348 NS_ASSERTION(!mFileInfos
.Contains(aFileInfo
),
349 "Adding the same file info agan?!");
351 nsRefPtr
<indexedDB::FileInfo
>* element
= mFileInfos
.AppendElement();
352 element
->swap(fileInfo
);
355 NS_IMETHODIMP_(indexedDB::FileInfo
*)
356 nsDOMFileBase::GetFileInfo(indexedDB::FileManager
* aFileManager
)
358 if (indexedDB::IndexedDatabaseManager::IsClosed()) {
359 NS_ERROR("Shouldn't be called after shutdown!");
363 // A slice created from a stored file must keep the file info alive.
364 // However, we don't support sharing of slices yet, so the slice must be
365 // copied again. That's why we have to ignore the first file info.
366 // Snapshots are handled in a similar way (they have to be copied).
368 if (IsStoredFile() && (!IsWholeFile() || IsSnapshot())) {
375 MutexAutoLock
lock(indexedDB::IndexedDatabaseManager::FileMutex());
377 for (uint32_t i
= startIndex
; i
< mFileInfos
.Length(); i
++) {
378 nsRefPtr
<indexedDB::FileInfo
>& fileInfo
= mFileInfos
.ElementAt(i
);
379 if (fileInfo
->Manager() == aFileManager
) {
388 nsDOMFileBase::GetSendInfo(nsIInputStream
** aBody
,
389 uint64_t* aContentLength
,
390 nsACString
& aContentType
,
391 nsACString
& aCharset
)
395 nsCOMPtr
<nsIInputStream
> stream
;
396 rv
= this->GetInternalStream(getter_AddRefs(stream
));
397 NS_ENSURE_SUCCESS(rv
, rv
);
399 rv
= this->GetSize(aContentLength
);
400 NS_ENSURE_SUCCESS(rv
, rv
);
402 nsString contentType
;
403 rv
= this->GetType(contentType
);
404 NS_ENSURE_SUCCESS(rv
, rv
);
406 CopyUTF16toUTF8(contentType
, aContentType
);
410 stream
.forget(aBody
);
415 nsDOMFileBase::GetMutable(bool* aMutable
)
417 *aMutable
= !mImmutable
;
422 nsDOMFileBase::SetMutable(bool aMutable
)
426 NS_ENSURE_ARG(!mImmutable
|| !aMutable
);
428 if (!mImmutable
&& !aMutable
) {
429 // Force the content type and size to be cached
430 nsString dummyString
;
431 rv
= this->GetType(dummyString
);
432 NS_ENSURE_SUCCESS(rv
, rv
);
435 rv
= this->GetSize(&dummyInt
);
436 NS_ENSURE_SUCCESS(rv
, rv
);
439 mImmutable
= !aMutable
;
443 ////////////////////////////////////////////////////////////////////////////
444 // nsDOMFile implementation
446 DOMCI_DATA(File
, nsDOMFile
)
447 DOMCI_DATA(Blob
, nsDOMFile
)
449 NS_INTERFACE_MAP_BEGIN(nsDOMFile
)
450 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIDOMFile
)
451 NS_INTERFACE_MAP_ENTRY(nsIDOMBlob
)
452 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIDOMFile
, mIsFile
)
453 NS_INTERFACE_MAP_ENTRY(nsIXHRSendable
)
454 NS_INTERFACE_MAP_ENTRY(nsIMutable
)
455 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_CONDITIONAL(File
, mIsFile
)
456 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_CONDITIONAL(Blob
, !mIsFile
)
459 // Threadsafe when GetMutable() == false
460 NS_IMPL_ADDREF(nsDOMFile
)
461 NS_IMPL_RELEASE(nsDOMFile
)
463 ////////////////////////////////////////////////////////////////////////////
464 // nsDOMFileCC implementation
466 NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMFileCC
)
468 NS_IMPL_CYCLE_COLLECTION_UNLINK_0(nsDOMFileCC
)
469 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMFileCC
)
470 // We don't have anything to traverse, but some of our subclasses do.
471 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
473 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMFileCC
)
474 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIDOMFile
)
475 NS_INTERFACE_MAP_ENTRY(nsIDOMBlob
)
476 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIDOMFile
, mIsFile
)
477 NS_INTERFACE_MAP_ENTRY(nsIXHRSendable
)
478 NS_INTERFACE_MAP_ENTRY(nsIMutable
)
479 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_CONDITIONAL(File
, mIsFile
)
480 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_CONDITIONAL(Blob
, !mIsFile
)
483 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMFileCC
)
484 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMFileCC
)
486 ////////////////////////////////////////////////////////////////////////////
487 // nsDOMFileFile implementation
489 already_AddRefed
<nsIDOMBlob
>
490 nsDOMFileFile::CreateSlice(uint64_t aStart
, uint64_t aLength
,
491 const nsAString
& aContentType
)
493 nsCOMPtr
<nsIDOMBlob
> t
= new nsDOMFileFile(this, aStart
, aLength
, aContentType
);
498 nsDOMFileFile::GetMozFullPathInternal(nsAString
&aFilename
)
500 NS_ASSERTION(mIsFile
, "Should only be called on files");
501 return mFile
->GetPath(aFilename
);
505 nsDOMFileFile::GetLastModifiedDate(JSContext
* cx
, JS::Value
* aLastModifiedDate
)
507 NS_ASSERTION(mIsFile
, "Should only be called on files");
510 if (IsDateUnknown()) {
511 nsresult rv
= mFile
->GetLastModifiedTime(&msecs
);
512 NS_ENSURE_SUCCESS(rv
, rv
);
513 mLastModificationDate
= msecs
;
515 msecs
= mLastModificationDate
;
518 JSObject
* date
= JS_NewDateObjectMsec(cx
, msecs
);
520 aLastModifiedDate
->setObject(*date
);
523 date
= JS_NewDateObjectMsec(cx
, JS_Now() / PR_USEC_PER_MSEC
);
524 aLastModifiedDate
->setObject(*date
);
531 nsDOMFileFile::GetSize(uint64_t *aFileSize
)
533 if (IsSizeUnknown()) {
534 NS_ASSERTION(mWholeFile
,
535 "Should only use lazy size when using the whole file");
537 nsresult rv
= mFile
->GetFileSize(&fileSize
);
538 NS_ENSURE_SUCCESS(rv
, rv
);
541 return NS_ERROR_FAILURE
;
547 *aFileSize
= mLength
;
553 nsDOMFileFile::GetType(nsAString
&aType
)
555 if (mContentType
.IsVoid()) {
556 NS_ASSERTION(mWholeFile
,
557 "Should only use lazy ContentType when using the whole file");
559 nsCOMPtr
<nsIMIMEService
> mimeService
=
560 do_GetService(NS_MIMESERVICE_CONTRACTID
, &rv
);
561 NS_ENSURE_SUCCESS(rv
, rv
);
563 nsAutoCString mimeType
;
564 rv
= mimeService
->GetTypeFromFile(mFile
, mimeType
);
569 AppendUTF8toUTF16(mimeType
, mContentType
);
570 mContentType
.SetIsVoid(false);
573 aType
= mContentType
;
579 nsDOMFileFile::GetMozLastModifiedDate(uint64_t* aLastModifiedDate
)
581 NS_ASSERTION(mIsFile
, "Should only be called on files");
582 if (IsDateUnknown()) {
584 nsresult rv
= mFile
->GetLastModifiedTime(&msecs
);
585 NS_ENSURE_SUCCESS(rv
, rv
);
586 mLastModificationDate
= msecs
;
588 *aLastModifiedDate
= mLastModificationDate
;
592 const uint32_t sFileStreamFlags
=
593 nsIFileInputStream::CLOSE_ON_EOF
|
594 nsIFileInputStream::REOPEN_ON_REWIND
|
595 nsIFileInputStream::DEFER_OPEN
;
598 nsDOMFileFile::GetInternalStream(nsIInputStream
**aStream
)
601 NS_NewLocalFileInputStream(aStream
, mFile
, -1, -1, sFileStreamFlags
) :
602 NS_NewPartialLocalFileInputStream(aStream
, mFile
, mStart
, mLength
,
603 -1, -1, sFileStreamFlags
);
607 nsDOMFileFile::SetPath(const nsAString
& aPath
)
609 MOZ_ASSERT(aPath
.IsEmpty() ||
610 aPath
[aPath
.Length() - 1] == PRUnichar('/'),
611 "Path must end with a path separator");
615 ////////////////////////////////////////////////////////////////////////////
616 // nsDOMMemoryFile implementation
618 already_AddRefed
<nsIDOMBlob
>
619 nsDOMMemoryFile::CreateSlice(uint64_t aStart
, uint64_t aLength
,
620 const nsAString
& aContentType
)
622 nsCOMPtr
<nsIDOMBlob
> t
=
623 new nsDOMMemoryFile(this, aStart
, aLength
, aContentType
);
628 nsDOMMemoryFile::GetInternalStream(nsIInputStream
**aStream
)
630 if (mLength
> INT32_MAX
)
631 return NS_ERROR_FAILURE
;
633 return DataOwnerAdapter::Create(mDataOwner
, mStart
, mLength
, aStream
);
636 /* static */ StaticMutex
637 nsDOMMemoryFile::DataOwner::sDataOwnerMutex
;
639 /* static */ StaticAutoPtr
<LinkedList
<nsDOMMemoryFile::DataOwner
> >
640 nsDOMMemoryFile::DataOwner::sDataOwners
;
643 nsDOMMemoryFile::DataOwner::sMemoryReporterRegistered
;
645 NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(DOMMemoryFileDataOwnerMallocSizeOf
)
647 class nsDOMMemoryFileDataOwnerMemoryReporter MOZ_FINAL
648 : public MemoryMultiReporter
651 nsDOMMemoryFileDataOwnerMemoryReporter()
652 : MemoryMultiReporter("dom-memory-file-data-owner")
655 NS_IMETHOD
CollectReports(nsIMemoryReporterCallback
*aCallback
,
656 nsISupports
*aClosure
)
658 typedef nsDOMMemoryFile::DataOwner DataOwner
;
660 StaticMutexAutoLock
lock(DataOwner::sDataOwnerMutex
);
662 if (!DataOwner::sDataOwners
) {
666 const size_t LARGE_OBJECT_MIN_SIZE
= 8 * 1024;
667 size_t smallObjectsTotal
= 0;
669 for (DataOwner
*owner
= DataOwner::sDataOwners
->getFirst();
670 owner
; owner
= owner
->getNext()) {
672 size_t size
= DOMMemoryFileDataOwnerMallocSizeOf(owner
->mData
);
674 if (size
< LARGE_OBJECT_MIN_SIZE
) {
675 smallObjectsTotal
+= size
;
679 sha1
.update(owner
->mData
, owner
->mLength
);
680 uint8_t digest
[SHA1Sum::HashSize
]; // SHA1 digests are 20 bytes long.
683 nsAutoCString digestString
;
684 for (size_t i
= 0; i
< sizeof(digest
); i
++) {
685 digestString
.AppendPrintf("%02x", digest
[i
]);
688 nsresult rv
= aCallback
->Callback(
689 /* process */ NS_LITERAL_CSTRING(""),
691 "explicit/dom/memory-file-data/large/file(length=%llu, sha1=%s)",
692 owner
->mLength
, digestString
.get()),
693 nsIMemoryReporter::KIND_HEAP
,
694 nsIMemoryReporter::UNITS_BYTES
,
697 "Memory used to back a memory file of length %llu bytes. The file "
698 "has a sha1 of %s.\n\n"
699 "Note that the allocator may round up a memory file's length -- "
700 "that is, an N-byte memory file may take up more than N bytes of "
702 owner
->mLength
, digestString
.get()),
704 NS_ENSURE_SUCCESS(rv
, rv
);
708 if (smallObjectsTotal
> 0) {
709 nsresult rv
= aCallback
->Callback(
710 /* process */ NS_LITERAL_CSTRING(""),
711 NS_LITERAL_CSTRING("explicit/dom/memory-file-data/small"),
712 nsIMemoryReporter::KIND_HEAP
,
713 nsIMemoryReporter::UNITS_BYTES
,
716 "Memory used to back small memory files (less than %d bytes each).\n\n"
717 "Note that the allocator may round up a memory file's length -- "
718 "that is, an N-byte memory file may take up more than N bytes of "
721 NS_ENSURE_SUCCESS(rv
, rv
);
729 nsDOMMemoryFile::DataOwner::EnsureMemoryReporterRegistered()
731 sDataOwnerMutex
.AssertCurrentThreadOwns();
732 if (sMemoryReporterRegistered
) {
736 RegisterStrongMemoryReporter(new nsDOMMemoryFileDataOwnerMemoryReporter());
738 sMemoryReporterRegistered
= true;
741 ////////////////////////////////////////////////////////////////////////////
742 // nsDOMFileList implementation
744 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(nsDOMFileList
)
746 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMFileList
)
747 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
748 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIDOMFileList
)
749 NS_INTERFACE_MAP_ENTRY(nsIDOMFileList
)
752 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMFileList
)
753 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMFileList
)
756 nsDOMFileList::WrapObject(JSContext
*cx
, JS::Handle
<JSObject
*> scope
)
758 return FileListBinding::Wrap(cx
, scope
, this);
762 nsDOMFileList::GetLength(uint32_t* aLength
)
770 nsDOMFileList::Item(uint32_t aIndex
, nsIDOMFile
**aFile
)
772 NS_IF_ADDREF(*aFile
= Item(aIndex
));
777 ////////////////////////////////////////////////////////////////////////////
778 // nsDOMFileInternalUrlHolder implementation
780 nsDOMFileInternalUrlHolder::nsDOMFileInternalUrlHolder(nsIDOMBlob
* aFile
,
781 nsIPrincipal
* aPrincipal
782 MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL
) {
783 MOZ_GUARD_OBJECT_NOTIFIER_INIT
;
784 aFile
->GetInternalUrl(aPrincipal
, mUrl
);
787 nsDOMFileInternalUrlHolder::~nsDOMFileInternalUrlHolder() {
788 if (!mUrl
.IsEmpty()) {
789 nsAutoCString narrowUrl
;
790 CopyUTF16toUTF8(mUrl
, narrowUrl
);
791 nsBlobProtocolHandler::RemoveDataEntry(narrowUrl
);
795 ////////////////////////////////////////////////////////////////////////////
796 // nsDOMTemporaryFileBlob implementation
797 already_AddRefed
<nsIDOMBlob
>
798 nsDOMTemporaryFileBlob::CreateSlice(uint64_t aStart
, uint64_t aLength
,
799 const nsAString
& aContentType
)
801 if (aStart
+ aLength
> mLength
)
804 nsCOMPtr
<nsIDOMBlob
> t
=
805 new nsDOMTemporaryFileBlob(this, aStart
+ mStartPos
, aLength
, aContentType
);
810 nsDOMTemporaryFileBlob::GetInternalStream(nsIInputStream
**aStream
)
812 nsCOMPtr
<nsTemporaryFileInputStream
> stream
=
813 new nsTemporaryFileInputStream(mFileDescOwner
, mStartPos
, mStartPos
+ mLength
);
814 stream
.forget(aStream
);