1/*
2 * Copyright (C) 2012-2015 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#pragma once
27
28#include "DownloadID.h"
29#include "MessageSender.h"
30#include "NetworkCache.h"
31#include "NetworkConnectionToWebProcessMessages.h"
32#include "NetworkLoadClient.h"
33#include "NetworkResourceLoadParameters.h"
34#include <WebCore/AdClickAttribution.h>
35#include <WebCore/ContentSecurityPolicyClient.h>
36#include <WebCore/ResourceResponse.h>
37#include <WebCore/SecurityPolicyViolationEvent.h>
38#include <WebCore/Timer.h>
39
40namespace WebCore {
41class BlobDataFileReference;
42class FormData;
43class NetworkStorageSession;
44class ResourceRequest;
45}
46
47namespace WebKit {
48
49class NetworkConnectionToWebProcess;
50class NetworkLoad;
51class NetworkLoadChecker;
52
53namespace NetworkCache {
54class Entry;
55}
56
57class NetworkResourceLoader final
58 : public RefCounted<NetworkResourceLoader>
59 , public NetworkLoadClient
60 , public IPC::MessageSender
61 , public WebCore::ContentSecurityPolicyClient {
62public:
63 static Ref<NetworkResourceLoader> create(NetworkResourceLoadParameters&& parameters, NetworkConnectionToWebProcess& connection, Messages::NetworkConnectionToWebProcess::PerformSynchronousLoad::DelayedReply&& reply = nullptr)
64 {
65 return adoptRef(*new NetworkResourceLoader(WTFMove(parameters), connection, WTFMove(reply)));
66 }
67 virtual ~NetworkResourceLoader();
68
69 const WebCore::ResourceRequest& originalRequest() const { return m_parameters.request; }
70
71 NetworkLoad* networkLoad() const { return m_networkLoad.get(); }
72
73 void start();
74 void abort();
75
76 // Message handlers.
77 void didReceiveNetworkResourceLoaderMessage(IPC::Connection&, IPC::Decoder&);
78
79 void continueWillSendRequest(WebCore::ResourceRequest&& newRequest, bool isAllowedToAskUserForCredentials);
80
81 const WebCore::ResourceResponse& response() const { return m_response; }
82
83 NetworkConnectionToWebProcess& connectionToWebProcess() const { return m_connection; }
84 PAL::SessionID sessionID() const { return m_parameters.sessionID; }
85 ResourceLoadIdentifier identifier() const { return m_parameters.identifier; }
86 uint64_t frameID() const { return m_parameters.webFrameID; }
87 WebCore::PageIdentifier pageID() const { return m_parameters.webPageID; }
88
89 struct SynchronousLoadData;
90
91 // NetworkLoadClient.
92 void didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent) override;
93 bool isSynchronous() const override;
94 bool isAllowedToAskUserForCredentials() const override { return m_isAllowedToAskUserForCredentials; }
95 void willSendRedirectedRequest(WebCore::ResourceRequest&&, WebCore::ResourceRequest&& redirectRequest, WebCore::ResourceResponse&&) override;
96 void didReceiveResponse(WebCore::ResourceResponse&&, ResponseCompletionHandler&&) override;
97 void didReceiveBuffer(Ref<WebCore::SharedBuffer>&&, int reportedEncodedDataLength) override;
98 void didFinishLoading(const WebCore::NetworkLoadMetrics&) override;
99 void didFailLoading(const WebCore::ResourceError&) override;
100 void didBlockAuthenticationChallenge() override;
101 bool shouldCaptureExtraNetworkLoadMetrics() const override;
102
103 void convertToDownload(DownloadID, const WebCore::ResourceRequest&, const WebCore::ResourceResponse&);
104
105 bool isMainResource() const { return m_parameters.request.requester() == WebCore::ResourceRequest::Requester::Main; }
106 bool isMainFrameLoad() const { return isMainResource() && m_parameters.frameAncestorOrigins.isEmpty(); }
107 bool isCrossOriginPrefetch() const;
108
109 bool isAlwaysOnLoggingAllowed() const;
110
111#if ENABLE(RESOURCE_LOAD_STATISTICS) && !RELEASE_LOG_DISABLED
112 static bool shouldLogCookieInformation(NetworkConnectionToWebProcess&, const PAL::SessionID&);
113 static void logCookieInformation(NetworkConnectionToWebProcess&, const String& label, const void* loggedObject, const WebCore::NetworkStorageSession&, const URL& firstParty, const WebCore::SameSiteInfo&, const URL&, const String& referrer, Optional<uint64_t> frameID, Optional<WebCore::PageIdentifier>, Optional<uint64_t> identifier);
114#endif
115
116 void disableExtraNetworkLoadMetricsCapture() { m_shouldCaptureExtraNetworkLoadMetrics = false; }
117
118 bool isKeptAlive() const { return m_isKeptAlive; }
119
120private:
121 NetworkResourceLoader(NetworkResourceLoadParameters&&, NetworkConnectionToWebProcess&, Messages::NetworkConnectionToWebProcess::PerformSynchronousLoad::DelayedReply&&);
122
123 // IPC::MessageSender
124 IPC::Connection* messageSenderConnection() const override;
125 uint64_t messageSenderDestinationID() const override { return m_parameters.identifier; }
126
127 bool canUseCache(const WebCore::ResourceRequest&) const;
128 bool canUseCachedRedirect(const WebCore::ResourceRequest&) const;
129
130 void tryStoreAsCacheEntry();
131 void retrieveCacheEntry(const WebCore::ResourceRequest&);
132 void didRetrieveCacheEntry(std::unique_ptr<NetworkCache::Entry>);
133 void sendResultForCacheEntry(std::unique_ptr<NetworkCache::Entry>);
134 void validateCacheEntry(std::unique_ptr<NetworkCache::Entry>);
135 void dispatchWillSendRequestForCacheEntry(WebCore::ResourceRequest&&, std::unique_ptr<NetworkCache::Entry>&&);
136
137 bool shouldInterruptLoadForXFrameOptions(const String&, const URL&);
138 bool shouldInterruptLoadForCSPFrameAncestorsOrXFrameOptions(const WebCore::ResourceResponse&);
139
140 enum class FirstLoad { No, Yes };
141 void startNetworkLoad(WebCore::ResourceRequest&&, FirstLoad);
142 void restartNetworkLoad(WebCore::ResourceRequest&&);
143 void continueDidReceiveResponse();
144
145 enum class LoadResult {
146 Unknown,
147 Success,
148 Failure,
149 Cancel
150 };
151 void cleanup(LoadResult);
152
153 void platformDidReceiveResponse(const WebCore::ResourceResponse&);
154
155 void startBufferingTimerIfNeeded();
156 void bufferingTimerFired();
157 void sendBuffer(WebCore::SharedBuffer&, size_t encodedDataLength);
158
159 void consumeSandboxExtensions();
160 void invalidateSandboxExtensions();
161
162#if ENABLE(RESOURCE_LOAD_STATISTICS) && !RELEASE_LOG_DISABLED
163 void logCookieInformation() const;
164#endif
165
166 void continueWillSendRedirectedRequest(WebCore::ResourceRequest&&, WebCore::ResourceRequest&& redirectRequest, WebCore::ResourceResponse&&, Optional<WebCore::AdClickAttribution::Conversion>&&);
167 void didFinishWithRedirectResponse(WebCore::ResourceRequest&&, WebCore::ResourceRequest&& redirectRequest, WebCore::ResourceResponse&&);
168 WebCore::ResourceResponse sanitizeResponseIfPossible(WebCore::ResourceResponse&&, WebCore::ResourceResponse::SanitizationType);
169
170 // ContentSecurityPolicyClient
171 void addConsoleMessage(MessageSource, MessageLevel, const String&, unsigned long) final;
172 void sendCSPViolationReport(URL&&, Ref<WebCore::FormData>&&) final;
173 void enqueueSecurityPolicyViolationEvent(WebCore::SecurityPolicyViolationEvent::Init&&) final;
174
175 void logSlowCacheRetrieveIfNeeded(const NetworkCache::Cache::RetrieveInfo&);
176
177 void handleAdClickAttributionConversion(WebCore::AdClickAttribution::Conversion&&, const URL&, const WebCore::ResourceRequest&);
178
179 Optional<Seconds> validateCacheEntryForMaxAgeCapValidation(const WebCore::ResourceRequest&, const WebCore::ResourceRequest& redirectRequest, const WebCore::ResourceResponse&);
180
181 const NetworkResourceLoadParameters m_parameters;
182
183 Ref<NetworkConnectionToWebProcess> m_connection;
184
185 std::unique_ptr<NetworkLoad> m_networkLoad;
186
187 WebCore::ResourceResponse m_response;
188
189 size_t m_bufferedDataEncodedDataLength { 0 };
190 RefPtr<WebCore::SharedBuffer> m_bufferedData;
191 unsigned m_redirectCount { 0 };
192
193 std::unique_ptr<SynchronousLoadData> m_synchronousLoadData;
194 Vector<RefPtr<WebCore::BlobDataFileReference>> m_fileReferences;
195
196 bool m_wasStarted { false };
197 bool m_didConsumeSandboxExtensions { false };
198 bool m_isAllowedToAskUserForCredentials { false };
199 size_t m_numBytesReceived { 0 };
200
201 unsigned m_retrievedDerivedDataCount { 0 };
202
203 WebCore::Timer m_bufferingTimer;
204 RefPtr<NetworkCache::Cache> m_cache;
205 RefPtr<WebCore::SharedBuffer> m_bufferedDataForCache;
206 std::unique_ptr<NetworkCache::Entry> m_cacheEntryForValidation;
207 std::unique_ptr<NetworkCache::Entry> m_cacheEntryForMaxAgeCapValidation;
208 bool m_isWaitingContinueWillSendRequestForCachedRedirect { false };
209 std::unique_ptr<NetworkCache::Entry> m_cacheEntryWaitingForContinueDidReceiveResponse;
210 std::unique_ptr<NetworkLoadChecker> m_networkLoadChecker;
211 bool m_shouldRestartLoad { false };
212 ResponseCompletionHandler m_responseCompletionHandler;
213 bool m_shouldCaptureExtraNetworkLoadMetrics { false };
214 bool m_isKeptAlive { false };
215
216 Optional<NetworkActivityTracker> m_networkActivityTracker;
217};
218
219} // namespace WebKit
220