Bumping gaia.json for 2 gaia revision(s) a=gaia-bump
[gecko.git] / content / base / src / FileIOObject.cpp
blob8f60b45a72a3d9b133c2091a5eaecdfd3fa5a509
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 #include "FileIOObject.h"
7 #include "mozilla/EventDispatcher.h"
8 #include "nsDOMFile.h"
9 #include "nsError.h"
10 #include "nsIDOMEvent.h"
11 #include "mozilla/dom/ProgressEvent.h"
12 #include "nsComponentManagerUtils.h"
14 #define ERROR_STR "error"
15 #define ABORT_STR "abort"
16 #define PROGRESS_STR "progress"
18 namespace mozilla {
19 namespace dom {
21 const uint64_t kUnknownSize = uint64_t(-1);
23 NS_IMPL_ADDREF_INHERITED(FileIOObject, DOMEventTargetHelper)
24 NS_IMPL_RELEASE_INHERITED(FileIOObject, DOMEventTargetHelper)
26 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(FileIOObject)
27 NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
28 NS_INTERFACE_MAP_ENTRY(nsIInputStreamCallback)
29 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
31 NS_IMPL_CYCLE_COLLECTION_CLASS(FileIOObject)
33 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(FileIOObject,
34 DOMEventTargetHelper)
35 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mProgressNotifier)
36 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mError)
37 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
39 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(FileIOObject,
40 DOMEventTargetHelper)
41 NS_IMPL_CYCLE_COLLECTION_UNLINK(mProgressNotifier)
42 NS_IMPL_CYCLE_COLLECTION_UNLINK(mError)
43 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
45 NS_IMPL_EVENT_HANDLER(FileIOObject, abort)
46 NS_IMPL_EVENT_HANDLER(FileIOObject, error)
47 NS_IMPL_EVENT_HANDLER(FileIOObject, progress)
49 FileIOObject::FileIOObject()
50 : mProgressEventWasDelayed(false),
51 mTimerIsActive(false),
52 mReadyState(0),
53 mTotal(0), mTransferred(0)
56 FileIOObject::~FileIOObject()
59 void
60 FileIOObject::StartProgressEventTimer()
62 if (!mProgressNotifier) {
63 mProgressNotifier = do_CreateInstance(NS_TIMER_CONTRACTID);
65 if (mProgressNotifier) {
66 mProgressEventWasDelayed = false;
67 mTimerIsActive = true;
68 mProgressNotifier->Cancel();
69 mProgressNotifier->InitWithCallback(this, NS_PROGRESS_EVENT_INTERVAL,
70 nsITimer::TYPE_ONE_SHOT);
74 void
75 FileIOObject::ClearProgressEventTimer()
77 mProgressEventWasDelayed = false;
78 mTimerIsActive = false;
79 if (mProgressNotifier) {
80 mProgressNotifier->Cancel();
84 void
85 FileIOObject::DispatchError(nsresult rv, nsAString& finalEvent)
87 // Set the status attribute, and dispatch the error event
88 switch (rv) {
89 case NS_ERROR_FILE_NOT_FOUND:
90 mError = new DOMError(GetOwner(), NS_LITERAL_STRING("NotFoundError"));
91 break;
92 case NS_ERROR_FILE_ACCESS_DENIED:
93 mError = new DOMError(GetOwner(), NS_LITERAL_STRING("SecurityError"));
94 break;
95 default:
96 mError = new DOMError(GetOwner(), NS_LITERAL_STRING("NotReadableError"));
97 break;
100 // Dispatch error event to signify load failure
101 DispatchProgressEvent(NS_LITERAL_STRING(ERROR_STR));
102 DispatchProgressEvent(finalEvent);
105 nsresult
106 FileIOObject::DispatchProgressEvent(const nsAString& aType)
108 ProgressEventInit init;
109 init.mBubbles = false;
110 init.mCancelable = false;
111 init.mLoaded = mTransferred;
113 if (mTotal != kUnknownSize) {
114 init.mLengthComputable = true;
115 init.mTotal = mTotal;
116 } else {
117 init.mLengthComputable = false;
118 init.mTotal = 0;
120 nsRefPtr<ProgressEvent> event =
121 ProgressEvent::Constructor(this, aType, init);
122 event->SetTrusted(true);
124 return DispatchDOMEvent(nullptr, event, nullptr, nullptr);
127 // nsITimerCallback
128 NS_IMETHODIMP
129 FileIOObject::Notify(nsITimer* aTimer)
131 nsresult rv;
132 mTimerIsActive = false;
134 if (mProgressEventWasDelayed) {
135 rv = DispatchProgressEvent(NS_LITERAL_STRING("progress"));
136 NS_ENSURE_SUCCESS(rv, rv);
138 StartProgressEventTimer();
141 return NS_OK;
144 // InputStreamCallback
145 NS_IMETHODIMP
146 FileIOObject::OnInputStreamReady(nsIAsyncInputStream* aStream)
148 if (mReadyState != 1 || aStream != mAsyncStream) {
149 return NS_OK;
152 uint64_t aCount;
153 nsresult rv = aStream->Available(&aCount);
155 if (NS_SUCCEEDED(rv) && aCount) {
156 rv = DoReadData(aStream, aCount);
159 if (NS_SUCCEEDED(rv)) {
160 rv = DoAsyncWait(aStream);
163 if (NS_FAILED(rv) || !aCount) {
164 if (rv == NS_BASE_STREAM_CLOSED) {
165 rv = NS_OK;
167 return OnLoadEnd(rv);
170 mTransferred += aCount;
172 //Notify the timer is the appropriate timeframe has passed
173 if (mTimerIsActive) {
174 mProgressEventWasDelayed = true;
175 } else {
176 rv = DispatchProgressEvent(NS_LITERAL_STRING(PROGRESS_STR));
177 NS_ENSURE_SUCCESS(rv, rv);
179 StartProgressEventTimer();
182 return NS_OK;
185 nsresult
186 FileIOObject::OnLoadEnd(nsresult aStatus)
188 // Cancel the progress event timer
189 ClearProgressEventTimer();
191 // FileIOObject must be in DONE stage after an operation
192 mReadyState = 2;
194 nsString successEvent, termEvent;
195 nsresult rv = DoOnLoadEnd(aStatus, successEvent, termEvent);
196 NS_ENSURE_SUCCESS(rv, rv);
198 // Set the status field as appropriate
199 if (NS_FAILED(aStatus)) {
200 DispatchError(aStatus, termEvent);
201 return NS_OK;
204 // Dispatch event to signify end of a successful operation
205 DispatchProgressEvent(successEvent);
206 DispatchProgressEvent(termEvent);
208 return NS_OK;
211 nsresult
212 FileIOObject::DoAsyncWait(nsIAsyncInputStream* aStream)
214 return aStream->AsyncWait(this,
215 /* aFlags*/ 0,
216 /* aRequestedCount */ 0,
217 NS_GetCurrentThread());
220 void
221 FileIOObject::Abort(ErrorResult& aRv)
223 if (mReadyState != 1) {
224 // XXX The spec doesn't say this
225 aRv.Throw(NS_ERROR_DOM_FILE_ABORT_ERR);
226 return;
229 ClearProgressEventTimer();
231 mReadyState = 2; // There are DONE constants on multiple interfaces,
232 // but they all have value 2.
233 // XXX The spec doesn't say this
234 mError = new DOMError(GetOwner(), NS_LITERAL_STRING("AbortError"));
236 nsString finalEvent;
237 DoAbort(finalEvent);
239 // Dispatch the events
240 DispatchProgressEvent(NS_LITERAL_STRING(ABORT_STR));
241 DispatchProgressEvent(finalEvent);
244 } // namespace dom
245 } // namespace mozilla