18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2008 Collin Jackson  <collinj@webkit.org>
3231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * Copyright (C) 2009 Apple Inc. All Rights Reserved.
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met:
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    documentation and/or other materials provided with the distribution.
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h"
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "DNS.h"
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
30f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include "KURL.h"
31231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "Timer.h"
32d0825bca7fe65beaee391d30da42e937db621564Steve Block#include <wtf/HashSet.h>
33231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include <wtf/RetainPtr.h>
34231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include <wtf/StdLibExtras.h>
35f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick#include <wtf/text/StringHash.h>
36231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
37231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#if PLATFORM(WIN)
38643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#include "LoaderRunLoopCF.h"
392fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include <CFNetwork/CFNetwork.h>
40231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#endif
41231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
42f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#if defined(BUILDING_ON_LEOPARD)
43f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include <SystemConfiguration/SystemConfiguration.h>
44f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#endif
45f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
46231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#ifdef BUILDING_ON_TIGER
47231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block// This function is available on Tiger, but not declared in the CFRunLoop.h header on Tiger.
48231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockextern "C" CFRunLoopRef CFRunLoopGetMain();
49231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#endif
508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
53231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block// When resolve queue is empty, we fire async resolution requests immediately (which is important if the prefetch is triggered by hovering).
54231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block// But during page parsing, we should coalesce identical requests to avoid stressing out CFHost.
55231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockconst int namesToResolveImmediately = 4;
56231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
57231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block// Coalesce prefetch requests for this long before sending them out.
5806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsenconst double coalesceDelayInSeconds = 1.0;
5906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
6006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen// Sending many DNS requests at once can overwhelm some gateways. CFHost doesn't currently throttle for us, see <rdar://8105550>.
6106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsenconst int maxSimultaneousRequests = 8;
62231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
63231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block// For a page has links to many outside sites, it is likely that the system DNS resolver won't be able to cache them all anyway, and we don't want
6406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen// to negatively affect other applications' performance by pushing their cached entries out.
65231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block// If we end up with lots of names to prefetch, some will be dropped.
6606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsenconst int maxRequestsToQueue = 64;
6706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
6806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen// If there were queued names that couldn't be sent simultaneously, check the state of resolvers after this delay.
6906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsenconst double retryResolvingInSeconds = 0.1;
70231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
71f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochstatic bool proxyIsEnabledInSystemPreferences()
72f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
73f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    // Don't do DNS prefetch if proxies are involved. For many proxy types, the user agent is never exposed
74f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    // to the IP address during normal operation. Querying an internal DNS server may not help performance,
75f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    // as it doesn't necessarily look up the actual external IP. Also, if DNS returns a fake internal address,
76f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    // local caches may keep it even after re-connecting to another network.
77f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
78f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#if !defined(BUILDING_ON_LEOPARD)
79f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    RetainPtr<CFDictionaryRef> proxySettings(AdoptCF, CFNetworkCopySystemProxySettings());
80f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#else
81f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    RetainPtr<CFDictionaryRef> proxySettings(AdoptCF, SCDynamicStoreCopyProxies(0));
82f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#endif
83f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (!proxySettings)
84f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        return false;
85f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
86f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    static CFURLRef httpCFURL = KURL(ParsedURLString, "http://example.com/").createCFURL();
87f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    static CFURLRef httpsCFURL = KURL(ParsedURLString, "https://example.com/").createCFURL();
88f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
89f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    RetainPtr<CFArrayRef> httpProxyArray(AdoptCF, CFNetworkCopyProxiesForURL(httpCFURL, proxySettings.get()));
90f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    RetainPtr<CFArrayRef> httpsProxyArray(AdoptCF, CFNetworkCopyProxiesForURL(httpsCFURL, proxySettings.get()));
91f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
92f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    CFIndex httpProxyCount = CFArrayGetCount(httpProxyArray.get());
93f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    CFIndex httpsProxyCount = CFArrayGetCount(httpsProxyArray.get());
94f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (httpProxyCount == 1 && CFEqual(CFDictionaryGetValue(static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(httpProxyArray.get(), 0)), kCFProxyTypeKey), kCFProxyTypeNone))
95f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        httpProxyCount = 0;
96f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (httpsProxyCount == 1 && CFEqual(CFDictionaryGetValue(static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(httpsProxyArray.get(), 0)), kCFProxyTypeKey), kCFProxyTypeNone))
97f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        httpsProxyCount = 0;
98f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
99f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    return httpProxyCount || httpsProxyCount;
100f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
101f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
102231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockclass DNSResolveQueue : public TimerBase {
103231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockpublic:
104231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    static DNSResolveQueue& shared();
105231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    void add(const String&);
106231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    void decrementRequestCount();
107231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
108231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockprivate:
109231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    DNSResolveQueue();
110231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
111231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    void resolve(const String&);
112231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    virtual void fired();
113231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    HashSet<String> m_names;
114231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    int m_requestsInFlight;
115231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block};
116231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
117231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve BlockDNSResolveQueue::DNSResolveQueue()
118231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    : m_requestsInFlight(0)
119231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
120231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
121231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
122231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve BlockDNSResolveQueue& DNSResolveQueue::shared()
123231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
124231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    DEFINE_STATIC_LOCAL(DNSResolveQueue, names, ());
125231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return names;
126231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
127231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
128231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockvoid DNSResolveQueue::add(const String& name)
129231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
130231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // If there are no names queued, and few enough are in flight, resolve immediately (the mouse may be over a link).
131231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (!m_names.size()) {
132f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        if (proxyIsEnabledInSystemPreferences())
133f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            return;
134f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
135231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if (atomicIncrement(&m_requestsInFlight) <= namesToResolveImmediately) {
136231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            resolve(name);
137231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            return;
138231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        }
139231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        atomicDecrement(&m_requestsInFlight);
140231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
14106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
14206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    // It's better to not prefetch some names than to clog the queue.
14306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    // Dropping the newest names, because on a single page, these are likely to be below oldest ones.
14406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    if (m_names.size() < maxRequestsToQueue) {
14506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        m_names.add(name);
14606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        if (!isActive())
14706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen            startOneShot(coalesceDelayInSeconds);
14806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    }
149231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
150231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
151231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockvoid DNSResolveQueue::decrementRequestCount()
152231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
153231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    atomicDecrement(&m_requestsInFlight);
154231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
155231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
156231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockvoid DNSResolveQueue::fired()
157231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
158f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (proxyIsEnabledInSystemPreferences()) {
159f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        m_names.clear();
160f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        return;
161f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    }
162f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
16306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    int requestsAllowed = maxSimultaneousRequests - m_requestsInFlight;
164231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
16506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    for (; !m_names.isEmpty() && requestsAllowed > 0; --requestsAllowed) {
166231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        atomicIncrement(&m_requestsInFlight);
16706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        HashSet<String>::iterator currentName = m_names.begin();
16806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        resolve(*currentName);
16906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        m_names.remove(currentName);
170231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
171231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
17206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    if (!m_names.isEmpty())
17306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        startOneShot(retryResolvingInSeconds);
174231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
175231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
176231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockstatic void clientCallback(CFHostRef theHost, CFHostInfoType, const CFStreamError*, void*)
177231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
178231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    DNSResolveQueue::shared().decrementRequestCount(); // It's ok to call shared() from a secondary thread, the static variable has already been initialized by now.
179231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    CFRelease(theHost);
180231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
181231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
182231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockvoid DNSResolveQueue::resolve(const String& hostname)
183231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
184231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    ASSERT(isMainThread());
185231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
186231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    RetainPtr<CFStringRef> hostnameCF(AdoptCF, hostname.createCFString());
187231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    RetainPtr<CFHostRef> host(AdoptCF, CFHostCreateWithName(0, hostnameCF.get()));
188231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (!host) {
189231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        atomicDecrement(&m_requestsInFlight);
190231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return;
191231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
192231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    CFHostClientContext context = { 0, 0, 0, 0, 0 };
193231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    Boolean result = CFHostSetClient(host.get(), clientCallback, &context);
194231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    ASSERT_UNUSED(result, result);
195231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#if !PLATFORM(WIN)
196231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    CFHostScheduleWithRunLoop(host.get(), CFRunLoopGetMain(), kCFRunLoopCommonModes);
197231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#else
198231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // On Windows, we run a separate thread with CFRunLoop, which is where clientCallback will be called.
199643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    CFHostScheduleWithRunLoop(host.get(), loaderRunLoop(), kCFRunLoopDefaultMode);
200231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#endif
201231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    CFHostStartInfoResolution(host.get(), kCFHostAddresses, 0);
202231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    host.releaseRef(); // The host will be released from clientCallback().
203231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
204231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
205231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockvoid prefetchDNS(const String& hostname)
2068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
207231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    ASSERT(isMainThread());
208231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (hostname.isEmpty())
209231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return;
210231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    DNSResolveQueue::shared().add(hostname);
2118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
214