Wed, 31 Dec 2014 06:09:35 +0100
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 "nsDOMBlobBuilder.h" |
michael@0 | 7 | #include "jsfriendapi.h" |
michael@0 | 8 | #include "mozilla/dom/BlobBinding.h" |
michael@0 | 9 | #include "mozilla/dom/FileBinding.h" |
michael@0 | 10 | #include "nsAutoPtr.h" |
michael@0 | 11 | #include "nsDOMClassInfoID.h" |
michael@0 | 12 | #include "nsIMultiplexInputStream.h" |
michael@0 | 13 | #include "nsStringStream.h" |
michael@0 | 14 | #include "nsTArray.h" |
michael@0 | 15 | #include "nsJSUtils.h" |
michael@0 | 16 | #include "nsContentUtils.h" |
michael@0 | 17 | #include "nsIScriptError.h" |
michael@0 | 18 | #include "nsIXPConnect.h" |
michael@0 | 19 | #include <algorithm> |
michael@0 | 20 | |
michael@0 | 21 | using namespace mozilla; |
michael@0 | 22 | using namespace mozilla::dom; |
michael@0 | 23 | |
michael@0 | 24 | NS_IMPL_ISUPPORTS_INHERITED(nsDOMMultipartFile, nsDOMFile, |
michael@0 | 25 | nsIJSNativeInitializer) |
michael@0 | 26 | |
michael@0 | 27 | NS_IMETHODIMP |
michael@0 | 28 | nsDOMMultipartFile::GetSize(uint64_t* aLength) |
michael@0 | 29 | { |
michael@0 | 30 | if (mLength == UINT64_MAX) { |
michael@0 | 31 | CheckedUint64 length = 0; |
michael@0 | 32 | |
michael@0 | 33 | uint32_t i; |
michael@0 | 34 | uint32_t len = mBlobs.Length(); |
michael@0 | 35 | for (i = 0; i < len; i++) { |
michael@0 | 36 | nsIDOMBlob* blob = mBlobs.ElementAt(i).get(); |
michael@0 | 37 | uint64_t l = 0; |
michael@0 | 38 | |
michael@0 | 39 | nsresult rv = blob->GetSize(&l); |
michael@0 | 40 | NS_ENSURE_SUCCESS(rv, rv); |
michael@0 | 41 | |
michael@0 | 42 | length += l; |
michael@0 | 43 | } |
michael@0 | 44 | |
michael@0 | 45 | NS_ENSURE_TRUE(length.isValid(), NS_ERROR_FAILURE); |
michael@0 | 46 | |
michael@0 | 47 | mLength = length.value(); |
michael@0 | 48 | } |
michael@0 | 49 | |
michael@0 | 50 | *aLength = mLength; |
michael@0 | 51 | return NS_OK; |
michael@0 | 52 | } |
michael@0 | 53 | |
michael@0 | 54 | NS_IMETHODIMP |
michael@0 | 55 | nsDOMMultipartFile::GetInternalStream(nsIInputStream** aStream) |
michael@0 | 56 | { |
michael@0 | 57 | nsresult rv; |
michael@0 | 58 | *aStream = nullptr; |
michael@0 | 59 | |
michael@0 | 60 | nsCOMPtr<nsIMultiplexInputStream> stream = |
michael@0 | 61 | do_CreateInstance("@mozilla.org/io/multiplex-input-stream;1"); |
michael@0 | 62 | NS_ENSURE_TRUE(stream, NS_ERROR_FAILURE); |
michael@0 | 63 | |
michael@0 | 64 | uint32_t i; |
michael@0 | 65 | for (i = 0; i < mBlobs.Length(); i++) { |
michael@0 | 66 | nsCOMPtr<nsIInputStream> scratchStream; |
michael@0 | 67 | nsIDOMBlob* blob = mBlobs.ElementAt(i).get(); |
michael@0 | 68 | |
michael@0 | 69 | rv = blob->GetInternalStream(getter_AddRefs(scratchStream)); |
michael@0 | 70 | NS_ENSURE_SUCCESS(rv, rv); |
michael@0 | 71 | |
michael@0 | 72 | rv = stream->AppendStream(scratchStream); |
michael@0 | 73 | NS_ENSURE_SUCCESS(rv, rv); |
michael@0 | 74 | } |
michael@0 | 75 | |
michael@0 | 76 | return CallQueryInterface(stream, aStream); |
michael@0 | 77 | } |
michael@0 | 78 | |
michael@0 | 79 | already_AddRefed<nsIDOMBlob> |
michael@0 | 80 | nsDOMMultipartFile::CreateSlice(uint64_t aStart, uint64_t aLength, |
michael@0 | 81 | const nsAString& aContentType) |
michael@0 | 82 | { |
michael@0 | 83 | // If we clamped to nothing we create an empty blob |
michael@0 | 84 | nsTArray<nsCOMPtr<nsIDOMBlob> > blobs; |
michael@0 | 85 | |
michael@0 | 86 | uint64_t length = aLength; |
michael@0 | 87 | uint64_t skipStart = aStart; |
michael@0 | 88 | |
michael@0 | 89 | // Prune the list of blobs if we can |
michael@0 | 90 | uint32_t i; |
michael@0 | 91 | for (i = 0; length && skipStart && i < mBlobs.Length(); i++) { |
michael@0 | 92 | nsIDOMBlob* blob = mBlobs[i].get(); |
michael@0 | 93 | |
michael@0 | 94 | uint64_t l; |
michael@0 | 95 | nsresult rv = blob->GetSize(&l); |
michael@0 | 96 | NS_ENSURE_SUCCESS(rv, nullptr); |
michael@0 | 97 | |
michael@0 | 98 | if (skipStart < l) { |
michael@0 | 99 | uint64_t upperBound = std::min<uint64_t>(l - skipStart, length); |
michael@0 | 100 | |
michael@0 | 101 | nsCOMPtr<nsIDOMBlob> firstBlob; |
michael@0 | 102 | rv = blob->Slice(skipStart, skipStart + upperBound, |
michael@0 | 103 | aContentType, 3, |
michael@0 | 104 | getter_AddRefs(firstBlob)); |
michael@0 | 105 | NS_ENSURE_SUCCESS(rv, nullptr); |
michael@0 | 106 | |
michael@0 | 107 | // Avoid wrapping a single blob inside an nsDOMMultipartFile |
michael@0 | 108 | if (length == upperBound) { |
michael@0 | 109 | return firstBlob.forget(); |
michael@0 | 110 | } |
michael@0 | 111 | |
michael@0 | 112 | blobs.AppendElement(firstBlob); |
michael@0 | 113 | length -= upperBound; |
michael@0 | 114 | i++; |
michael@0 | 115 | break; |
michael@0 | 116 | } |
michael@0 | 117 | skipStart -= l; |
michael@0 | 118 | } |
michael@0 | 119 | |
michael@0 | 120 | // Now append enough blobs until we're done |
michael@0 | 121 | for (; length && i < mBlobs.Length(); i++) { |
michael@0 | 122 | nsIDOMBlob* blob = mBlobs[i].get(); |
michael@0 | 123 | |
michael@0 | 124 | uint64_t l; |
michael@0 | 125 | nsresult rv = blob->GetSize(&l); |
michael@0 | 126 | NS_ENSURE_SUCCESS(rv, nullptr); |
michael@0 | 127 | |
michael@0 | 128 | if (length < l) { |
michael@0 | 129 | nsCOMPtr<nsIDOMBlob> lastBlob; |
michael@0 | 130 | rv = blob->Slice(0, length, aContentType, 3, |
michael@0 | 131 | getter_AddRefs(lastBlob)); |
michael@0 | 132 | NS_ENSURE_SUCCESS(rv, nullptr); |
michael@0 | 133 | |
michael@0 | 134 | blobs.AppendElement(lastBlob); |
michael@0 | 135 | } else { |
michael@0 | 136 | blobs.AppendElement(blob); |
michael@0 | 137 | } |
michael@0 | 138 | length -= std::min<uint64_t>(l, length); |
michael@0 | 139 | } |
michael@0 | 140 | |
michael@0 | 141 | // we can create our blob now |
michael@0 | 142 | nsCOMPtr<nsIDOMBlob> blob = new nsDOMMultipartFile(blobs, aContentType); |
michael@0 | 143 | return blob.forget(); |
michael@0 | 144 | } |
michael@0 | 145 | |
michael@0 | 146 | /* static */ nsresult |
michael@0 | 147 | nsDOMMultipartFile::NewFile(const nsAString& aName, nsISupports* *aNewObject) |
michael@0 | 148 | { |
michael@0 | 149 | nsCOMPtr<nsISupports> file = |
michael@0 | 150 | do_QueryObject(new nsDOMMultipartFile(aName)); |
michael@0 | 151 | file.forget(aNewObject); |
michael@0 | 152 | return NS_OK; |
michael@0 | 153 | } |
michael@0 | 154 | |
michael@0 | 155 | /* static */ nsresult |
michael@0 | 156 | nsDOMMultipartFile::NewBlob(nsISupports* *aNewObject) |
michael@0 | 157 | { |
michael@0 | 158 | nsCOMPtr<nsISupports> file = do_QueryObject(new nsDOMMultipartFile()); |
michael@0 | 159 | file.forget(aNewObject); |
michael@0 | 160 | return NS_OK; |
michael@0 | 161 | } |
michael@0 | 162 | |
michael@0 | 163 | static nsIDOMBlob* |
michael@0 | 164 | GetXPConnectNative(JSContext* aCx, JSObject* aObj) { |
michael@0 | 165 | nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface( |
michael@0 | 166 | nsContentUtils::XPConnect()->GetNativeOfWrapper(aCx, aObj)); |
michael@0 | 167 | return blob; |
michael@0 | 168 | } |
michael@0 | 169 | |
michael@0 | 170 | NS_IMETHODIMP |
michael@0 | 171 | nsDOMMultipartFile::Initialize(nsISupports* aOwner, |
michael@0 | 172 | JSContext* aCx, |
michael@0 | 173 | JSObject* aObj, |
michael@0 | 174 | const JS::CallArgs& aArgs) |
michael@0 | 175 | { |
michael@0 | 176 | if (!mIsFile) { |
michael@0 | 177 | return InitBlob(aCx, aArgs.length(), aArgs.array(), GetXPConnectNative); |
michael@0 | 178 | } |
michael@0 | 179 | |
michael@0 | 180 | if (!nsContentUtils::IsCallerChrome()) { |
michael@0 | 181 | return InitFile(aCx, aArgs.length(), aArgs.array()); |
michael@0 | 182 | } |
michael@0 | 183 | |
michael@0 | 184 | if (aArgs.length() > 0) { |
michael@0 | 185 | JS::Value* argv = aArgs.array(); |
michael@0 | 186 | if (argv[0].isObject()) { |
michael@0 | 187 | JS::Rooted<JSObject*> obj(aCx, &argv[0].toObject()); |
michael@0 | 188 | if (JS_IsArrayObject(aCx, obj)) { |
michael@0 | 189 | return InitFile(aCx, aArgs.length(), aArgs.array()); |
michael@0 | 190 | } |
michael@0 | 191 | } |
michael@0 | 192 | } |
michael@0 | 193 | |
michael@0 | 194 | return InitChromeFile(aCx, aArgs.length(), aArgs.array()); |
michael@0 | 195 | } |
michael@0 | 196 | |
michael@0 | 197 | nsresult |
michael@0 | 198 | nsDOMMultipartFile::InitBlob(JSContext* aCx, |
michael@0 | 199 | uint32_t aArgc, |
michael@0 | 200 | JS::Value* aArgv, |
michael@0 | 201 | UnwrapFuncPtr aUnwrapFunc) |
michael@0 | 202 | { |
michael@0 | 203 | bool nativeEOL = false; |
michael@0 | 204 | if (aArgc > 1) { |
michael@0 | 205 | BlobPropertyBag d; |
michael@0 | 206 | if (!d.Init(aCx, JS::Handle<JS::Value>::fromMarkedLocation(&aArgv[1]))) { |
michael@0 | 207 | return NS_ERROR_TYPE_ERR; |
michael@0 | 208 | } |
michael@0 | 209 | mContentType = d.mType; |
michael@0 | 210 | nativeEOL = d.mEndings == EndingTypes::Native; |
michael@0 | 211 | } |
michael@0 | 212 | |
michael@0 | 213 | if (aArgc > 0) { |
michael@0 | 214 | return ParseBlobArrayArgument(aCx, aArgv[0], nativeEOL, aUnwrapFunc); |
michael@0 | 215 | } |
michael@0 | 216 | |
michael@0 | 217 | return NS_OK; |
michael@0 | 218 | } |
michael@0 | 219 | |
michael@0 | 220 | nsresult |
michael@0 | 221 | nsDOMMultipartFile::ParseBlobArrayArgument(JSContext* aCx, JS::Value& aValue, |
michael@0 | 222 | bool aNativeEOL, |
michael@0 | 223 | UnwrapFuncPtr aUnwrapFunc) |
michael@0 | 224 | { |
michael@0 | 225 | if (!aValue.isObject()) { |
michael@0 | 226 | return NS_ERROR_TYPE_ERR; // We're not interested |
michael@0 | 227 | } |
michael@0 | 228 | |
michael@0 | 229 | JS::Rooted<JSObject*> obj(aCx, &aValue.toObject()); |
michael@0 | 230 | if (!JS_IsArrayObject(aCx, obj)) { |
michael@0 | 231 | return NS_ERROR_TYPE_ERR; // We're not interested |
michael@0 | 232 | } |
michael@0 | 233 | |
michael@0 | 234 | BlobSet blobSet; |
michael@0 | 235 | |
michael@0 | 236 | uint32_t length; |
michael@0 | 237 | MOZ_ALWAYS_TRUE(JS_GetArrayLength(aCx, obj, &length)); |
michael@0 | 238 | for (uint32_t i = 0; i < length; ++i) { |
michael@0 | 239 | JS::Rooted<JS::Value> element(aCx); |
michael@0 | 240 | if (!JS_GetElement(aCx, obj, i, &element)) |
michael@0 | 241 | return NS_ERROR_TYPE_ERR; |
michael@0 | 242 | |
michael@0 | 243 | if (element.isObject()) { |
michael@0 | 244 | JS::Rooted<JSObject*> obj(aCx, &element.toObject()); |
michael@0 | 245 | nsCOMPtr<nsIDOMBlob> blob = aUnwrapFunc(aCx, obj); |
michael@0 | 246 | if (blob) { |
michael@0 | 247 | // Flatten so that multipart blobs will never nest |
michael@0 | 248 | nsDOMFileBase* file = static_cast<nsDOMFileBase*>( |
michael@0 | 249 | static_cast<nsIDOMBlob*>(blob)); |
michael@0 | 250 | const nsTArray<nsCOMPtr<nsIDOMBlob> >* |
michael@0 | 251 | subBlobs = file->GetSubBlobs(); |
michael@0 | 252 | if (subBlobs) { |
michael@0 | 253 | blobSet.AppendBlobs(*subBlobs); |
michael@0 | 254 | } else { |
michael@0 | 255 | blobSet.AppendBlob(blob); |
michael@0 | 256 | } |
michael@0 | 257 | continue; |
michael@0 | 258 | } |
michael@0 | 259 | if (JS_IsArrayBufferViewObject(obj)) { |
michael@0 | 260 | nsresult rv = blobSet.AppendVoidPtr( |
michael@0 | 261 | JS_GetArrayBufferViewData(obj), |
michael@0 | 262 | JS_GetArrayBufferViewByteLength(obj)); |
michael@0 | 263 | NS_ENSURE_SUCCESS(rv, rv); |
michael@0 | 264 | continue; |
michael@0 | 265 | } |
michael@0 | 266 | if (JS_IsArrayBufferObject(obj)) { |
michael@0 | 267 | nsresult rv = blobSet.AppendArrayBuffer(obj); |
michael@0 | 268 | NS_ENSURE_SUCCESS(rv, rv); |
michael@0 | 269 | continue; |
michael@0 | 270 | } |
michael@0 | 271 | } |
michael@0 | 272 | |
michael@0 | 273 | // coerce it to a string |
michael@0 | 274 | JSString* str = JS::ToString(aCx, element); |
michael@0 | 275 | NS_ENSURE_TRUE(str, NS_ERROR_TYPE_ERR); |
michael@0 | 276 | |
michael@0 | 277 | nsresult rv = blobSet.AppendString(str, aNativeEOL, aCx); |
michael@0 | 278 | NS_ENSURE_SUCCESS(rv, rv); |
michael@0 | 279 | } |
michael@0 | 280 | |
michael@0 | 281 | mBlobs = blobSet.GetBlobs(); |
michael@0 | 282 | return NS_OK; |
michael@0 | 283 | } |
michael@0 | 284 | |
michael@0 | 285 | NS_IMETHODIMP |
michael@0 | 286 | nsDOMMultipartFile::GetMozFullPathInternal(nsAString &aFilename) |
michael@0 | 287 | { |
michael@0 | 288 | if (!mIsFromNsiFile || mBlobs.Length() == 0) { |
michael@0 | 289 | return nsDOMFile::GetMozFullPathInternal(aFilename); |
michael@0 | 290 | } |
michael@0 | 291 | |
michael@0 | 292 | nsIDOMBlob* blob = mBlobs.ElementAt(0).get(); |
michael@0 | 293 | nsDOMFileFile* file = static_cast<nsDOMFileFile*>(blob); |
michael@0 | 294 | if (!file) { |
michael@0 | 295 | return nsDOMFile::GetMozFullPathInternal(aFilename); |
michael@0 | 296 | } |
michael@0 | 297 | |
michael@0 | 298 | return file->GetMozFullPathInternal(aFilename); |
michael@0 | 299 | } |
michael@0 | 300 | |
michael@0 | 301 | nsresult |
michael@0 | 302 | nsDOMMultipartFile::InitChromeFile(JSContext* aCx, |
michael@0 | 303 | uint32_t aArgc, |
michael@0 | 304 | JS::Value* aArgv) |
michael@0 | 305 | { |
michael@0 | 306 | nsresult rv; |
michael@0 | 307 | |
michael@0 | 308 | NS_ASSERTION(!mImmutable, "Something went wrong ..."); |
michael@0 | 309 | NS_ENSURE_TRUE(!mImmutable, NS_ERROR_UNEXPECTED); |
michael@0 | 310 | MOZ_ASSERT(nsContentUtils::IsCallerChrome()); |
michael@0 | 311 | NS_ENSURE_TRUE(aArgc > 0, NS_ERROR_UNEXPECTED); |
michael@0 | 312 | |
michael@0 | 313 | if (aArgc > 1) { |
michael@0 | 314 | FilePropertyBag d; |
michael@0 | 315 | if (!d.Init(aCx, JS::Handle<JS::Value>::fromMarkedLocation(&aArgv[1]))) { |
michael@0 | 316 | return NS_ERROR_TYPE_ERR; |
michael@0 | 317 | } |
michael@0 | 318 | mName = d.mName; |
michael@0 | 319 | mContentType = d.mType; |
michael@0 | 320 | } |
michael@0 | 321 | |
michael@0 | 322 | |
michael@0 | 323 | // We expect to get a path to represent as a File object or |
michael@0 | 324 | // Blob object, an nsIFile, or an nsIDOMFile. |
michael@0 | 325 | nsCOMPtr<nsIFile> file; |
michael@0 | 326 | nsCOMPtr<nsIDOMBlob> blob; |
michael@0 | 327 | if (!aArgv[0].isString()) { |
michael@0 | 328 | // Lets see if it's an nsIFile |
michael@0 | 329 | if (!aArgv[0].isObject()) { |
michael@0 | 330 | return NS_ERROR_UNEXPECTED; // We're not interested |
michael@0 | 331 | } |
michael@0 | 332 | |
michael@0 | 333 | JSObject* obj = &aArgv[0].toObject(); |
michael@0 | 334 | |
michael@0 | 335 | nsISupports* supports = |
michael@0 | 336 | nsContentUtils::XPConnect()->GetNativeOfWrapper(aCx, obj); |
michael@0 | 337 | if (!supports) { |
michael@0 | 338 | return NS_ERROR_UNEXPECTED; |
michael@0 | 339 | } |
michael@0 | 340 | |
michael@0 | 341 | blob = do_QueryInterface(supports); |
michael@0 | 342 | file = do_QueryInterface(supports); |
michael@0 | 343 | if (!blob && !file) { |
michael@0 | 344 | return NS_ERROR_UNEXPECTED; |
michael@0 | 345 | } |
michael@0 | 346 | |
michael@0 | 347 | mIsFromNsiFile = true; |
michael@0 | 348 | } else { |
michael@0 | 349 | // It's a string |
michael@0 | 350 | JSString* str = JS::ToString(aCx, JS::Handle<JS::Value>::fromMarkedLocation(&aArgv[0])); |
michael@0 | 351 | NS_ENSURE_TRUE(str, NS_ERROR_XPC_BAD_CONVERT_JS); |
michael@0 | 352 | |
michael@0 | 353 | nsDependentJSString xpcomStr; |
michael@0 | 354 | if (!xpcomStr.init(aCx, str)) { |
michael@0 | 355 | return NS_ERROR_XPC_BAD_CONVERT_JS; |
michael@0 | 356 | } |
michael@0 | 357 | |
michael@0 | 358 | rv = NS_NewLocalFile(xpcomStr, false, getter_AddRefs(file)); |
michael@0 | 359 | NS_ENSURE_SUCCESS(rv, rv); |
michael@0 | 360 | } |
michael@0 | 361 | |
michael@0 | 362 | if (file) { |
michael@0 | 363 | bool exists; |
michael@0 | 364 | rv = file->Exists(&exists); |
michael@0 | 365 | NS_ENSURE_SUCCESS(rv, rv); |
michael@0 | 366 | NS_ENSURE_TRUE(exists, NS_ERROR_FILE_NOT_FOUND); |
michael@0 | 367 | |
michael@0 | 368 | bool isDir; |
michael@0 | 369 | rv = file->IsDirectory(&isDir); |
michael@0 | 370 | NS_ENSURE_SUCCESS(rv, rv); |
michael@0 | 371 | NS_ENSURE_FALSE(isDir, NS_ERROR_FILE_IS_DIRECTORY); |
michael@0 | 372 | |
michael@0 | 373 | if (mName.IsEmpty()) { |
michael@0 | 374 | file->GetLeafName(mName); |
michael@0 | 375 | } |
michael@0 | 376 | |
michael@0 | 377 | blob = new nsDOMFileFile(file); |
michael@0 | 378 | } |
michael@0 | 379 | |
michael@0 | 380 | // XXXkhuey this is terrible |
michael@0 | 381 | if (mContentType.IsEmpty()) { |
michael@0 | 382 | blob->GetType(mContentType); |
michael@0 | 383 | } |
michael@0 | 384 | |
michael@0 | 385 | BlobSet blobSet; |
michael@0 | 386 | blobSet.AppendBlob(blob); |
michael@0 | 387 | mBlobs = blobSet.GetBlobs(); |
michael@0 | 388 | |
michael@0 | 389 | return NS_OK; |
michael@0 | 390 | } |
michael@0 | 391 | |
michael@0 | 392 | nsresult |
michael@0 | 393 | nsDOMMultipartFile::InitFile(JSContext* aCx, |
michael@0 | 394 | uint32_t aArgc, |
michael@0 | 395 | JS::Value* aArgv) |
michael@0 | 396 | { |
michael@0 | 397 | NS_ASSERTION(!mImmutable, "Something went wrong ..."); |
michael@0 | 398 | NS_ENSURE_TRUE(!mImmutable, NS_ERROR_UNEXPECTED); |
michael@0 | 399 | |
michael@0 | 400 | if (aArgc < 2) { |
michael@0 | 401 | return NS_ERROR_TYPE_ERR; |
michael@0 | 402 | } |
michael@0 | 403 | |
michael@0 | 404 | // File name |
michael@0 | 405 | JSString* str = JS::ToString(aCx, JS::Handle<JS::Value>::fromMarkedLocation(&aArgv[1])); |
michael@0 | 406 | NS_ENSURE_TRUE(str, NS_ERROR_XPC_BAD_CONVERT_JS); |
michael@0 | 407 | |
michael@0 | 408 | nsDependentJSString xpcomStr; |
michael@0 | 409 | if (!xpcomStr.init(aCx, str)) { |
michael@0 | 410 | return NS_ERROR_XPC_BAD_CONVERT_JS; |
michael@0 | 411 | } |
michael@0 | 412 | |
michael@0 | 413 | mName = xpcomStr; |
michael@0 | 414 | |
michael@0 | 415 | // Optional params |
michael@0 | 416 | bool nativeEOL = false; |
michael@0 | 417 | if (aArgc > 2) { |
michael@0 | 418 | BlobPropertyBag d; |
michael@0 | 419 | if (!d.Init(aCx, JS::Handle<JS::Value>::fromMarkedLocation(&aArgv[2]))) { |
michael@0 | 420 | return NS_ERROR_TYPE_ERR; |
michael@0 | 421 | } |
michael@0 | 422 | mContentType = d.mType; |
michael@0 | 423 | nativeEOL = d.mEndings == EndingTypes::Native; |
michael@0 | 424 | } |
michael@0 | 425 | |
michael@0 | 426 | return ParseBlobArrayArgument(aCx, aArgv[0], nativeEOL, GetXPConnectNative); |
michael@0 | 427 | } |
michael@0 | 428 | |
michael@0 | 429 | nsresult |
michael@0 | 430 | BlobSet::AppendVoidPtr(const void* aData, uint32_t aLength) |
michael@0 | 431 | { |
michael@0 | 432 | NS_ENSURE_ARG_POINTER(aData); |
michael@0 | 433 | |
michael@0 | 434 | uint64_t offset = mDataLen; |
michael@0 | 435 | |
michael@0 | 436 | if (!ExpandBufferSize(aLength)) |
michael@0 | 437 | return NS_ERROR_OUT_OF_MEMORY; |
michael@0 | 438 | |
michael@0 | 439 | memcpy((char*)mData + offset, aData, aLength); |
michael@0 | 440 | return NS_OK; |
michael@0 | 441 | } |
michael@0 | 442 | |
michael@0 | 443 | nsresult |
michael@0 | 444 | BlobSet::AppendString(JSString* aString, bool nativeEOL, JSContext* aCx) |
michael@0 | 445 | { |
michael@0 | 446 | nsDependentJSString xpcomStr; |
michael@0 | 447 | if (!xpcomStr.init(aCx, aString)) { |
michael@0 | 448 | return NS_ERROR_XPC_BAD_CONVERT_JS; |
michael@0 | 449 | } |
michael@0 | 450 | |
michael@0 | 451 | nsCString utf8Str = NS_ConvertUTF16toUTF8(xpcomStr); |
michael@0 | 452 | |
michael@0 | 453 | if (nativeEOL) { |
michael@0 | 454 | if (utf8Str.FindChar('\r') != kNotFound) { |
michael@0 | 455 | utf8Str.ReplaceSubstring("\r\n", "\n"); |
michael@0 | 456 | utf8Str.ReplaceSubstring("\r", "\n"); |
michael@0 | 457 | } |
michael@0 | 458 | #ifdef XP_WIN |
michael@0 | 459 | utf8Str.ReplaceSubstring("\n", "\r\n"); |
michael@0 | 460 | #endif |
michael@0 | 461 | } |
michael@0 | 462 | |
michael@0 | 463 | return AppendVoidPtr((void*)utf8Str.Data(), |
michael@0 | 464 | utf8Str.Length()); |
michael@0 | 465 | } |
michael@0 | 466 | |
michael@0 | 467 | nsresult |
michael@0 | 468 | BlobSet::AppendBlob(nsIDOMBlob* aBlob) |
michael@0 | 469 | { |
michael@0 | 470 | NS_ENSURE_ARG_POINTER(aBlob); |
michael@0 | 471 | |
michael@0 | 472 | Flush(); |
michael@0 | 473 | mBlobs.AppendElement(aBlob); |
michael@0 | 474 | |
michael@0 | 475 | return NS_OK; |
michael@0 | 476 | } |
michael@0 | 477 | |
michael@0 | 478 | nsresult |
michael@0 | 479 | BlobSet::AppendBlobs(const nsTArray<nsCOMPtr<nsIDOMBlob> >& aBlob) |
michael@0 | 480 | { |
michael@0 | 481 | Flush(); |
michael@0 | 482 | mBlobs.AppendElements(aBlob); |
michael@0 | 483 | |
michael@0 | 484 | return NS_OK; |
michael@0 | 485 | } |
michael@0 | 486 | |
michael@0 | 487 | nsresult |
michael@0 | 488 | BlobSet::AppendArrayBuffer(JSObject* aBuffer) |
michael@0 | 489 | { |
michael@0 | 490 | return AppendVoidPtr(JS_GetArrayBufferData(aBuffer), |
michael@0 | 491 | JS_GetArrayBufferByteLength(aBuffer)); |
michael@0 | 492 | } |