|
1 /* |
|
2 * Copyright (C) 2005 Apple Computer, 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 Computer, 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 <WebKit/WebDownload.h> |
|
30 |
|
31 #import <Foundation/NSURLAuthenticationChallenge.h> |
|
32 #import <Foundation/NSURLDownload.h> |
|
33 #import <JavaScriptCore/Assertions.h> |
|
34 #import <WebKit/WebPanelAuthenticationHandler.h> |
|
35 |
|
36 #import "WebTypesInternal.h" |
|
37 |
|
38 @class NSURLConnectionDelegateProxy; |
|
39 |
|
40 // FIXME: The following are NSURLDownload SPI - it would be nice to not have to override them at |
|
41 // some point in the future |
|
42 @interface NSURLDownload (WebDownloadCapability) |
|
43 - (id)_initWithLoadingConnection:(NSURLConnection *)connection |
|
44 request:(NSURLRequest *)request |
|
45 response:(NSURLResponse *)response |
|
46 delegate:(id)delegate |
|
47 proxy:(NSURLConnectionDelegateProxy *)proxy; |
|
48 - (id)_initWithRequest:(NSURLRequest *)request |
|
49 delegate:(id)delegate |
|
50 directory:(NSString *)directory; |
|
51 @end |
|
52 |
|
53 @interface WebDownloadInternal : NSObject |
|
54 { |
|
55 @public |
|
56 id realDelegate; |
|
57 } |
|
58 |
|
59 - (void)setRealDelegate:(id)rd; |
|
60 |
|
61 @end |
|
62 |
|
63 @implementation WebDownloadInternal |
|
64 |
|
65 - (void)dealloc |
|
66 { |
|
67 [realDelegate release]; |
|
68 [super dealloc]; |
|
69 } |
|
70 |
|
71 - (void)setRealDelegate:(id)rd |
|
72 { |
|
73 [rd retain]; |
|
74 [realDelegate release]; |
|
75 realDelegate = rd; |
|
76 } |
|
77 |
|
78 - (BOOL)respondsToSelector:(SEL)selector |
|
79 { |
|
80 if (selector == @selector(downloadDidBegin:) || |
|
81 selector == @selector(download:willSendRequest:redirectResponse:) || |
|
82 selector == @selector(download:didReceiveResponse:) || |
|
83 selector == @selector(download:didReceiveDataOfLength:) || |
|
84 selector == @selector(download:shouldDecodeSourceDataOfMIMEType:) || |
|
85 selector == @selector(download:decideDestinationWithSuggestedFilename:) || |
|
86 selector == @selector(download:didCreateDestination:) || |
|
87 selector == @selector(downloadDidFinish:) || |
|
88 selector == @selector(download:didFailWithError:) || |
|
89 selector == @selector(download:shouldBeginChildDownloadOfSource:delegate:) || |
|
90 selector == @selector(download:didBeginChildDownload:)) { |
|
91 return [realDelegate respondsToSelector:selector]; |
|
92 } |
|
93 |
|
94 return [super respondsToSelector:selector]; |
|
95 } |
|
96 |
|
97 - (void)downloadDidBegin:(NSURLDownload *)download |
|
98 { |
|
99 [realDelegate downloadDidBegin:download]; |
|
100 } |
|
101 |
|
102 - (NSURLRequest *)download:(NSURLDownload *)download willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse |
|
103 { |
|
104 return [realDelegate download:download willSendRequest:request redirectResponse:redirectResponse]; |
|
105 } |
|
106 |
|
107 - (void)download:(NSURLDownload *)download didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge |
|
108 { |
|
109 if ([realDelegate respondsToSelector:@selector(download:didReceiveAuthenticationChallenge:)]) { |
|
110 [realDelegate download:download didReceiveAuthenticationChallenge:challenge]; |
|
111 } else { |
|
112 NSWindow *window = nil; |
|
113 if ([realDelegate respondsToSelector:@selector(downloadWindowForAuthenticationSheet:)]) { |
|
114 window = [realDelegate downloadWindowForAuthenticationSheet:(WebDownload *)download]; |
|
115 } |
|
116 |
|
117 [[WebPanelAuthenticationHandler sharedHandler] startAuthentication:challenge window:window]; |
|
118 } |
|
119 } |
|
120 |
|
121 - (void)download:(NSURLDownload *)download didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge |
|
122 { |
|
123 if ([realDelegate respondsToSelector:@selector(download:didCancelAuthenticationChallenge:)]) { |
|
124 [realDelegate download:download didCancelAuthenticationChallenge:challenge]; |
|
125 } else { |
|
126 [[WebPanelAuthenticationHandler sharedHandler] cancelAuthentication:challenge]; |
|
127 } |
|
128 } |
|
129 |
|
130 - (void)download:(NSURLDownload *)download didReceiveResponse:(NSURLResponse *)response |
|
131 { |
|
132 [realDelegate download:download didReceiveResponse:response]; |
|
133 } |
|
134 |
|
135 - (void)download:(NSURLDownload *)download didReceiveDataOfLength:(NSUInteger)length |
|
136 { |
|
137 [realDelegate download:download didReceiveDataOfLength:length]; |
|
138 } |
|
139 |
|
140 - (BOOL)download:(NSURLDownload *)download shouldDecodeSourceDataOfMIMEType:(NSString *)encodingType |
|
141 { |
|
142 return [realDelegate download:download shouldDecodeSourceDataOfMIMEType:encodingType]; |
|
143 } |
|
144 |
|
145 - (void)download:(NSURLDownload *)download decideDestinationWithSuggestedFilename:(NSString *)filename |
|
146 { |
|
147 [realDelegate download:download decideDestinationWithSuggestedFilename:filename]; |
|
148 } |
|
149 |
|
150 - (void)download:(NSURLDownload *)download didCreateDestination:(NSString *)path |
|
151 { |
|
152 [realDelegate download:download didCreateDestination:path]; |
|
153 } |
|
154 |
|
155 - (void)downloadDidFinish:(NSURLDownload *)download |
|
156 { |
|
157 [realDelegate downloadDidFinish:download]; |
|
158 } |
|
159 |
|
160 - (void)download:(NSURLDownload *)download didFailWithError:(NSError *)error |
|
161 { |
|
162 [realDelegate download:download didFailWithError:error]; |
|
163 } |
|
164 |
|
165 - (NSURLRequest *)download:(NSURLDownload *)download shouldBeginChildDownloadOfSource:(NSURLRequest *)child delegate:(id *)childDelegate |
|
166 { |
|
167 return [realDelegate download:download shouldBeginChildDownloadOfSource:child delegate:childDelegate]; |
|
168 } |
|
169 |
|
170 - (void)download:(NSURLDownload *)parent didBeginChildDownload:(NSURLDownload *)child |
|
171 { |
|
172 [realDelegate download:parent didBeginChildDownload:child]; |
|
173 } |
|
174 |
|
175 @end |
|
176 |
|
177 @implementation WebDownload |
|
178 |
|
179 - (void)_setRealDelegate:(id)delegate |
|
180 { |
|
181 if (_webInternal == nil) { |
|
182 _webInternal = [[WebDownloadInternal alloc] init]; |
|
183 [_webInternal setRealDelegate:delegate]; |
|
184 } else { |
|
185 ASSERT(_webInternal == delegate); |
|
186 } |
|
187 } |
|
188 |
|
189 - (id)init |
|
190 { |
|
191 self = [super init]; |
|
192 if (self != nil) { |
|
193 // _webInternal can be set up before init by _setRealDelegate |
|
194 if (_webInternal == nil) { |
|
195 _webInternal = [[WebDownloadInternal alloc] init]; |
|
196 } |
|
197 } |
|
198 return self; |
|
199 } |
|
200 |
|
201 - (void)dealloc |
|
202 { |
|
203 [_webInternal release]; |
|
204 [super dealloc]; |
|
205 } |
|
206 |
|
207 - (id)initWithRequest:(NSURLRequest *)request delegate:(id)delegate |
|
208 { |
|
209 [self _setRealDelegate:delegate]; |
|
210 return [super initWithRequest:request delegate:_webInternal]; |
|
211 } |
|
212 |
|
213 - (id)_initWithLoadingConnection:(NSURLConnection *)connection |
|
214 request:(NSURLRequest *)request |
|
215 response:(NSURLResponse *)response |
|
216 delegate:(id)delegate |
|
217 proxy:(NSURLConnectionDelegateProxy *)proxy |
|
218 { |
|
219 [self _setRealDelegate:delegate]; |
|
220 return [super _initWithLoadingConnection:connection request:request response:response delegate:_webInternal proxy:proxy]; |
|
221 } |
|
222 |
|
223 - (id)_initWithRequest:(NSURLRequest *)request |
|
224 delegate:(id)delegate |
|
225 directory:(NSString *)directory |
|
226 { |
|
227 [self _setRealDelegate:delegate]; |
|
228 return [super _initWithRequest:request delegate:_webInternal directory:directory]; |
|
229 } |
|
230 |
|
231 - (void)connection:(NSURLConnection *)connection willStopBufferingData:(NSData *)data |
|
232 { |
|
233 // NSURLConnection calls this method even if it is not implemented. |
|
234 // This happens because NSURLConnection caches the results of respondsToSelector. |
|
235 // Those results become invalid when the delegate of NSURLConnectionDelegateProxy is changed. |
|
236 // This is a workaround since this problem needs to be fixed in NSURLConnectionDelegateProxy. |
|
237 // <rdar://problem/3913270> NSURLConnection calls unimplemented delegate method in WebDownload |
|
238 } |
|
239 |
|
240 @end |