Thu, 15 Jan 2015 21:03:48 +0100
Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)
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 "nsIDOMProgressEvent.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(nsIStreamListener)
29 NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
30 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
32 NS_IMPL_CYCLE_COLLECTION_CLASS(FileIOObject)
34 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(FileIOObject,
35 DOMEventTargetHelper)
36 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mProgressNotifier)
37 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mError)
38 // Can't traverse mChannel because it's a multithreaded object.
39 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
41 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(FileIOObject,
42 DOMEventTargetHelper)
43 NS_IMPL_CYCLE_COLLECTION_UNLINK(mProgressNotifier)
44 NS_IMPL_CYCLE_COLLECTION_UNLINK(mError)
45 NS_IMPL_CYCLE_COLLECTION_UNLINK(mChannel)
46 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
48 NS_IMPL_EVENT_HANDLER(FileIOObject, abort)
49 NS_IMPL_EVENT_HANDLER(FileIOObject, error)
50 NS_IMPL_EVENT_HANDLER(FileIOObject, progress)
52 FileIOObject::FileIOObject()
53 : mProgressEventWasDelayed(false),
54 mTimerIsActive(false),
55 mReadyState(0),
56 mTotal(0), mTransferred(0)
57 {}
59 void
60 FileIOObject::StartProgressEventTimer()
61 {
62 if (!mProgressNotifier) {
63 mProgressNotifier = do_CreateInstance(NS_TIMER_CONTRACTID);
64 }
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);
71 }
72 }
74 void
75 FileIOObject::ClearProgressEventTimer()
76 {
77 mProgressEventWasDelayed = false;
78 mTimerIsActive = false;
79 if (mProgressNotifier) {
80 mProgressNotifier->Cancel();
81 }
82 }
84 void
85 FileIOObject::DispatchError(nsresult rv, nsAString& finalEvent)
86 {
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;
98 }
100 // Dispatch error event to signify load failure
101 DispatchProgressEvent(NS_LITERAL_STRING(ERROR_STR));
102 DispatchProgressEvent(finalEvent);
103 }
105 nsresult
106 FileIOObject::DispatchProgressEvent(const nsAString& aType)
107 {
108 nsCOMPtr<nsIDOMEvent> event;
109 nsresult rv = NS_NewDOMProgressEvent(getter_AddRefs(event), this,
110 nullptr, nullptr);
111 NS_ENSURE_SUCCESS(rv, rv);
113 event->SetTrusted(true);
114 nsCOMPtr<nsIDOMProgressEvent> progress = do_QueryInterface(event);
115 NS_ENSURE_TRUE(progress, NS_ERROR_UNEXPECTED);
117 bool known;
118 uint64_t size;
119 if (mTotal != kUnknownSize) {
120 known = true;
121 size = mTotal;
122 } else {
123 known = false;
124 size = 0;
125 }
126 rv = progress->InitProgressEvent(aType, false, false, known,
127 mTransferred, size);
128 NS_ENSURE_SUCCESS(rv, rv);
130 return DispatchDOMEvent(nullptr, event, nullptr, nullptr);
131 }
133 // nsITimerCallback
134 NS_IMETHODIMP
135 FileIOObject::Notify(nsITimer* aTimer)
136 {
137 nsresult rv;
138 mTimerIsActive = false;
140 if (mProgressEventWasDelayed) {
141 rv = DispatchProgressEvent(NS_LITERAL_STRING("progress"));
142 NS_ENSURE_SUCCESS(rv, rv);
144 StartProgressEventTimer();
145 }
147 return NS_OK;
148 }
150 // nsIStreamListener
151 NS_IMETHODIMP
152 FileIOObject::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
153 {
154 return DoOnStartRequest(aRequest, aContext);
155 }
157 NS_IMETHODIMP
158 FileIOObject::DoOnStartRequest(nsIRequest *request, nsISupports *ctxt)
159 {
160 return NS_OK;
161 }
163 NS_IMETHODIMP
164 FileIOObject::OnDataAvailable(nsIRequest *aRequest,
165 nsISupports *aContext,
166 nsIInputStream *aInputStream,
167 uint64_t aOffset,
168 uint32_t aCount)
169 {
170 nsresult rv;
171 rv = DoOnDataAvailable(aRequest, aContext, aInputStream, aOffset, aCount);
172 NS_ENSURE_SUCCESS(rv, rv);
174 mTransferred += aCount;
176 //Notify the timer is the appropriate timeframe has passed
177 if (mTimerIsActive) {
178 mProgressEventWasDelayed = true;
179 } else {
180 rv = DispatchProgressEvent(NS_LITERAL_STRING(PROGRESS_STR));
181 NS_ENSURE_SUCCESS(rv, rv);
183 StartProgressEventTimer();
184 }
186 return NS_OK;
187 }
189 NS_IMETHODIMP
190 FileIOObject::OnStopRequest(nsIRequest* aRequest, nsISupports* aContext,
191 nsresult aStatus)
192 {
193 // If we're here as a result of a call from Abort(),
194 // simply ignore the request.
195 if (aRequest != mChannel)
196 return NS_OK;
198 // Cancel the progress event timer
199 ClearProgressEventTimer();
201 // FileIOObject must be in DONE stage after an operation
202 mReadyState = 2;
204 nsString successEvent, termEvent;
205 nsresult rv = DoOnStopRequest(aRequest, aContext, aStatus,
206 successEvent, termEvent);
207 NS_ENSURE_SUCCESS(rv, rv);
209 // Set the status field as appropriate
210 if (NS_FAILED(aStatus)) {
211 DispatchError(aStatus, termEvent);
212 return NS_OK;
213 }
215 // Dispatch event to signify end of a successful operation
216 DispatchProgressEvent(successEvent);
217 DispatchProgressEvent(termEvent);
219 return NS_OK;
220 }
222 void
223 FileIOObject::Abort(ErrorResult& aRv)
224 {
225 if (mReadyState != 1) {
226 // XXX The spec doesn't say this
227 aRv.Throw(NS_ERROR_DOM_FILE_ABORT_ERR);
228 return;
229 }
231 ClearProgressEventTimer();
233 mReadyState = 2; // There are DONE constants on multiple interfaces,
234 // but they all have value 2.
235 // XXX The spec doesn't say this
236 mError = new DOMError(GetOwner(), NS_LITERAL_STRING("AbortError"));
238 nsString finalEvent;
239 DoAbort(finalEvent);
241 // Dispatch the events
242 DispatchProgressEvent(NS_LITERAL_STRING(ABORT_STR));
243 DispatchProgressEvent(finalEvent);
244 }
246 } // namespace dom
247 } // namespace mozilla