1/*
2 * Copyright (C) 2004-2017 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. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#pragma once
27
28#include "AuthenticationClient.h"
29#include "StoredCredentialsPolicy.h"
30#include <wtf/MonotonicTime.h>
31#include <wtf/RefCounted.h>
32#include <wtf/RefPtr.h>
33#include <wtf/text/AtomString.h>
34
35#if PLATFORM(COCOA) || USE(CFURLCONNECTION)
36#include <wtf/RetainPtr.h>
37#endif
38
39#if USE(CURL)
40#include "CurlResourceHandleDelegate.h"
41#endif
42
43#if USE(CF)
44typedef const struct __CFData * CFDataRef;
45#endif
46
47#if PLATFORM(COCOA)
48OBJC_CLASS NSCachedURLResponse;
49OBJC_CLASS NSData;
50OBJC_CLASS NSDictionary;
51OBJC_CLASS NSError;
52OBJC_CLASS NSURLConnection;
53OBJC_CLASS NSURLRequest;
54#ifndef __OBJC__
55typedef struct objc_object *id;
56#endif
57#endif
58
59#if USE(CFURLCONNECTION)
60typedef const struct _CFCachedURLResponse* CFCachedURLResponseRef;
61typedef struct _CFURLConnection* CFURLConnectionRef;
62typedef int CFHTTPCookieStorageAcceptPolicy;
63typedef struct OpaqueCFHTTPCookieStorage* CFHTTPCookieStorageRef;
64#endif
65
66#if PLATFORM(COCOA) || USE(CFURLCONNECTION)
67typedef const struct __CFURLStorageSession* CFURLStorageSessionRef;
68#endif
69
70namespace WTF {
71class SchedulePair;
72template<typename T> class MessageQueue;
73}
74
75namespace WebCore {
76
77class AuthenticationChallenge;
78class Credential;
79class Frame;
80class NetworkingContext;
81class ProtectionSpace;
82class ResourceError;
83class ResourceHandleClient;
84class ResourceHandleInternal;
85class NetworkLoadMetrics;
86class ResourceRequest;
87class ResourceResponse;
88class SharedBuffer;
89class Timer;
90
91#if USE(CURL)
92class CurlRequest;
93class CurlResourceHandleDelegate;
94#endif
95
96class ResourceHandle : public RefCounted<ResourceHandle>, public AuthenticationClient {
97public:
98 WEBCORE_EXPORT static RefPtr<ResourceHandle> create(NetworkingContext*, const ResourceRequest&, ResourceHandleClient*, bool defersLoading, bool shouldContentSniff, bool shouldContentEncodingSniff);
99 WEBCORE_EXPORT static void loadResourceSynchronously(NetworkingContext*, const ResourceRequest&, StoredCredentialsPolicy, ResourceError&, ResourceResponse&, Vector<char>& data);
100 WEBCORE_EXPORT virtual ~ResourceHandle();
101
102#if PLATFORM(COCOA) || USE(CFURLCONNECTION)
103 void willSendRequest(ResourceRequest&&, ResourceResponse&&, CompletionHandler<void(ResourceRequest&&)>&&);
104#endif
105
106 void didReceiveResponse(ResourceResponse&&, CompletionHandler<void()>&&);
107
108 bool shouldUseCredentialStorage();
109 void didReceiveAuthenticationChallenge(const AuthenticationChallenge&);
110 void receivedCredential(const AuthenticationChallenge&, const Credential&) override;
111 void receivedRequestToContinueWithoutCredential(const AuthenticationChallenge&) override;
112 void receivedCancellation(const AuthenticationChallenge&) override;
113 void receivedRequestToPerformDefaultHandling(const AuthenticationChallenge&) override;
114 void receivedChallengeRejection(const AuthenticationChallenge&) override;
115
116#if PLATFORM(COCOA) || USE(CFURLCONNECTION)
117 bool tryHandlePasswordBasedAuthentication(const AuthenticationChallenge&);
118#endif
119
120#if PLATFORM(COCOA) && USE(PROTECTION_SPACE_AUTH_CALLBACK)
121 void canAuthenticateAgainstProtectionSpace(const ProtectionSpace&, CompletionHandler<void(bool)>&&);
122#endif
123
124#if PLATFORM(COCOA)
125 WEBCORE_EXPORT NSURLConnection *connection() const;
126 id makeDelegate(bool, WTF::MessageQueue<WTF::Function<void()>>*);
127 id delegate();
128 void releaseDelegate();
129#endif
130
131#if PLATFORM(COCOA)
132#if USE(CFURLCONNECTION)
133 static void getConnectionTimingData(CFURLConnectionRef, NetworkLoadMetrics&);
134#else
135 static void getConnectionTimingData(NSURLConnection *, NetworkLoadMetrics&);
136#endif
137#endif
138
139#if PLATFORM(COCOA)
140 void schedule(WTF::SchedulePair&);
141 void unschedule(WTF::SchedulePair&);
142#endif
143
144#if USE(CFURLCONNECTION)
145 CFURLStorageSessionRef storageSession() const;
146 CFURLConnectionRef connection() const;
147 WEBCORE_EXPORT RetainPtr<CFURLConnectionRef> releaseConnectionForDownload();
148 const ResourceRequest& currentRequest() const;
149 static void setHostAllowsAnyHTTPSCertificate(const String&);
150 static void setClientCertificate(const String& host, CFDataRef);
151#endif
152
153#if OS(WINDOWS) && USE(CURL)
154 static void setHostAllowsAnyHTTPSCertificate(const String&);
155 static void setClientCertificateInfo(const String&, const String&, const String&);
156#endif
157
158#if OS(WINDOWS) && USE(CURL) && USE(CF)
159 static void setClientCertificate(const String& host, CFDataRef);
160#endif
161
162 bool shouldContentSniff() const;
163 static bool shouldContentSniffURL(const URL&);
164
165 bool shouldContentEncodingSniff() const;
166
167 WEBCORE_EXPORT static void forceContentSniffing();
168
169#if USE(CURL)
170 ResourceHandleInternal* getInternal() { return d.get(); }
171#endif
172
173#if USE(CURL)
174 bool cancelledOrClientless();
175 CurlResourceHandleDelegate* delegate();
176
177 void continueAfterDidReceiveResponse();
178 void willSendRequest();
179 void continueAfterWillSendRequest(ResourceRequest&&);
180#endif
181
182 bool hasAuthenticationChallenge() const;
183 void clearAuthentication();
184 WEBCORE_EXPORT virtual void cancel();
185
186 // The client may be 0, in which case no callbacks will be made.
187 WEBCORE_EXPORT ResourceHandleClient* client() const;
188 WEBCORE_EXPORT void clearClient();
189
190 WEBCORE_EXPORT void setDefersLoading(bool);
191
192 WEBCORE_EXPORT ResourceRequest& firstRequest();
193 const String& lastHTTPMethod() const;
194
195 void failureTimerFired();
196
197 NetworkingContext* context() const;
198
199 using RefCounted<ResourceHandle>::ref;
200 using RefCounted<ResourceHandle>::deref;
201
202#if PLATFORM(COCOA) || USE(CFURLCONNECTION)
203 WEBCORE_EXPORT static CFStringRef synchronousLoadRunLoopMode();
204#endif
205
206 typedef Ref<ResourceHandle> (*BuiltinConstructor)(const ResourceRequest& request, ResourceHandleClient* client);
207 static void registerBuiltinConstructor(const AtomString& protocol, BuiltinConstructor);
208
209 typedef void (*BuiltinSynchronousLoader)(NetworkingContext*, const ResourceRequest&, StoredCredentialsPolicy, ResourceError&, ResourceResponse&, Vector<char>& data);
210 static void registerBuiltinSynchronousLoader(const AtomString& protocol, BuiltinSynchronousLoader);
211
212protected:
213 ResourceHandle(NetworkingContext*, const ResourceRequest&, ResourceHandleClient*, bool defersLoading, bool shouldContentSniff, bool shouldContentEncodingSniff);
214
215private:
216 enum FailureType {
217 NoFailure,
218 BlockedFailure,
219 InvalidURLFailure
220 };
221
222 void platformSetDefersLoading(bool);
223
224 void platformContinueSynchronousDidReceiveResponse();
225
226 void scheduleFailure(FailureType);
227
228 bool start();
229 static void platformLoadResourceSynchronously(NetworkingContext*, const ResourceRequest&, StoredCredentialsPolicy, ResourceError&, ResourceResponse&, Vector<char>& data);
230
231 void refAuthenticationClient() override { ref(); }
232 void derefAuthenticationClient() override { deref(); }
233
234#if PLATFORM(COCOA) || USE(CFURLCONNECTION)
235 enum class SchedulingBehavior { Asynchronous, Synchronous };
236#endif
237
238#if USE(CFURLCONNECTION)
239 void createCFURLConnection(bool shouldUseCredentialStorage, bool shouldContentSniff, bool shouldContentEncodingSniff, WTF::MessageQueue<WTF::Function<void()>>*, CFDictionaryRef clientProperties);
240#endif
241
242#if PLATFORM(MAC)
243 void createNSURLConnection(id delegate, bool shouldUseCredentialStorage, bool shouldContentSniff, bool shouldContentEncodingSniff, SchedulingBehavior);
244#endif
245
246#if PLATFORM(IOS_FAMILY)
247 void createNSURLConnection(id delegate, bool shouldUseCredentialStorage, bool shouldContentSniff, bool shouldContentEncodingSniff, SchedulingBehavior, NSDictionary *connectionProperties);
248#endif
249
250#if PLATFORM(COCOA)
251 NSURLRequest *applySniffingPoliciesIfNeeded(NSURLRequest *, bool shouldContentSniff, bool shouldContentEncodingSniff);
252#endif
253
254#if USE(CURL)
255 enum class RequestStatus {
256 NewRequest,
257 ReusedRequest
258 };
259
260 void addCacheValidationHeaders(ResourceRequest&);
261 Ref<CurlRequest> createCurlRequest(ResourceRequest&&, RequestStatus = RequestStatus::NewRequest);
262
263 bool shouldRedirectAsGET(const ResourceRequest&, bool crossOrigin);
264
265 Optional<Credential> getCredential(const ResourceRequest&, bool);
266 void restartRequestWithCredential(const ProtectionSpace&, const Credential&);
267
268 void handleDataURL();
269#endif
270
271 friend class ResourceHandleInternal;
272 std::unique_ptr<ResourceHandleInternal> d;
273};
274
275}
276