content/base/src/nsDOMFileReader.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 "nsDOMFileReader.h"
michael@0 7
michael@0 8 #include "nsContentCID.h"
michael@0 9 #include "nsContentUtils.h"
michael@0 10 #include "nsDOMClassInfoID.h"
michael@0 11 #include "nsDOMFile.h"
michael@0 12 #include "nsError.h"
michael@0 13 #include "nsIConverterInputStream.h"
michael@0 14 #include "nsIDocument.h"
michael@0 15 #include "nsIFile.h"
michael@0 16 #include "nsIFileStreams.h"
michael@0 17 #include "nsIInputStream.h"
michael@0 18 #include "nsIMIMEService.h"
michael@0 19 #include "nsIUnicodeDecoder.h"
michael@0 20 #include "nsNetCID.h"
michael@0 21 #include "nsNetUtil.h"
michael@0 22
michael@0 23 #include "nsLayoutCID.h"
michael@0 24 #include "nsXPIDLString.h"
michael@0 25 #include "nsReadableUtils.h"
michael@0 26 #include "nsIURI.h"
michael@0 27 #include "nsStreamUtils.h"
michael@0 28 #include "nsXPCOM.h"
michael@0 29 #include "nsIDOMEventListener.h"
michael@0 30 #include "nsJSEnvironment.h"
michael@0 31 #include "nsIScriptGlobalObject.h"
michael@0 32 #include "nsCExternalHandlerService.h"
michael@0 33 #include "nsIStreamConverterService.h"
michael@0 34 #include "nsCycleCollectionParticipant.h"
michael@0 35 #include "nsIScriptObjectPrincipal.h"
michael@0 36 #include "nsHostObjectProtocolHandler.h"
michael@0 37 #include "mozilla/Base64.h"
michael@0 38 #include "mozilla/DOMEventTargetHelper.h"
michael@0 39 #include "mozilla/Preferences.h"
michael@0 40 #include "mozilla/dom/EncodingUtils.h"
michael@0 41 #include "mozilla/dom/FileReaderBinding.h"
michael@0 42 #include "xpcpublic.h"
michael@0 43 #include "nsIScriptSecurityManager.h"
michael@0 44 #include "nsDOMJSUtils.h"
michael@0 45
michael@0 46 #include "jsfriendapi.h"
michael@0 47
michael@0 48 using namespace mozilla;
michael@0 49 using namespace mozilla::dom;
michael@0 50
michael@0 51 #define LOAD_STR "load"
michael@0 52 #define LOADSTART_STR "loadstart"
michael@0 53 #define LOADEND_STR "loadend"
michael@0 54
michael@0 55 NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMFileReader)
michael@0 56
michael@0 57 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMFileReader,
michael@0 58 FileIOObject)
michael@0 59 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFile)
michael@0 60 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPrincipal)
michael@0 61 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
michael@0 62
michael@0 63 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMFileReader,
michael@0 64 FileIOObject)
michael@0 65 tmp->mResultArrayBuffer = nullptr;
michael@0 66 NS_IMPL_CYCLE_COLLECTION_UNLINK(mFile)
michael@0 67 NS_IMPL_CYCLE_COLLECTION_UNLINK(mPrincipal)
michael@0 68 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
michael@0 69
michael@0 70
michael@0 71 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(nsDOMFileReader,
michael@0 72 DOMEventTargetHelper)
michael@0 73 NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mResultArrayBuffer)
michael@0 74 NS_IMPL_CYCLE_COLLECTION_TRACE_END
michael@0 75
michael@0 76 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsDOMFileReader)
michael@0 77 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
michael@0 78 NS_INTERFACE_MAP_ENTRY(nsIDOMFileReader)
michael@0 79 NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
michael@0 80 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
michael@0 81 NS_INTERFACE_MAP_END_INHERITING(FileIOObject)
michael@0 82
michael@0 83 NS_IMPL_ADDREF_INHERITED(nsDOMFileReader, FileIOObject)
michael@0 84 NS_IMPL_RELEASE_INHERITED(nsDOMFileReader, FileIOObject)
michael@0 85
michael@0 86 NS_IMPL_EVENT_HANDLER(nsDOMFileReader, load)
michael@0 87 NS_IMPL_EVENT_HANDLER(nsDOMFileReader, loadend)
michael@0 88 NS_IMPL_EVENT_HANDLER(nsDOMFileReader, loadstart)
michael@0 89 NS_IMPL_FORWARD_EVENT_HANDLER(nsDOMFileReader, abort, FileIOObject)
michael@0 90 NS_IMPL_FORWARD_EVENT_HANDLER(nsDOMFileReader, progress, FileIOObject)
michael@0 91 NS_IMPL_FORWARD_EVENT_HANDLER(nsDOMFileReader, error, FileIOObject)
michael@0 92
michael@0 93 void
michael@0 94 nsDOMFileReader::RootResultArrayBuffer()
michael@0 95 {
michael@0 96 mozilla::HoldJSObjects(this);
michael@0 97 }
michael@0 98
michael@0 99 //nsDOMFileReader constructors/initializers
michael@0 100
michael@0 101 nsDOMFileReader::nsDOMFileReader()
michael@0 102 : mFileData(nullptr),
michael@0 103 mDataLen(0), mDataFormat(FILE_AS_BINARY),
michael@0 104 mResultArrayBuffer(nullptr)
michael@0 105 {
michael@0 106 SetDOMStringToNull(mResult);
michael@0 107 SetIsDOMBinding();
michael@0 108 }
michael@0 109
michael@0 110 nsDOMFileReader::~nsDOMFileReader()
michael@0 111 {
michael@0 112 FreeFileData();
michael@0 113 mResultArrayBuffer = nullptr;
michael@0 114 mozilla::DropJSObjects(this);
michael@0 115 }
michael@0 116
michael@0 117
michael@0 118 /**
michael@0 119 * This Init method is called from the factory constructor.
michael@0 120 */
michael@0 121 nsresult
michael@0 122 nsDOMFileReader::Init()
michael@0 123 {
michael@0 124 nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
michael@0 125 nsCOMPtr<nsIPrincipal> principal;
michael@0 126 if (secMan) {
michael@0 127 secMan->GetSystemPrincipal(getter_AddRefs(principal));
michael@0 128 }
michael@0 129 NS_ENSURE_STATE(principal);
michael@0 130 mPrincipal.swap(principal);
michael@0 131
michael@0 132 // Instead of grabbing some random global from the context stack,
michael@0 133 // let's use the default one (junk scope) for now.
michael@0 134 // We should move away from this Init...
michael@0 135 nsCOMPtr<nsIGlobalObject> global = xpc::GetJunkScopeGlobal();
michael@0 136 NS_ENSURE_TRUE(global, NS_ERROR_FAILURE);
michael@0 137 BindToOwner(global);
michael@0 138 return NS_OK;
michael@0 139 }
michael@0 140
michael@0 141 /* static */ already_AddRefed<nsDOMFileReader>
michael@0 142 nsDOMFileReader::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
michael@0 143 {
michael@0 144 nsRefPtr<nsDOMFileReader> fileReader = new nsDOMFileReader();
michael@0 145
michael@0 146 nsCOMPtr<nsPIDOMWindow> owner = do_QueryInterface(aGlobal.GetAsSupports());
michael@0 147 if (!owner) {
michael@0 148 NS_WARNING("Unexpected nsIJSNativeInitializer owner");
michael@0 149 aRv.Throw(NS_ERROR_FAILURE);
michael@0 150 return nullptr;
michael@0 151 }
michael@0 152
michael@0 153 fileReader->BindToOwner(owner);
michael@0 154
michael@0 155 // This object is bound to a |window|,
michael@0 156 // so reset the principal.
michael@0 157 nsCOMPtr<nsIScriptObjectPrincipal> scriptPrincipal = do_QueryInterface(owner);
michael@0 158 if (!scriptPrincipal) {
michael@0 159 aRv.Throw(NS_ERROR_FAILURE);
michael@0 160 return nullptr;
michael@0 161 }
michael@0 162 fileReader->mPrincipal = scriptPrincipal->GetPrincipal();
michael@0 163 return fileReader.forget();
michael@0 164 }
michael@0 165
michael@0 166 // nsIInterfaceRequestor
michael@0 167
michael@0 168 NS_IMETHODIMP
michael@0 169 nsDOMFileReader::GetInterface(const nsIID & aIID, void **aResult)
michael@0 170 {
michael@0 171 return QueryInterface(aIID, aResult);
michael@0 172 }
michael@0 173
michael@0 174 // nsIDOMFileReader
michael@0 175
michael@0 176 NS_IMETHODIMP
michael@0 177 nsDOMFileReader::GetReadyState(uint16_t *aReadyState)
michael@0 178 {
michael@0 179 *aReadyState = ReadyState();
michael@0 180 return NS_OK;
michael@0 181 }
michael@0 182
michael@0 183 void
michael@0 184 nsDOMFileReader::GetResult(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
michael@0 185 ErrorResult& aRv)
michael@0 186 {
michael@0 187 aRv = GetResult(aCx, aResult);
michael@0 188 }
michael@0 189
michael@0 190 NS_IMETHODIMP
michael@0 191 nsDOMFileReader::GetResult(JSContext* aCx, JS::MutableHandle<JS::Value> aResult)
michael@0 192 {
michael@0 193 JS::Rooted<JS::Value> result(aCx);
michael@0 194 if (mDataFormat == FILE_AS_ARRAYBUFFER) {
michael@0 195 if (mReadyState == nsIDOMFileReader::DONE && mResultArrayBuffer) {
michael@0 196 result.setObject(*mResultArrayBuffer);
michael@0 197 } else {
michael@0 198 result.setNull();
michael@0 199 }
michael@0 200 if (!JS_WrapValue(aCx, &result)) {
michael@0 201 return NS_ERROR_FAILURE;
michael@0 202 }
michael@0 203 aResult.set(result);
michael@0 204 return NS_OK;
michael@0 205 }
michael@0 206
michael@0 207 nsString tmpResult = mResult;
michael@0 208 if (!xpc::StringToJsval(aCx, tmpResult, aResult)) {
michael@0 209 return NS_ERROR_FAILURE;
michael@0 210 }
michael@0 211 return NS_OK;
michael@0 212 }
michael@0 213
michael@0 214 NS_IMETHODIMP
michael@0 215 nsDOMFileReader::GetError(nsISupports** aError)
michael@0 216 {
michael@0 217 NS_IF_ADDREF(*aError = GetError());
michael@0 218 return NS_OK;
michael@0 219 }
michael@0 220
michael@0 221 NS_IMETHODIMP
michael@0 222 nsDOMFileReader::ReadAsArrayBuffer(nsIDOMBlob* aFile, JSContext* aCx)
michael@0 223 {
michael@0 224 NS_ENSURE_TRUE(aFile, NS_ERROR_NULL_POINTER);
michael@0 225 ErrorResult rv;
michael@0 226 ReadAsArrayBuffer(aCx, aFile, rv);
michael@0 227 return rv.ErrorCode();
michael@0 228 }
michael@0 229
michael@0 230 NS_IMETHODIMP
michael@0 231 nsDOMFileReader::ReadAsBinaryString(nsIDOMBlob* aFile)
michael@0 232 {
michael@0 233 NS_ENSURE_TRUE(aFile, NS_ERROR_NULL_POINTER);
michael@0 234 ErrorResult rv;
michael@0 235 ReadAsBinaryString(aFile, rv);
michael@0 236 return rv.ErrorCode();
michael@0 237 }
michael@0 238
michael@0 239 NS_IMETHODIMP
michael@0 240 nsDOMFileReader::ReadAsText(nsIDOMBlob* aFile,
michael@0 241 const nsAString &aCharset)
michael@0 242 {
michael@0 243 NS_ENSURE_TRUE(aFile, NS_ERROR_NULL_POINTER);
michael@0 244 ErrorResult rv;
michael@0 245 ReadAsText(aFile, aCharset, rv);
michael@0 246 return rv.ErrorCode();
michael@0 247 }
michael@0 248
michael@0 249 NS_IMETHODIMP
michael@0 250 nsDOMFileReader::ReadAsDataURL(nsIDOMBlob* aFile)
michael@0 251 {
michael@0 252 NS_ENSURE_TRUE(aFile, NS_ERROR_NULL_POINTER);
michael@0 253 ErrorResult rv;
michael@0 254 ReadAsDataURL(aFile, rv);
michael@0 255 return rv.ErrorCode();
michael@0 256 }
michael@0 257
michael@0 258 NS_IMETHODIMP
michael@0 259 nsDOMFileReader::Abort()
michael@0 260 {
michael@0 261 ErrorResult rv;
michael@0 262 FileIOObject::Abort(rv);
michael@0 263 return rv.ErrorCode();
michael@0 264 }
michael@0 265
michael@0 266 /* virtual */ void
michael@0 267 nsDOMFileReader::DoAbort(nsAString& aEvent)
michael@0 268 {
michael@0 269 // Revert status and result attributes
michael@0 270 SetDOMStringToNull(mResult);
michael@0 271 mResultArrayBuffer = nullptr;
michael@0 272
michael@0 273 // Non-null channel indicates a read is currently active
michael@0 274 if (mChannel) {
michael@0 275 // Cancel request requires an error status
michael@0 276 mChannel->Cancel(NS_ERROR_FAILURE);
michael@0 277 mChannel = nullptr;
michael@0 278 }
michael@0 279 mFile = nullptr;
michael@0 280
michael@0 281 //Clean up memory buffer
michael@0 282 FreeFileData();
michael@0 283
michael@0 284 // Tell the base class which event to dispatch
michael@0 285 aEvent = NS_LITERAL_STRING(LOADEND_STR);
michael@0 286 }
michael@0 287
michael@0 288 static
michael@0 289 NS_METHOD
michael@0 290 ReadFuncBinaryString(nsIInputStream* in,
michael@0 291 void* closure,
michael@0 292 const char* fromRawSegment,
michael@0 293 uint32_t toOffset,
michael@0 294 uint32_t count,
michael@0 295 uint32_t *writeCount)
michael@0 296 {
michael@0 297 char16_t* dest = static_cast<char16_t*>(closure) + toOffset;
michael@0 298 char16_t* end = dest + count;
michael@0 299 const unsigned char* source = (const unsigned char*)fromRawSegment;
michael@0 300 while (dest != end) {
michael@0 301 *dest = *source;
michael@0 302 ++dest;
michael@0 303 ++source;
michael@0 304 }
michael@0 305 *writeCount = count;
michael@0 306
michael@0 307 return NS_OK;
michael@0 308 }
michael@0 309
michael@0 310 nsresult
michael@0 311 nsDOMFileReader::DoOnDataAvailable(nsIRequest *aRequest,
michael@0 312 nsISupports *aContext,
michael@0 313 nsIInputStream *aInputStream,
michael@0 314 uint64_t aOffset,
michael@0 315 uint32_t aCount)
michael@0 316 {
michael@0 317 if (mDataFormat == FILE_AS_BINARY) {
michael@0 318 //Continuously update our binary string as data comes in
michael@0 319 NS_ASSERTION(mResult.Length() == aOffset,
michael@0 320 "unexpected mResult length");
michael@0 321 uint32_t oldLen = mResult.Length();
michael@0 322 if (uint64_t(oldLen) + aCount > UINT32_MAX)
michael@0 323 return NS_ERROR_OUT_OF_MEMORY;
michael@0 324
michael@0 325 char16_t *buf = nullptr;
michael@0 326 mResult.GetMutableData(&buf, oldLen + aCount, fallible_t());
michael@0 327 NS_ENSURE_TRUE(buf, NS_ERROR_OUT_OF_MEMORY);
michael@0 328
michael@0 329 uint32_t bytesRead = 0;
michael@0 330 aInputStream->ReadSegments(ReadFuncBinaryString, buf + oldLen, aCount,
michael@0 331 &bytesRead);
michael@0 332 NS_ASSERTION(bytesRead == aCount, "failed to read data");
michael@0 333 }
michael@0 334 else if (mDataFormat == FILE_AS_ARRAYBUFFER) {
michael@0 335 uint32_t bytesRead = 0;
michael@0 336 aInputStream->Read((char*)JS_GetArrayBufferData(mResultArrayBuffer) + aOffset,
michael@0 337 aCount, &bytesRead);
michael@0 338 NS_ASSERTION(bytesRead == aCount, "failed to read data");
michael@0 339 }
michael@0 340 else {
michael@0 341 //Update memory buffer to reflect the contents of the file
michael@0 342 if (aOffset + aCount > UINT32_MAX) {
michael@0 343 // PR_Realloc doesn't support over 4GB memory size even if 64-bit OS
michael@0 344 return NS_ERROR_OUT_OF_MEMORY;
michael@0 345 }
michael@0 346 mFileData = (char *)moz_realloc(mFileData, aOffset + aCount);
michael@0 347 NS_ENSURE_TRUE(mFileData, NS_ERROR_OUT_OF_MEMORY);
michael@0 348
michael@0 349 uint32_t bytesRead = 0;
michael@0 350 aInputStream->Read(mFileData + aOffset, aCount, &bytesRead);
michael@0 351 NS_ASSERTION(bytesRead == aCount, "failed to read data");
michael@0 352
michael@0 353 mDataLen += aCount;
michael@0 354 }
michael@0 355
michael@0 356 return NS_OK;
michael@0 357 }
michael@0 358
michael@0 359 nsresult
michael@0 360 nsDOMFileReader::DoOnStopRequest(nsIRequest *aRequest,
michael@0 361 nsISupports *aContext,
michael@0 362 nsresult aStatus,
michael@0 363 nsAString& aSuccessEvent,
michael@0 364 nsAString& aTerminationEvent)
michael@0 365 {
michael@0 366 // Make sure we drop all the objects that could hold files open now.
michael@0 367 nsCOMPtr<nsIChannel> channel;
michael@0 368 mChannel.swap(channel);
michael@0 369
michael@0 370 nsCOMPtr<nsIDOMBlob> file;
michael@0 371 mFile.swap(file);
michael@0 372
michael@0 373 aSuccessEvent = NS_LITERAL_STRING(LOAD_STR);
michael@0 374 aTerminationEvent = NS_LITERAL_STRING(LOADEND_STR);
michael@0 375
michael@0 376 // Clear out the data if necessary
michael@0 377 if (NS_FAILED(aStatus)) {
michael@0 378 FreeFileData();
michael@0 379 return NS_OK;
michael@0 380 }
michael@0 381
michael@0 382 nsresult rv = NS_OK;
michael@0 383 switch (mDataFormat) {
michael@0 384 case FILE_AS_ARRAYBUFFER:
michael@0 385 break; //Already accumulated mResultArrayBuffer
michael@0 386 case FILE_AS_BINARY:
michael@0 387 break; //Already accumulated mResult
michael@0 388 case FILE_AS_TEXT:
michael@0 389 if (!mFileData) {
michael@0 390 if (mDataLen) {
michael@0 391 rv = NS_ERROR_OUT_OF_MEMORY;
michael@0 392 break;
michael@0 393 }
michael@0 394 rv = GetAsText(file, mCharset, "", mDataLen, mResult);
michael@0 395 break;
michael@0 396 }
michael@0 397 rv = GetAsText(file, mCharset, mFileData, mDataLen, mResult);
michael@0 398 break;
michael@0 399 case FILE_AS_DATAURL:
michael@0 400 rv = GetAsDataURL(file, mFileData, mDataLen, mResult);
michael@0 401 break;
michael@0 402 }
michael@0 403
michael@0 404 mResult.SetIsVoid(false);
michael@0 405
michael@0 406 FreeFileData();
michael@0 407
michael@0 408 return rv;
michael@0 409 }
michael@0 410
michael@0 411 // Helper methods
michael@0 412
michael@0 413 void
michael@0 414 nsDOMFileReader::ReadFileContent(JSContext* aCx,
michael@0 415 nsIDOMBlob* aFile,
michael@0 416 const nsAString &aCharset,
michael@0 417 eDataFormat aDataFormat,
michael@0 418 ErrorResult& aRv)
michael@0 419 {
michael@0 420 MOZ_ASSERT(aFile);
michael@0 421
michael@0 422 //Implicit abort to clear any other activity going on
michael@0 423 Abort();
michael@0 424 mError = nullptr;
michael@0 425 SetDOMStringToNull(mResult);
michael@0 426 mTransferred = 0;
michael@0 427 mTotal = 0;
michael@0 428 mReadyState = nsIDOMFileReader::EMPTY;
michael@0 429 FreeFileData();
michael@0 430
michael@0 431 mFile = aFile;
michael@0 432 mDataFormat = aDataFormat;
michael@0 433 CopyUTF16toUTF8(aCharset, mCharset);
michael@0 434
michael@0 435 //Establish a channel with our file
michael@0 436 {
michael@0 437 // Hold the internal URL alive only as long as necessary
michael@0 438 // After the channel is created it will own whatever is backing
michael@0 439 // the DOMFile.
michael@0 440 nsDOMFileInternalUrlHolder urlHolder(mFile, mPrincipal);
michael@0 441
michael@0 442 nsCOMPtr<nsIURI> uri;
michael@0 443 aRv = NS_NewURI(getter_AddRefs(uri), urlHolder.mUrl);
michael@0 444 NS_ENSURE_SUCCESS_VOID(aRv.ErrorCode());
michael@0 445
michael@0 446 nsCOMPtr<nsILoadGroup> loadGroup;
michael@0 447 if (HasOrHasHadOwner()) {
michael@0 448 if (!GetOwner()) {
michael@0 449 aRv.Throw(NS_ERROR_FAILURE);
michael@0 450 return;
michael@0 451 }
michael@0 452 nsIDocument* doc = GetOwner()->GetExtantDoc();
michael@0 453 if (doc) {
michael@0 454 loadGroup = doc->GetDocumentLoadGroup();
michael@0 455 }
michael@0 456 }
michael@0 457
michael@0 458 aRv = NS_NewChannel(getter_AddRefs(mChannel), uri, nullptr, loadGroup,
michael@0 459 nullptr, nsIRequest::LOAD_BACKGROUND);
michael@0 460 NS_ENSURE_SUCCESS_VOID(aRv.ErrorCode());
michael@0 461 }
michael@0 462
michael@0 463 //Obtain the total size of the file before reading
michael@0 464 mTotal = mozilla::dom::kUnknownSize;
michael@0 465 mFile->GetSize(&mTotal);
michael@0 466
michael@0 467 aRv = mChannel->AsyncOpen(this, nullptr);
michael@0 468 NS_ENSURE_SUCCESS_VOID(aRv.ErrorCode());
michael@0 469
michael@0 470 //FileReader should be in loading state here
michael@0 471 mReadyState = nsIDOMFileReader::LOADING;
michael@0 472 DispatchProgressEvent(NS_LITERAL_STRING(LOADSTART_STR));
michael@0 473
michael@0 474 if (mDataFormat == FILE_AS_ARRAYBUFFER) {
michael@0 475 RootResultArrayBuffer();
michael@0 476 mResultArrayBuffer = JS_NewArrayBuffer(aCx, mTotal);
michael@0 477 if (!mResultArrayBuffer) {
michael@0 478 NS_WARNING("Failed to create JS array buffer");
michael@0 479 aRv.Throw(NS_ERROR_FAILURE);
michael@0 480 }
michael@0 481 }
michael@0 482 }
michael@0 483
michael@0 484 nsresult
michael@0 485 nsDOMFileReader::GetAsText(nsIDOMBlob *aFile,
michael@0 486 const nsACString &aCharset,
michael@0 487 const char *aFileData,
michael@0 488 uint32_t aDataLen,
michael@0 489 nsAString& aResult)
michael@0 490 {
michael@0 491 // The BOM sniffing is baked into the "decode" part of the Encoding
michael@0 492 // Standard, which the File API references.
michael@0 493 nsAutoCString encoding;
michael@0 494 if (!nsContentUtils::CheckForBOM(
michael@0 495 reinterpret_cast<const unsigned char *>(aFileData),
michael@0 496 aDataLen,
michael@0 497 encoding)) {
michael@0 498 // BOM sniffing failed. Try the API argument.
michael@0 499 if (!EncodingUtils::FindEncodingForLabel(aCharset,
michael@0 500 encoding)) {
michael@0 501 // API argument failed. Try the type property of the blob.
michael@0 502 nsAutoString type16;
michael@0 503 aFile->GetType(type16);
michael@0 504 NS_ConvertUTF16toUTF8 type(type16);
michael@0 505 nsAutoCString specifiedCharset;
michael@0 506 bool haveCharset;
michael@0 507 int32_t charsetStart, charsetEnd;
michael@0 508 NS_ExtractCharsetFromContentType(type,
michael@0 509 specifiedCharset,
michael@0 510 &haveCharset,
michael@0 511 &charsetStart,
michael@0 512 &charsetEnd);
michael@0 513 if (!EncodingUtils::FindEncodingForLabel(specifiedCharset, encoding)) {
michael@0 514 // Type property failed. Use UTF-8.
michael@0 515 encoding.AssignLiteral("UTF-8");
michael@0 516 }
michael@0 517 }
michael@0 518 }
michael@0 519
michael@0 520 nsDependentCSubstring data(aFileData, aDataLen);
michael@0 521 return nsContentUtils::ConvertStringFromEncoding(encoding, data, aResult);
michael@0 522 }
michael@0 523
michael@0 524 nsresult
michael@0 525 nsDOMFileReader::GetAsDataURL(nsIDOMBlob *aFile,
michael@0 526 const char *aFileData,
michael@0 527 uint32_t aDataLen,
michael@0 528 nsAString& aResult)
michael@0 529 {
michael@0 530 aResult.AssignLiteral("data:");
michael@0 531
michael@0 532 nsresult rv;
michael@0 533 nsString contentType;
michael@0 534 rv = aFile->GetType(contentType);
michael@0 535 if (NS_SUCCEEDED(rv) && !contentType.IsEmpty()) {
michael@0 536 aResult.Append(contentType);
michael@0 537 } else {
michael@0 538 aResult.AppendLiteral("application/octet-stream");
michael@0 539 }
michael@0 540 aResult.AppendLiteral(";base64,");
michael@0 541
michael@0 542 nsCString encodedData;
michael@0 543 rv = Base64Encode(Substring(aFileData, aDataLen), encodedData);
michael@0 544 NS_ENSURE_SUCCESS(rv, rv);
michael@0 545
michael@0 546 if (!AppendASCIItoUTF16(encodedData, aResult, fallible_t())) {
michael@0 547 return NS_ERROR_OUT_OF_MEMORY;
michael@0 548 }
michael@0 549
michael@0 550 return NS_OK;
michael@0 551 }
michael@0 552
michael@0 553 /* virtual */ JSObject*
michael@0 554 nsDOMFileReader::WrapObject(JSContext* aCx)
michael@0 555 {
michael@0 556 return FileReaderBinding::Wrap(aCx, this);
michael@0 557 }

mercurial