|
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* vim: set ts=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 file, |
|
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 #ifndef mozilla_dom_file_lockedfile_h__ |
|
8 #define mozilla_dom_file_lockedfile_h__ |
|
9 |
|
10 #include "FileCommon.h" |
|
11 #include "mozilla/Attributes.h" |
|
12 #include "mozilla/DOMEventTargetHelper.h" |
|
13 #include "mozilla/dom/FileModeBinding.h" |
|
14 #include "mozilla/dom/TypedArray.h" |
|
15 #include "nsIInputStream.h" |
|
16 #include "nsIRunnable.h" |
|
17 |
|
18 namespace mozilla { |
|
19 namespace dom { |
|
20 class DOMFileMetadataParameters; |
|
21 class DOMRequest; |
|
22 } // namespace dom |
|
23 } // namespace mozilla |
|
24 |
|
25 namespace mozilla { |
|
26 class EventChainPreVisitor; |
|
27 } // namespace mozilla |
|
28 |
|
29 BEGIN_FILE_NAMESPACE |
|
30 |
|
31 class FileHandle; |
|
32 class FileRequest; |
|
33 class MetadataHelper; |
|
34 |
|
35 class LockedFile : public DOMEventTargetHelper, |
|
36 public nsIRunnable |
|
37 { |
|
38 friend class FinishHelper; |
|
39 friend class FileService; |
|
40 friend class FileHelper; |
|
41 friend class MetadataHelper; |
|
42 |
|
43 public: |
|
44 NS_DECL_ISUPPORTS_INHERITED |
|
45 NS_DECL_NSIRUNNABLE |
|
46 |
|
47 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(LockedFile, DOMEventTargetHelper) |
|
48 |
|
49 enum RequestMode |
|
50 { |
|
51 NORMAL = 0, // Sequential |
|
52 PARALLEL |
|
53 }; |
|
54 |
|
55 enum ReadyState |
|
56 { |
|
57 INITIAL = 0, |
|
58 LOADING, |
|
59 FINISHING, |
|
60 DONE |
|
61 }; |
|
62 |
|
63 static already_AddRefed<LockedFile> |
|
64 Create(FileHandle* aFileHandle, |
|
65 FileMode aMode, |
|
66 RequestMode aRequestMode = NORMAL); |
|
67 |
|
68 // nsIDOMEventTarget |
|
69 virtual nsresult |
|
70 PreHandleEvent(EventChainPreVisitor& aVisitor) MOZ_OVERRIDE; |
|
71 |
|
72 nsresult |
|
73 CreateParallelStream(nsISupports** aStream); |
|
74 |
|
75 nsresult |
|
76 GetOrCreateStream(nsISupports** aStream); |
|
77 |
|
78 bool |
|
79 IsOpen() const; |
|
80 |
|
81 bool |
|
82 IsAborted() const |
|
83 { |
|
84 return mAborted; |
|
85 } |
|
86 |
|
87 FileHandle* |
|
88 Handle() const |
|
89 { |
|
90 return mFileHandle; |
|
91 } |
|
92 |
|
93 nsresult |
|
94 OpenInputStream(bool aWholeFile, uint64_t aStart, uint64_t aLength, |
|
95 nsIInputStream** aResult); |
|
96 |
|
97 // WrapperCache |
|
98 virtual JSObject* |
|
99 WrapObject(JSContext* aCx) MOZ_OVERRIDE; |
|
100 |
|
101 // WebIDL |
|
102 nsPIDOMWindow* |
|
103 GetParentObject() const |
|
104 { |
|
105 return GetOwner(); |
|
106 } |
|
107 |
|
108 FileHandle* |
|
109 GetFileHandle() const |
|
110 { |
|
111 MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!"); |
|
112 |
|
113 return Handle(); |
|
114 } |
|
115 |
|
116 FileMode |
|
117 Mode() const |
|
118 { |
|
119 MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!"); |
|
120 |
|
121 return mMode; |
|
122 } |
|
123 |
|
124 bool |
|
125 Active() const |
|
126 { |
|
127 MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!"); |
|
128 |
|
129 return IsOpen(); |
|
130 } |
|
131 |
|
132 Nullable<uint64_t> |
|
133 GetLocation() const |
|
134 { |
|
135 MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!"); |
|
136 |
|
137 if (mLocation == UINT64_MAX) { |
|
138 return Nullable<uint64_t>(); |
|
139 } |
|
140 |
|
141 return Nullable<uint64_t>(mLocation); |
|
142 } |
|
143 |
|
144 void |
|
145 SetLocation(const Nullable<uint64_t>& aLocation) |
|
146 { |
|
147 MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!"); |
|
148 |
|
149 // Null means the end-of-file. |
|
150 if (aLocation.IsNull()) { |
|
151 mLocation = UINT64_MAX; |
|
152 } else { |
|
153 mLocation = aLocation.Value(); |
|
154 } |
|
155 } |
|
156 |
|
157 already_AddRefed<FileRequest> |
|
158 GetMetadata(const DOMFileMetadataParameters& aParameters, ErrorResult& aRv); |
|
159 |
|
160 already_AddRefed<FileRequest> |
|
161 ReadAsArrayBuffer(uint64_t aSize, ErrorResult& aRv); |
|
162 |
|
163 already_AddRefed<FileRequest> |
|
164 ReadAsText(uint64_t aSize, const nsAString& aEncoding, ErrorResult& aRv); |
|
165 |
|
166 template<class T> |
|
167 already_AddRefed<FileRequest> |
|
168 Write(const T& aValue, ErrorResult& aRv) |
|
169 { |
|
170 MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!"); |
|
171 |
|
172 return WriteOrAppend(aValue, false, aRv); |
|
173 } |
|
174 |
|
175 template<class T> |
|
176 already_AddRefed<FileRequest> |
|
177 Append(const T& aValue, ErrorResult& aRv) |
|
178 { |
|
179 MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!"); |
|
180 |
|
181 return WriteOrAppend(aValue, true, aRv); |
|
182 } |
|
183 |
|
184 already_AddRefed<FileRequest> |
|
185 Truncate(const Optional<uint64_t>& aSize, ErrorResult& aRv); |
|
186 |
|
187 already_AddRefed<FileRequest> |
|
188 Flush(ErrorResult& aRv); |
|
189 |
|
190 void |
|
191 Abort(ErrorResult& aRv); |
|
192 |
|
193 IMPL_EVENT_HANDLER(complete) |
|
194 IMPL_EVENT_HANDLER(abort) |
|
195 IMPL_EVENT_HANDLER(error) |
|
196 |
|
197 private: |
|
198 LockedFile(); |
|
199 ~LockedFile(); |
|
200 |
|
201 void |
|
202 OnNewRequest(); |
|
203 |
|
204 void |
|
205 OnRequestFinished(); |
|
206 |
|
207 bool |
|
208 CheckState(ErrorResult& aRv); |
|
209 |
|
210 bool |
|
211 CheckStateAndArgumentsForRead(uint64_t aSize, ErrorResult& aRv); |
|
212 |
|
213 bool |
|
214 CheckStateForWrite(ErrorResult& aRv); |
|
215 |
|
216 already_AddRefed<FileRequest> |
|
217 GenerateFileRequest(); |
|
218 |
|
219 template<class T> |
|
220 already_AddRefed<FileRequest> |
|
221 WriteOrAppend(const T& aValue, bool aAppend, ErrorResult& aRv) |
|
222 { |
|
223 MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!"); |
|
224 |
|
225 // State checking for write |
|
226 if (!CheckStateForWrite(aRv)) { |
|
227 return nullptr; |
|
228 } |
|
229 |
|
230 // Additional state checking for write |
|
231 if (!aAppend && mLocation == UINT64_MAX) { |
|
232 aRv.Throw(NS_ERROR_DOM_FILEHANDLE_NOT_ALLOWED_ERR); |
|
233 return nullptr; |
|
234 } |
|
235 |
|
236 uint64_t length; |
|
237 nsCOMPtr<nsIInputStream> stream = GetInputStream(aValue, &length, aRv); |
|
238 if (aRv.Failed()) { |
|
239 return nullptr; |
|
240 } |
|
241 |
|
242 if (!length) { |
|
243 return nullptr; |
|
244 } |
|
245 |
|
246 // Do nothing if the window is closed |
|
247 if (!GetOwner()) { |
|
248 return nullptr; |
|
249 } |
|
250 |
|
251 return WriteInternal(stream, length, aAppend, aRv); |
|
252 } |
|
253 |
|
254 already_AddRefed<FileRequest> |
|
255 WriteInternal(nsIInputStream* aInputStream, uint64_t aInputLength, |
|
256 bool aAppend, ErrorResult& aRv); |
|
257 |
|
258 nsresult |
|
259 Finish(); |
|
260 |
|
261 static already_AddRefed<nsIInputStream> |
|
262 GetInputStream(const ArrayBuffer& aValue, uint64_t* aInputLength, |
|
263 ErrorResult& aRv); |
|
264 |
|
265 static already_AddRefed<nsIInputStream> |
|
266 GetInputStream(nsIDOMBlob* aValue, uint64_t* aInputLength, ErrorResult& aRv); |
|
267 |
|
268 static already_AddRefed<nsIInputStream> |
|
269 GetInputStream(const nsAString& aValue, uint64_t* aInputLength, |
|
270 ErrorResult& aRv); |
|
271 |
|
272 nsRefPtr<FileHandle> mFileHandle; |
|
273 ReadyState mReadyState; |
|
274 FileMode mMode; |
|
275 RequestMode mRequestMode; |
|
276 uint64_t mLocation; |
|
277 uint32_t mPendingRequests; |
|
278 |
|
279 nsTArray<nsCOMPtr<nsISupports> > mParallelStreams; |
|
280 nsCOMPtr<nsISupports> mStream; |
|
281 |
|
282 bool mAborted; |
|
283 bool mCreating; |
|
284 }; |
|
285 |
|
286 class FinishHelper MOZ_FINAL : public nsIRunnable |
|
287 { |
|
288 friend class LockedFile; |
|
289 |
|
290 public: |
|
291 NS_DECL_THREADSAFE_ISUPPORTS |
|
292 NS_DECL_NSIRUNNABLE |
|
293 |
|
294 private: |
|
295 FinishHelper(LockedFile* aLockedFile); |
|
296 ~FinishHelper() |
|
297 { } |
|
298 |
|
299 nsRefPtr<LockedFile> mLockedFile; |
|
300 nsTArray<nsCOMPtr<nsISupports> > mParallelStreams; |
|
301 nsCOMPtr<nsISupports> mStream; |
|
302 |
|
303 bool mAborted; |
|
304 }; |
|
305 |
|
306 END_FILE_NAMESPACE |
|
307 |
|
308 #endif // mozilla_dom_file_lockedfile_h__ |