Use "= default" to denote default constructor or destructor
[WebKit-https.git] / Source / WebCore / platform / network / cf / ResourceHandleCFURLConnectionDelegate.cpp
1 /*
2  * Copyright (C) 2004-2013 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 #include "config.h"
27 #include "ResourceHandleCFURLConnectionDelegate.h"
28
29 #if USE(CFURLCONNECTION)
30
31 #include "FormDataStreamCFNet.h"
32 #include "NetworkingContext.h"
33 #include "ResourceHandle.h"
34 #include <pal/spi/cf/CFNetworkSPI.h>
35
36 #if PLATFORM(WIN)
37 #include <WebKitSystemInterface/WebKitSystemInterface.h>
38 #endif
39
40 namespace WebCore {
41
42 ResourceHandleCFURLConnectionDelegate::ResourceHandleCFURLConnectionDelegate(ResourceHandle* handle)
43     : m_handle(handle)
44 {
45 }
46
47 ResourceHandleCFURLConnectionDelegate::~ResourceHandleCFURLConnectionDelegate() = default;
48
49 void ResourceHandleCFURLConnectionDelegate::releaseHandle()
50 {
51     m_handle = nullptr;
52 }
53
54 const void* ResourceHandleCFURLConnectionDelegate::retain(const void* clientInfo)
55 {
56     static_cast<ResourceHandleCFURLConnectionDelegate*>(const_cast<void*>(clientInfo))->ref();
57     return clientInfo;
58 }
59
60 void ResourceHandleCFURLConnectionDelegate::release(const void* clientInfo)
61 {
62     static_cast<ResourceHandleCFURLConnectionDelegate*>(const_cast<void*>(clientInfo))->deref();
63 }
64
65 CFURLRequestRef ResourceHandleCFURLConnectionDelegate::willSendRequestCallback(CFURLConnectionRef, CFURLRequestRef cfRequest, CFURLResponseRef originalRedirectResponse, const void* clientInfo)
66 {
67     return static_cast<ResourceHandleCFURLConnectionDelegate*>(const_cast<void*>(clientInfo))->willSendRequest(cfRequest, originalRedirectResponse);
68 }
69
70 void ResourceHandleCFURLConnectionDelegate::didReceiveResponseCallback(CFURLConnectionRef connection, CFURLResponseRef cfResponse, const void* clientInfo)
71 {
72     static_cast<ResourceHandleCFURLConnectionDelegate*>(const_cast<void*>(clientInfo))->didReceiveResponse(connection, cfResponse);
73 }
74
75 void ResourceHandleCFURLConnectionDelegate::didReceiveDataCallback(CFURLConnectionRef, CFDataRef data, CFIndex originalLength, const void* clientInfo)
76 {
77     static_cast<ResourceHandleCFURLConnectionDelegate*>(const_cast<void*>(clientInfo))->didReceiveData(data, originalLength);
78 }
79
80 void ResourceHandleCFURLConnectionDelegate::didFinishLoadingCallback(CFURLConnectionRef, const void* clientInfo)
81 {
82     static_cast<ResourceHandleCFURLConnectionDelegate*>(const_cast<void*>(clientInfo))->didFinishLoading();
83 }
84
85 void ResourceHandleCFURLConnectionDelegate::didFailCallback(CFURLConnectionRef, CFErrorRef error, const void* clientInfo)
86 {
87     static_cast<ResourceHandleCFURLConnectionDelegate*>(const_cast<void*>(clientInfo))->didFail(error);
88 }
89
90 CFCachedURLResponseRef ResourceHandleCFURLConnectionDelegate::willCacheResponseCallback(CFURLConnectionRef, CFCachedURLResponseRef cachedResponse, const void* clientInfo)
91 {
92     return static_cast<ResourceHandleCFURLConnectionDelegate*>(const_cast<void*>(clientInfo))->willCacheResponse(cachedResponse);
93 }
94
95 void ResourceHandleCFURLConnectionDelegate::didReceiveChallengeCallback(CFURLConnectionRef, CFURLAuthChallengeRef challenge, const void* clientInfo)
96 {
97     static_cast<ResourceHandleCFURLConnectionDelegate*>(const_cast<void*>(clientInfo))->didReceiveChallenge(challenge);
98 }
99
100 void ResourceHandleCFURLConnectionDelegate::didSendBodyDataCallback(CFURLConnectionRef, CFIndex, CFIndex totalBytesWritten, CFIndex totalBytesExpectedToWrite, const void *clientInfo)
101 {
102     static_cast<ResourceHandleCFURLConnectionDelegate*>(const_cast<void*>(clientInfo))->didSendBodyData(totalBytesWritten, totalBytesExpectedToWrite);
103 }
104
105 Boolean ResourceHandleCFURLConnectionDelegate::shouldUseCredentialStorageCallback(CFURLConnectionRef, const void* clientInfo)
106 {
107     return static_cast<ResourceHandleCFURLConnectionDelegate*>(const_cast<void*>(clientInfo))->shouldUseCredentialStorage();
108
109 }
110
111 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
112 Boolean ResourceHandleCFURLConnectionDelegate::canRespondToProtectionSpaceCallback(CFURLConnectionRef, CFURLProtectionSpaceRef protectionSpace, const void* clientInfo)
113 {
114     return static_cast<ResourceHandleCFURLConnectionDelegate*>(const_cast<void*>(clientInfo))->canRespondToProtectionSpace(protectionSpace);
115 }
116 #endif // USE(PROTECTION_SPACE_AUTH_CALLBACK)
117
118 RetainPtr<CFURLResponseRef> ResourceHandleCFURLConnectionDelegate::synthesizeRedirectResponseIfNecessary(CFURLRequestRef newRequest, CFURLResponseRef cfRedirectResponse)
119 {
120     if (cfRedirectResponse)
121         return cfRedirectResponse;
122
123     CFURLRef newURL = CFURLRequestGetURL(newRequest);
124     RetainPtr<CFStringRef> newScheme = adoptCF(CFURLCopyScheme(newURL));
125
126     // If the protocols of the new request and the current request match, this is not an HSTS redirect and we shouldn't synthesize a redirect response.
127     const ResourceRequest& currentRequest = m_handle->currentRequest();
128     if (currentRequest.url().protocol() == String(newScheme.get()))
129         return nullptr;
130
131     RetainPtr<CFURLRef> currentURL = currentRequest.url().createCFURL();
132     RetainPtr<CFHTTPMessageRef> responseMessage = adoptCF(CFHTTPMessageCreateResponse(0, 302, 0, kCFHTTPVersion1_1));
133     RetainPtr<CFURLRef> newAbsoluteURL = adoptCF(CFURLCopyAbsoluteURL(newURL));
134     CFHTTPMessageSetHeaderFieldValue(responseMessage.get(), CFSTR("Location"), CFURLGetString(newAbsoluteURL.get()));
135     CFHTTPMessageSetHeaderFieldValue(responseMessage.get(), CFSTR("Cache-Control"), CFSTR("no-store"));
136
137     RetainPtr<CFURLResponseRef> newResponse = adoptCF(CFURLResponseCreateWithHTTPResponse(0, currentURL.get(), responseMessage.get(), kCFURLCacheStorageNotAllowed));
138     return newResponse;
139 }
140
141 ResourceRequest ResourceHandleCFURLConnectionDelegate::createResourceRequest(CFURLRequestRef cfRequest, CFURLResponseRef redirectResponse)
142 {
143     ResourceRequest request;
144     CFHTTPMessageRef httpMessage = CFURLResponseGetHTTPResponse(redirectResponse);
145     if (httpMessage && CFHTTPMessageGetResponseStatusCode(httpMessage) == 307) {
146         RetainPtr<CFStringRef> lastHTTPMethod = m_handle->lastHTTPMethod().createCFString();
147         RetainPtr<CFStringRef> newMethod = adoptCF(CFURLRequestCopyHTTPRequestMethod(cfRequest));
148         if (CFStringCompareWithOptions(lastHTTPMethod.get(), newMethod.get(), CFRangeMake(0, CFStringGetLength(lastHTTPMethod.get())), kCFCompareCaseInsensitive)) {
149             auto mutableRequest = adoptCF(CFURLRequestCreateMutableCopy(kCFAllocatorDefault, cfRequest));
150             if (auto storageSession = m_handle->storageSession())
151                 _CFURLRequestSetStorageSession(mutableRequest.get(), storageSession);
152             CFURLRequestSetHTTPRequestMethod(mutableRequest.get(), lastHTTPMethod.get());
153
154             FormData* body = m_handle->firstRequest().httpBody();
155             if (!equalLettersIgnoringASCIICase(m_handle->firstRequest().httpMethod(), "get") && body && !body->isEmpty())
156                 WebCore::setHTTPBody(mutableRequest.get(), body);
157
158             String originalContentType = m_handle->firstRequest().httpContentType();
159             if (!originalContentType.isEmpty())
160                 CFURLRequestSetHTTPHeaderFieldValue(mutableRequest.get(), CFSTR("Content-Type"), originalContentType.createCFString().get());
161
162             request = mutableRequest.get();
163         }
164     }
165
166     if (request.isNull())
167         request = cfRequest;
168
169     if (!request.url().protocolIs("https") && protocolIs(request.httpReferrer(), "https") && m_handle->context()->shouldClearReferrerOnHTTPSToHTTPRedirect())
170         request.clearHTTPReferrer();
171     return request;
172 }
173
174 CFURLConnectionClient_V6 ResourceHandleCFURLConnectionDelegate::makeConnectionClient() const
175 {
176     CFURLConnectionClient_V6 client = { 6, this,
177         &ResourceHandleCFURLConnectionDelegate::retain,
178         &ResourceHandleCFURLConnectionDelegate::release,
179         0, // copyDescription
180         &ResourceHandleCFURLConnectionDelegate::willSendRequestCallback,
181         &ResourceHandleCFURLConnectionDelegate::didReceiveResponseCallback,
182         &ResourceHandleCFURLConnectionDelegate::didReceiveDataCallback,
183         0,
184         &ResourceHandleCFURLConnectionDelegate::didFinishLoadingCallback,
185         &ResourceHandleCFURLConnectionDelegate::didFailCallback,
186         &ResourceHandleCFURLConnectionDelegate::willCacheResponseCallback,
187         &ResourceHandleCFURLConnectionDelegate::didReceiveChallengeCallback,
188         &ResourceHandleCFURLConnectionDelegate::didSendBodyDataCallback,
189         &ResourceHandleCFURLConnectionDelegate::shouldUseCredentialStorageCallback,
190         0,
191 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
192         &ResourceHandleCFURLConnectionDelegate::canRespondToProtectionSpaceCallback,
193 #else
194         0,
195 #endif
196         0,
197         0
198     };
199     return client;
200 }
201
202 } // namespace WebCore.
203
204 #endif // USE(CFURLCONNECTION)