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