content/base/src/FileIOObject.cpp

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.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "FileIOObject.h"
michael@0 7 #include "mozilla/EventDispatcher.h"
michael@0 8 #include "nsDOMFile.h"
michael@0 9 #include "nsError.h"
michael@0 10 #include "nsIDOMEvent.h"
michael@0 11 #include "nsIDOMProgressEvent.h"
michael@0 12 #include "nsComponentManagerUtils.h"
michael@0 13
michael@0 14 #define ERROR_STR "error"
michael@0 15 #define ABORT_STR "abort"
michael@0 16 #define PROGRESS_STR "progress"
michael@0 17
michael@0 18 namespace mozilla {
michael@0 19 namespace dom {
michael@0 20
michael@0 21 const uint64_t kUnknownSize = uint64_t(-1);
michael@0 22
michael@0 23 NS_IMPL_ADDREF_INHERITED(FileIOObject, DOMEventTargetHelper)
michael@0 24 NS_IMPL_RELEASE_INHERITED(FileIOObject, DOMEventTargetHelper)
michael@0 25
michael@0 26 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(FileIOObject)
michael@0 27 NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
michael@0 28 NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
michael@0 29 NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
michael@0 30 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
michael@0 31
michael@0 32 NS_IMPL_CYCLE_COLLECTION_CLASS(FileIOObject)
michael@0 33
michael@0 34 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(FileIOObject,
michael@0 35 DOMEventTargetHelper)
michael@0 36 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mProgressNotifier)
michael@0 37 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mError)
michael@0 38 // Can't traverse mChannel because it's a multithreaded object.
michael@0 39 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
michael@0 40
michael@0 41 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(FileIOObject,
michael@0 42 DOMEventTargetHelper)
michael@0 43 NS_IMPL_CYCLE_COLLECTION_UNLINK(mProgressNotifier)
michael@0 44 NS_IMPL_CYCLE_COLLECTION_UNLINK(mError)
michael@0 45 NS_IMPL_CYCLE_COLLECTION_UNLINK(mChannel)
michael@0 46 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
michael@0 47
michael@0 48 NS_IMPL_EVENT_HANDLER(FileIOObject, abort)
michael@0 49 NS_IMPL_EVENT_HANDLER(FileIOObject, error)
michael@0 50 NS_IMPL_EVENT_HANDLER(FileIOObject, progress)
michael@0 51
michael@0 52 FileIOObject::FileIOObject()
michael@0 53 : mProgressEventWasDelayed(false),
michael@0 54 mTimerIsActive(false),
michael@0 55 mReadyState(0),
michael@0 56 mTotal(0), mTransferred(0)
michael@0 57 {}
michael@0 58
michael@0 59 void
michael@0 60 FileIOObject::StartProgressEventTimer()
michael@0 61 {
michael@0 62 if (!mProgressNotifier) {
michael@0 63 mProgressNotifier = do_CreateInstance(NS_TIMER_CONTRACTID);
michael@0 64 }
michael@0 65 if (mProgressNotifier) {
michael@0 66 mProgressEventWasDelayed = false;
michael@0 67 mTimerIsActive = true;
michael@0 68 mProgressNotifier->Cancel();
michael@0 69 mProgressNotifier->InitWithCallback(this, NS_PROGRESS_EVENT_INTERVAL,
michael@0 70 nsITimer::TYPE_ONE_SHOT);
michael@0 71 }
michael@0 72 }
michael@0 73
michael@0 74 void
michael@0 75 FileIOObject::ClearProgressEventTimer()
michael@0 76 {
michael@0 77 mProgressEventWasDelayed = false;
michael@0 78 mTimerIsActive = false;
michael@0 79 if (mProgressNotifier) {
michael@0 80 mProgressNotifier->Cancel();
michael@0 81 }
michael@0 82 }
michael@0 83
michael@0 84 void
michael@0 85 FileIOObject::DispatchError(nsresult rv, nsAString& finalEvent)
michael@0 86 {
michael@0 87 // Set the status attribute, and dispatch the error event
michael@0 88 switch (rv) {
michael@0 89 case NS_ERROR_FILE_NOT_FOUND:
michael@0 90 mError = new DOMError(GetOwner(), NS_LITERAL_STRING("NotFoundError"));
michael@0 91 break;
michael@0 92 case NS_ERROR_FILE_ACCESS_DENIED:
michael@0 93 mError = new DOMError(GetOwner(), NS_LITERAL_STRING("SecurityError"));
michael@0 94 break;
michael@0 95 default:
michael@0 96 mError = new DOMError(GetOwner(), NS_LITERAL_STRING("NotReadableError"));
michael@0 97 break;
michael@0 98 }
michael@0 99
michael@0 100 // Dispatch error event to signify load failure
michael@0 101 DispatchProgressEvent(NS_LITERAL_STRING(ERROR_STR));
michael@0 102 DispatchProgressEvent(finalEvent);
michael@0 103 }
michael@0 104
michael@0 105 nsresult
michael@0 106 FileIOObject::DispatchProgressEvent(const nsAString& aType)
michael@0 107 {
michael@0 108 nsCOMPtr<nsIDOMEvent> event;
michael@0 109 nsresult rv = NS_NewDOMProgressEvent(getter_AddRefs(event), this,
michael@0 110 nullptr, nullptr);
michael@0 111 NS_ENSURE_SUCCESS(rv, rv);
michael@0 112
michael@0 113 event->SetTrusted(true);
michael@0 114 nsCOMPtr<nsIDOMProgressEvent> progress = do_QueryInterface(event);
michael@0 115 NS_ENSURE_TRUE(progress, NS_ERROR_UNEXPECTED);
michael@0 116
michael@0 117 bool known;
michael@0 118 uint64_t size;
michael@0 119 if (mTotal != kUnknownSize) {
michael@0 120 known = true;
michael@0 121 size = mTotal;
michael@0 122 } else {
michael@0 123 known = false;
michael@0 124 size = 0;
michael@0 125 }
michael@0 126 rv = progress->InitProgressEvent(aType, false, false, known,
michael@0 127 mTransferred, size);
michael@0 128 NS_ENSURE_SUCCESS(rv, rv);
michael@0 129
michael@0 130 return DispatchDOMEvent(nullptr, event, nullptr, nullptr);
michael@0 131 }
michael@0 132
michael@0 133 // nsITimerCallback
michael@0 134 NS_IMETHODIMP
michael@0 135 FileIOObject::Notify(nsITimer* aTimer)
michael@0 136 {
michael@0 137 nsresult rv;
michael@0 138 mTimerIsActive = false;
michael@0 139
michael@0 140 if (mProgressEventWasDelayed) {
michael@0 141 rv = DispatchProgressEvent(NS_LITERAL_STRING("progress"));
michael@0 142 NS_ENSURE_SUCCESS(rv, rv);
michael@0 143
michael@0 144 StartProgressEventTimer();
michael@0 145 }
michael@0 146
michael@0 147 return NS_OK;
michael@0 148 }
michael@0 149
michael@0 150 // nsIStreamListener
michael@0 151 NS_IMETHODIMP
michael@0 152 FileIOObject::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
michael@0 153 {
michael@0 154 return DoOnStartRequest(aRequest, aContext);
michael@0 155 }
michael@0 156
michael@0 157 NS_IMETHODIMP
michael@0 158 FileIOObject::DoOnStartRequest(nsIRequest *request, nsISupports *ctxt)
michael@0 159 {
michael@0 160 return NS_OK;
michael@0 161 }
michael@0 162
michael@0 163 NS_IMETHODIMP
michael@0 164 FileIOObject::OnDataAvailable(nsIRequest *aRequest,
michael@0 165 nsISupports *aContext,
michael@0 166 nsIInputStream *aInputStream,
michael@0 167 uint64_t aOffset,
michael@0 168 uint32_t aCount)
michael@0 169 {
michael@0 170 nsresult rv;
michael@0 171 rv = DoOnDataAvailable(aRequest, aContext, aInputStream, aOffset, aCount);
michael@0 172 NS_ENSURE_SUCCESS(rv, rv);
michael@0 173
michael@0 174 mTransferred += aCount;
michael@0 175
michael@0 176 //Notify the timer is the appropriate timeframe has passed
michael@0 177 if (mTimerIsActive) {
michael@0 178 mProgressEventWasDelayed = true;
michael@0 179 } else {
michael@0 180 rv = DispatchProgressEvent(NS_LITERAL_STRING(PROGRESS_STR));
michael@0 181 NS_ENSURE_SUCCESS(rv, rv);
michael@0 182
michael@0 183 StartProgressEventTimer();
michael@0 184 }
michael@0 185
michael@0 186 return NS_OK;
michael@0 187 }
michael@0 188
michael@0 189 NS_IMETHODIMP
michael@0 190 FileIOObject::OnStopRequest(nsIRequest* aRequest, nsISupports* aContext,
michael@0 191 nsresult aStatus)
michael@0 192 {
michael@0 193 // If we're here as a result of a call from Abort(),
michael@0 194 // simply ignore the request.
michael@0 195 if (aRequest != mChannel)
michael@0 196 return NS_OK;
michael@0 197
michael@0 198 // Cancel the progress event timer
michael@0 199 ClearProgressEventTimer();
michael@0 200
michael@0 201 // FileIOObject must be in DONE stage after an operation
michael@0 202 mReadyState = 2;
michael@0 203
michael@0 204 nsString successEvent, termEvent;
michael@0 205 nsresult rv = DoOnStopRequest(aRequest, aContext, aStatus,
michael@0 206 successEvent, termEvent);
michael@0 207 NS_ENSURE_SUCCESS(rv, rv);
michael@0 208
michael@0 209 // Set the status field as appropriate
michael@0 210 if (NS_FAILED(aStatus)) {
michael@0 211 DispatchError(aStatus, termEvent);
michael@0 212 return NS_OK;
michael@0 213 }
michael@0 214
michael@0 215 // Dispatch event to signify end of a successful operation
michael@0 216 DispatchProgressEvent(successEvent);
michael@0 217 DispatchProgressEvent(termEvent);
michael@0 218
michael@0 219 return NS_OK;
michael@0 220 }
michael@0 221
michael@0 222 void
michael@0 223 FileIOObject::Abort(ErrorResult& aRv)
michael@0 224 {
michael@0 225 if (mReadyState != 1) {
michael@0 226 // XXX The spec doesn't say this
michael@0 227 aRv.Throw(NS_ERROR_DOM_FILE_ABORT_ERR);
michael@0 228 return;
michael@0 229 }
michael@0 230
michael@0 231 ClearProgressEventTimer();
michael@0 232
michael@0 233 mReadyState = 2; // There are DONE constants on multiple interfaces,
michael@0 234 // but they all have value 2.
michael@0 235 // XXX The spec doesn't say this
michael@0 236 mError = new DOMError(GetOwner(), NS_LITERAL_STRING("AbortError"));
michael@0 237
michael@0 238 nsString finalEvent;
michael@0 239 DoAbort(finalEvent);
michael@0 240
michael@0 241 // Dispatch the events
michael@0 242 DispatchProgressEvent(NS_LITERAL_STRING(ABORT_STR));
michael@0 243 DispatchProgressEvent(finalEvent);
michael@0 244 }
michael@0 245
michael@0 246 } // namespace dom
michael@0 247 } // namespace mozilla

mercurial