1/* 2 * Copyright (C) 2010 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 "Blob.h" 33 34#include "BlobURL.h" 35#include "File.h" 36#include "ScriptExecutionContext.h" 37#include "ThreadableBlobRegistry.h" 38#include <wtf/text/CString.h> 39 40namespace WebCore { 41 42class BlobURLRegistry final : public URLRegistry { 43public: 44 virtual void registerURL(SecurityOrigin*, const URL&, URLRegistrable*) override; 45 virtual void unregisterURL(const URL&) override; 46 47 static URLRegistry& registry(); 48}; 49 50 51void BlobURLRegistry::registerURL(SecurityOrigin* origin, const URL& publicURL, URLRegistrable* blob) 52{ 53 ASSERT(&blob->registry() == this); 54 ThreadableBlobRegistry::registerBlobURL(origin, publicURL, static_cast<Blob*>(blob)->url()); 55} 56 57void BlobURLRegistry::unregisterURL(const URL& url) 58{ 59 ThreadableBlobRegistry::unregisterBlobURL(url); 60} 61 62URLRegistry& BlobURLRegistry::registry() 63{ 64 DEPRECATED_DEFINE_STATIC_LOCAL(BlobURLRegistry, instance, ()); 65 return instance; 66} 67 68 69Blob::Blob(UninitializedContructor) 70{ 71} 72 73Blob::Blob() 74 : m_size(0) 75{ 76 m_internalURL = BlobURL::createInternalURL(); 77 ThreadableBlobRegistry::registerBlobURL(m_internalURL, Vector<BlobPart>(), String()); 78} 79 80Blob::Blob(Vector<char> data, const String& contentType) 81 : m_type(contentType) 82 , m_size(data.size()) 83{ 84 Vector<BlobPart> blobParts; 85 blobParts.append(BlobPart(WTF::move(data))); 86 m_internalURL = BlobURL::createInternalURL(); 87 ThreadableBlobRegistry::registerBlobURL(m_internalURL, WTF::move(blobParts), contentType); 88} 89 90Blob::Blob(Vector<BlobPart> blobParts, const String& contentType) 91 : m_type(contentType) 92 , m_size(-1) 93{ 94 m_internalURL = BlobURL::createInternalURL(); 95 ThreadableBlobRegistry::registerBlobURL(m_internalURL, WTF::move(blobParts), contentType); 96} 97 98Blob::Blob(DeserializationContructor, const URL& srcURL, const String& type, long long size) 99 : m_type(Blob::normalizedContentType(type)) 100 , m_size(size) 101{ 102 m_internalURL = BlobURL::createInternalURL(); 103 ThreadableBlobRegistry::registerBlobURL(0, m_internalURL, srcURL); 104} 105 106Blob::Blob(const URL& srcURL, long long start, long long end, const String& type) 107 : m_type(Blob::normalizedContentType(type)) 108 , m_size(-1) // size is not necessarily equal to end - start. 109{ 110 m_internalURL = BlobURL::createInternalURL(); 111 ThreadableBlobRegistry::registerBlobURLForSlice(m_internalURL, srcURL, start, end); 112} 113 114Blob::~Blob() 115{ 116 ThreadableBlobRegistry::unregisterBlobURL(m_internalURL); 117} 118 119unsigned long long Blob::size() const 120{ 121 if (m_size < 0) { 122 // FIXME: JavaScript cannot represent sizes as large as unsigned long long, we need to 123 // come up with an exception to throw if file size is not representable. 124 unsigned long long actualSize = ThreadableBlobRegistry::blobSize(m_internalURL); 125 m_size = (WTF::isInBounds<long long>(actualSize)) ? static_cast<long long>(actualSize) : 0; 126 } 127 128 return static_cast<unsigned long long>(m_size); 129} 130 131bool Blob::isValidContentType(const String& contentType) 132{ 133 if (contentType.isNull()) 134 return true; 135 136 size_t length = contentType.length(); 137 if (contentType.is8Bit()) { 138 const LChar* characters = contentType.characters8(); 139 for (size_t i = 0; i < length; ++i) { 140 if (characters[i] < 0x20 || characters[i] > 0x7e) 141 return false; 142 } 143 } else { 144 const UChar* characters = contentType.characters16(); 145 for (size_t i = 0; i < length; ++i) { 146 if (characters[i] < 0x20 || characters[i] > 0x7e) 147 return false; 148 } 149 } 150 return true; 151} 152 153String Blob::normalizedContentType(const String& contentType) 154{ 155 if (Blob::isValidContentType(contentType)) 156 return contentType.lower(); 157 return emptyString(); 158} 159 160bool Blob::isNormalizedContentType(const String& contentType) 161{ 162 if (contentType.isNull()) 163 return true; 164 165 size_t length = contentType.length(); 166 if (contentType.is8Bit()) { 167 const LChar* characters = contentType.characters8(); 168 for (size_t i = 0; i < length; ++i) { 169 if (characters[i] < 0x20 || characters[i] > 0x7e) 170 return false; 171 if (characters[i] >= 'A' && characters[i] <= 'Z') 172 return false; 173 } 174 } else { 175 const UChar* characters = contentType.characters16(); 176 for (size_t i = 0; i < length; ++i) { 177 if (characters[i] < 0x20 || characters[i] > 0x7e) 178 return false; 179 if (characters[i] >= 'A' && characters[i] <= 'Z') 180 return false; 181 } 182 } 183 return true; 184} 185 186bool Blob::isNormalizedContentType(const CString& contentType) 187{ 188 size_t length = contentType.length(); 189 const char* characters = contentType.data(); 190 for (size_t i = 0; i < length; ++i) { 191 if (characters[i] < 0x20 || characters[i] > 0x7e) 192 return false; 193 if (characters[i] >= 'A' && characters[i] <= 'Z') 194 return false; 195 } 196 return true; 197} 198 199URLRegistry& Blob::registry() const 200{ 201 return BlobURLRegistry::registry(); 202} 203 204 205} // namespace WebCore 206