Home | History | Annotate | Download | only in cf
      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 #include "config.h"
     27 #include "ResourceRequestCFNet.h"
     28 
     29 #include "FormDataStreamCFNet.h"
     30 #include "ResourceRequest.h"
     31 
     32 #include <CFNetwork/CFURLRequestPriv.h>
     33 #include <WebKitSystemInterface/WebKitSystemInterface.h>
     34 
     35 namespace WebCore {
     36 
     37 typedef void (*CFURLRequestSetContentDispositionEncodingFallbackArrayFunction)(CFMutableURLRequestRef, CFArrayRef);
     38 typedef CFArrayRef (*CFURLRequestCopyContentDispositionEncodingFallbackArrayFunction)(CFURLRequestRef);
     39 
     40 static HMODULE findCFNetworkModule()
     41 {
     42 #ifndef DEBUG_ALL
     43     return GetModuleHandleA("CFNetwork");
     44 #else
     45     return GetModuleHandleA("CFNetwork_debug");
     46 #endif
     47 }
     48 
     49 static CFURLRequestSetContentDispositionEncodingFallbackArrayFunction findCFURLRequestSetContentDispositionEncodingFallbackArrayFunction()
     50 {
     51     return reinterpret_cast<CFURLRequestSetContentDispositionEncodingFallbackArrayFunction>(GetProcAddress(findCFNetworkModule(), "_CFURLRequestSetContentDispositionEncodingFallbackArray"));
     52 }
     53 
     54 static CFURLRequestCopyContentDispositionEncodingFallbackArrayFunction findCFURLRequestCopyContentDispositionEncodingFallbackArrayFunction()
     55 {
     56     return reinterpret_cast<CFURLRequestCopyContentDispositionEncodingFallbackArrayFunction>(GetProcAddress(findCFNetworkModule(), "_CFURLRequestCopyContentDispositionEncodingFallbackArray"));
     57 }
     58 
     59 static void setContentDispositionEncodingFallbackArray(CFMutableURLRequestRef request, CFArrayRef fallbackArray)
     60 {
     61     static CFURLRequestSetContentDispositionEncodingFallbackArrayFunction function = findCFURLRequestSetContentDispositionEncodingFallbackArrayFunction();
     62     if (function)
     63         function(request, fallbackArray);
     64 }
     65 
     66 static CFArrayRef copyContentDispositionEncodingFallbackArray(CFURLRequestRef request)
     67 {
     68     static CFURLRequestCopyContentDispositionEncodingFallbackArrayFunction function = findCFURLRequestCopyContentDispositionEncodingFallbackArrayFunction();
     69     if (!function)
     70         return 0;
     71     return function(request);
     72 }
     73 
     74 CFURLRequestRef ResourceRequest::cfURLRequest() const
     75 {
     76     updatePlatformRequest();
     77 
     78     return m_cfRequest.get();
     79 }
     80 
     81 static inline void setHeaderFields(CFMutableURLRequestRef request, const HTTPHeaderMap& requestHeaders)
     82 {
     83     // Remove existing headers first, as some of them may no longer be present in the map.
     84     RetainPtr<CFDictionaryRef> oldHeaderFields(AdoptCF, CFURLRequestCopyAllHTTPHeaderFields(request));
     85     CFIndex oldHeaderFieldCount = CFDictionaryGetCount(oldHeaderFields.get());
     86     if (oldHeaderFieldCount) {
     87         Vector<CFStringRef> oldHeaderFieldNames(oldHeaderFieldCount);
     88         CFDictionaryGetKeysAndValues(oldHeaderFields.get(), reinterpret_cast<const void**>(&oldHeaderFieldNames[0]), 0);
     89         for (CFIndex i = 0; i < oldHeaderFieldCount; ++i)
     90             CFURLRequestSetHTTPHeaderFieldValue(request, oldHeaderFieldNames[i], 0);
     91     }
     92 
     93     HTTPHeaderMap::const_iterator end = requestHeaders.end();
     94     for (HTTPHeaderMap::const_iterator it = requestHeaders.begin(); it != end; ++it) {
     95         CFStringRef key = it->first.createCFString();
     96         CFStringRef value = it->second.createCFString();
     97         CFURLRequestSetHTTPHeaderFieldValue(request, key, value);
     98         CFRelease(key);
     99         CFRelease(value);
    100     }
    101 }
    102 
    103 void ResourceRequest::doUpdatePlatformRequest()
    104 {
    105     CFMutableURLRequestRef cfRequest;
    106 
    107     RetainPtr<CFURLRef> url(AdoptCF, ResourceRequest::url().createCFURL());
    108     RetainPtr<CFURLRef> firstPartyForCookies(AdoptCF, ResourceRequest::firstPartyForCookies().createCFURL());
    109     if (m_cfRequest) {
    110         cfRequest = CFURLRequestCreateMutableCopy(0, m_cfRequest.get());
    111         CFURLRequestSetURL(cfRequest, url.get());
    112         CFURLRequestSetMainDocumentURL(cfRequest, firstPartyForCookies.get());
    113         CFURLRequestSetCachePolicy(cfRequest, (CFURLRequestCachePolicy)cachePolicy());
    114         CFURLRequestSetTimeoutInterval(cfRequest, timeoutInterval());
    115     } else {
    116         cfRequest = CFURLRequestCreateMutable(0, url.get(), (CFURLRequestCachePolicy)cachePolicy(), timeoutInterval(), firstPartyForCookies.get());
    117     }
    118 
    119     RetainPtr<CFStringRef> requestMethod(AdoptCF, httpMethod().createCFString());
    120     CFURLRequestSetHTTPRequestMethod(cfRequest, requestMethod.get());
    121 
    122     setHeaderFields(cfRequest, httpHeaderFields());
    123     WebCore::setHTTPBody(cfRequest, httpBody());
    124     CFURLRequestSetShouldHandleHTTPCookies(cfRequest, allowCookies());
    125 
    126     unsigned fallbackCount = m_responseContentDispositionEncodingFallbackArray.size();
    127     RetainPtr<CFMutableArrayRef> encodingFallbacks(AdoptCF, CFArrayCreateMutable(kCFAllocatorDefault, fallbackCount, 0));
    128     for (unsigned i = 0; i != fallbackCount; ++i) {
    129         RetainPtr<CFStringRef> encodingName(AdoptCF, m_responseContentDispositionEncodingFallbackArray[i].createCFString());
    130         CFStringEncoding encoding = CFStringConvertIANACharSetNameToEncoding(encodingName.get());
    131         if (encoding != kCFStringEncodingInvalidId)
    132             CFArrayAppendValue(encodingFallbacks.get(), reinterpret_cast<const void*>(encoding));
    133     }
    134     setContentDispositionEncodingFallbackArray(cfRequest, encodingFallbacks.get());
    135 
    136     if (m_cfRequest) {
    137         RetainPtr<CFHTTPCookieStorageRef> cookieStorage(AdoptCF, CFURLRequestCopyHTTPCookieStorage(m_cfRequest.get()));
    138         if (cookieStorage)
    139             CFURLRequestSetHTTPCookieStorage(cfRequest, cookieStorage.get());
    140         CFURLRequestSetHTTPCookieStorageAcceptPolicy(cfRequest, CFURLRequestGetHTTPCookieStorageAcceptPolicy(m_cfRequest.get()));
    141         CFURLRequestSetSSLProperties(cfRequest, CFURLRequestGetSSLProperties(m_cfRequest.get()));
    142     }
    143 
    144     m_cfRequest.adoptCF(cfRequest);
    145 }
    146 
    147 void ResourceRequest::doUpdateResourceRequest()
    148 {
    149     m_url = CFURLRequestGetURL(m_cfRequest.get());
    150 
    151     m_cachePolicy = (ResourceRequestCachePolicy)CFURLRequestGetCachePolicy(m_cfRequest.get());
    152     m_timeoutInterval = CFURLRequestGetTimeoutInterval(m_cfRequest.get());
    153     m_firstPartyForCookies = CFURLRequestGetMainDocumentURL(m_cfRequest.get());
    154     if (CFStringRef method = CFURLRequestCopyHTTPRequestMethod(m_cfRequest.get())) {
    155         m_httpMethod = method;
    156         CFRelease(method);
    157     }
    158     m_allowCookies = CFURLRequestShouldHandleHTTPCookies(m_cfRequest.get());
    159 
    160     m_httpHeaderFields.clear();
    161     if (CFDictionaryRef headers = CFURLRequestCopyAllHTTPHeaderFields(m_cfRequest.get())) {
    162         CFIndex headerCount = CFDictionaryGetCount(headers);
    163         Vector<const void*, 128> keys(headerCount);
    164         Vector<const void*, 128> values(headerCount);
    165         CFDictionaryGetKeysAndValues(headers, keys.data(), values.data());
    166         for (int i = 0; i < headerCount; ++i)
    167             m_httpHeaderFields.set((CFStringRef)keys[i], (CFStringRef)values[i]);
    168         CFRelease(headers);
    169     }
    170 
    171     m_responseContentDispositionEncodingFallbackArray.clear();
    172     RetainPtr<CFArrayRef> encodingFallbacks(AdoptCF, copyContentDispositionEncodingFallbackArray(m_cfRequest.get()));
    173     if (encodingFallbacks) {
    174         CFIndex count = CFArrayGetCount(encodingFallbacks.get());
    175         for (CFIndex i = 0; i < count; ++i) {
    176             CFStringEncoding encoding = reinterpret_cast<CFIndex>(CFArrayGetValueAtIndex(encodingFallbacks.get(), i));
    177             if (encoding != kCFStringEncodingInvalidId)
    178                 m_responseContentDispositionEncodingFallbackArray.append(CFStringConvertEncodingToIANACharSetName(encoding));
    179         }
    180     }
    181 
    182     m_httpBody = httpBodyFromRequest(m_cfRequest.get());
    183 }
    184 
    185 unsigned initializeMaximumHTTPConnectionCountPerHost()
    186 {
    187     static const unsigned preferredConnectionCount = 6;
    188     return wkInitializeMaximumHTTPConnectionCountPerHost(preferredConnectionCount);
    189 }
    190 
    191 }
    192