Change NetworkConnectionToWebProcess* to NetworkConnectionToWebProcess& where possible
[WebKit-https.git] / Source / WebKit / NetworkProcess / FileAPI / NetworkBlobRegistry.cpp
1 /*
2  * Copyright (C) 2013-2016 Apple 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
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "NetworkBlobRegistry.h"
28
29 #include "BlobDataFileReferenceWithSandboxExtension.h"
30 #include "NetworkConnectionToWebProcess.h"
31 #include "SandboxExtension.h"
32 #include <WebCore/BlobPart.h>
33 #include <WebCore/BlobRegistryImpl.h>
34 #include <wtf/NeverDestroyed.h>
35 #include <wtf/RunLoop.h>
36
37 namespace WebKit {
38 using namespace WebCore;
39
40 NetworkBlobRegistry& NetworkBlobRegistry::singleton()
41 {
42     ASSERT(RunLoop::isMain());
43     static NeverDestroyed<NetworkBlobRegistry> registry;
44     return registry;
45 }
46
47 NetworkBlobRegistry::NetworkBlobRegistry()
48 {
49 }
50
51 void NetworkBlobRegistry::registerFileBlobURL(NetworkConnectionToWebProcess& connection, const URL& url, const String& path, RefPtr<SandboxExtension>&& sandboxExtension, const String& contentType)
52 {
53     blobRegistry().registerFileBlobURL(url, BlobDataFileReferenceWithSandboxExtension::create(path, WTFMove(sandboxExtension)), contentType);
54
55     ASSERT(!m_blobsForConnection.get(&connection).contains(url));
56     BlobForConnectionMap::iterator mapIterator = m_blobsForConnection.find(&connection);
57     if (mapIterator == m_blobsForConnection.end())
58         mapIterator = m_blobsForConnection.add(&connection, HashSet<URL>()).iterator;
59     mapIterator->value.add(url);
60 }
61
62 void NetworkBlobRegistry::registerBlobURL(NetworkConnectionToWebProcess& connection, const URL& url, Vector<WebCore::BlobPart>&& blobParts, const String& contentType)
63 {
64     blobRegistry().registerBlobURL(url, WTFMove(blobParts), contentType);
65
66     ASSERT(!m_blobsForConnection.get(&connection).contains(url));
67     BlobForConnectionMap::iterator mapIterator = m_blobsForConnection.find(&connection);
68     if (mapIterator == m_blobsForConnection.end())
69         mapIterator = m_blobsForConnection.add(&connection, HashSet<URL>()).iterator;
70     mapIterator->value.add(url);
71 }
72
73 void NetworkBlobRegistry::registerBlobURL(NetworkConnectionToWebProcess& connection, const URL& url, const URL& srcURL, bool shouldBypassConnectionCheck)
74 {
75     // The connection may not be registered if NetworkProcess prevously crashed for any reason.
76     BlobForConnectionMap::iterator mapIterator = m_blobsForConnection.find(&connection);
77     if (mapIterator == m_blobsForConnection.end()) {
78         if (!shouldBypassConnectionCheck)
79             return;
80         mapIterator = m_blobsForConnection.add(&connection, HashSet<URL>()).iterator;
81     }
82
83     blobRegistry().registerBlobURL(url, srcURL);
84
85     ASSERT(shouldBypassConnectionCheck || mapIterator->value.contains(srcURL));
86     mapIterator->value.add(url);
87 }
88
89 void NetworkBlobRegistry::registerBlobURLOptionallyFileBacked(NetworkConnectionToWebProcess& connection, const URL& url, const URL& srcURL, const String& fileBackedPath, const String& contentType)
90 {
91     blobRegistry().registerBlobURLOptionallyFileBacked(url, srcURL, BlobDataFileReferenceWithSandboxExtension::create(fileBackedPath, nullptr), contentType);
92
93     ASSERT(!m_blobsForConnection.get(&connection).contains(url));
94     BlobForConnectionMap::iterator mapIterator = m_blobsForConnection.find(&connection);
95     if (mapIterator == m_blobsForConnection.end())
96         mapIterator = m_blobsForConnection.add(&connection, HashSet<URL>()).iterator;
97     mapIterator->value.add(url);
98 }
99
100 void NetworkBlobRegistry::registerBlobURLForSlice(NetworkConnectionToWebProcess& connection, const URL& url, const URL& srcURL, int64_t start, int64_t end)
101 {
102     // The connection may not be registered if NetworkProcess prevously crashed for any reason.
103     BlobForConnectionMap::iterator mapIterator = m_blobsForConnection.find(&connection);
104     if (mapIterator == m_blobsForConnection.end())
105         return;
106
107     blobRegistry().registerBlobURLForSlice(url, srcURL, start, end);
108
109     ASSERT(mapIterator->value.contains(srcURL));
110     mapIterator->value.add(url);
111 }
112
113 void NetworkBlobRegistry::unregisterBlobURL(NetworkConnectionToWebProcess& connection, const URL& url)
114 {
115     // The connection may not be registered if NetworkProcess prevously crashed for any reason.
116     BlobForConnectionMap::iterator mapIterator = m_blobsForConnection.find(&connection);
117     if (mapIterator == m_blobsForConnection.end())
118         return;
119
120     blobRegistry().unregisterBlobURL(url);
121
122     mapIterator->value.remove(url);
123 }
124
125 uint64_t NetworkBlobRegistry::blobSize(NetworkConnectionToWebProcess& connection, const URL& url)
126 {
127     if (!m_blobsForConnection.contains(&connection) || !m_blobsForConnection.find(&connection)->value.contains(url))
128         return 0;
129
130     return blobRegistry().blobSize(url);
131 }
132
133 void NetworkBlobRegistry::writeBlobsToTemporaryFiles(const Vector<String>& blobURLs, CompletionHandler<void(Vector<String>&&)>&& completionHandler)
134 {
135     blobRegistry().writeBlobsToTemporaryFiles(blobURLs, WTFMove(completionHandler));
136 }
137
138 void NetworkBlobRegistry::writeBlobToFilePath(const URL& blobURL, const String& path, CompletionHandler<void(bool success)>&& completionHandler)
139 {
140     if (!blobRegistry().isBlobRegistryImpl()) {
141         completionHandler(false);
142         ASSERT_NOT_REACHED();
143         return;
144     }
145
146     auto blobFiles = filesInBlob({ { }, blobURL });
147     for (auto& file : blobFiles)
148         file->prepareForFileAccess();
149
150     static_cast<BlobRegistryImpl&>(blobRegistry()).writeBlobToFilePath(blobURL, path, [blobFiles = WTFMove(blobFiles), completionHandler = WTFMove(completionHandler)] (bool success) mutable {
151         for (auto& file : blobFiles)
152             file->revokeFileAccess();
153         completionHandler(success);
154     });
155 }
156
157 void NetworkBlobRegistry::connectionToWebProcessDidClose(NetworkConnectionToWebProcess& connection)
158 {
159     if (!m_blobsForConnection.contains(&connection))
160         return;
161
162     HashSet<URL>& blobsForConnection = m_blobsForConnection.find(&connection)->value;
163     for (HashSet<URL>::iterator iter = blobsForConnection.begin(), end = blobsForConnection.end(); iter != end; ++iter)
164         blobRegistry().unregisterBlobURL(*iter);
165
166     m_blobsForConnection.remove(&connection);
167 }
168
169 Vector<RefPtr<BlobDataFileReference>> NetworkBlobRegistry::filesInBlob(NetworkConnectionToWebProcess& connection, const URL& url)
170 {
171     if (!m_blobsForConnection.contains(&connection) || !m_blobsForConnection.find(&connection)->value.contains(url))
172         return { };
173
174     return filesInBlob(url);
175 }
176
177 Vector<RefPtr<BlobDataFileReference>> NetworkBlobRegistry::filesInBlob(const URL& url)
178 {
179     ASSERT(blobRegistry().isBlobRegistryImpl());
180     BlobData* blobData = static_cast<BlobRegistryImpl&>(blobRegistry()).getBlobDataFromURL(url);
181     if (!blobData)
182         return { };
183
184     Vector<RefPtr<BlobDataFileReference>> result;
185     for (const BlobDataItem& item : blobData->items()) {
186         if (item.type() == BlobDataItem::Type::File)
187             result.append(item.file());
188     }
189
190     return result;
191 }
192
193 }