2 * Copyright (C) 2005 Apple Computer, Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
29 #import <WebKit/WebSubresourceLoader.h>
31 #import <JavaScriptCore/Assertions.h>
32 #import <WebKit/WebDataSourceInternal.h>
33 #import <WebKit/WebFormDataStream.h>
34 #import <WebKit/WebFrameInternal.h>
35 #import <WebKit/WebFrameLoader.h>
36 #import <WebKit/WebKitErrorsPrivate.h>
37 #import <WebKit/WebNSURLRequestExtras.h>
39 #import <Foundation/NSURLResponse.h>
41 #import <WebCore/WebCoreResourceLoader.h>
42 #import <WebKitSystemInterface.h>
44 @implementation WebSubresourceLoader
46 - initWithLoader:(id <WebCoreResourceLoader>)l frameLoader:(WebFrameLoader *)fl
50 coreLoader = [l retain];
52 [self setFrameLoader:fl];
63 + (WebSubresourceLoader *)startLoadingResource:(id <WebCoreResourceLoader>)rLoader
64 withRequest:(NSMutableURLRequest *)newRequest
65 customHeaders:(NSDictionary *)customHeaders
66 referrer:(NSString *)referrer
67 forFrameLoader:(WebFrameLoader *)fl
69 WebSubresourceLoader *loader = [[[self alloc] initWithLoader:rLoader frameLoader:fl] autorelease];
71 [fl _addSubresourceLoader:loader];
73 NSEnumerator *e = [customHeaders keyEnumerator];
75 while ((key = [e nextObject]))
76 [newRequest addValue:[customHeaders objectForKey:key] forHTTPHeaderField:key];
78 // Use the original request's cache policy for two reasons:
79 // 1. For POST requests, we mutate the cache policy for the main resource,
80 // but we do not want this to apply to subresources
81 // 2. Delegates that modify the cache policy using willSendRequest: should
82 // not affect any other resources. Such changes need to be done
84 if ([newRequest _web_isConditionalRequest])
85 [newRequest setCachePolicy:NSURLRequestReloadIgnoringCacheData];
87 [newRequest setCachePolicy:[[fl _originalRequest] cachePolicy]];
88 [newRequest _web_setHTTPReferrer:referrer];
90 [[fl webFrame] _addExtraFieldsToRequest:newRequest mainResource:NO alwaysFromRequest:NO];
92 if (![loader loadWithRequest:newRequest])
98 + (WebSubresourceLoader *)startLoadingResource:(id <WebCoreResourceLoader>)rLoader
99 withMethod:(NSString *)method
101 customHeaders:(NSDictionary *)customHeaders
102 referrer:(NSString *)referrer
103 forFrameLoader:(WebFrameLoader *)fl
105 NSMutableURLRequest *newRequest = [[NSMutableURLRequest alloc] initWithURL:URL];
107 // setHTTPMethod is not called for GET requests to work around <rdar://4464032>.
108 if (![method isEqualToString:@"GET"])
109 [newRequest setHTTPMethod:method];
111 WebSubresourceLoader *loader = [self startLoadingResource:rLoader withRequest:newRequest customHeaders:customHeaders referrer:referrer forFrameLoader:fl];
112 [newRequest release];
117 + (WebSubresourceLoader *)startLoadingResource:(id <WebCoreResourceLoader>)rLoader
118 withMethod:(NSString *)method
120 customHeaders:(NSDictionary *)customHeaders
121 postData:(NSArray *)postData
122 referrer:(NSString *)referrer
123 forFrameLoader:(WebFrameLoader *)fl
125 NSMutableURLRequest *newRequest = [[NSMutableURLRequest alloc] initWithURL:URL];
127 // setHTTPMethod is not called for GET requests to work around <rdar://4464032>.
128 if (![method isEqualToString:@"GET"])
129 [newRequest setHTTPMethod:method];
131 webSetHTTPBody(newRequest, postData);
133 WebSubresourceLoader *loader = [self startLoadingResource:rLoader withRequest:newRequest customHeaders:customHeaders referrer:referrer forFrameLoader:fl];
134 [newRequest release];
140 - (void)receivedError:(NSError *)error
142 [frameLoader _receivedError:error];
145 - (NSURLRequest *)willSendRequest:(NSURLRequest *)newRequest redirectResponse:(NSURLResponse *)redirectResponse;
147 NSURL *oldURL = [request URL];
148 NSURLRequest *clientRequest = [super willSendRequest:newRequest redirectResponse:redirectResponse];
150 if (clientRequest != nil && oldURL != [clientRequest URL] && ![oldURL isEqual:[clientRequest URL]])
151 [coreLoader redirectedToURL:[clientRequest URL]];
153 return clientRequest;
156 - (void)didReceiveResponse:(NSURLResponse *)r
160 if ([[r MIMEType] isEqualToString:@"multipart/x-mixed-replace"])
161 loadingMultipartContent = YES;
163 // retain/release self in this delegate method since the additional processing can do
164 // anything including possibly releasing self; one example of this is 3266216
166 [coreLoader receivedResponse:r];
167 // The coreLoader can cancel a load if it receives a multipart response for a non-image
168 if (reachedTerminalState) {
172 [super didReceiveResponse:r];
175 if (loadingMultipartContent && [[self resourceData] length]) {
176 // A subresource loader does not load multipart sections progressively, deliver the previously received data to the coreLoader all at once
177 [coreLoader addData:[self resourceData]];
178 // Clears the data to make way for the next multipart section
179 [self clearResourceData];
181 // After the first multipart section is complete, signal to delegates that this load is "finished"
182 if (!signalledFinish)
187 - (void)didReceiveData:(NSData *)data lengthReceived:(long long)lengthReceived
189 // retain/release self in this delegate method since the additional processing can do
190 // anything including possibly releasing self; one example of this is 3266216
192 // A subresource loader does not load multipart sections progressively, don't deliver any data to the coreLoader yet
193 if (!loadingMultipartContent)
194 [coreLoader addData:data];
195 [super didReceiveData:data lengthReceived:lengthReceived];
201 [frameLoader _removeSubresourceLoader:self];
202 [frameLoader _finishedLoadingResource];
203 [super signalFinish];
206 - (void)didFinishLoading
208 // Calling _removeSubresourceLoader will likely result in a call to release, so we must retain.
211 [coreLoader finishWithData:[self resourceData]];
213 if (!signalledFinish)
216 [super didFinishLoading];
221 - (void)didFailWithError:(NSError *)error
223 // Calling _removeSubresourceLoader will likely result in a call to release, so we must retain.
226 [coreLoader reportError];
227 [frameLoader _removeSubresourceLoader:self];
228 [self receivedError:error];
229 [super didFailWithError:error];
236 // Calling _removeSubresourceLoader will likely result in a call to release, so we must retain.
240 [frameLoader _removeSubresourceLoader:self];
241 [self receivedError:[self cancelledError]];