• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2006, 2007, 2008 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 COMPUTER, 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 COMPUTER, 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#import "config.h"
27#import "ResourceRequest.h"
28
29#if !USE(CFNETWORK)
30
31#import "WebCoreSystemInterface.h"
32
33#import "FormDataStreamMac.h"
34#import "ResourceRequestCFNet.h"
35#import "WebCoreSystemInterface.h"
36
37#import <Foundation/Foundation.h>
38
39#ifdef BUILDING_ON_TIGER
40typedef unsigned NSUInteger;
41#endif
42
43@interface NSURLRequest (WebNSURLRequestDetails)
44- (NSArray *)contentDispositionEncodingFallbackArray;
45+ (void)setDefaultTimeoutInterval:(NSTimeInterval)seconds;
46@end
47
48@interface NSMutableURLRequest (WebMutableNSURLRequestDetails)
49- (void)setContentDispositionEncodingFallbackArray:(NSArray *)theEncodingFallbackArray;
50@end
51
52namespace WebCore {
53
54NSURLRequest* ResourceRequest::nsURLRequest() const
55{
56    updatePlatformRequest();
57
58    return [[m_nsRequest.get() retain] autorelease];
59}
60
61void ResourceRequest::doUpdateResourceRequest()
62{
63    m_url = [m_nsRequest.get() URL];
64    m_cachePolicy = (ResourceRequestCachePolicy)[m_nsRequest.get() cachePolicy];
65    m_timeoutInterval = [m_nsRequest.get() timeoutInterval];
66    m_firstPartyForCookies = [m_nsRequest.get() mainDocumentURL];
67
68    if (NSString* method = [m_nsRequest.get() HTTPMethod])
69        m_httpMethod = method;
70    m_allowCookies = [m_nsRequest.get() HTTPShouldHandleCookies];
71
72#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
73    if (ResourceRequest::httpPipeliningEnabled())
74        m_priority = toResourceLoadPriority(wkGetHTTPPipeliningPriority(m_nsRequest.get()));
75#endif
76
77    NSDictionary *headers = [m_nsRequest.get() allHTTPHeaderFields];
78    NSEnumerator *e = [headers keyEnumerator];
79    NSString *name;
80    m_httpHeaderFields.clear();
81    while ((name = [e nextObject]))
82        m_httpHeaderFields.set(name, [headers objectForKey:name]);
83
84    // The below check can be removed once we require a version of Foundation with -[NSURLRequest contentDispositionEncodingFallbackArray] method.
85    static bool supportsContentDispositionEncodingFallbackArray = [NSURLRequest instancesRespondToSelector:@selector(contentDispositionEncodingFallbackArray)];
86    if (supportsContentDispositionEncodingFallbackArray) {
87        m_responseContentDispositionEncodingFallbackArray.clear();
88        NSArray *encodingFallbacks = [m_nsRequest.get() contentDispositionEncodingFallbackArray];
89        NSUInteger count = [encodingFallbacks count];
90        for (NSUInteger i = 0; i < count; ++i) {
91            CFStringEncoding encoding = CFStringConvertNSStringEncodingToEncoding([(NSNumber *)[encodingFallbacks objectAtIndex:i] unsignedLongValue]);
92            if (encoding != kCFStringEncodingInvalidId)
93                m_responseContentDispositionEncodingFallbackArray.append(CFStringConvertEncodingToIANACharSetName(encoding));
94        }
95    }
96
97    if (NSData* bodyData = [m_nsRequest.get() HTTPBody])
98        m_httpBody = FormData::create([bodyData bytes], [bodyData length]);
99    else if (NSInputStream* bodyStream = [m_nsRequest.get() HTTPBodyStream])
100        if (FormData* formData = httpBodyFromStream(bodyStream))
101            m_httpBody = formData;
102}
103
104void ResourceRequest::doUpdatePlatformRequest()
105{
106    if (isNull()) {
107        m_nsRequest = nil;
108        return;
109    }
110
111    NSMutableURLRequest* nsRequest = [m_nsRequest.get() mutableCopy];
112
113    if (nsRequest)
114        [nsRequest setURL:url()];
115    else
116        nsRequest = [[NSMutableURLRequest alloc] initWithURL:url()];
117
118#ifdef BUILDING_ON_TIGER
119    wkSupportsMultipartXMixedReplace(nsRequest);
120#endif
121
122#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
123    if (ResourceRequest::httpPipeliningEnabled())
124        wkSetHTTPPipeliningPriority(nsRequest, toHTTPPipeliningPriority(m_priority));
125#endif
126
127    [nsRequest setCachePolicy:(NSURLRequestCachePolicy)cachePolicy()];
128
129    double timeoutInterval = ResourceRequestBase::timeoutInterval();
130    if (timeoutInterval)
131        [nsRequest setTimeoutInterval:timeoutInterval];
132    // Otherwise, respect NSURLRequest default timeout.
133
134    [nsRequest setMainDocumentURL:firstPartyForCookies()];
135    if (!httpMethod().isEmpty())
136        [nsRequest setHTTPMethod:httpMethod()];
137    [nsRequest setHTTPShouldHandleCookies:allowCookies()];
138
139    // Cannot just use setAllHTTPHeaderFields here, because it does not remove headers.
140    NSArray *oldHeaderFieldNames = [[nsRequest allHTTPHeaderFields] allKeys];
141    for (unsigned i = [oldHeaderFieldNames count]; i != 0; --i)
142        [nsRequest setValue:nil forHTTPHeaderField:[oldHeaderFieldNames objectAtIndex:i - 1]];
143    HTTPHeaderMap::const_iterator end = httpHeaderFields().end();
144    for (HTTPHeaderMap::const_iterator it = httpHeaderFields().begin(); it != end; ++it)
145        [nsRequest setValue:it->second forHTTPHeaderField:it->first];
146
147    // The below check can be removed once we require a version of Foundation with -[NSMutableURLRequest setContentDispositionEncodingFallbackArray:] method.
148    static bool supportsContentDispositionEncodingFallbackArray = [NSMutableURLRequest instancesRespondToSelector:@selector(setContentDispositionEncodingFallbackArray:)];
149    if (supportsContentDispositionEncodingFallbackArray) {
150        NSMutableArray *encodingFallbacks = [NSMutableArray array];
151        unsigned count = m_responseContentDispositionEncodingFallbackArray.size();
152        for (unsigned i = 0; i != count; ++i) {
153            CFStringRef encodingName = m_responseContentDispositionEncodingFallbackArray[i].createCFString();
154            unsigned long nsEncoding = CFStringConvertEncodingToNSStringEncoding(CFStringConvertIANACharSetNameToEncoding(encodingName));
155            CFRelease(encodingName);
156            if (nsEncoding != kCFStringEncodingInvalidId)
157                [encodingFallbacks addObject:[NSNumber numberWithUnsignedLong:nsEncoding]];
158        }
159        [nsRequest setContentDispositionEncodingFallbackArray:encodingFallbacks];
160    }
161
162    RefPtr<FormData> formData = httpBody();
163    if (formData && !formData->isEmpty())
164        WebCore::setHTTPBody(nsRequest, formData);
165
166    m_nsRequest.adoptNS(nsRequest);
167}
168
169void ResourceRequest::applyWebArchiveHackForMail()
170{
171    // Hack because Mail checks for this property to detect data / archive loads
172    [NSURLProtocol setProperty:@"" forKey:@"WebDataRequest" inRequest:(NSMutableURLRequest *)nsURLRequest()];
173}
174
175#if USE(CFURLSTORAGESESSIONS)
176
177void ResourceRequest::setStorageSession(CFURLStorageSessionRef storageSession)
178{
179    m_nsRequest = wkCopyRequestWithStorageSession(storageSession, m_nsRequest.get());
180}
181
182#endif
183
184} // namespace WebCore
185
186#endif // !USE(CFNETWORK)
187