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