content/base/public/nsDOMFile.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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/. */
     6 #ifndef nsDOMFile_h__
     7 #define nsDOMFile_h__
     9 #include "mozilla/Attributes.h"
    10 #include "nsICharsetDetectionObserver.h"
    11 #include "nsIFile.h"
    12 #include "nsIDOMFile.h"
    13 #include "nsIDOMFileList.h"
    14 #include "nsIInputStream.h"
    15 #include "nsIJSNativeInitializer.h"
    16 #include "nsIMutable.h"
    17 #include "nsCOMArray.h"
    18 #include "nsCOMPtr.h"
    19 #include "nsString.h"
    20 #include "nsIXMLHttpRequest.h"
    21 #include "nsAutoPtr.h"
    22 #include "nsFileStreams.h"
    23 #include "nsTemporaryFileInputStream.h"
    25 #include "mozilla/GuardObjects.h"
    26 #include "mozilla/LinkedList.h"
    27 #include <stdint.h>
    28 #include "mozilla/StaticMutex.h"
    29 #include "mozilla/StaticPtr.h"
    30 #include "mozilla/dom/DOMError.h"
    31 #include "mozilla/dom/indexedDB/FileInfo.h"
    32 #include "mozilla/dom/indexedDB/FileManager.h"
    33 #include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
    34 #include "nsWrapperCache.h"
    35 #include "nsCycleCollectionParticipant.h"
    37 class nsIFile;
    38 class nsIInputStream;
    39 class nsIClassInfo;
    41 class nsDOMFileBase : public nsIDOMFile,
    42                       public nsIXHRSendable,
    43                       public nsIMutable
    44 {
    45 public:
    46   typedef mozilla::dom::indexedDB::FileInfo FileInfo;
    48   virtual already_AddRefed<nsIDOMBlob>
    49   CreateSlice(uint64_t aStart, uint64_t aLength,
    50               const nsAString& aContentType) = 0;
    52   virtual const nsTArray<nsCOMPtr<nsIDOMBlob> >*
    53   GetSubBlobs() const { return nullptr; }
    55   NS_DECL_NSIDOMBLOB
    56   NS_DECL_NSIDOMFILE
    57   NS_DECL_NSIXHRSENDABLE
    58   NS_DECL_NSIMUTABLE
    60   void
    61   SetLazyData(const nsAString& aName, const nsAString& aContentType,
    62               uint64_t aLength, uint64_t aLastModifiedDate)
    63   {
    64     NS_ASSERTION(aLength, "must have length");
    66     mName = aName;
    67     mContentType = aContentType;
    68     mLength = aLength;
    69     mLastModificationDate = aLastModifiedDate;
    70     mIsFile = !aName.IsVoid();
    71   }
    73   bool IsSizeUnknown() const
    74   {
    75     return mLength == UINT64_MAX;
    76   }
    78   bool IsDateUnknown() const
    79   {
    80     return mIsFile && mLastModificationDate == UINT64_MAX;
    81   }
    83 protected:
    84   nsDOMFileBase(const nsAString& aName, const nsAString& aContentType,
    85                 uint64_t aLength, uint64_t aLastModifiedDate)
    86     : mIsFile(true), mImmutable(false), mContentType(aContentType),
    87       mName(aName), mStart(0), mLength(aLength), mLastModificationDate(aLastModifiedDate)
    88   {
    89     // Ensure non-null mContentType by default
    90     mContentType.SetIsVoid(false);
    91   }
    93   nsDOMFileBase(const nsAString& aName, const nsAString& aContentType,
    94                 uint64_t aLength)
    95     : mIsFile(true), mImmutable(false), mContentType(aContentType),
    96       mName(aName), mStart(0), mLength(aLength), mLastModificationDate(UINT64_MAX)
    97   {
    98     // Ensure non-null mContentType by default
    99     mContentType.SetIsVoid(false);
   100   }
   102   nsDOMFileBase(const nsAString& aContentType, uint64_t aLength)
   103     : mIsFile(false), mImmutable(false), mContentType(aContentType),
   104       mStart(0), mLength(aLength), mLastModificationDate(UINT64_MAX)
   105   {
   106     // Ensure non-null mContentType by default
   107     mContentType.SetIsVoid(false);
   108   }
   110   nsDOMFileBase(const nsAString& aContentType, uint64_t aStart,
   111                 uint64_t aLength)
   112     : mIsFile(false), mImmutable(false), mContentType(aContentType),
   113       mStart(aStart), mLength(aLength), mLastModificationDate(UINT64_MAX)
   114   {
   115     NS_ASSERTION(aLength != UINT64_MAX,
   116                  "Must know length when creating slice");
   117     // Ensure non-null mContentType by default
   118     mContentType.SetIsVoid(false);
   119   }
   121   virtual ~nsDOMFileBase() {}
   123   virtual bool IsStoredFile() const
   124   {
   125     return false;
   126   }
   128   virtual bool IsWholeFile() const
   129   {
   130     NS_NOTREACHED("Should only be called on dom blobs backed by files!");
   131     return false;
   132   }
   134   virtual bool IsSnapshot() const
   135   {
   136     return false;
   137   }
   139   FileInfo* GetFileInfo() const
   140   {
   141     NS_ASSERTION(IsStoredFile(), "Should only be called on stored files!");
   142     NS_ASSERTION(!mFileInfos.IsEmpty(), "Must have at least one file info!");
   144     return mFileInfos.ElementAt(0);
   145   }
   147   bool mIsFile;
   148   bool mImmutable;
   150   nsString mContentType;
   151   nsString mName;
   152   nsString mPath; // The path relative to a directory chosen by the user
   154   uint64_t mStart;
   155   uint64_t mLength;
   157   uint64_t mLastModificationDate;
   159   // Protected by IndexedDatabaseManager::FileMutex()
   160   nsTArray<nsRefPtr<FileInfo> > mFileInfos;
   161 };
   163 class nsDOMFile : public nsDOMFileBase
   164 {
   165 public:
   166   nsDOMFile(const nsAString& aName, const nsAString& aContentType,
   167             uint64_t aLength, uint64_t aLastModifiedDate)
   168   : nsDOMFileBase(aName, aContentType, aLength, aLastModifiedDate)
   169   { }
   171   nsDOMFile(const nsAString& aName, const nsAString& aContentType,
   172             uint64_t aLength)
   173   : nsDOMFileBase(aName, aContentType, aLength)
   174   { }
   176   nsDOMFile(const nsAString& aContentType, uint64_t aLength)
   177   : nsDOMFileBase(aContentType, aLength)
   178   { }
   180   nsDOMFile(const nsAString& aContentType, uint64_t aStart, uint64_t aLength)
   181   : nsDOMFileBase(aContentType, aStart, aLength)
   182   { }
   184   NS_DECL_THREADSAFE_ISUPPORTS
   185 };
   187 class nsDOMFileCC : public nsDOMFileBase
   188 {
   189 public:
   190   nsDOMFileCC(const nsAString& aName, const nsAString& aContentType,
   191               uint64_t aLength)
   192   : nsDOMFileBase(aName, aContentType, aLength)
   193   { }
   195   nsDOMFileCC(const nsAString& aContentType, uint64_t aLength)
   196   : nsDOMFileBase(aContentType, aLength)
   197   { }
   199   nsDOMFileCC(const nsAString& aContentType, uint64_t aStart, uint64_t aLength)
   200   : nsDOMFileBase(aContentType, aStart, aLength)
   201   { }
   203   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   205   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsDOMFileCC, nsIDOMFile)
   206 };
   208 class nsDOMFileFile : public nsDOMFile
   209 {
   210 public:
   211   // Create as a file
   212   nsDOMFileFile(nsIFile *aFile)
   213     : nsDOMFile(EmptyString(), EmptyString(), UINT64_MAX, UINT64_MAX),
   214       mFile(aFile), mWholeFile(true), mStoredFile(false)
   215   {
   216     NS_ASSERTION(mFile, "must have file");
   217     // Lazily get the content type and size
   218     mContentType.SetIsVoid(true);
   219     mFile->GetLeafName(mName);
   220   }
   222   nsDOMFileFile(nsIFile *aFile, FileInfo *aFileInfo)
   223     : nsDOMFile(EmptyString(), EmptyString(), UINT64_MAX, UINT64_MAX),
   224       mFile(aFile), mWholeFile(true), mStoredFile(true)
   225   {
   226     NS_ASSERTION(mFile, "must have file");
   227     NS_ASSERTION(aFileInfo, "must have file info");
   228     // Lazily get the content type and size
   229     mContentType.SetIsVoid(true);
   230     mFile->GetLeafName(mName);
   232     mFileInfos.AppendElement(aFileInfo);
   233   }
   235   // Create as a file
   236   nsDOMFileFile(const nsAString& aName, const nsAString& aContentType,
   237                 uint64_t aLength, nsIFile *aFile)
   238     : nsDOMFile(aName, aContentType, aLength, UINT64_MAX),
   239       mFile(aFile), mWholeFile(true), mStoredFile(false)
   240   {
   241     NS_ASSERTION(mFile, "must have file");
   242   }
   244   nsDOMFileFile(const nsAString& aName, const nsAString& aContentType,
   245                 uint64_t aLength, nsIFile *aFile, uint64_t aLastModificationDate)
   246     : nsDOMFile(aName, aContentType, aLength, aLastModificationDate),
   247       mFile(aFile), mWholeFile(true), mStoredFile(false)
   248   {
   249     NS_ASSERTION(mFile, "must have file");
   250   }
   252   // Create as a file with custom name
   253   nsDOMFileFile(nsIFile *aFile, const nsAString& aName,
   254                 const nsAString& aContentType)
   255     : nsDOMFile(aName, aContentType, UINT64_MAX, UINT64_MAX),
   256       mFile(aFile), mWholeFile(true), mStoredFile(false)
   257   {
   258     NS_ASSERTION(mFile, "must have file");
   259     if (aContentType.IsEmpty()) {
   260       // Lazily get the content type and size
   261       mContentType.SetIsVoid(true);
   262     }
   263   }
   265   // Create as a stored file
   266   nsDOMFileFile(const nsAString& aName, const nsAString& aContentType,
   267                 uint64_t aLength, nsIFile* aFile,
   268                 FileInfo* aFileInfo)
   269     : nsDOMFile(aName, aContentType, aLength, UINT64_MAX),
   270       mFile(aFile), mWholeFile(true), mStoredFile(true)
   271   {
   272     NS_ASSERTION(mFile, "must have file");
   273     mFileInfos.AppendElement(aFileInfo);
   274   }
   276   // Create as a stored blob
   277   nsDOMFileFile(const nsAString& aContentType, uint64_t aLength,
   278                 nsIFile* aFile, FileInfo* aFileInfo)
   279     : nsDOMFile(aContentType, aLength),
   280       mFile(aFile), mWholeFile(true), mStoredFile(true)
   281   {
   282     NS_ASSERTION(mFile, "must have file");
   283     mFileInfos.AppendElement(aFileInfo);
   284   }
   286   // Create as a file to be later initialized
   287   nsDOMFileFile()
   288     : nsDOMFile(EmptyString(), EmptyString(), UINT64_MAX, UINT64_MAX),
   289       mWholeFile(true), mStoredFile(false)
   290   {
   291     // Lazily get the content type and size
   292     mContentType.SetIsVoid(true);
   293     mName.SetIsVoid(true);
   294   }
   296   // Overrides
   297   NS_IMETHOD GetSize(uint64_t* aSize) MOZ_OVERRIDE;
   298   NS_IMETHOD GetType(nsAString& aType) MOZ_OVERRIDE;
   299   NS_IMETHOD GetLastModifiedDate(JSContext* cx, JS::MutableHandle<JS::Value> aLastModifiedDate) MOZ_OVERRIDE;
   300   NS_IMETHOD GetMozLastModifiedDate(uint64_t* aLastModifiedDate) MOZ_OVERRIDE;
   301   NS_IMETHOD GetMozFullPathInternal(nsAString& aFullPath) MOZ_OVERRIDE;
   302   NS_IMETHOD GetInternalStream(nsIInputStream**) MOZ_OVERRIDE;
   304   void SetPath(const nsAString& aFullPath);
   306 protected:
   307   // Create slice
   308   nsDOMFileFile(const nsDOMFileFile* aOther, uint64_t aStart, uint64_t aLength,
   309                 const nsAString& aContentType)
   310     : nsDOMFile(aContentType, aOther->mStart + aStart, aLength),
   311       mFile(aOther->mFile), mWholeFile(false),
   312       mStoredFile(aOther->mStoredFile)
   313   {
   314     NS_ASSERTION(mFile, "must have file");
   315     mImmutable = aOther->mImmutable;
   317     if (mStoredFile) {
   318       FileInfo* fileInfo;
   320       using mozilla::dom::indexedDB::IndexedDatabaseManager;
   322       if (IndexedDatabaseManager::IsClosed()) {
   323         fileInfo = aOther->GetFileInfo();
   324       }
   325       else {
   326         mozilla::MutexAutoLock lock(IndexedDatabaseManager::FileMutex());
   327         fileInfo = aOther->GetFileInfo();
   328       }
   330       mFileInfos.AppendElement(fileInfo);
   331     }
   332   }
   334   virtual already_AddRefed<nsIDOMBlob>
   335   CreateSlice(uint64_t aStart, uint64_t aLength,
   336               const nsAString& aContentType) MOZ_OVERRIDE;
   338   virtual bool IsStoredFile() const MOZ_OVERRIDE
   339   {
   340     return mStoredFile;
   341   }
   343   virtual bool IsWholeFile() const MOZ_OVERRIDE
   344   {
   345     return mWholeFile;
   346   }
   348   nsCOMPtr<nsIFile> mFile;
   349   bool mWholeFile;
   350   bool mStoredFile;
   351 };
   353 /**
   354  * This class may be used off the main thread, and in particular, its
   355  * constructor and destructor may not run on the same thread.  Be careful!
   356  */
   357 class nsDOMMemoryFile : public nsDOMFile
   358 {
   359 public:
   360   // Create as file
   361   nsDOMMemoryFile(void *aMemoryBuffer,
   362                   uint64_t aLength,
   363                   const nsAString& aName,
   364                   const nsAString& aContentType)
   365     : nsDOMFile(aName, aContentType, aLength, UINT64_MAX),
   366       mDataOwner(new DataOwner(aMemoryBuffer, aLength))
   367   {
   368     NS_ASSERTION(mDataOwner && mDataOwner->mData, "must have data");
   369   }
   371   // Create as blob
   372   nsDOMMemoryFile(void *aMemoryBuffer,
   373                   uint64_t aLength,
   374                   const nsAString& aContentType)
   375     : nsDOMFile(aContentType, aLength),
   376       mDataOwner(new DataOwner(aMemoryBuffer, aLength))
   377   {
   378     NS_ASSERTION(mDataOwner && mDataOwner->mData, "must have data");
   379   }
   381   NS_IMETHOD GetInternalStream(nsIInputStream**) MOZ_OVERRIDE;
   383   NS_IMETHOD_(bool) IsMemoryFile(void) MOZ_OVERRIDE;
   385 protected:
   386   // Create slice
   387   nsDOMMemoryFile(const nsDOMMemoryFile* aOther, uint64_t aStart,
   388                   uint64_t aLength, const nsAString& aContentType)
   389     : nsDOMFile(aContentType, aOther->mStart + aStart, aLength),
   390       mDataOwner(aOther->mDataOwner)
   391   {
   392     NS_ASSERTION(mDataOwner && mDataOwner->mData, "must have data");
   393     mImmutable = aOther->mImmutable;
   394   }
   395   virtual already_AddRefed<nsIDOMBlob>
   396   CreateSlice(uint64_t aStart, uint64_t aLength,
   397               const nsAString& aContentType) MOZ_OVERRIDE;
   399   // These classes need to see DataOwner.
   400   friend class DataOwnerAdapter;
   401   friend class nsDOMMemoryFileDataOwnerMemoryReporter;
   403   class DataOwner MOZ_FINAL : public mozilla::LinkedListElement<DataOwner> {
   404   public:
   405     NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DataOwner)
   406     DataOwner(void* aMemoryBuffer, uint64_t aLength)
   407       : mData(aMemoryBuffer)
   408       , mLength(aLength)
   409     {
   410       mozilla::StaticMutexAutoLock lock(sDataOwnerMutex);
   412       if (!sDataOwners) {
   413         sDataOwners = new mozilla::LinkedList<DataOwner>();
   414         EnsureMemoryReporterRegistered();
   415       }
   416       sDataOwners->insertBack(this);
   417     }
   419   private:
   420     // Private destructor, to discourage deletion outside of Release():
   421     ~DataOwner() {
   422       mozilla::StaticMutexAutoLock lock(sDataOwnerMutex);
   424       remove();
   425       if (sDataOwners->isEmpty()) {
   426         // Free the linked list if it's empty.
   427         sDataOwners = nullptr;
   428       }
   430       moz_free(mData);
   431     }
   433   public:
   434     static void EnsureMemoryReporterRegistered();
   436     // sDataOwners and sMemoryReporterRegistered may only be accessed while
   437     // holding sDataOwnerMutex!  You also must hold the mutex while touching
   438     // elements of the linked list that DataOwner inherits from.
   439     static mozilla::StaticMutex sDataOwnerMutex;
   440     static mozilla::StaticAutoPtr<mozilla::LinkedList<DataOwner> > sDataOwners;
   441     static bool sMemoryReporterRegistered;
   443     void* mData;
   444     uint64_t mLength;
   445   };
   447   // Used when backed by a memory store
   448   nsRefPtr<DataOwner> mDataOwner;
   449 };
   451 class nsDOMFileList MOZ_FINAL : public nsIDOMFileList,
   452                                 public nsWrapperCache
   453 {
   454 public:
   455   nsDOMFileList(nsISupports *aParent) : mParent(aParent)
   456   {
   457     SetIsDOMBinding();
   458   }
   460   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   461   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsDOMFileList)
   463   NS_DECL_NSIDOMFILELIST
   465   virtual JSObject* WrapObject(JSContext *cx) MOZ_OVERRIDE;
   467   nsISupports* GetParentObject()
   468   {
   469     return mParent;
   470   }
   472   void Disconnect()
   473   {
   474     mParent = nullptr;
   475   }
   477   bool Append(nsIDOMFile *aFile) { return mFiles.AppendObject(aFile); }
   479   bool Remove(uint32_t aIndex) { return mFiles.RemoveObjectAt(aIndex); }
   480   void Clear() { return mFiles.Clear(); }
   482   static nsDOMFileList* FromSupports(nsISupports* aSupports)
   483   {
   484 #ifdef DEBUG
   485     {
   486       nsCOMPtr<nsIDOMFileList> list_qi = do_QueryInterface(aSupports);
   488       // If this assertion fires the QI implementation for the object in
   489       // question doesn't use the nsIDOMFileList pointer as the nsISupports
   490       // pointer. That must be fixed, or we'll crash...
   491       NS_ASSERTION(list_qi == static_cast<nsIDOMFileList*>(aSupports),
   492                    "Uh, fix QI!");
   493     }
   494 #endif
   496     return static_cast<nsDOMFileList*>(aSupports);
   497   }
   499   nsIDOMFile* Item(uint32_t aIndex)
   500   {
   501     return mFiles.SafeObjectAt(aIndex);
   502   }
   503   nsIDOMFile* IndexedGetter(uint32_t aIndex, bool& aFound)
   504   {
   505     aFound = aIndex < static_cast<uint32_t>(mFiles.Count());
   506     return aFound ? mFiles.ObjectAt(aIndex) : nullptr;
   507   }
   508   uint32_t Length()
   509   {
   510     return mFiles.Count();
   511   }
   513 private:
   514   nsCOMArray<nsIDOMFile> mFiles;
   515   nsISupports *mParent;
   516 };
   518 class MOZ_STACK_CLASS nsDOMFileInternalUrlHolder {
   519 public:
   520   nsDOMFileInternalUrlHolder(nsIDOMBlob* aFile, nsIPrincipal* aPrincipal
   521                              MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
   522   ~nsDOMFileInternalUrlHolder();
   523   nsAutoString mUrl;
   524 private:
   525   MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
   526 };
   527 // This class would take the ownership of aFD and the caller must not close it.
   528 class nsDOMTemporaryFileBlob : public nsDOMFile
   529 {
   530 public:
   531   nsDOMTemporaryFileBlob(PRFileDesc* aFD, uint64_t aStartPos, uint64_t aLength,
   532                          const nsAString& aContentType)
   533     : nsDOMFile(aContentType, aLength),
   534       mLength(aLength),
   535       mStartPos(aStartPos),
   536       mContentType(aContentType)
   537   {
   538     mFileDescOwner = new nsTemporaryFileInputStream::FileDescOwner(aFD);
   539   }
   541   ~nsDOMTemporaryFileBlob() { }
   542   NS_IMETHOD GetInternalStream(nsIInputStream**) MOZ_OVERRIDE;
   544 protected:
   545   nsDOMTemporaryFileBlob(const nsDOMTemporaryFileBlob* aOther, uint64_t aStart, uint64_t aLength,
   546                          const nsAString& aContentType)
   547     : nsDOMFile(aContentType, aLength),
   548       mLength(aLength),
   549       mStartPos(aStart),
   550       mFileDescOwner(aOther->mFileDescOwner),
   551       mContentType(aContentType) { }
   553   virtual already_AddRefed<nsIDOMBlob>
   554   CreateSlice(uint64_t aStart, uint64_t aLength,
   555               const nsAString& aContentType) MOZ_OVERRIDE;
   557 private:
   558   uint64_t mLength;
   559   uint64_t mStartPos;
   560   nsRefPtr<nsTemporaryFileInputStream::FileDescOwner> mFileDescOwner;
   561   nsString mContentType;
   562 };
   564 #endif

mercurial