Move NetworkCache ownership from NetworkProcess to NetworkSession
[WebKit-https.git] / Source / WebKit / NetworkProcess / NetworkSession.cpp
1 /*
2  * Copyright (C) 2015-2019 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 "NetworkSession.h"
28
29 #include "AdClickAttributionManager.h"
30 #include "Logging.h"
31 #include "NetworkProcess.h"
32 #include "NetworkProcessProxyMessages.h"
33 #include "NetworkResourceLoadParameters.h"
34 #include "NetworkResourceLoader.h"
35 #include "PingLoad.h"
36 #include "StorageManager.h"
37 #include "WebPageProxy.h"
38 #include "WebPageProxyMessages.h"
39 #include "WebProcessProxy.h"
40 #include "WebSocketTask.h"
41 #include <WebCore/AdClickAttribution.h>
42 #include <WebCore/CookieJar.h>
43 #include <WebCore/NetworkStorageSession.h>
44 #include <WebCore/ResourceRequest.h>
45
46 #if PLATFORM(COCOA)
47 #include "NetworkSessionCocoa.h"
48 #endif
49 #if USE(SOUP)
50 #include "NetworkSessionSoup.h"
51 #endif
52 #if USE(CURL)
53 #include "NetworkSessionCurl.h"
54 #endif
55
56 namespace WebKit {
57 using namespace WebCore;
58
59 Ref<NetworkSession> NetworkSession::create(NetworkProcess& networkProcess, NetworkSessionCreationParameters&& parameters)
60 {
61 #if PLATFORM(COCOA)
62     return NetworkSessionCocoa::create(networkProcess, WTFMove(parameters));
63 #endif
64 #if USE(SOUP)
65     return NetworkSessionSoup::create(networkProcess, WTFMove(parameters));
66 #endif
67 #if USE(CURL)
68     return NetworkSessionCurl::create(networkProcess, WTFMove(parameters));
69 #endif
70 }
71
72 NetworkStorageSession* NetworkSession::networkStorageSession() const
73 {
74     // FIXME: https://bugs.webkit.org/show_bug.cgi?id=194926 NetworkSession should own NetworkStorageSession
75     // instead of having separate maps with the same key and different management.
76     auto* storageSession = m_networkProcess->storageSession(m_sessionID);
77     ASSERT(storageSession);
78     return storageSession;
79 }
80
81 NetworkSession::NetworkSession(NetworkProcess& networkProcess, const NetworkSessionCreationParameters& parameters)
82     : m_sessionID(parameters.sessionID)
83     , m_networkProcess(networkProcess)
84     , m_adClickAttribution(makeUniqueRef<AdClickAttributionManager>(parameters.sessionID))
85     , m_storageManager(StorageManager::create(String(parameters.localStorageDirectory)))
86 {
87     if (!m_sessionID.isEphemeral()) {
88         String networkCacheDirectory = parameters.networkCacheDirectory;
89         if (networkCacheDirectory.isNull())
90             networkCacheDirectory = networkProcess.diskCacheDirectory();
91         else
92             SandboxExtension::consumePermanently(parameters.networkCacheDirectoryExtensionHandle);
93
94         m_cache = NetworkCache::Cache::open(networkProcess, networkCacheDirectory, networkProcess.cacheOptions());
95         if (!m_cache)
96             RELEASE_LOG_ERROR(NetworkCache, "Failed to initialize the WebKit network disk cache");
97     }
98
99     SandboxExtension::consumePermanently(parameters.localStorageDirectoryExtensionHandle);
100     m_adClickAttribution->setPingLoadFunction([this, weakThis = makeWeakPtr(this)](NetworkResourceLoadParameters&& loadParameters, CompletionHandler<void(const WebCore::ResourceError&, const WebCore::ResourceResponse&)>&& completionHandler) {
101         if (!weakThis)
102             return;
103         // PingLoad manages its own lifetime, deleting itself when its purpose has been fulfilled.
104         new PingLoad(m_networkProcess, WTFMove(loadParameters), WTFMove(completionHandler));
105     });
106 }
107
108 NetworkSession::~NetworkSession()
109 {
110     m_storageManager->resume();
111     m_storageManager->waitUntilTasksFinished();
112 }
113
114 void NetworkSession::invalidateAndCancel()
115 {
116     for (auto* task : m_dataTaskSet)
117         task->invalidateAndCancel();
118 #if ENABLE(RESOURCE_LOAD_STATISTICS)
119     if (m_resourceLoadStatistics)
120         m_resourceLoadStatistics->invalidateAndCancel();
121 #endif
122 #if !ASSERT_DISABLED
123     m_isInvalidated = true;
124 #endif
125 }
126
127 #if ENABLE(RESOURCE_LOAD_STATISTICS)
128 void NetworkSession::setResourceLoadStatisticsEnabled(bool enable)
129 {
130     ASSERT(!m_isInvalidated);
131     if (!enable) {
132         m_resourceLoadStatistics = nullptr;
133         return;
134     }
135
136     if (m_resourceLoadStatistics)
137         return;
138
139     // FIXME(193728): Support ResourceLoadStatistics for ephemeral sessions, too.
140     if (m_sessionID.isEphemeral())
141         return;
142
143     m_resourceLoadStatistics = WebResourceLoadStatisticsStore::create(*this, m_resourceLoadStatisticsDirectory, m_shouldIncludeLocalhostInResourceLoadStatistics);
144
145     if (m_enableResourceLoadStatisticsDebugMode == EnableResourceLoadStatisticsDebugMode::Yes)
146         m_resourceLoadStatistics->setResourceLoadStatisticsDebugMode(true, [] { });
147     // This should always be forwarded since debug mode may be enabled at runtime.
148     if (!m_resourceLoadStatisticsManualPrevalentResource.isEmpty())
149         m_resourceLoadStatistics->setPrevalentResourceForDebugMode(m_resourceLoadStatisticsManualPrevalentResource, [] { });
150 }
151
152 void NetworkSession::notifyResourceLoadStatisticsProcessed()
153 {
154     m_networkProcess->parentProcessConnection()->send(Messages::NetworkProcessProxy::NotifyResourceLoadStatisticsProcessed(), 0);
155 }
156
157 void NetworkSession::logDiagnosticMessageWithValue(const String& message, const String& description, unsigned value, unsigned significantFigures, WebCore::ShouldSample shouldSample)
158 {
159     m_networkProcess->parentProcessConnection()->send(Messages::WebPageProxy::LogDiagnosticMessageWithValue(message, description, value, significantFigures, shouldSample), 0);
160 }
161
162 void NetworkSession::notifyPageStatisticsTelemetryFinished(unsigned totalPrevalentResources, unsigned totalPrevalentResourcesWithUserInteraction, unsigned top3SubframeUnderTopFrameOrigins)
163 {
164     m_networkProcess->parentProcessConnection()->send(Messages::NetworkProcessProxy::NotifyResourceLoadStatisticsTelemetryFinished(totalPrevalentResources, totalPrevalentResourcesWithUserInteraction, top3SubframeUnderTopFrameOrigins), 0);
165 }
166
167 void NetworkSession::deleteWebsiteDataForRegistrableDomains(OptionSet<WebsiteDataType> dataTypes, HashMap<RegistrableDomain, WebsiteDataToRemove>&& domains, bool shouldNotifyPage, CompletionHandler<void(const HashSet<RegistrableDomain>&)>&& completionHandler)
168 {
169     m_networkProcess->deleteWebsiteDataForRegistrableDomains(m_sessionID, dataTypes, WTFMove(domains), shouldNotifyPage, WTFMove(completionHandler));
170 }
171
172 void NetworkSession::registrableDomainsWithWebsiteData(OptionSet<WebsiteDataType> dataTypes, bool shouldNotifyPage, CompletionHandler<void(HashSet<RegistrableDomain>&&)>&& completionHandler)
173 {
174     m_networkProcess->registrableDomainsWithWebsiteData(m_sessionID, dataTypes, shouldNotifyPage, WTFMove(completionHandler));
175 }
176 #endif // ENABLE(RESOURCE_LOAD_STATISTICS)
177
178 void NetworkSession::storeAdClickAttribution(WebCore::AdClickAttribution&& adClickAttribution)
179 {
180     m_adClickAttribution->storeUnconverted(WTFMove(adClickAttribution));
181 }
182
183 void NetworkSession::handleAdClickAttributionConversion(AdClickAttribution::Conversion&& conversion, const URL& requestURL, const WebCore::ResourceRequest& redirectRequest)
184 {
185     m_adClickAttribution->handleConversion(WTFMove(conversion), requestURL, redirectRequest);
186 }
187
188 void NetworkSession::dumpAdClickAttribution(CompletionHandler<void(String)>&& completionHandler)
189 {
190     m_adClickAttribution->toString(WTFMove(completionHandler));
191 }
192
193 void NetworkSession::clearAdClickAttribution()
194 {
195     m_adClickAttribution->clear();
196 }
197
198 void NetworkSession::clearAdClickAttributionForRegistrableDomain(WebCore::RegistrableDomain&& domain)
199 {
200     m_adClickAttribution->clearForRegistrableDomain(WTFMove(domain));
201 }
202
203 void NetworkSession::setAdClickAttributionOverrideTimerForTesting(bool value)
204 {
205     m_adClickAttribution->setOverrideTimerForTesting(value);
206 }
207
208 void NetworkSession::setAdClickAttributionConversionURLForTesting(URL&& url)
209 {
210     m_adClickAttribution->setConversionURLForTesting(WTFMove(url));
211 }
212
213 void NetworkSession::markAdClickAttributionsAsExpiredForTesting()
214 {
215     m_adClickAttribution->markAllUnconvertedAsExpiredForTesting();
216 }
217
218 void NetworkSession::addKeptAliveLoad(Ref<NetworkResourceLoader>&& loader)
219 {
220     ASSERT(m_sessionID == loader->sessionID());
221     ASSERT(!m_keptAliveLoads.contains(loader));
222     m_keptAliveLoads.add(WTFMove(loader));
223 }
224
225 void NetworkSession::removeKeptAliveLoad(NetworkResourceLoader& loader)
226 {
227     ASSERT(m_sessionID == loader.sessionID());
228     ASSERT(m_keptAliveLoads.contains(loader));
229     m_keptAliveLoads.remove(loader);
230 }
231
232 std::unique_ptr<WebSocketTask> NetworkSession::createWebSocketTask(NetworkSocketChannel&, const WebCore::ResourceRequest&, const String& protocol)
233 {
234     return nullptr;
235 }
236
237 } // namespace WebKit