1cd375cf8e62b055feab8ce4808b8372908951ac
[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 using namespace WebCore;
38
39 namespace WebKit {
40
41 NetworkBlobRegistry& NetworkBlobRegistry::singleton()
42 {
43     ASSERT(RunLoop::isMain());
44     static NeverDestroyed<NetworkBlobRegistry> registry;
45     return registry;
46 }
47
48 NetworkBlobRegistry::NetworkBlobRegistry()
49 {
50 }
51
52 void NetworkBlobRegistry::registerFileBlobURL(NetworkConnectionToWebProcess* connection, const URL& url, const String& path, RefPtr<SandboxExtension>&& sandboxExtension, const String& contentType)
53 {
54     blobRegistry().registerFileBlobURL(url, BlobDataFileReferenceWithSandboxExtension::create(path, WTFMove(sandboxExtension)), contentType);
55
56     ASSERT(!m_blobsForConnection.get(connection).contains(url));
57     BlobForConnectionMap::iterator mapIterator = m_blobsForConnection.find(connection);
58     if (mapIterator == m_blobsForConnection.end())
59         mapIterator = m_blobsForConnection.add(connection, HashSet<URL>()).iterator;
60     mapIterator->value.add(url);
61 }
62
63 void NetworkBlobRegistry::registerBlobURL(NetworkConnectionToWebProcess* connection, const URL& url, Vector<WebCore::BlobPart>&& blobParts, const String& contentType)
64 {
65     blobRegistry().registerBlobURL(url, WTFMove(blobParts), contentType);
66
67     ASSERT(!m_blobsForConnection.get(connection).contains(url));
68     BlobForConnectionMap::iterator mapIterator = m_blobsForConnection.find(connection);
69     if (mapIterator == m_blobsForConnection.end())
70         mapIterator = m_blobsForConnection.add(connection, HashSet<URL>()).iterator;
71     mapIterator->value.add(url);
72 }
73
74 void NetworkBlobRegistry::registerBlobURL(NetworkConnectionToWebProcess* connection, const WebCore::URL& url, const WebCore::URL& srcURL, bool shouldBypassConnectionCheck)
75 {
76     // The connection may not be registered if NetworkProcess prevously crashed for any reason.
77     BlobForConnectionMap::iterator mapIterator = m_blobsForConnection.find(connection);
78     if (mapIterator == m_blobsForConnection.end()) {
79         if (!shouldBypassConnectionCheck)
80             return;
81         mapIterator = m_blobsForConnection.add(connection, HashSet<URL>()).iterator;
82     }
83
84     blobRegistry().registerBlobURL(url, srcURL);
85
86     ASSERT(shouldBypassConnectionCheck || mapIterator->value.contains(srcURL));
87     mapIterator->value.add(url);
88 }
89
90 void NetworkBlobRegistry::registerBlobURLOptionallyFileBacked(NetworkConnectionToWebProcess* connection, const URL& url, const URL& srcURL, const String& fileBackedPath, const String& contentType)
91 {
92     auto fileReference = connection->getBlobDataFileReferenceForPath(fileBackedPath);
93     ASSERT(fileReference);
94
95     blobRegistry().registerBlobURLOptionallyFileBacked(url, srcURL, WTFMove(fileReference), contentType);
96
97     ASSERT(!m_blobsForConnection.get(connection).contains(url));
98     BlobForConnectionMap::iterator mapIterator = m_blobsForConnection.find(connection);
99     if (mapIterator == m_blobsForConnection.end())
100         mapIterator = m_blobsForConnection.add(connection, HashSet<URL>()).iterator;
101     mapIterator->value.add(url);
102 }
103
104 void NetworkBlobRegistry::registerBlobURLForSlice(NetworkConnectionToWebProcess* connection, const WebCore::URL& url, const WebCore::URL& srcURL, int64_t start, int64_t end)
105 {
106     // The connection may not be registered if NetworkProcess prevously crashed for any reason.
107     BlobForConnectionMap::iterator mapIterator = m_blobsForConnection.find(connection);
108     if (mapIterator == m_blobsForConnection.end())
109         return;
110
111     blobRegistry().registerBlobURLForSlice(url, srcURL, start, end);
112
113     ASSERT(mapIterator->value.contains(srcURL));
114     mapIterator->value.add(url);
115 }
116
117 void NetworkBlobRegistry::unregisterBlobURL(NetworkConnectionToWebProcess* connection, const WebCore::URL& url)
118 {
119     // The connection may not be registered if NetworkProcess prevously crashed for any reason.
120     BlobForConnectionMap::iterator mapIterator = m_blobsForConnection.find(connection);
121     if (mapIterator == m_blobsForConnection.end())
122         return;
123
124     blobRegistry().unregisterBlobURL(url);
125
126     ASSERT(mapIterator->value.contains(url));
127     mapIterator->value.remove(url);
128 }
129
130 uint64_t NetworkBlobRegistry::blobSize(NetworkConnectionToWebProcess* connection, const WebCore::URL& url)
131 {
132     if (!m_blobsForConnection.contains(connection) || !m_blobsForConnection.find(connection)->value.contains(url))
133         return 0;
134
135     return blobRegistry().blobSize(url);
136 }
137
138 void NetworkBlobRegistry::writeBlobsToTemporaryFiles(const Vector<String>& blobURLs, Function<void(const Vector<String>&)>&& completionHandler)
139 {
140     blobRegistry().writeBlobsToTemporaryFiles(blobURLs, WTFMove(completionHandler));
141 }
142
143 void NetworkBlobRegistry::connectionToWebProcessDidClose(NetworkConnectionToWebProcess* connection)
144 {
145     if (!m_blobsForConnection.contains(connection))
146         return;
147
148     HashSet<URL>& blobsForConnection = m_blobsForConnection.find(connection)->value;
149     for (HashSet<URL>::iterator iter = blobsForConnection.begin(), end = blobsForConnection.end(); iter != end; ++iter)
150         blobRegistry().unregisterBlobURL(*iter);
151
152     m_blobsForConnection.remove(connection);
153 }
154
155 Vector<RefPtr<BlobDataFileReference>> NetworkBlobRegistry::filesInBlob(NetworkConnectionToWebProcess& connection, const WebCore::URL& url)
156 {
157     if (!m_blobsForConnection.contains(&connection) || !m_blobsForConnection.find(&connection)->value.contains(url))
158         return Vector<RefPtr<BlobDataFileReference>>();
159
160     ASSERT(blobRegistry().isBlobRegistryImpl());
161     BlobData* blobData = static_cast<BlobRegistryImpl&>(blobRegistry()).getBlobDataFromURL(url);
162     if (!blobData)
163         return Vector<RefPtr<BlobDataFileReference>>();
164
165     Vector<RefPtr<BlobDataFileReference>> result;
166     for (const BlobDataItem& item : blobData->items()) {
167         if (item.type() == BlobDataItem::Type::File)
168             result.append(item.file());
169     }
170
171     return result;
172 }
173
174 }