1/* 2 * Copyright (C) 2012 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31#include "config.h" 32#include "JSBlob.h" 33 34#include "Blob.h" 35#include "ExceptionCode.h" 36#include "ExceptionCodePlaceholder.h" 37#include "JSDOMBinding.h" 38#include "JSDictionary.h" 39#include "JSFile.h" 40#include "WebKitBlobBuilder.h" 41#include <runtime/Error.h> 42#include <runtime/JSArray.h> 43#include <runtime/JSArrayBuffer.h> 44#include <runtime/JSArrayBufferView.h> 45#include <wtf/Assertions.h> 46 47using namespace JSC; 48 49namespace WebCore { 50 51JSValue toJS(ExecState*, JSDOMGlobalObject* globalObject, Blob* blob) 52{ 53 if (!blob) 54 return jsNull(); 55 56 if (blob->isFile()) 57 return wrap<JSFile>(globalObject, static_cast<File*>(blob)); 58 59 return wrap<JSBlob>(globalObject, blob); 60} 61 62EncodedJSValue JSC_HOST_CALL constructJSBlob(ExecState* exec) 63{ 64 DOMConstructorObject* jsConstructor = jsCast<DOMConstructorObject*>(exec->callee()); 65 ScriptExecutionContext* context = jsConstructor->scriptExecutionContext(); 66 if (!context) 67 return throwVMError(exec, createReferenceError(exec, "Blob constructor associated document is unavailable")); 68 69 if (!exec->argumentCount()) { 70 RefPtr<Blob> blob = Blob::create(); 71 return JSValue::encode(CREATE_DOM_WRAPPER(jsConstructor->globalObject(), Blob, blob.get())); 72 } 73 74 unsigned blobPartsLength = 0; 75 JSObject* blobParts = toJSSequence(exec, exec->argument(0), blobPartsLength); 76 if (exec->hadException()) 77 return JSValue::encode(jsUndefined()); 78 ASSERT(blobParts); 79 80 String type; 81 String endings = ASCIILiteral("transparent"); 82 83 if (exec->argumentCount() > 1) { 84 JSValue blobPropertyBagValue = exec->argument(1); 85 86 if (!blobPropertyBagValue.isObject()) 87 return throwVMError(exec, createTypeError(exec, "Second argument of the constructor is not of type Object")); 88 89 // Given the above test, this will always yield an object. 90 JSObject* blobPropertyBagObject = blobPropertyBagValue.toObject(exec); 91 92 // Create the dictionary wrapper from the initializer object. 93 JSDictionary dictionary(exec, blobPropertyBagObject); 94 95 // Attempt to get the endings property and validate it. 96 bool containsEndings = dictionary.get("endings", endings); 97 if (exec->hadException()) 98 return JSValue::encode(jsUndefined()); 99 100 if (containsEndings) { 101 if (endings != "transparent" && endings != "native") 102 return throwVMError(exec, createTypeError(exec, "The endings property must be either \"transparent\" or \"native\"")); 103 } 104 105 // Attempt to get the type property. 106 dictionary.get("type", type); 107 if (exec->hadException()) 108 return JSValue::encode(jsUndefined()); 109 } 110 111 ASSERT(endings == "transparent" || endings == "native"); 112 113 BlobBuilder blobBuilder; 114 115 for (unsigned i = 0; i < blobPartsLength; ++i) { 116 JSValue item = blobParts->get(exec, i); 117 if (exec->hadException()) 118 return JSValue::encode(jsUndefined()); 119 120 if (ArrayBuffer* arrayBuffer = toArrayBuffer(item)) 121 blobBuilder.append(arrayBuffer); 122 else if (RefPtr<ArrayBufferView> arrayBufferView = toArrayBufferView(item)) 123 blobBuilder.append(arrayBufferView.release()); 124 else if (Blob* blob = toBlob(item)) 125 blobBuilder.append(blob); 126 else { 127 String string = item.toString(exec)->value(exec); 128 if (exec->hadException()) 129 return JSValue::encode(jsUndefined()); 130 blobBuilder.append(string, endings); 131 } 132 } 133 134 RefPtr<Blob> blob = Blob::create(blobBuilder.finalize(), Blob::normalizedContentType(type)); 135 136 return JSValue::encode(CREATE_DOM_WRAPPER(jsConstructor->globalObject(), Blob, blob.get())); 137} 138 139} // namespace WebCore 140