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