1/* 2 * Copyright (C) 2005 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 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of Apple Inc. ("Apple") nor the names of 14 * its contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#import <WebKitLegacy/WebDownload.h> 30 31#import <Foundation/NSURLAuthenticationChallenge.h> 32#import <Foundation/NSURLDownload.h> 33#import <WebCore/AuthenticationCF.h> 34#import <WebCore/AuthenticationMac.h> 35#import <WebCore/Credential.h> 36#import <WebCore/CredentialStorage.h> 37#import <WebCore/ProtectionSpace.h> 38#import <WebKitLegacy/WebPanelAuthenticationHandler.h> 39#import <wtf/Assertions.h> 40 41#import "WebTypesInternal.h" 42 43#if USE(CFNETWORK) 44#import <CFNetwork/CFNetwork.h> 45#import <CFNetwork/CFURLConnection.h> 46#endif 47 48using namespace WebCore; 49 50@class NSURLConnectionDelegateProxy; 51 52// FIXME: The following are NSURLDownload SPI - it would be nice to not have to override them at 53// some point in the future 54@interface NSURLDownload (WebDownloadCapability) 55- (id)_initWithLoadingConnection:(NSURLConnection *)connection 56 request:(NSURLRequest *)request 57 response:(NSURLResponse *)response 58 delegate:(id)delegate 59 proxy:(NSURLConnectionDelegateProxy *)proxy; 60- (id)_initWithRequest:(NSURLRequest *)request 61 delegate:(id)delegate 62 directory:(NSString *)directory; 63 64#if USE(CFNETWORK) 65- (id)_initWithLoadingCFURLConnection:(CFURLConnectionRef)connection 66 request:(CFURLRequestRef)request 67 response:(CFURLResponseRef)response 68 delegate:(id)delegate 69 proxy:(NSURLConnectionDelegateProxy *)proxy; 70#endif 71 72@end 73 74@interface WebDownloadInternal : NSObject <NSURLDownloadDelegate> 75{ 76@public 77 id realDelegate; 78} 79 80- (void)setRealDelegate:(id)rd; 81 82@end 83 84@implementation WebDownloadInternal 85 86- (void)dealloc 87{ 88 [realDelegate release]; 89 [super dealloc]; 90} 91 92- (void)setRealDelegate:(id)rd 93{ 94 [rd retain]; 95 [realDelegate release]; 96 realDelegate = rd; 97} 98 99- (BOOL)respondsToSelector:(SEL)selector 100{ 101 if (selector == @selector(downloadDidBegin:) || 102 selector == @selector(download:willSendRequest:redirectResponse:) || 103 selector == @selector(download:didReceiveResponse:) || 104 selector == @selector(download:didReceiveDataOfLength:) || 105 selector == @selector(download:shouldDecodeSourceDataOfMIMEType:) || 106 selector == @selector(download:decideDestinationWithSuggestedFilename:) || 107 selector == @selector(download:didCreateDestination:) || 108 selector == @selector(downloadDidFinish:) || 109 selector == @selector(download:didFailWithError:)) { 110 return [realDelegate respondsToSelector:selector]; 111 } 112 113 return [super respondsToSelector:selector]; 114} 115 116- (void)downloadDidBegin:(NSURLDownload *)download 117{ 118 [realDelegate downloadDidBegin:download]; 119} 120 121- (NSURLRequest *)download:(NSURLDownload *)download willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse 122{ 123 return [realDelegate download:download willSendRequest:request redirectResponse:redirectResponse]; 124} 125 126- (void)download:(NSURLDownload *)download didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge 127{ 128#if !PLATFORM(IOS) 129 // Try previously stored credential first. 130 if (![challenge previousFailureCount]) { 131 NSURLCredential *credential = mac(CredentialStorage::get(ProtectionSpace([challenge protectionSpace]))); 132 if (credential) { 133 [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge]; 134 return; 135 } 136 } 137 138 if ([realDelegate respondsToSelector:@selector(download:didReceiveAuthenticationChallenge:)]) { 139 [realDelegate download:download didReceiveAuthenticationChallenge:challenge]; 140 } else { 141 NSWindow *window = nil; 142 if ([realDelegate respondsToSelector:@selector(downloadWindowForAuthenticationSheet:)]) { 143 window = [realDelegate downloadWindowForAuthenticationSheet:(WebDownload *)download]; 144 } 145 146 [[WebPanelAuthenticationHandler sharedHandler] startAuthentication:challenge window:window]; 147 } 148#endif 149} 150 151- (void)download:(NSURLDownload *)download didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge 152{ 153#if !PLATFORM(IOS) 154 if ([realDelegate respondsToSelector:@selector(download:didCancelAuthenticationChallenge:)]) { 155 [realDelegate download:download didCancelAuthenticationChallenge:challenge]; 156 } else { 157 [[WebPanelAuthenticationHandler sharedHandler] cancelAuthentication:challenge]; 158 } 159#endif 160} 161 162- (void)download:(NSURLDownload *)download didReceiveResponse:(NSURLResponse *)response 163{ 164 [realDelegate download:download didReceiveResponse:response]; 165} 166 167- (void)download:(NSURLDownload *)download didReceiveDataOfLength:(NSUInteger)length 168{ 169 [realDelegate download:download didReceiveDataOfLength:length]; 170} 171 172- (BOOL)download:(NSURLDownload *)download shouldDecodeSourceDataOfMIMEType:(NSString *)encodingType 173{ 174 return [realDelegate download:download shouldDecodeSourceDataOfMIMEType:encodingType]; 175} 176 177- (void)download:(NSURLDownload *)download decideDestinationWithSuggestedFilename:(NSString *)filename 178{ 179 [realDelegate download:download decideDestinationWithSuggestedFilename:filename]; 180} 181 182- (void)download:(NSURLDownload *)download didCreateDestination:(NSString *)path 183{ 184 [realDelegate download:download didCreateDestination:path]; 185} 186 187- (void)downloadDidFinish:(NSURLDownload *)download 188{ 189 [realDelegate downloadDidFinish:download]; 190} 191 192- (void)download:(NSURLDownload *)download didFailWithError:(NSError *)error 193{ 194 [realDelegate download:download didFailWithError:error]; 195} 196 197@end 198 199@implementation WebDownload 200 201- (void)_setRealDelegate:(id)delegate 202{ 203 if (_webInternal == nil) { 204 _webInternal = [[WebDownloadInternal alloc] init]; 205 [_webInternal setRealDelegate:delegate]; 206 } else { 207 ASSERT(_webInternal == delegate); 208 } 209} 210 211- (id)init 212{ 213 self = [super init]; 214 if (self != nil) { 215 // _webInternal can be set up before init by _setRealDelegate 216 if (_webInternal == nil) { 217 _webInternal = [[WebDownloadInternal alloc] init]; 218 } 219 } 220 return self; 221} 222 223- (void)dealloc 224{ 225 [_webInternal release]; 226 [super dealloc]; 227} 228 229- (id)initWithRequest:(NSURLRequest *)request delegate:(id<NSURLDownloadDelegate>)delegate 230{ 231 [self _setRealDelegate:delegate]; 232 return [super initWithRequest:request delegate:_webInternal]; 233} 234 235- (id)_initWithLoadingConnection:(NSURLConnection *)connection 236 request:(NSURLRequest *)request 237 response:(NSURLResponse *)response 238 delegate:(id)delegate 239 proxy:(NSURLConnectionDelegateProxy *)proxy 240{ 241 [self _setRealDelegate:delegate]; 242 return [super _initWithLoadingConnection:connection request:request response:response delegate:_webInternal proxy:proxy]; 243} 244 245#if USE(CFNETWORK) 246- (id)_initWithLoadingCFURLConnection:(CFURLConnectionRef)connection 247 request:(CFURLRequestRef)request 248 response:(CFURLResponseRef)response 249 delegate:(id)delegate 250 proxy:(NSURLConnectionDelegateProxy *)proxy 251{ 252 [self _setRealDelegate:delegate]; 253 return [super _initWithLoadingCFURLConnection:connection request:request response:response delegate:_webInternal proxy:proxy]; 254} 255#endif 256 257- (id)_initWithRequest:(NSURLRequest *)request 258 delegate:(id)delegate 259 directory:(NSString *)directory 260{ 261 [self _setRealDelegate:delegate]; 262 return [super _initWithRequest:request delegate:_webInternal directory:directory]; 263} 264 265@end 266