Drop legacy WebCore::toRegistrableDomain() utility function
[WebKit-https.git] / Source / WebCore / platform / network / cf / ResourceRequestCFNet.cpp
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 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 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 "HTTPHeaderNames.h"
30 #include "RegistrableDomain.h"
31 #include "ResourceRequest.h"
32 #include <pal/spi/cf/CFNetworkSPI.h>
33 #include <wtf/cf/TypeCastsCF.h>
34
35 #if ENABLE(PUBLIC_SUFFIX_LIST)
36 #include "PublicSuffix.h"
37 #endif
38
39 #if USE(CFURLCONNECTION)
40 #include "FormDataStreamCFNet.h"
41 #include <CFNetwork/CFURLRequestPriv.h>
42 #include <wtf/text/CString.h>
43 #endif
44
45 #if PLATFORM(COCOA)
46 #include "ResourceLoadPriority.h"
47 #include <dlfcn.h>
48 #endif
49
50 WTF_DECLARE_CF_TYPE_TRAIT(CFURL);
51
52 namespace WebCore {
53
54 // FIXME: Make this a NetworkingContext property.
55 #if PLATFORM(IOS_FAMILY)
56 bool ResourceRequest::s_httpPipeliningEnabled = true;
57 #else
58 bool ResourceRequest::s_httpPipeliningEnabled = false;
59 #endif
60
61 #if USE(CFURLCONNECTION)
62
63 typedef void (*CFURLRequestSetContentDispositionEncodingFallbackArrayFunction)(CFMutableURLRequestRef, CFArrayRef);
64 typedef CFArrayRef (*CFURLRequestCopyContentDispositionEncodingFallbackArrayFunction)(CFURLRequestRef);
65
66 #if PLATFORM(WIN)
67 static HMODULE findCFNetworkModule()
68 {
69 #ifndef DEBUG_ALL
70     return GetModuleHandleA("CFNetwork");
71 #else
72     return GetModuleHandleA("CFNetwork_debug");
73 #endif
74 }
75
76 static CFURLRequestSetContentDispositionEncodingFallbackArrayFunction findCFURLRequestSetContentDispositionEncodingFallbackArrayFunction()
77 {
78     return reinterpret_cast<CFURLRequestSetContentDispositionEncodingFallbackArrayFunction>(GetProcAddress(findCFNetworkModule(), "_CFURLRequestSetContentDispositionEncodingFallbackArray"));
79 }
80
81 static CFURLRequestCopyContentDispositionEncodingFallbackArrayFunction findCFURLRequestCopyContentDispositionEncodingFallbackArrayFunction()
82 {
83     return reinterpret_cast<CFURLRequestCopyContentDispositionEncodingFallbackArrayFunction>(GetProcAddress(findCFNetworkModule(), "_CFURLRequestCopyContentDispositionEncodingFallbackArray"));
84 }
85 #endif
86
87 static void setContentDispositionEncodingFallbackArray(CFMutableURLRequestRef request, CFArrayRef fallbackArray)
88 {
89     static CFURLRequestSetContentDispositionEncodingFallbackArrayFunction function = findCFURLRequestSetContentDispositionEncodingFallbackArrayFunction();
90     if (function)
91         function(request, fallbackArray);
92 }
93
94 static CFArrayRef copyContentDispositionEncodingFallbackArray(CFURLRequestRef request)
95 {
96     static CFURLRequestCopyContentDispositionEncodingFallbackArrayFunction function = findCFURLRequestCopyContentDispositionEncodingFallbackArrayFunction();
97     if (!function)
98         return 0;
99     return function(request);
100 }
101
102 CFURLRequestRef ResourceRequest::cfURLRequest(HTTPBodyUpdatePolicy bodyPolicy) const
103 {
104     updatePlatformRequest(bodyPolicy);
105
106     return m_cfRequest.get();
107 }
108
109 static inline void setHeaderFields(CFMutableURLRequestRef request, const HTTPHeaderMap& requestHeaders) 
110 {
111     // Remove existing headers first, as some of them may no longer be present in the map.
112     RetainPtr<CFDictionaryRef> oldHeaderFields = adoptCF(CFURLRequestCopyAllHTTPHeaderFields(request));
113     CFIndex oldHeaderFieldCount = CFDictionaryGetCount(oldHeaderFields.get());
114     if (oldHeaderFieldCount) {
115         Vector<CFStringRef> oldHeaderFieldNames(oldHeaderFieldCount);
116         CFDictionaryGetKeysAndValues(oldHeaderFields.get(), reinterpret_cast<const void**>(&oldHeaderFieldNames[0]), 0);
117         for (CFIndex i = 0; i < oldHeaderFieldCount; ++i)
118             CFURLRequestSetHTTPHeaderFieldValue(request, oldHeaderFieldNames[i], 0);
119     }
120
121     for (const auto& header : requestHeaders)
122         CFURLRequestSetHTTPHeaderFieldValue(request, header.key.createCFString().get(), header.value.createCFString().get());
123 }
124
125 static inline CFURLRequestCachePolicy toPlatformRequestCachePolicy(ResourceRequestCachePolicy policy)
126 {
127     switch (policy) {
128     case ResourceRequestCachePolicy::UseProtocolCachePolicy:
129         return kCFURLRequestCachePolicyProtocolDefault;
130     case ResourceRequestCachePolicy::ReturnCacheDataElseLoad:
131         return kCFURLRequestCachePolicyReturnCacheDataElseLoad;
132     case ResourceRequestCachePolicy::ReturnCacheDataDontLoad:
133         return kCFURLRequestCachePolicyReturnCacheDataDontLoad;
134     case ResourceRequestCachePolicy::ReloadIgnoringCacheData:
135     case ResourceRequestCachePolicy::DoNotUseAnyCache:
136     case ResourceRequestCachePolicy::RefreshAnyCacheData:
137         return kCFURLRequestCachePolicyReloadIgnoringCache;
138     }
139
140     ASSERT_NOT_REACHED();
141     return kCFURLRequestCachePolicyReloadIgnoringCache;
142 }
143
144 static inline ResourceRequestCachePolicy fromPlatformRequestCachePolicy(CFURLRequestCachePolicy policy)
145 {
146     switch (policy) {
147     case kCFURLRequestCachePolicyProtocolDefault:
148         return ResourceRequestCachePolicy::UseProtocolCachePolicy;
149     case kCFURLRequestCachePolicyReloadIgnoringCache:
150         return ResourceRequestCachePolicy::ReloadIgnoringCacheData;
151     case kCFURLRequestCachePolicyReturnCacheDataElseLoad:
152         return ResourceRequestCachePolicy::ReturnCacheDataElseLoad;
153     case kCFURLRequestCachePolicyReturnCacheDataDontLoad:
154         return ResourceRequestCachePolicy::ReturnCacheDataDontLoad;
155     default:
156         return ResourceRequestCachePolicy::ReloadIgnoringCacheData;
157     }
158 }
159
160 #if PLATFORM(IOS_FAMILY) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 120000
161 static CFURLRef siteForCookies(ResourceRequest::SameSiteDisposition disposition, CFURLRef url)
162 {
163     switch (disposition) {
164     case ResourceRequest::SameSiteDisposition::Unspecified:
165         return { };
166     case ResourceRequest::SameSiteDisposition::SameSite:
167         return url;
168     case ResourceRequest::SameSiteDisposition::CrossSite:
169         static CFURLRef emptyURL = CFURLCreateWithString(nullptr, CFSTR(""), nullptr);
170         return emptyURL;
171     }
172 }
173 #endif
174
175 void ResourceRequest::doUpdatePlatformRequest()
176 {
177     CFMutableURLRequestRef cfRequest;
178
179     RetainPtr<CFURLRef> url = ResourceRequest::url().createCFURL();
180     RetainPtr<CFURLRef> firstPartyForCookies = ResourceRequest::firstPartyForCookies().createCFURL();
181     double timeoutInterval = ResourceRequestBase::timeoutInterval() ? ResourceRequestBase::timeoutInterval() : ResourceRequestBase::defaultTimeoutInterval();
182     if (m_cfRequest) {
183         cfRequest = CFURLRequestCreateMutableCopy(0, m_cfRequest.get());
184         CFURLRequestSetURL(cfRequest, url.get());
185         CFURLRequestSetMainDocumentURL(cfRequest, firstPartyForCookies.get());
186         CFURLRequestSetCachePolicy(cfRequest, toPlatformRequestCachePolicy(cachePolicy()));
187         CFURLRequestSetTimeoutInterval(cfRequest, timeoutInterval);
188     } else
189         cfRequest = CFURLRequestCreateMutable(0, url.get(), toPlatformRequestCachePolicy(cachePolicy()), timeoutInterval, firstPartyForCookies.get());
190
191     CFURLRequestSetHTTPRequestMethod(cfRequest, httpMethod().createCFString().get());
192
193     if (httpPipeliningEnabled())
194         CFURLRequestSetShouldPipelineHTTP(cfRequest, true, true);
195
196     if (resourcePrioritiesEnabled())
197         CFURLRequestSetRequestPriority(cfRequest, toPlatformRequestPriority(priority()));
198
199     setHeaderFields(cfRequest, httpHeaderFields());
200
201     CFURLRequestSetShouldHandleHTTPCookies(cfRequest, allowCookies());
202
203 #if PLATFORM(IOS_FAMILY) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 120000
204     _CFURLRequestSetProtocolProperty(cfRequest, CFSTR("_kCFHTTPCookiePolicyPropertySiteForCookies"), siteForCookies(m_sameSiteDisposition, url.get()));
205
206     int isTopSite = m_isTopSite;
207     RetainPtr<CFNumberRef> isTopSiteCF = adoptCF(CFNumberCreate(nullptr, kCFNumberIntType, &isTopSite));
208     _CFURLRequestSetProtocolProperty(cfRequest, CFSTR("_kCFHTTPCookiePolicyPropertyisTopSite"), isTopSiteCF.get());
209 #endif
210
211     unsigned fallbackCount = m_responseContentDispositionEncodingFallbackArray.size();
212     RetainPtr<CFMutableArrayRef> encodingFallbacks = adoptCF(CFArrayCreateMutable(kCFAllocatorDefault, fallbackCount, 0));
213     for (unsigned i = 0; i != fallbackCount; ++i) {
214         RetainPtr<CFStringRef> encodingName = m_responseContentDispositionEncodingFallbackArray[i].createCFString();
215         CFStringEncoding encoding = CFStringConvertIANACharSetNameToEncoding(encodingName.get());
216         if (encoding != kCFStringEncodingInvalidId)
217             CFArrayAppendValue(encodingFallbacks.get(), reinterpret_cast<const void*>(encoding));
218     }
219     setContentDispositionEncodingFallbackArray(cfRequest, encodingFallbacks.get());
220
221 #if ENABLE(CACHE_PARTITIONING)
222     String partition = cachePartition();
223     if (!partition.isNull() && !partition.isEmpty()) {
224         CString utf8String = partition.utf8();
225         RetainPtr<CFStringRef> partitionValue = adoptCF(CFStringCreateWithBytes(0, reinterpret_cast<const UInt8*>(utf8String.data()), utf8String.length(), kCFStringEncodingUTF8, false));
226         _CFURLRequestSetProtocolProperty(cfRequest, _kCFURLCachePartitionKey, partitionValue.get());
227     }
228 #endif
229
230     m_cfRequest = adoptCF(cfRequest);
231 }
232
233 void ResourceRequest::doUpdatePlatformHTTPBody()
234 {
235     CFMutableURLRequestRef cfRequest;
236
237     RetainPtr<CFURLRef> url = ResourceRequest::url().createCFURL();
238     RetainPtr<CFURLRef> firstPartyForCookies = ResourceRequest::firstPartyForCookies().createCFURL();
239     double timeoutInterval = ResourceRequestBase::timeoutInterval() ? ResourceRequestBase::timeoutInterval() : ResourceRequestBase::defaultTimeoutInterval();
240     if (m_cfRequest) {
241         cfRequest = CFURLRequestCreateMutableCopy(0, m_cfRequest.get());
242         CFURLRequestSetURL(cfRequest, url.get());
243         CFURLRequestSetMainDocumentURL(cfRequest, firstPartyForCookies.get());
244         CFURLRequestSetCachePolicy(cfRequest, toPlatformRequestCachePolicy(cachePolicy()));
245         CFURLRequestSetTimeoutInterval(cfRequest, timeoutInterval);
246     } else
247         cfRequest = CFURLRequestCreateMutable(0, url.get(), toPlatformRequestCachePolicy(cachePolicy()), timeoutInterval, firstPartyForCookies.get());
248
249     FormData* formData = httpBody();
250     if (formData && !formData->isEmpty())
251         WebCore::setHTTPBody(cfRequest, formData);
252
253     if (RetainPtr<CFReadStreamRef> bodyStream = adoptCF(CFURLRequestCopyHTTPRequestBodyStream(cfRequest))) {
254         // For streams, provide a Content-Length to avoid using chunked encoding, and to get accurate total length in callbacks.
255         if (RetainPtr<CFStringRef> lengthString = adoptCF(static_cast<CFStringRef>(CFReadStreamCopyProperty(bodyStream.get(), formDataStreamLengthPropertyName())))) {
256             CFURLRequestSetHTTPHeaderFieldValue(cfRequest, CFSTR("Content-Length"), lengthString.get());
257             // Since resource request is already marked updated, we need to keep it up to date too.
258             ASSERT(m_resourceRequestUpdated);
259             m_httpHeaderFields.set(HTTPHeaderName::ContentLength, lengthString.get());
260         }
261     }
262
263     m_cfRequest = adoptCF(cfRequest);
264 }
265
266 void ResourceRequest::doUpdateResourceRequest()
267 {
268     if (!m_cfRequest) {
269         *this = ResourceRequest();
270         return;
271     }
272
273     m_url = CFURLRequestGetURL(m_cfRequest.get());
274
275     if (m_cachePolicy == ResourceRequestCachePolicy::UseProtocolCachePolicy)
276         m_cachePolicy = fromPlatformRequestCachePolicy(CFURLRequestGetCachePolicy(m_cfRequest.get()));
277     m_timeoutInterval = CFURLRequestGetTimeoutInterval(m_cfRequest.get());
278     m_firstPartyForCookies = CFURLRequestGetMainDocumentURL(m_cfRequest.get());
279     if (CFStringRef method = CFURLRequestCopyHTTPRequestMethod(m_cfRequest.get())) {
280         m_httpMethod = method;
281         CFRelease(method);
282     }
283     m_allowCookies = CFURLRequestShouldHandleHTTPCookies(m_cfRequest.get());
284
285     if (resourcePrioritiesEnabled())
286         m_priority = toResourceLoadPriority(CFURLRequestGetRequestPriority(m_cfRequest.get()));
287
288 #if PLATFORM(IOS_FAMILY) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 120000
289     RetainPtr<CFURLRef> siteForCookies = adoptCF(checked_cf_cast<CFURLRef>(_CFURLRequestCopyProtocolPropertyForKey(m_cfRequest.get(), CFSTR("_kCFHTTPCookiePolicyPropertySiteForCookies"))));
290     m_sameSiteDisposition = !siteForCookies ? SameSiteDisposition::Unspecified : (areRegistrableDomainsEqual(siteForCookies.get(), m_url) ? SameSiteDisposition::SameSite : SameSiteDisposition::CrossSite);
291
292     RetainPtr<CFNumberRef> isTopSiteCF = adoptCF(checked_cf_cast<CFNumber>(_CFURLRequestCopyProtocolPropertyForKey(m_cfRequest.get(), CFSTR("_kCFHTTPCookiePolicyPropertyisTopSite"))));
293     if (!isTopSiteCF)
294         m_isTopSite = false;
295     else {
296         int isTopSite = 0;
297         CFNumberGetValue(isTopSiteCF.get(), kCFNumberIntType, &isTopSite);
298         m_isTopSite = isTopSite;
299     }
300 #endif
301
302     m_httpHeaderFields.clear();
303     if (CFDictionaryRef headers = CFURLRequestCopyAllHTTPHeaderFields(m_cfRequest.get())) {
304         CFIndex headerCount = CFDictionaryGetCount(headers);
305         Vector<const void*, 128> keys(headerCount);
306         Vector<const void*, 128> values(headerCount);
307         CFDictionaryGetKeysAndValues(headers, keys.data(), values.data());
308         for (int i = 0; i < headerCount; ++i)
309             m_httpHeaderFields.set((CFStringRef)keys[i], (CFStringRef)values[i]);
310         CFRelease(headers);
311     }
312
313     m_responseContentDispositionEncodingFallbackArray.clear();
314     RetainPtr<CFArrayRef> encodingFallbacks = adoptCF(copyContentDispositionEncodingFallbackArray(m_cfRequest.get()));
315     if (encodingFallbacks) {
316         CFIndex count = CFArrayGetCount(encodingFallbacks.get());
317         for (CFIndex i = 0; i < count; ++i) {
318             CFStringEncoding encoding = reinterpret_cast<CFIndex>(CFArrayGetValueAtIndex(encodingFallbacks.get(), i));
319             if (encoding != kCFStringEncodingInvalidId)
320                 m_responseContentDispositionEncodingFallbackArray.append(CFStringConvertEncodingToIANACharSetName(encoding));
321         }
322     }
323
324 #if ENABLE(CACHE_PARTITIONING)
325     RetainPtr<CFStringRef> cachePartition = adoptCF(static_cast<CFStringRef>(_CFURLRequestCopyProtocolPropertyForKey(m_cfRequest.get(), _kCFURLCachePartitionKey)));
326     if (cachePartition)
327         m_cachePartition = cachePartition.get();
328 #endif
329 }
330
331 void ResourceRequest::doUpdateResourceHTTPBody()
332 {
333     if (!m_cfRequest) {
334         m_httpBody = nullptr;
335         return;
336     }
337
338     if (RetainPtr<CFDataRef> bodyData = adoptCF(CFURLRequestCopyHTTPRequestBody(m_cfRequest.get())))
339         m_httpBody = FormData::create(CFDataGetBytePtr(bodyData.get()), CFDataGetLength(bodyData.get()));
340     else if (RetainPtr<CFReadStreamRef> bodyStream = adoptCF(CFURLRequestCopyHTTPRequestBodyStream(m_cfRequest.get()))) {
341         FormData* formData = httpBodyFromStream(bodyStream.get());
342         // There is no FormData object if a client provided a custom data stream.
343         // We shouldn't be looking at http body after client callbacks.
344         ASSERT(formData);
345         if (formData)
346             m_httpBody = formData;
347     }
348 }
349
350
351 void ResourceRequest::setStorageSession(CFURLStorageSessionRef storageSession)
352 {
353     updatePlatformRequest();
354
355     auto cfRequest = CFURLRequestCreateMutableCopy(0, m_cfRequest.get());
356     if (storageSession)
357         _CFURLRequestSetStorageSession(cfRequest, storageSession);
358     m_cfRequest = adoptCF(cfRequest);
359 }
360
361 #endif // USE(CFURLCONNECTION)
362
363 void ResourceRequest::updateFromDelegatePreservingOldProperties(const ResourceRequest& delegateProvidedRequest)
364 {
365     // These are things we don't want willSendRequest delegate to mutate or reset.
366     ResourceLoadPriority oldPriority = priority();
367     RefPtr<FormData> oldHTTPBody = httpBody();
368     bool isHiddenFromInspector = hiddenFromInspector();
369     auto oldRequester = requester();
370     auto oldInitiatorIdentifier = initiatorIdentifier();
371     auto oldInspectorInitiatorNodeIdentifier = inspectorInitiatorNodeIdentifier();
372
373     *this = delegateProvidedRequest;
374
375     setPriority(oldPriority);
376     setHTTPBody(WTFMove(oldHTTPBody));
377     setHiddenFromInspector(isHiddenFromInspector);
378     setRequester(oldRequester);
379     setInitiatorIdentifier(oldInitiatorIdentifier);
380     if (oldInspectorInitiatorNodeIdentifier)
381         setInspectorInitiatorNodeIdentifier(*oldInspectorInitiatorNodeIdentifier);
382 }
383
384 bool ResourceRequest::httpPipeliningEnabled()
385 {
386     return s_httpPipeliningEnabled;
387 }
388
389 void ResourceRequest::setHTTPPipeliningEnabled(bool flag)
390 {
391     s_httpPipeliningEnabled = flag;
392 }
393
394 // FIXME: It is confusing that this function both sets connection count and determines maximum request count at network layer. This can and should be done separately.
395 unsigned initializeMaximumHTTPConnectionCountPerHost()
396 {
397     static const unsigned preferredConnectionCount = 6;
398     static const unsigned unlimitedRequestCount = 10000;
399
400     _CFNetworkHTTPConnectionCacheSetLimit(kHTTPLoadWidth, preferredConnectionCount);
401     unsigned maximumHTTPConnectionCountPerHost = _CFNetworkHTTPConnectionCacheGetLimit(kHTTPLoadWidth);
402
403     Boolean keyExistsAndHasValidFormat = false;
404     Boolean prefValue = CFPreferencesGetAppBooleanValue(CFSTR("WebKitEnableHTTPPipelining"), kCFPreferencesCurrentApplication, &keyExistsAndHasValidFormat);
405     if (keyExistsAndHasValidFormat)
406         ResourceRequest::setHTTPPipeliningEnabled(prefValue);
407
408     // Use WebCore scheduler when we can't use request priorities with CFNetwork.
409     if (!ResourceRequest::resourcePrioritiesEnabled())
410         return maximumHTTPConnectionCountPerHost;
411
412     _CFNetworkHTTPConnectionCacheSetLimit(kHTTPPriorityNumLevels, toPlatformRequestPriority(ResourceLoadPriority::Highest));
413 #if !PLATFORM(WIN)
414     // FIXME: <rdar://problem/9375609> Implement minimum fast lane priority setting on Windows
415     _CFNetworkHTTPConnectionCacheSetLimit(kHTTPMinimumFastLanePriority, toPlatformRequestPriority(ResourceLoadPriority::Medium));
416 #endif
417
418     return unlimitedRequestCount;
419 }
420
421 #if PLATFORM(IOS_FAMILY)
422 void initializeHTTPConnectionSettingsOnStartup()
423 {
424     // This need to be called from WebKitInitialize so the calls happen early enough, before any requests are made. <rdar://problem/9691871>
425     // Desktop doesn't have early initialization so it is not clear how this should be done there. The CFNetwork SPI probably
426     // needs to become more forgiving.
427     // We can't read settings here as this is called too early for that. All values need to be constants.
428     static const unsigned preferredConnectionCount = 6;
429     static const unsigned fastLaneConnectionCount = 1;
430     _CFNetworkHTTPConnectionCacheSetLimit(kHTTPLoadWidth, preferredConnectionCount);
431     _CFNetworkHTTPConnectionCacheSetLimit(kHTTPPriorityNumLevels, toPlatformRequestPriority(ResourceLoadPriority::Highest));
432     _CFNetworkHTTPConnectionCacheSetLimit(kHTTPMinimumFastLanePriority, toPlatformRequestPriority(ResourceLoadPriority::Medium));
433     _CFNetworkHTTPConnectionCacheSetLimit(kHTTPNumFastLanes, fastLaneConnectionCount);
434 }
435 #endif
436
437 #if PLATFORM(COCOA)
438 CFStringRef ResourceRequest::isUserInitiatedKey()
439 {
440     static CFStringRef key = CFSTR("ResourceRequestIsUserInitiatedKey");
441     return key;
442 }
443 #endif
444
445 } // namespace WebCore