[iOS] Redundant pointer events causes material design buttons to flush twice
[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(SecurityOrigin*, const URL&, URLRegistrable&) override;
52     void unregisterURL(const URL&) override;
53
54     static URLRegistry& registry();
55 };
56
57
58 void BlobURLRegistry::registerURL(SecurityOrigin* origin, const URL& publicURL, URLRegistrable& blob)
59 {
60     ASSERT(&blob.registry() == this);
61     ThreadableBlobRegistry::registerBlobURL(origin, 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)
76 {
77 }
78
79 Blob::Blob()
80     : m_size(0)
81 {
82     m_internalURL = BlobURL::createInternalURL();
83     ThreadableBlobRegistry::registerBlobURL(m_internalURL, { },  { });
84 }
85
86 Blob::Blob(Vector<BlobPartVariant>&& blobPartVariants, const BlobPropertyBag& propertyBag)
87     : m_internalURL(BlobURL::createInternalURL())
88     , m_type(normalizedContentType(propertyBag.type))
89     , m_size(-1)
90 {
91     BlobBuilder builder(propertyBag.endings);
92     for (auto& blobPartVariant : blobPartVariants) {
93         WTF::switchOn(blobPartVariant,
94             [&] (auto& part) {
95                 builder.append(WTFMove(part));
96             }
97         );
98     }
99
100     ThreadableBlobRegistry::registerBlobURL(m_internalURL, builder.finalize(), m_type);
101 }
102
103 Blob::Blob(const SharedBuffer& buffer, const String& contentType)
104     : m_type(contentType)
105     , m_size(buffer.size())
106 {
107     Vector<uint8_t> data;
108     data.append(buffer.data(), buffer.size());
109
110     Vector<BlobPart> blobParts;
111     blobParts.append(BlobPart(WTFMove(data)));
112     m_internalURL = BlobURL::createInternalURL();
113     ThreadableBlobRegistry::registerBlobURL(m_internalURL, WTFMove(blobParts), contentType);
114 }
115
116 Blob::Blob(Vector<uint8_t>&& data, const String& contentType)
117     : m_type(contentType)
118     , m_size(data.size())
119 {
120     Vector<BlobPart> blobParts;
121     blobParts.append(BlobPart(WTFMove(data)));
122     m_internalURL = BlobURL::createInternalURL();
123     ThreadableBlobRegistry::registerBlobURL(m_internalURL, WTFMove(blobParts), contentType);
124 }
125
126 Blob::Blob(ReferencingExistingBlobConstructor, const Blob& blob)
127     : m_internalURL(BlobURL::createInternalURL())
128     , m_type(blob.type())
129     , m_size(blob.size())
130 {
131     ThreadableBlobRegistry::registerBlobURL(m_internalURL, { BlobPart(blob.url()) } , m_type);
132 }
133
134 Blob::Blob(DeserializationContructor, const URL& srcURL, const String& type, long long size, const String& fileBackedPath)
135     : m_type(normalizedContentType(type))
136     , m_size(size)
137 {
138     m_internalURL = BlobURL::createInternalURL();
139     if (fileBackedPath.isEmpty())
140         ThreadableBlobRegistry::registerBlobURL(nullptr, m_internalURL, srcURL);
141     else
142         ThreadableBlobRegistry::registerBlobURLOptionallyFileBacked(m_internalURL, srcURL, fileBackedPath, m_type);
143 }
144
145 Blob::Blob(const URL& srcURL, long long start, long long end, const String& type)
146     : m_type(normalizedContentType(type))
147     , m_size(-1) // size is not necessarily equal to end - start.
148 {
149     m_internalURL = BlobURL::createInternalURL();
150     ThreadableBlobRegistry::registerBlobURLForSlice(m_internalURL, srcURL, start, end);
151 }
152
153 Blob::~Blob()
154 {
155     ThreadableBlobRegistry::unregisterBlobURL(m_internalURL);
156 }
157
158 unsigned long long Blob::size() const
159 {
160     if (m_size < 0) {
161         // FIXME: JavaScript cannot represent sizes as large as unsigned long long, we need to
162         // come up with an exception to throw if file size is not representable.
163         unsigned long long actualSize = ThreadableBlobRegistry::blobSize(m_internalURL);
164         m_size = WTF::isInBounds<long long>(actualSize) ? static_cast<long long>(actualSize) : 0;
165     }
166
167     return static_cast<unsigned long long>(m_size);
168 }
169
170 bool Blob::isValidContentType(const String& contentType)
171 {
172     // FIXME: Do we really want to treat the empty string and null string as valid content types?
173     unsigned length = contentType.length();
174     for (unsigned i = 0; i < length; ++i) {
175         if (contentType[i] < 0x20 || contentType[i] > 0x7e)
176             return false;
177     }
178     return true;
179 }
180
181 String Blob::normalizedContentType(const String& contentType)
182 {
183     if (!isValidContentType(contentType))
184         return emptyString();
185     return contentType.convertToASCIILowercase();
186 }
187
188 #if !ASSERT_DISABLED
189 bool Blob::isNormalizedContentType(const String& contentType)
190 {
191     // FIXME: Do we really want to treat the empty string and null string as valid content types?
192     unsigned length = contentType.length();
193     for (size_t i = 0; i < length; ++i) {
194         if (contentType[i] < 0x20 || contentType[i] > 0x7e)
195             return false;
196         if (isASCIIUpper(contentType[i]))
197             return false;
198     }
199     return true;
200 }
201
202 bool Blob::isNormalizedContentType(const CString& contentType)
203 {
204     // FIXME: Do we really want to treat the empty string and null string as valid content types?
205     size_t length = contentType.length();
206     const char* characters = contentType.data();
207     for (size_t i = 0; i < length; ++i) {
208         if (characters[i] < 0x20 || characters[i] > 0x7e)
209             return false;
210         if (isASCIIUpper(characters[i]))
211             return false;
212     }
213     return true;
214 }
215 #endif
216
217 URLRegistry& Blob::registry() const
218 {
219     return BlobURLRegistry::registry();
220 }
221
222
223 } // namespace WebCore