[WTF] Use Semaphore and BinarySemaphore instead of dispatch_semaphore_t
[WebKit-https.git] / Source / WebCore / fileapi / ThreadableBlobRegistry.cpp
1 /*
2  * Copyright (C) 2010 Google Inc. All rights reserved.
3  * Copyright (C) 2013, 2014, 2016 Apple Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  *     * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *     * Redistributions in binary form must reproduce the above
12  * copyright notice, this list of conditions and the following disclaimer
13  * in the documentation and/or other materials provided with the
14  * distribution.
15  *     * Neither the name of Google Inc. nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 #include "config.h"
33 #include "ThreadableBlobRegistry.h"
34
35 #include "BlobDataFileReference.h"
36 #include "BlobPart.h"
37 #include "BlobRegistry.h"
38 #include "BlobURL.h"
39 #include "SecurityOrigin.h"
40 #include <mutex>
41 #include <wtf/CrossThreadQueue.h>
42 #include <wtf/CrossThreadTask.h>
43 #include <wtf/HashMap.h>
44 #include <wtf/MainThread.h>
45 #include <wtf/RefPtr.h>
46 #include <wtf/ThreadSpecific.h>
47 #include <wtf/text/StringHash.h>
48 #include <wtf/threads/BinarySemaphore.h>
49
50 using WTF::ThreadSpecific;
51
52 namespace WebCore {
53
54 typedef HashMap<String, RefPtr<SecurityOrigin>> BlobUrlOriginMap;
55
56 static ThreadSpecific<BlobUrlOriginMap>& originMap()
57 {
58     static std::once_flag onceFlag;
59     static ThreadSpecific<BlobUrlOriginMap>* map;
60     std::call_once(onceFlag, []{
61         map = new ThreadSpecific<BlobUrlOriginMap>;
62     });
63
64     return *map;
65 }
66
67 static void postToMainThread(CrossThreadTask&& task)
68 {
69     static std::once_flag onceFlag;
70     static CrossThreadQueue<CrossThreadTask>* queue;
71     std::call_once(onceFlag, [] {
72         queue = new CrossThreadQueue<CrossThreadTask>;
73     });
74
75     queue->append(WTFMove(task));
76
77     callOnMainThread([] {
78         auto task = queue->tryGetMessage();
79         ASSERT(task);
80         task->performTask();
81     });
82 }
83
84 void ThreadableBlobRegistry::registerFileBlobURL(const URL& url, const String& path, const String& contentType)
85 {
86     if (isMainThread())
87         blobRegistry().registerFileBlobURL(url, BlobDataFileReference::create(path), contentType);
88     else {
89         callOnMainThread([url = url.isolatedCopy(), path = path.isolatedCopy(), contentType = contentType.isolatedCopy()] {
90             blobRegistry().registerFileBlobURL(url, BlobDataFileReference::create(path), contentType);
91         });
92     }
93 }
94
95 void ThreadableBlobRegistry::registerBlobURL(const URL& url, Vector<BlobPart>&& blobParts, const String& contentType)
96 {
97     if (isMainThread())
98         blobRegistry().registerBlobURL(url, WTFMove(blobParts), contentType);
99     else {
100         for (auto& part : blobParts)
101             part.detachFromCurrentThread();
102         callOnMainThread([url = url.isolatedCopy(), blobParts = WTFMove(blobParts), contentType = contentType.isolatedCopy()]() mutable {
103             blobRegistry().registerBlobURL(url, WTFMove(blobParts), contentType);
104         });
105     }
106 }
107
108 void ThreadableBlobRegistry::registerBlobURL(SecurityOrigin* origin, const URL& url, const URL& srcURL)
109 {
110     // If the blob URL contains null origin, as in the context with unique security origin or file URL, save the mapping between url and origin so that the origin can be retrived when doing security origin check.
111     if (origin && BlobURL::getOrigin(url) == "null")
112         originMap()->add(url.string(), origin);
113
114     if (isMainThread())
115         blobRegistry().registerBlobURL(url, srcURL);
116     else {
117         callOnMainThread([url = url.isolatedCopy(), srcURL = srcURL.isolatedCopy()] {
118             blobRegistry().registerBlobURL(url, srcURL);
119         });
120     }
121 }
122
123 void ThreadableBlobRegistry::registerBlobURLOptionallyFileBacked(const URL& url, const URL& srcURL, const String& fileBackedPath, const String& contentType)
124 {
125     if (isMainThread())
126         blobRegistry().registerBlobURLOptionallyFileBacked(url, srcURL, BlobDataFileReference::create(fileBackedPath), contentType);
127     else
128         postToMainThread(createCrossThreadTask(ThreadableBlobRegistry::registerBlobURLOptionallyFileBacked, url, srcURL, fileBackedPath, contentType));
129 }
130
131 void ThreadableBlobRegistry::registerBlobURLForSlice(const URL& newURL, const URL& srcURL, long long start, long long end)
132 {
133     if (isMainThread())
134         blobRegistry().registerBlobURLForSlice(newURL, srcURL, start, end);
135     else {
136         callOnMainThread([newURL = newURL.isolatedCopy(), srcURL = srcURL.isolatedCopy(), start, end] {
137             blobRegistry().registerBlobURLForSlice(newURL, srcURL, start, end);
138         });
139     }
140 }
141
142 unsigned long long ThreadableBlobRegistry::blobSize(const URL& url)
143 {
144     unsigned long long resultSize;
145     if (isMainThread())
146         resultSize = blobRegistry().blobSize(url);
147     else {
148         BinarySemaphore semaphore;
149         callOnMainThread([url = url.isolatedCopy(), &semaphore, &resultSize] {
150             resultSize = blobRegistry().blobSize(url);
151             semaphore.signal();
152         });
153         semaphore.wait();
154     }
155     return resultSize;
156 }
157
158 void ThreadableBlobRegistry::unregisterBlobURL(const URL& url)
159 {
160     if (BlobURL::getOrigin(url) == "null")
161         originMap()->remove(url.string());
162
163     if (isMainThread())
164         blobRegistry().unregisterBlobURL(url);
165     else {
166         callOnMainThread([url = url.isolatedCopy()] {
167             blobRegistry().unregisterBlobURL(url);
168         });
169     }
170 }
171
172 RefPtr<SecurityOrigin> ThreadableBlobRegistry::getCachedOrigin(const URL& url)
173 {
174     return originMap()->get(url.string());
175 }
176
177 } // namespace WebCore