1 /* -*- Mode: C++; tab-width: 8; 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/. */
6 
7 #ifndef mozilla_dom_FileBlobImpl_h
8 #define mozilla_dom_FileBlobImpl_h
9 
10 #include "mozilla/dom/BlobImpl.h"
11 #include "mozilla/Maybe.h"
12 #include "mozilla/Mutex.h"
13 
14 class nsIFile;
15 
16 namespace mozilla {
17 namespace dom {
18 
19 class FileBlobImpl : public BlobImpl {
20  public:
21   NS_INLINE_DECL_REFCOUNTING_INHERITED(FileBlobImpl, BlobImpl)
22 
23   // Create as a file
24   explicit FileBlobImpl(nsIFile* aFile);
25 
26   // Create as a file
27   FileBlobImpl(const nsAString& aName, const nsAString& aContentType,
28                uint64_t aLength, nsIFile* aFile);
29 
30   FileBlobImpl(const nsAString& aName, const nsAString& aContentType,
31                uint64_t aLength, nsIFile* aFile, int64_t aLastModificationDate);
32 
33   // Create as a file with custom name
34   FileBlobImpl(nsIFile* aFile, const nsAString& aName,
35                const nsAString& aContentType);
36 
GetName(nsAString & aName)37   void GetName(nsAString& aName) const override {
38     MOZ_ASSERT(mIsFile, "Should only be called on files");
39     aName = mName;
40   }
41 
SetName(const nsAString & aName)42   void SetName(const nsAString& aName) { mName = aName; }
43 
GetDOMPath(nsAString & aPath)44   void GetDOMPath(nsAString& aPath) const override {
45     MOZ_ASSERT(mIsFile, "Should only be called on files");
46     aPath = mPath;
47   }
48 
SetDOMPath(const nsAString & aPath)49   void SetDOMPath(const nsAString& aPath) override {
50     MOZ_ASSERT(mIsFile, "Should only be called on files");
51     mPath = aPath;
52   }
53 
54   int64_t GetLastModified(ErrorResult& aRv) override;
55 
GetMozFullPath(nsAString & aFileName,SystemCallerGuarantee,ErrorResult & aRv)56   void GetMozFullPath(nsAString& aFileName, SystemCallerGuarantee /* unused */,
57                       ErrorResult& aRv) override {
58     MOZ_ASSERT(mIsFile, "Should only be called on files");
59 
60     GetMozFullPathInternal(aFileName, aRv);
61   }
62 
63   void GetMozFullPathInternal(nsAString& aFilename, ErrorResult& aRv) override;
64 
65   uint64_t GetSize(ErrorResult& aRv) override;
66 
67   void GetType(nsAString& aType) override;
68 
69   virtual void GetBlobImplType(nsAString& aBlobImplType) const override;
70 
GetAllocationSize()71   size_t GetAllocationSize() const override { return 0; }
72 
GetAllocationSize(FallibleTArray<BlobImpl * > & aVisitedBlobImpls)73   size_t GetAllocationSize(
74       FallibleTArray<BlobImpl*>& aVisitedBlobImpls) const override {
75     return GetAllocationSize();
76   }
77 
GetSerialNumber()78   uint64_t GetSerialNumber() const override { return mSerialNumber; }
79 
GetSubBlobImpls()80   const nsTArray<RefPtr<BlobImpl>>* GetSubBlobImpls() const override {
81     return nullptr;
82   }
83 
84   virtual void CreateInputStream(nsIInputStream** aInputStream,
85                                  ErrorResult& aRv) override;
86 
GetFileId()87   int64_t GetFileId() override { return mFileId; }
88 
SetLazyData(const nsAString & aName,const nsAString & aContentType,uint64_t aLength,int64_t aLastModifiedDate)89   void SetLazyData(const nsAString& aName, const nsAString& aContentType,
90                    uint64_t aLength, int64_t aLastModifiedDate) override {
91     mName = aName;
92     mContentType = aContentType;
93     mIsFile = !aName.IsVoid();
94     mLength.emplace(aLength);
95     mLastModified.emplace(aLastModifiedDate);
96   }
97 
IsMemoryFile()98   bool IsMemoryFile() const override { return false; }
99 
IsFile()100   bool IsFile() const override { return mIsFile; }
101 
102   bool IsDirectory() const override;
103 
SetType(const nsAString & aType)104   void SetType(const nsAString& aType) { mContentType = aType; }
105 
SetFileId(int64_t aFileId)106   void SetFileId(int64_t aFileId) { mFileId = aFileId; }
107 
SetEmptySize()108   void SetEmptySize() { mLength.emplace(0); }
109 
SetMozFullPath(const nsAString & aPath)110   void SetMozFullPath(const nsAString& aPath) { mMozFullPath = aPath; }
111 
SetLastModified(int64_t aLastModified)112   void SetLastModified(int64_t aLastModified) {
113     mLastModified.emplace(aLastModified);
114   }
115 
116  protected:
117   ~FileBlobImpl() = default;
118 
119   // Create slice
120   FileBlobImpl(const FileBlobImpl* aOther, uint64_t aStart, uint64_t aLength,
121                const nsAString& aContentType);
122 
123   already_AddRefed<BlobImpl> CreateSlice(uint64_t aStart, uint64_t aLength,
124                                          const nsAString& aContentType,
125                                          ErrorResult& aRv) override;
126 
127   class GetTypeRunnable;
128   void GetTypeInternal(nsAString& aType, const MutexAutoLock& aProofOfLock);
129 
130   // FileBlobImpl has getter methods with lazy initialization. Because any
131   // BlobImpl must work thread-safe, we use a mutex.
132   Mutex mMutex;
133 
134   nsCOMPtr<nsIFile> mFile;
135 
136   nsString mContentType;
137   nsString mName;
138   nsString mPath;  // The path relative to a directory chosen by the user
139   nsString mMozFullPath;
140 
141   const uint64_t mSerialNumber;
142   uint64_t mStart;
143 
144   int64_t mFileId;
145 
146   Maybe<uint64_t> mLength;
147 
148   Maybe<int64_t> mLastModified;
149 
150   bool mIsFile;
151   bool mWholeFile;
152 };
153 
154 }  // namespace dom
155 }  // namespace mozilla
156 
157 #endif  // mozilla_dom_FileBlobImpl_h
158