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