BlobRegistry no longer needs SessionIDs
[WebKit-https.git] / Source / WebCore / fileapi / Blob.cpp
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 "BlobBuilder.h"
35 #include "BlobPart.h"
36 #include "BlobURL.h"
37 #include "File.h"
38 #include "ScriptExecutionContext.h"
39 #include "SharedBuffer.h"
40 #include "ThreadableBlobRegistry.h"
41 #include <wtf/IsoMallocInlines.h>
42 #include <wtf/NeverDestroyed.h>
43 #include <wtf/text/CString.h>
44
45 namespace WebCore {
46
47 WTF_MAKE_ISO_ALLOCATED_IMPL(Blob);
48
49 class BlobURLRegistry final : public URLRegistry {
50 public:
51     void registerURL(ScriptExecutionContext&, const URL&, URLRegistrable&) final;
52     void unregisterURL(const URL&) final;
53
54     static URLRegistry& registry();
55 };
56
57
58 void BlobURLRegistry::registerURL(ScriptExecutionContext& context, const URL& publicURL, URLRegistrable& blob)
59 {
60     ASSERT(&blob.registry() == this);
61     ThreadableBlobRegistry::registerBlobURL(context.securityOrigin(), publicURL, static_cast<Blob&>(blob).url());
62 }
63
64 void BlobURLRegistry::unregisterURL(const URL& url)
65 {
66     ThreadableBlobRegistry::unregisterBlobURL(url);
67 }
68
69 URLRegistry& BlobURLRegistry::registry()
70 {
71     static NeverDestroyed<BlobURLRegistry> instance;
72     return instance;
73 }
74
75 Blob::Blob(UninitializedContructor, URL&& url, String&& type)
76     : m_internalURL(WTFMove(url))
77     , m_type(WTFMove(type))
78 {
79 }
80
81 Blob::Blob()
82     : m_size(0)
83 {
84     m_internalURL = BlobURL::createInternalURL();
85     ThreadableBlobRegistry::registerBlobURL(m_internalURL, { },  { });
86 }
87
88 Blob::Blob(Vector<BlobPartVariant>&& blobPartVariants, const BlobPropertyBag& propertyBag)
89     : m_internalURL(BlobURL::createInternalURL())
90     , m_type(normalizedContentType(propertyBag.type))
91 {
92     BlobBuilder builder(propertyBag.endings);
93     for (auto& blobPartVariant : blobPartVariants) {
94         WTF::switchOn(blobPartVariant,
95             [&] (auto& part) {
96                 builder.append(WTFMove(part));
97             }
98         );
99     }
100
101     ThreadableBlobRegistry::registerBlobURL(m_internalURL, builder.finalize(), m_type);
102 }
103
104 Blob::Blob(const SharedBuffer& buffer, const String& contentType)
105     : m_type(contentType)
106     , m_size(buffer.size())
107 {
108     Vector<uint8_t> data;
109     data.append(buffer.data(), buffer.size());
110
111     Vector<BlobPart> blobParts;
112     blobParts.append(BlobPart(WTFMove(data)));
113     m_internalURL = BlobURL::createInternalURL();
114     ThreadableBlobRegistry::registerBlobURL(m_internalURL, WTFMove(blobParts), contentType);
115 }
116
117 Blob::Blob(Vector<uint8_t>&& data, const String& contentType)
118     : m_type(contentType)
119     , m_size(data.size())
120 {
121     Vector<BlobPart> blobParts;
122     blobParts.append(BlobPart(WTFMove(data)));
123     m_internalURL = BlobURL::createInternalURL();
124     ThreadableBlobRegistry::registerBlobURL(m_internalURL, WTFMove(blobParts), contentType);
125 }
126
127 Blob::Blob(ReferencingExistingBlobConstructor, const Blob& blob)
128     : m_internalURL(BlobURL::createInternalURL())
129     , m_type(blob.type())
130     , m_size(blob.size())
131 {
132     ThreadableBlobRegistry::registerBlobURL(m_internalURL, { BlobPart(blob.url()) } , m_type);
133 }
134
135 Blob::Blob(DeserializationContructor, const URL& srcURL, const String& type, Optional<unsigned long long> size, const String& fileBackedPath)
136     : m_type(normalizedContentType(type))
137     , m_size(size)
138 {
139     m_internalURL = BlobURL::createInternalURL();
140     if (fileBackedPath.isEmpty())
141         ThreadableBlobRegistry::registerBlobURL(nullptr, m_internalURL, srcURL);
142     else
143         ThreadableBlobRegistry::registerBlobURLOptionallyFileBacked(m_internalURL, srcURL, fileBackedPath, m_type);
144 }
145
146 Blob::Blob(const URL& srcURL, long long start, long long end, const String& type)
147     : m_type(normalizedContentType(type))
148     // m_size is not necessarily equal to end - start so we do not initialize it here.
149 {
150     m_internalURL = BlobURL::createInternalURL();
151     ThreadableBlobRegistry::registerBlobURLForSlice(m_internalURL, srcURL, start, end);
152 }
153
154 Blob::~Blob()
155 {
156     ThreadableBlobRegistry::unregisterBlobURL(m_internalURL);
157 }
158
159 unsigned long long Blob::size() const
160 {
161     if (!m_size) {
162         // FIXME: JavaScript cannot represent sizes as large as unsigned long long, we need to
163         // come up with an exception to throw if file size is not representable.
164         unsigned long long actualSize = ThreadableBlobRegistry::blobSize(m_internalURL);
165         m_size = WTF::isInBounds<long long>(actualSize) ? actualSize : 0;
166     }
167
168     return *m_size;
169 }
170
171 bool Blob::isValidContentType(const String& contentType)
172 {
173     // FIXME: Do we really want to treat the empty string and null string as valid content types?
174     unsigned length = contentType.length();
175     for (unsigned i = 0; i < length; ++i) {
176         if (contentType[i] < 0x20 || contentType[i] > 0x7e)
177             return false;
178     }
179     return true;
180 }
181
182 String Blob::normalizedContentType(const String& contentType)
183 {
184     if (!isValidContentType(contentType))
185         return emptyString();
186     return contentType.convertToASCIILowercase();
187 }
188
189 #if !ASSERT_DISABLED
190 bool Blob::isNormalizedContentType(const String& contentType)
191 {
192     // FIXME: Do we really want to treat the empty string and null string as valid content types?
193     unsigned length = contentType.length();
194     for (size_t i = 0; i < length; ++i) {
195         if (contentType[i] < 0x20 || contentType[i] > 0x7e)
196             return false;
197         if (isASCIIUpper(contentType[i]))
198             return false;
199     }
200     return true;
201 }
202
203 bool Blob::isNormalizedContentType(const CString& contentType)
204 {
205     // FIXME: Do we really want to treat the empty string and null string as valid content types?
206     size_t length = contentType.length();
207     const char* characters = contentType.data();
208     for (size_t i = 0; i < length; ++i) {
209         if (characters[i] < 0x20 || characters[i] > 0x7e)
210             return false;
211         if (isASCIIUpper(characters[i]))
212             return false;
213     }
214     return true;
215 }
216 #endif
217
218 URLRegistry& Blob::registry() const
219 {
220     return BlobURLRegistry::registry();
221 }
222
223
224 } // namespace WebCore