1/* 2 * Copyright (C) 2004, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 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. 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#import "config.h" 27#import "WebCoreResourceHandleAsDelegate.h" 28 29#if !USE(CFNETWORK) 30 31#import "AuthenticationChallenge.h" 32#import "AuthenticationMac.h" 33#import "Logging.h" 34#import "ResourceHandle.h" 35#import "ResourceHandleClient.h" 36#import "ResourceRequest.h" 37#import "ResourceResponse.h" 38#import "SharedBuffer.h" 39#import "WebCoreURLResponse.h" 40 41@interface NSURLRequest (Details) 42- (id)_propertyForKey:(NSString *)key; 43@end 44 45using namespace WebCore; 46 47@implementation WebCoreResourceHandleAsDelegate 48 49- (id)initWithHandle:(ResourceHandle*)handle 50{ 51 self = [self init]; 52 if (!self) 53 return nil; 54 m_handle = handle; 55 return self; 56} 57 58- (void)detachHandle 59{ 60 m_handle = 0; 61} 62 63- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)newRequest redirectResponse:(NSURLResponse *)redirectResponse 64{ 65 UNUSED_PARAM(connection); 66 67 if (!m_handle) 68 return nil; 69 70 redirectResponse = synthesizeRedirectResponseIfNecessary(connection, newRequest, redirectResponse); 71 72 // See <rdar://problem/5380697>. This is a workaround for a behavior change in CFNetwork where willSendRequest gets called more often. 73 if (!redirectResponse) 74 return newRequest; 75 76#if !LOG_DISABLED 77 if ([redirectResponse isKindOfClass:[NSHTTPURLResponse class]]) 78 LOG(Network, "Handle %p delegate connection:%p willSendRequest:%@ redirectResponse:%d, Location:<%@>", m_handle, connection, [newRequest description], static_cast<int>([(id)redirectResponse statusCode]), [[(id)redirectResponse allHeaderFields] objectForKey:@"Location"]); 79 else 80 LOG(Network, "Handle %p delegate connection:%p willSendRequest:%@ redirectResponse:non-HTTP", m_handle, connection, [newRequest description]); 81#endif 82 83 ResourceRequest request = newRequest; 84 85 m_handle->willSendRequest(request, redirectResponse); 86 87 return request.nsURLRequest(UpdateHTTPBody); 88} 89 90- (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection *)connection 91{ 92 UNUSED_PARAM(connection); 93 94 LOG(Network, "Handle %p delegate connectionShouldUseCredentialStorage:%p", m_handle, connection); 95 96#if PLATFORM(IOS) 97 return NO; 98#else 99 if (!m_handle) 100 return NO; 101 102 return m_handle->shouldUseCredentialStorage(); 103#endif 104} 105 106- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge 107{ 108 UNUSED_PARAM(connection); 109 110 LOG(Network, "Handle %p delegate connection:%p didReceiveAuthenticationChallenge:%p", m_handle, connection, challenge); 111 112 if (!m_handle) { 113 [[challenge sender] cancelAuthenticationChallenge:challenge]; 114 return; 115 } 116 m_handle->didReceiveAuthenticationChallenge(core(challenge)); 117} 118 119- (void)connection:(NSURLConnection *)connection didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge 120{ 121 // FIXME: We probably don't need to implement this (see <rdar://problem/8960124>). 122 123 UNUSED_PARAM(connection); 124 125 LOG(Network, "Handle %p delegate connection:%p didCancelAuthenticationChallenge:%p", m_handle, connection, challenge); 126 127 if (!m_handle) 128 return; 129 m_handle->didCancelAuthenticationChallenge(core(challenge)); 130} 131 132#if USE(PROTECTION_SPACE_AUTH_CALLBACK) 133- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace 134{ 135 UNUSED_PARAM(connection); 136 137 LOG(Network, "Handle %p delegate connection:%p canAuthenticateAgainstProtectionSpace:%@://%@:%u realm:%@ method:%@ %@%@", m_handle, connection, [protectionSpace protocol], [protectionSpace host], [protectionSpace port], [protectionSpace realm], [protectionSpace authenticationMethod], [protectionSpace isProxy] ? @"proxy:" : @"", [protectionSpace isProxy] ? [protectionSpace proxyType] : @""); 138 139 if (!m_handle) 140 return NO; 141 142 return m_handle->canAuthenticateAgainstProtectionSpace(ProtectionSpace(protectionSpace)); 143} 144#endif 145 146- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)r 147{ 148#if !PLATFORM(IOS) 149 UNUSED_PARAM(connection); 150#endif 151 152 LOG(Network, "Handle %p delegate connection:%p didReceiveResponse:%p (HTTP status %d, reported MIMEType '%s')", m_handle, connection, r, [r respondsToSelector:@selector(statusCode)] ? [(id)r statusCode] : 0, [[r MIMEType] UTF8String]); 153 154 if (!m_handle || !m_handle->client()) 155 return; 156 157 // Avoid MIME type sniffing if the response comes back as 304 Not Modified. 158 int statusCode = [r respondsToSelector:@selector(statusCode)] ? [(id)r statusCode] : 0; 159 if (statusCode != 304) 160 adjustMIMETypeIfNecessary([r _CFURLResponse]); 161 162#if !PLATFORM(IOS) 163 if ([m_handle->firstRequest().nsURLRequest(DoNotUpdateHTTPBody) _propertyForKey:@"ForceHTMLMIMEType"]) 164 [r _setMIMEType:@"text/html"]; 165#endif 166 167#if USE(QUICK_LOOK) 168 m_handle->setQuickLookHandle(QuickLookHandle::create(m_handle, connection, r, self)); 169 if (m_handle->quickLookHandle()) 170 r = m_handle->quickLookHandle()->nsResponse(); 171#endif 172 173 ResourceResponse resourceResponse(r); 174#if ENABLE(WEB_TIMING) 175 ResourceHandle::getConnectionTimingData(connection, resourceResponse.resourceLoadTiming()); 176#else 177 UNUSED_PARAM(connection); 178#endif 179 180 m_handle->client()->didReceiveResponse(m_handle, resourceResponse); 181} 182 183#if USE(NETWORK_CFDATA_ARRAY_CALLBACK) 184- (void)connection:(NSURLConnection *)connection didReceiveDataArray:(NSArray *)dataArray 185{ 186 UNUSED_PARAM(connection); 187 LOG(Network, "Handle %p delegate connection:%p didReceiveDataArray:%p arraySize:%d", m_handle, connection, dataArray, [dataArray count]); 188 189 if (!dataArray) 190 return; 191 192 if (!m_handle || !m_handle->client()) 193 return; 194 195#if USE(QUICK_LOOK) 196 if (m_handle->quickLookHandle() && m_handle->quickLookHandle()->didReceiveDataArray(reinterpret_cast<CFArrayRef>(dataArray))) 197 return; 198#endif 199 200 m_handle->client()->didReceiveBuffer(m_handle, SharedBuffer::wrapCFDataArray(reinterpret_cast<CFArrayRef>(dataArray)), -1); 201 // The call to didReceiveData above can cancel a load, and if so, the delegate (self) could have been deallocated by this point. 202} 203#endif 204 205- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data lengthReceived:(long long)lengthReceived 206{ 207 UNUSED_PARAM(connection); 208 UNUSED_PARAM(lengthReceived); 209 210 LOG(Network, "Handle %p delegate connection:%p didReceiveData:%p lengthReceived:%lld", m_handle, connection, data, lengthReceived); 211 212#if PLATFORM(IOS) 213 if ([data length] == 0) // <rdar://problem/5532931> 214 return; 215#endif 216 217 if (!m_handle || !m_handle->client()) 218 return; 219 // FIXME: If we get more than 2B bytes in a single chunk, this code won't do the right thing. 220 // However, with today's computers and networking speeds, this won't happen in practice. 221 // Could be an issue with a giant local file. 222 223#if USE(QUICK_LOOK) 224 if (m_handle->quickLookHandle() && m_handle->quickLookHandle()->didReceiveData(reinterpret_cast<CFDataRef>(data))) 225 return; 226#endif 227 228 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=19793 229 // -1 means we do not provide any data about transfer size to inspector so it would use 230 // Content-Length headers or content size to show transfer size. 231 m_handle->client()->didReceiveBuffer(m_handle, SharedBuffer::wrapNSData(data), -1); 232} 233 234- (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite 235{ 236 UNUSED_PARAM(connection); 237 UNUSED_PARAM(bytesWritten); 238 239 LOG(Network, "Handle %p delegate connection:%p didSendBodyData:%d totalBytesWritten:%d totalBytesExpectedToWrite:%d", m_handle, connection, bytesWritten, totalBytesWritten, totalBytesExpectedToWrite); 240 241 if (!m_handle || !m_handle->client()) 242 return; 243 m_handle->client()->didSendData(m_handle, totalBytesWritten, totalBytesExpectedToWrite); 244} 245 246- (void)connectionDidFinishLoading:(NSURLConnection *)connection 247{ 248 UNUSED_PARAM(connection); 249 250 LOG(Network, "Handle %p delegate connectionDidFinishLoading:%p", m_handle, connection); 251 252 if (!m_handle || !m_handle->client()) 253 return; 254 255#if USE(QUICK_LOOK) 256 if (m_handle->quickLookHandle() && m_handle->quickLookHandle()->didFinishLoading()) 257 return; 258#endif 259 260 m_handle->client()->didFinishLoading(m_handle, 0); 261} 262 263- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 264{ 265 UNUSED_PARAM(connection); 266 267 LOG(Network, "Handle %p delegate connection:%p didFailWithError:%@", m_handle, connection, error); 268 269 if (!m_handle || !m_handle->client()) 270 return; 271 272#if USE(QUICK_LOOK) 273 if (m_handle->quickLookHandle()) 274 m_handle->quickLookHandle()->didFail(); 275#endif 276 277 m_handle->client()->didFail(m_handle, error); 278} 279 280 281- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse 282{ 283 LOG(Network, "Handle %p delegate connection:%p willCacheResponse:%p", m_handle, connection, cachedResponse); 284 285 UNUSED_PARAM(connection); 286 287 if (!m_handle || !m_handle->client()) 288 return nil; 289 290 return m_handle->client()->willCacheResponse(m_handle, cachedResponse); 291} 292 293@end 294 295#endif // !USE(CFNETWORK) 296 297