Use NeverDestroyed instead of DEPRECATED_DEFINE_STATIC_LOCAL
[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 "BlobURL.h"
35 #include "File.h"
36 #include "ScriptExecutionContext.h"
37 #include "ThreadableBlobRegistry.h"
38 #include <wtf/NeverDestroyed.h>
39 #include <wtf/text/CString.h>
40
41 namespace WebCore {
42
43 class BlobURLRegistry final : public URLRegistry {
44 public:
45     virtual void registerURL(SecurityOrigin*, const URL&, URLRegistrable*) override;
46     virtual void unregisterURL(const URL&) override;
47
48     static URLRegistry& registry();
49 };
50
51
52 void BlobURLRegistry::registerURL(SecurityOrigin* origin, const URL& publicURL, URLRegistrable* blob)
53 {
54     ASSERT(&blob->registry() == this);
55     ThreadableBlobRegistry::registerBlobURL(origin, publicURL, static_cast<Blob*>(blob)->url());
56 }
57
58 void BlobURLRegistry::unregisterURL(const URL& url)
59 {
60     ThreadableBlobRegistry::unregisterBlobURL(url);
61 }
62
63 URLRegistry& BlobURLRegistry::registry()
64 {
65     static NeverDestroyed<BlobURLRegistry> instance;
66     return instance;
67 }
68
69 Blob::Blob(UninitializedContructor)
70 {
71 }
72
73 Blob::Blob()
74     : m_size(0)
75 {
76     m_internalURL = BlobURL::createInternalURL();
77     ThreadableBlobRegistry::registerBlobURL(m_internalURL, Vector<BlobPart>(), String());
78 }
79
80 Blob::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(WTFMove(data)));
86     m_internalURL = BlobURL::createInternalURL();
87     ThreadableBlobRegistry::registerBlobURL(m_internalURL, WTFMove(blobParts), contentType);
88 }
89
90 Blob::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, WTFMove(blobParts), contentType);
96 }
97
98 Blob::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
106 Blob::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
114 Blob::~Blob()
115 {
116     ThreadableBlobRegistry::unregisterBlobURL(m_internalURL);
117 }
118
119 unsigned 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
131 bool 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
153 String Blob::normalizedContentType(const String& contentType)
154 {
155     if (Blob::isValidContentType(contentType))
156         return contentType.lower();
157     return emptyString();
158 }
159
160 bool 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
186 bool 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
199 URLRegistry& Blob::registry() const
200 {
201     return BlobURLRegistry::registry();
202 }
203
204
205 } // namespace WebCore