[WTF] Add makeUnique<T>, which ensures T is fast-allocated, makeUnique / makeUniqueWi...
[WebKit-https.git] / Source / WebCore / platform / network / cf / ResourceHandleCFURLConnectionDelegateWithOperationQueue.cpp
index a07cd8b..713b4df 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Apple Inc.  All rights reserved.
+ * Copyright (C) 2013-2018 Apple Inc.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #include "config.h"
 #include "ResourceHandleCFURLConnectionDelegateWithOperationQueue.h"
 
-#if USE(CFNETWORK)
+#if USE(CFURLCONNECTION)
 
 #include "AuthenticationCF.h"
 #include "AuthenticationChallenge.h"
 #include "Logging.h"
+#include "MIMETypeRegistry.h"
 #include "ResourceHandle.h"
 #include "ResourceHandleClient.h"
 #include "ResourceResponse.h"
 #include "SharedBuffer.h"
-#include "WebCoreSystemInterface.h"
+#if !PLATFORM(WIN)
 #include "WebCoreURLResponse.h"
+#endif
+#include <pal/spi/cf/CFNetworkSPI.h>
+#include <wtf/CompletionHandler.h>
 #include <wtf/MainThread.h>
+#include <wtf/Threading.h>
 #include <wtf/text/CString.h>
 #include <wtf/text/WTFString.h>
 
 namespace WebCore {
 
-ResourceHandleCFURLConnectionDelegateWithOperationQueue::ResourceHandleCFURLConnectionDelegateWithOperationQueue(ResourceHandle* handle)
+ResourceHandleCFURLConnectionDelegateWithOperationQueue::ResourceHandleCFURLConnectionDelegateWithOperationQueue(ResourceHandle* handle, MessageQueue<Function<void()>>* messageQueue)
     : ResourceHandleCFURLConnectionDelegate(handle)
-    , m_queue(dispatch_queue_create("com.apple.WebCore/CFNetwork", DISPATCH_QUEUE_SERIAL))
-    , m_semaphore(dispatch_semaphore_create(0))
+    , m_messageQueue(messageQueue)
 {
-    dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
-    dispatch_set_target_queue(m_queue, backgroundQueue);
 }
 
 ResourceHandleCFURLConnectionDelegateWithOperationQueue::~ResourceHandleCFURLConnectionDelegateWithOperationQueue()
 {
-    dispatch_release(m_semaphore);
-    dispatch_release(m_queue);
 }
 
 bool ResourceHandleCFURLConnectionDelegateWithOperationQueue::hasHandle() const
@@ -63,20 +63,74 @@ bool ResourceHandleCFURLConnectionDelegateWithOperationQueue::hasHandle() const
     return !!m_handle;
 }
 
+void ResourceHandleCFURLConnectionDelegateWithOperationQueue::releaseHandle()
+{
+    ResourceHandleCFURLConnectionDelegate::releaseHandle();
+    m_requestResult = nullptr;
+    m_cachedResponseResult = nullptr;
+    m_semaphore.signal();
+}
+
 void ResourceHandleCFURLConnectionDelegateWithOperationQueue::setupRequest(CFMutableURLRequestRef request)
 {
-#if PLATFORM(IOS)
-    CFURLRequestSetShouldStartSynchronously(request, 1);
-#endif
     CFURLRef requestURL = CFURLRequestGetURL(request);
     if (!requestURL)
         return;
     m_originalScheme = adoptCF(CFURLCopyScheme(requestURL));
 }
 
+LRESULT CALLBACK hookToRemoveCFNetworkMessage(int code, WPARAM wParam, LPARAM lParam)
+{
+    MSG* msg = reinterpret_cast<MSG*>(lParam);
+    // This message which CFNetwork sends to itself, will block the main thread, remove it.
+    if (msg->message == WM_USER + 0xcf)
+        msg->message = WM_NULL;
+    return CallNextHookEx(nullptr, code, wParam, lParam);
+}
+
+static void installHookToRemoveCFNetworkMessageBlockingMainThread()
+{
+    static HHOOK hook = nullptr;
+    if (!hook) {
+        DWORD threadID = ::GetCurrentThreadId();
+        hook = ::SetWindowsHookExW(WH_GETMESSAGE, hookToRemoveCFNetworkMessage, 0, threadID);
+    }
+}
+
+static void emptyPerform(void*)
+{
+}
+
+static CFRunLoopRef getRunLoop()
+{
+    static CFRunLoopRef runLoop = nullptr;
+
+    if (!runLoop) {
+        BinarySemaphore sem;
+        Thread::create("CFNetwork Loader", [&] {
+            runLoop = CFRunLoopGetCurrent();
+
+            // Must add a source to the run loop to prevent CFRunLoopRun() from exiting.
+            CFRunLoopSourceContext ctxt = { 0, (void*)1 /*must be non-null*/, 0, 0, 0, 0, 0, 0, 0, emptyPerform };
+            CFRunLoopSourceRef bogusSource = CFRunLoopSourceCreate(0, 0, &ctxt);
+            CFRunLoopAddSource(runLoop, bogusSource, kCFRunLoopDefaultMode);
+            sem.signal();
+
+            while (true)
+                CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1E30, true);
+        });
+        sem.wait();
+    }
+
+    return runLoop;
+}
+
 void ResourceHandleCFURLConnectionDelegateWithOperationQueue::setupConnectionScheduling(CFURLConnectionRef connection)
 {
-    CFURLConnectionSetDelegateDispatchQueue(connection, m_queue);
+    installHookToRemoveCFNetworkMessageBlockingMainThread();
+    CFRunLoopRef runLoop = getRunLoop();
+    CFURLConnectionScheduleWithRunLoop(connection, runLoop, kCFRunLoopDefaultMode);
+    CFURLConnectionScheduleDownloadWithRunLoop(connection, runLoop, kCFRunLoopDefaultMode);
 }
 
 CFURLRequestRef ResourceHandleCFURLConnectionDelegateWithOperationQueue::willSendRequest(CFURLRequestRef cfRequest, CFURLResponseRef originalRedirectResponse)
@@ -92,227 +146,254 @@ CFURLRequestRef ResourceHandleCFURLConnectionDelegateWithOperationQueue::willSen
 
     ASSERT(!isMainThread());
 
-    RefPtr<ResourceHandleCFURLConnectionDelegateWithOperationQueue> protector(this);
+    auto protectedThis = makeRef(*this);
+    auto work = [this, protectedThis = makeRef(*this), cfRequest = RetainPtr<CFURLRequestRef>(cfRequest), originalRedirectResponse = RetainPtr<CFURLResponseRef>(originalRedirectResponse)] () mutable {
+        auto& handle = protectedThis->m_handle;
+        auto completionHandler = [this, protectedThis = WTFMove(protectedThis)] (ResourceRequest&& request) {
+            m_requestResult = request.cfURLRequest(UpdateHTTPBody);
+            m_semaphore.signal();
+        };
 
-    dispatch_async(dispatch_get_main_queue(), ^{
-        if (!protector->hasHandle()) {
-            continueWillSendRequest(nullptr);
+        if (!hasHandle()) {
+            completionHandler({ });
             return;
         }
 
-        LOG(Network, "CFNet - ResourceHandleCFURLConnectionDelegateWithOperationQueue::willSendRequest(handle=%p) (%s)", m_handle, m_handle->firstRequest().url().string().utf8().data());
+        LOG(Network, "CFNet - ResourceHandleCFURLConnectionDelegateWithOperationQueue::willSendRequest(handle=%p) (%s)", handle, handle->firstRequest().url().string().utf8().data());
 
-        RetainPtr<CFURLResponseRef> redirectResponse = synthesizeRedirectResponseIfNecessary(cfRequest, originalRedirectResponse);
+        RetainPtr<CFURLResponseRef> redirectResponse = synthesizeRedirectResponseIfNecessary(cfRequest.get(), originalRedirectResponse.get());
         ASSERT(redirectResponse);
 
-        ResourceRequest request = createResourceRequest(cfRequest, redirectResponse.get());
-        m_handle->willSendRequest(request, redirectResponse.get());
-    });
+        ResourceRequest request = createResourceRequest(cfRequest.get(), redirectResponse.get());
+        handle->willSendRequest(WTFMove(request), redirectResponse.get(), WTFMove(completionHandler));
+    };
 
-    dispatch_semaphore_wait(m_semaphore, DISPATCH_TIME_FOREVER);
+    if (m_messageQueue)
+        m_messageQueue->append(makeUnique<Function<void()>>(WTFMove(work)));
+    else
+        callOnMainThread(WTFMove(work));
+    m_semaphore.wait();
 
     return m_requestResult.leakRef();
 }
 
 void ResourceHandleCFURLConnectionDelegateWithOperationQueue::didReceiveResponse(CFURLConnectionRef connection, CFURLResponseRef cfResponse)
 {
-    RefPtr<ResourceHandleCFURLConnectionDelegateWithOperationQueue> protector(this);
-
-    dispatch_async(dispatch_get_main_queue(), ^{
-        if (!protector->hasHandle()) {
-            continueDidReceiveResponse();
+    auto protectedThis = makeRef(*this);
+    auto work = [this, protectedThis = makeRef(*this), cfResponse = RetainPtr<CFURLResponseRef>(cfResponse), connection = RetainPtr<CFURLConnectionRef>(connection)] () mutable {
+        if (!hasHandle() || !m_handle->client() || !m_handle->connection()) {
+            m_semaphore.signal();
             return;
         }
 
         LOG(Network, "CFNet - ResourceHandleCFURLConnectionDelegateWithOperationQueue::didReceiveResponse(handle=%p) (%s)", m_handle, m_handle->firstRequest().url().string().utf8().data());
 
         // Avoid MIME type sniffing if the response comes back as 304 Not Modified.
-        CFHTTPMessageRef msg = wkGetCFURLResponseHTTPResponse(cfResponse);
+        auto msg = CFURLResponseGetHTTPResponse(cfResponse.get());
         int statusCode = msg ? CFHTTPMessageGetResponseStatusCode(msg) : 0;
 
-        if (statusCode != 304)
-            adjustMIMETypeIfNecessary(cfResponse);
+        if (statusCode != 304) {
+            bool isMainResourceLoad = m_handle->firstRequest().requester() == ResourceRequest::Requester::Main;
+        }
 
-#if !PLATFORM(IOS)
         if (_CFURLRequestCopyProtocolPropertyForKey(m_handle->firstRequest().cfURLRequest(DoNotUpdateHTTPBody), CFSTR("ForceHTMLMIMEType")))
-            wkSetCFURLResponseMIMEType(cfResponse, CFSTR("text/html"));
-#endif // !PLATFORM(IOS)
-        
-        ResourceResponse resourceResponse(cfResponse);
-#if ENABLE(WEB_TIMING)
-        ResourceHandle::getConnectionTimingData(connection, resourceResponse.resourceLoadTiming());
-#else
-        UNUSED_PARAM(connection);
-#endif
-        
-        m_handle->client()->didReceiveResponseAsync(m_handle, resourceResponse);
-    });
-    dispatch_semaphore_wait(m_semaphore, DISPATCH_TIME_FOREVER);
+            CFURLResponseSetMIMEType(cfResponse.get(), CFSTR("text/html"));
+
+        ResourceResponse resourceResponse(cfResponse.get());
+        resourceResponse.setSource(ResourceResponse::Source::Network);
+        m_handle->didReceiveResponse(WTFMove(resourceResponse), [this, protectedThis = WTFMove(protectedThis)] {
+            m_semaphore.signal();
+        });
+    };
+
+    if (m_messageQueue)
+        m_messageQueue->append(makeUnique<Function<void()>>(WTFMove(work)));
+    else
+        callOnMainThread(WTFMove(work));
+    m_semaphore.wait();
 }
 
 void ResourceHandleCFURLConnectionDelegateWithOperationQueue::didReceiveData(CFDataRef data, CFIndex originalLength)
 {
-    RefPtr<ResourceHandleCFURLConnectionDelegateWithOperationQueue> protector(this);
-    CFRetain(data);
-
-    dispatch_async(dispatch_get_main_queue(), ^{
-        if (protector->hasHandle()) {
-            LOG(Network, "CFNet - ResourceHandleCFURLConnectionDelegateWithOperationQueue::didReceiveData(handle=%p) (%s)", m_handle, m_handle->firstRequest().url().string().utf8().data());
-
-            m_handle->client()->didReceiveBuffer(m_handle, SharedBuffer::wrapCFData(data), originalLength);
-        }
-
-        CFRelease(data);
-    });
+    auto work = [protectedThis = makeRef(*this), data = RetainPtr<CFDataRef>(data), originalLength = originalLength] () mutable {
+        auto& handle = protectedThis->m_handle;
+        if (!protectedThis->hasHandle() || !handle->client() || !handle->connection())
+            return;
+        
+        LOG(Network, "CFNet - ResourceHandleCFURLConnectionDelegateWithOperationQueue::didReceiveData(handle=%p) (%s)", handle, handle->firstRequest().url().string().utf8().data());
+
+        handle->client()->didReceiveBuffer(handle, SharedBuffer::create(data.get()), originalLength);
+    };
+    
+    if (m_messageQueue)
+        m_messageQueue->append(makeUnique<Function<void()>>(WTFMove(work)));
+    else
+        callOnMainThread(WTFMove(work));
 }
 
 void ResourceHandleCFURLConnectionDelegateWithOperationQueue::didFinishLoading()
 {
-    RefPtr<ResourceHandleCFURLConnectionDelegateWithOperationQueue> protector(this);
-    dispatch_async(dispatch_get_main_queue(), ^{
-        if (!protector->hasHandle())
+    auto work = [protectedThis = makeRef(*this)] () mutable {
+        auto& handle = protectedThis->m_handle;
+        if (!protectedThis->hasHandle() || !handle->client() || !handle->connection()) {
+            protectedThis->m_handle->deref();
             return;
+        }
 
-        LOG(Network, "CFNet - ResourceHandleCFURLConnectionDelegateWithOperationQueue::didFinishLoading(handle=%p) (%s)", m_handle, m_handle->firstRequest().url().string().utf8().data());
+        LOG(Network, "CFNet - ResourceHandleCFURLConnectionDelegateWithOperationQueue::didFinishLoading(handle=%p) (%s)", handle, handle->firstRequest().url().string().utf8().data());
 
-        m_handle->client()->didFinishLoading(m_handle, 0);
-    });
+        handle->client()->didFinishLoading(handle);
+        if (protectedThis->m_messageQueue) {
+            protectedThis->m_messageQueue->kill();
+            protectedThis->m_messageQueue = nullptr;
+        }
+        protectedThis->m_handle->deref();
+    };
+    
+    if (m_messageQueue)
+        m_messageQueue->append(makeUnique<Function<void()>>(WTFMove(work)));
+    else
+        callOnMainThread(WTFMove(work));
 }
 
 void ResourceHandleCFURLConnectionDelegateWithOperationQueue::didFail(CFErrorRef error)
 {
-    RefPtr<ResourceHandleCFURLConnectionDelegateWithOperationQueue> protector(this);
-    CFRetain(error);
-    dispatch_async(dispatch_get_main_queue(), ^{
-        if (protector->hasHandle()) {
-            LOG(Network, "CFNet - ResourceHandleCFURLConnectionDelegateWithOperationQueue::didFail(handle=%p) (%s)", m_handle, m_handle->firstRequest().url().string().utf8().data());
+    auto work = [protectedThis = makeRef(*this), error = RetainPtr<CFErrorRef>(error)] () mutable {
+        auto& handle = protectedThis->m_handle;
+        if (!protectedThis->hasHandle() || !handle->client() || !handle->connection()) {
+            protectedThis->m_handle->deref();
+            return;
+        }
+        
+        LOG(Network, "CFNet - ResourceHandleCFURLConnectionDelegateWithOperationQueue::didFail(handle=%p) (%s)", handle, handle->firstRequest().url().string().utf8().data());
 
-            m_handle->client()->didFail(m_handle, ResourceError(error));
+        handle->client()->didFail(handle, ResourceError(error.get()));
+        if (protectedThis->m_messageQueue) {
+            protectedThis->m_messageQueue->kill();
+            protectedThis->m_messageQueue = nullptr;
         }
+        protectedThis->m_handle->deref();
+    };
 
-        CFRelease(error);
-    });
+    if (m_messageQueue)
+        m_messageQueue->append(makeUnique<Function<void()>>(WTFMove(work)));
+    else
+        callOnMainThread(WTFMove(work));
 }
 
 CFCachedURLResponseRef ResourceHandleCFURLConnectionDelegateWithOperationQueue::willCacheResponse(CFCachedURLResponseRef cachedResponse)
 {
-    RefPtr<ResourceHandleCFURLConnectionDelegateWithOperationQueue> protector(this);
+    // Workaround for <rdar://problem/6300990> Caching does not respect Vary HTTP header.
+    // FIXME: WebCore cache has issues with Vary, too (bug 58797, bug 71509).
+    CFURLResponseRef wrappedResponse = CFCachedURLResponseGetWrappedResponse(cachedResponse);
+    if (CFHTTPMessageRef httpResponse = CFURLResponseGetHTTPResponse(wrappedResponse)) {
+        ASSERT(CFHTTPMessageIsHeaderComplete(httpResponse));
+        RetainPtr<CFStringRef> varyValue = adoptCF(CFHTTPMessageCopyHeaderFieldValue(httpResponse, CFSTR("Vary")));
+        if (varyValue)
+            return nullptr;
+    }
 
-    dispatch_async(dispatch_get_main_queue(), ^{
-        if (!protector->hasHandle()) {
-            continueWillCacheResponse(nullptr);
-            return;
-        }
+    auto protectedThis = makeRef(*this);
+    auto work = [protectedThis = makeRef(*this), cachedResponse = RetainPtr<CFCachedURLResponseRef>(cachedResponse)] () mutable {
+        auto& handle = protectedThis->m_handle;
+
+        auto completionHandler = [protectedThis = WTFMove(protectedThis)] (CFCachedURLResponseRef response) mutable {
+            protectedThis->m_cachedResponseResult = response;
+            protectedThis->m_semaphore.signal();
+        };
 
-        LOG(Network, "CFNet - ResourceHandleCFURLConnectionDelegateWithOperationQueue::willCacheResponse(handle=%p) (%s)", m_handle, m_handle->firstRequest().url().string().utf8().data());
+        if (!handle || !handle->client() || !handle->connection())
+            return completionHandler(nullptr);
 
-        m_handle->client()->willCacheResponseAsync(m_handle, cachedResponse);
-    });
-    dispatch_semaphore_wait(m_semaphore, DISPATCH_TIME_FOREVER);
+        LOG(Network, "CFNet - ResourceHandleCFURLConnectionDelegateWithOperationQueue::willCacheResponse(handle=%p) (%s)", handle, handle->firstRequest().url().string().utf8().data());
+
+        handle->client()->willCacheResponseAsync(handle, cachedResponse.get(), WTFMove(completionHandler));
+    };
+    
+    if (m_messageQueue)
+        m_messageQueue->append(makeUnique<Function<void()>>(WTFMove(work)));
+    else
+        callOnMainThread(WTFMove(work));
+    m_semaphore.wait();
     return m_cachedResponseResult.leakRef();
 }
 
 void ResourceHandleCFURLConnectionDelegateWithOperationQueue::didReceiveChallenge(CFURLAuthChallengeRef challenge)
 {
-    RefPtr<ResourceHandleCFURLConnectionDelegateWithOperationQueue> protector(this);
-    CFRetain(challenge);
-    dispatch_async(dispatch_get_main_queue(), ^{
-        if (protector->hasHandle()) {
-            LOG(Network, "CFNet - ResourceHandleCFURLConnectionDelegateWithOperationQueue::didReceiveChallenge(handle=%p) (%s)", m_handle, m_handle->firstRequest().url().string().utf8().data());
+    auto work = [protectedThis = makeRef(*this), challenge = RetainPtr<CFURLAuthChallengeRef>(challenge)] () mutable {
+        auto& handle = protectedThis->m_handle;
+        if (!protectedThis->hasHandle())
+            return;
+        
+        LOG(Network, "CFNet - ResourceHandleCFURLConnectionDelegateWithOperationQueue::didReceiveChallenge(handle=%p) (%s)", handle, handle->firstRequest().url().string().utf8().data());
 
-            m_handle->didReceiveAuthenticationChallenge(AuthenticationChallenge(challenge, m_handle));
-        }
+        handle->didReceiveAuthenticationChallenge(AuthenticationChallenge(challenge.get(), handle));
+    };
 
-        CFRelease(challenge);
-    });
+    if (m_messageQueue)
+        m_messageQueue->append(makeUnique<Function<void()>>(WTFMove(work)));
+    else
+        callOnMainThread(WTFMove(work));
 }
 
 void ResourceHandleCFURLConnectionDelegateWithOperationQueue::didSendBodyData(CFIndex totalBytesWritten, CFIndex totalBytesExpectedToWrite)
 {
-    RefPtr<ResourceHandleCFURLConnectionDelegateWithOperationQueue> protector(this);
-    dispatch_async(dispatch_get_main_queue(), ^{
-        if (!protector->hasHandle())
+    auto work = [protectedThis = makeRef(*this), totalBytesWritten, totalBytesExpectedToWrite] () mutable {
+        auto& handle = protectedThis->m_handle;
+        if (!protectedThis->hasHandle() || !handle->client() || !handle->connection())
             return;
 
-        LOG(Network, "CFNet - ResourceHandleCFURLConnectionDelegateWithOperationQueue::didSendBodyData(handle=%p) (%s)", m_handle, m_handle->firstRequest().url().string().utf8().data());
+        LOG(Network, "CFNet - ResourceHandleCFURLConnectionDelegateWithOperationQueue::didSendBodyData(handle=%p) (%s)", handle, handle->firstRequest().url().string().utf8().data());
 
-        m_handle->client()->didSendData(m_handle, totalBytesWritten, totalBytesExpectedToWrite);
-    });
+        handle->client()->didSendData(handle, totalBytesWritten, totalBytesExpectedToWrite);
+    };
+
+    if (m_messageQueue)
+        m_messageQueue->append(makeUnique<Function<void()>>(WTFMove(work)));
+    else
+        callOnMainThread(WTFMove(work));
 }
 
 Boolean ResourceHandleCFURLConnectionDelegateWithOperationQueue::shouldUseCredentialStorage()
 {
-    return NO;
+    return false;
 }
 
 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
 Boolean ResourceHandleCFURLConnectionDelegateWithOperationQueue::canRespondToProtectionSpace(CFURLProtectionSpaceRef protectionSpace)
 {
-    RefPtr<ResourceHandleCFURLConnectionDelegateWithOperationQueue> protector(this);
-
-    dispatch_async(dispatch_get_main_queue(), ^{
-        if (!protector->hasHandle()) {
-            continueCanAuthenticateAgainstProtectionSpace(false);
-            return;
-        }
-
-        LOG(Network, "CFNet - ResourceHandleCFURLConnectionDelegateWithOperationQueue::canRespondToProtectionSpace(handle=%p) (%s)", m_handle, m_handle->firstRequest().url().string().utf8().data());
-
-        ProtectionSpace coreProtectionSpace = ProtectionSpace(protectionSpace);
-#if PLATFORM(IOS)
-        if (coreProtectionSpace.authenticationScheme() == ProtectionSpaceAuthenticationSchemeUnknown) {
-            m_boolResult = false;
-            dispatch_semaphore_signal(m_semaphore);
-            return;
+    auto protectedThis = makeRef(*this);
+    auto work = [protectedThis = makeRef(*this), protectionSpace = RetainPtr<CFURLProtectionSpaceRef>(protectionSpace)] () mutable {
+        auto& handle = protectedThis->m_handle;
+        
+        auto completionHandler = [protectedThis = WTFMove(protectedThis)] (bool result) mutable {
+            protectedThis->m_boolResult = canAuthenticate;
+            protectedThis->m_semaphore.signal();
         }
-#endif // PLATFORM(IOS)
-        m_handle->canAuthenticateAgainstProtectionSpace(coreProtectionSpace);
-    });
-    dispatch_semaphore_wait(m_semaphore, DISPATCH_TIME_FOREVER);
+        
+        if (!handle)
+            return completionHandler(false);
+
+        LOG(Network, "CFNet - ResourceHandleCFURLConnectionDelegateWithOperationQueue::canRespondToProtectionSpace(handle=%p) (%s)", handle, handle->firstRequest().url().string().utf8().data());
+
+        handle->canAuthenticateAgainstProtectionSpace(ProtectionSpace(protectionSpace.get()), WTFMove(completionHandler));
+    };
+    
+    if (m_messageQueue)
+        m_messageQueue->append(makeUnique<Function<void()>>(WTFMove(work)));
+    else
+        callOnMainThread(WTFMove(work));
+    m_semaphore.wait();
     return m_boolResult;
 }
-#endif // USE(PROTECTION_SPACE_AUTH_CALLBACK)
-
-#if USE(NETWORK_CFDATA_ARRAY_CALLBACK)
-void ResourceHandleCFURLConnectionDelegateWithOperationQueue::didReceiveDataArray(CFArrayRef dataArray)
-{
-    RefPtr<ResourceHandleCFURLConnectionDelegateWithOperationQueue> protector(this);
-    CFRetain(dataArray);
-    dispatch_async(dispatch_get_main_queue(), ^{
-        if (protector->hasHandle()) {
-            LOG(Network, "CFNet - ResourceHandleCFURLConnectionDelegateWithOperationQueue::didSendBodyData(handle=%p) (%s)", m_handle, m_handle->firstRequest().url().string().utf8().data());
-
-            m_handle->client()->didReceiveBuffer(m_handle, SharedBuffer::wrapCFDataArray(dataArray), -1);
-        }
-        CFRelease(dataArray);
-    });
-}
-#endif // USE(NETWORK_CFDATA_ARRAY_CALLBACK)
-
-void ResourceHandleCFURLConnectionDelegateWithOperationQueue::continueWillSendRequest(CFURLRequestRef request)
-{
-    m_requestResult = request;
-    dispatch_semaphore_signal(m_semaphore);
-}
 
-void ResourceHandleCFURLConnectionDelegateWithOperationQueue::continueDidReceiveResponse()
-{
-    dispatch_semaphore_signal(m_semaphore);
-}
-
-void ResourceHandleCFURLConnectionDelegateWithOperationQueue::continueWillCacheResponse(CFCachedURLResponseRef response)
-{
-    m_cachedResponseResult = response;
-    dispatch_semaphore_signal(m_semaphore);
-}
-
-#if USE(PROTECTION_SPACE_AUTH_CALLBACK)
 void ResourceHandleCFURLConnectionDelegateWithOperationQueue::continueCanAuthenticateAgainstProtectionSpace(bool canAuthenticate)
 {
     m_boolResult = canAuthenticate;
-    dispatch_semaphore_signal(m_semaphore);
+    m_semaphore.signal();
 }
 #endif // USE(PROTECTION_SPACE_AUTH_CALLBACK)
+
 } // namespace WebCore
 
-#endif // USE(CFNETWORK)
+#endif // USE(CFURLCONNECTION)