SynchronousResourceHandleCFURLConnectionDelegate.cpp [plain text]
#include "config.h"
#include "SynchronousResourceHandleCFURLConnectionDelegate.h"
#if USE(CFNETWORK)
#include "AuthenticationCF.h"
#include "AuthenticationChallenge.h"
#include "LoaderRunLoopCF.h"
#include "Logging.h"
#include "ResourceHandle.h"
#include "ResourceHandleClient.h"
#include "ResourceResponse.h"
#include "SharedBuffer.h"
#include <wtf/RetainPtr.h>
#include <wtf/text/CString.h>
#include <wtf/text/WTFString.h>
#if PLATFORM(COCOA)
#include "WebCoreSystemInterface.h"
#include "WebCoreURLResponse.h"
#endif // PLATFORM(COCOA)
#if PLATFORM(IOS)
#include "WebCoreThread.h"
#endif // PLATFORM(IOS)
#if PLATFORM(WIN)
#include "MIMETypeRegistry.h"
#endif // PLATFORM(WIN)
namespace WebCore {
SynchronousResourceHandleCFURLConnectionDelegate::SynchronousResourceHandleCFURLConnectionDelegate(ResourceHandle* handle)
: ResourceHandleCFURLConnectionDelegate(handle)
{
}
void SynchronousResourceHandleCFURLConnectionDelegate::setupRequest(CFMutableURLRequestRef request)
{
#if PLATFORM(IOS)
CFURLRequestSetShouldStartSynchronously(request, 1);
#endif
}
void SynchronousResourceHandleCFURLConnectionDelegate::setupConnectionScheduling(CFURLConnectionRef connection)
{
#if PLATFORM(WIN)
CFURLConnectionScheduleWithCurrentMessageQueue(connection);
#elif PLATFORM(IOS)
CFURLConnectionScheduleWithRunLoop(connection, WebThreadRunLoop(), kCFRunLoopDefaultMode);
#else
CFURLConnectionScheduleWithRunLoop(connection, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
#endif
CFURLConnectionScheduleDownloadWithRunLoop(connection, loaderRunLoop(), kCFRunLoopDefaultMode);
}
CFURLRequestRef SynchronousResourceHandleCFURLConnectionDelegate::willSendRequest(CFURLRequestRef cfRequest, CFURLResponseRef originalRedirectResponse)
{
RetainPtr<CFURLResponseRef> redirectResponse = synthesizeRedirectResponseIfNecessary(cfRequest, originalRedirectResponse);
if (!redirectResponse) {
CFRetain(cfRequest);
return cfRequest;
}
LOG(Network, "CFNet - SynchronousResourceHandleCFURLConnectionDelegate::willSendRequest(handle=%p) (%s)", m_handle, m_handle->firstRequest().url().string().utf8().data());
ResourceRequest request = createResourceRequest(cfRequest, redirectResponse.get());
m_handle->willSendRequest(request, redirectResponse.get());
if (request.isNull())
return 0;
cfRequest = request.cfURLRequest(UpdateHTTPBody);
CFRetain(cfRequest);
return cfRequest;
}
#if !PLATFORM(COCOA)
static void setDefaultMIMEType(CFURLResponseRef response)
{
static CFStringRef defaultMIMETypeString = defaultMIMEType().createCFString().leakRef();
CFURLResponseSetMIMEType(response, defaultMIMETypeString);
}
static void adjustMIMETypeIfNecessary(CFURLResponseRef cfResponse)
{
RetainPtr<CFStringRef> result = CFURLResponseGetMIMEType(cfResponse);
RetainPtr<CFStringRef> originalResult = result;
if (!result) {
CFURLRef cfURL = CFURLResponseGetURL(cfResponse);
URL url(cfURL);
if (url.isLocalFile()) {
String mimeType = mimeTypeFromURL(url);
result = mimeType.createCFString().leakRef();
}
}
if (!result) {
static CFStringRef defaultMIMETypeString = WebCore::defaultMIMEType().createCFString().leakRef();
result = defaultMIMETypeString;
}
if (result != originalResult)
CFURLResponseSetMIMEType(cfResponse, result.get());
}
#endif // !PLATFORM(COCOA)
void SynchronousResourceHandleCFURLConnectionDelegate::didReceiveResponse(CFURLConnectionRef connection, CFURLResponseRef cfResponse)
{
LOG(Network, "CFNet - SynchronousResourceHandleCFURLConnectionDelegate::didReceiveResponse(handle=%p) (%s)", m_handle, m_handle->firstRequest().url().string().utf8().data());
if (!m_handle->client())
return;
#if PLATFORM(COCOA)
CFHTTPMessageRef msg = wkGetCFURLResponseHTTPResponse(cfResponse);
int statusCode = msg ? CFHTTPMessageGetResponseStatusCode(msg) : 0;
if (statusCode != 304)
adjustMIMETypeIfNecessary(cfResponse);
#if !PLATFORM(IOS)
if (_CFURLRequestCopyProtocolPropertyForKey(m_handle->firstRequest().cfURLRequest(DoNotUpdateHTTPBody), CFSTR("ForceHTMLMIMEType")))
wkSetCFURLResponseMIMEType(cfResponse, CFSTR("text/html"));
#endif // !PLATFORM(IOS)
#else
if (!CFURLResponseGetMIMEType(cfResponse))
adjustMIMETypeIfNecessary(cfResponse);
if (!CFURLResponseGetMIMEType(cfResponse)) {
ASSERT(!m_handle->shouldContentSniff());
setDefaultMIMEType(cfResponse);
}
#endif
#if USE(QUICK_LOOK)
m_handle->setQuickLookHandle(QuickLookHandle::create(m_handle, this, cfResponse));
if (m_handle->quickLookHandle())
cfResponse = m_handle->quickLookHandle()->cfResponse();
#endif
ResourceResponse resourceResponse(cfResponse);
#if PLATFORM(COCOA) && ENABLE(WEB_TIMING)
ResourceHandle::getConnectionTimingData(connection, resourceResponse.resourceLoadTiming());
#else
UNUSED_PARAM(connection);
#endif
m_handle->client()->didReceiveResponse(m_handle, resourceResponse);
}
void SynchronousResourceHandleCFURLConnectionDelegate::didReceiveData(CFDataRef data, CFIndex originalLength)
{
LOG(Network, "CFNet - SynchronousResourceHandleCFURLConnectionDelegate::didReceiveData(handle=%p, bytes=%ld) (%s)", m_handle, CFDataGetLength(data), m_handle->firstRequest().url().string().utf8().data());
#if USE(QUICK_LOOK)
if (m_handle->quickLookHandle() && m_handle->quickLookHandle()->didReceiveData(data))
return;
#endif
if (ResourceHandleClient* client = m_handle->client())
client->didReceiveBuffer(m_handle, SharedBuffer::wrapCFData(data), originalLength);
}
void SynchronousResourceHandleCFURLConnectionDelegate::didFinishLoading()
{
LOG(Network, "CFNet - SynchronousResourceHandleCFURLConnectionDelegate::didFinishLoading(handle=%p) (%s)", m_handle, m_handle->firstRequest().url().string().utf8().data());
#if USE(QUICK_LOOK)
if (m_handle->quickLookHandle() && m_handle->quickLookHandle()->didFinishLoading())
return;
#endif
if (ResourceHandleClient* client = m_handle->client())
client->didFinishLoading(m_handle, 0);
}
void SynchronousResourceHandleCFURLConnectionDelegate::didFail(CFErrorRef error)
{
LOG(Network, "CFNet - SynchronousResourceHandleCFURLConnectionDelegate::didFail(handle=%p, error = %p) (%s)", m_handle, error, m_handle->firstRequest().url().string().utf8().data());
#if USE(QUICK_LOOK)
if (QuickLookHandle* quickLookHandle = m_handle->quickLookHandle())
quickLookHandle->didFail();
#endif
if (ResourceHandleClient* client = m_handle->client())
client->didFail(m_handle, ResourceError(error));
}
CFCachedURLResponseRef SynchronousResourceHandleCFURLConnectionDelegate::willCacheResponse(CFCachedURLResponseRef cachedResponse)
{
#if PLATFORM(WIN)
CFURLResponseRef wrappedResponse = CFCachedURLResponseGetWrappedResponse(cachedResponse);
if (CFHTTPMessageRef httpResponse = CFURLResponseGetHTTPResponse(wrappedResponse)) {
ASSERT(CFHTTPMessageIsHeaderComplete(httpResponse));
RetainPtr<CFStringRef> varyValue = adoptCF(CFHTTPMessageCopyHeaderFieldValue(httpResponse, CFSTR("Vary")));
if (varyValue)
return 0;
}
#endif // PLATFORM(WIN)
#if PLATFORM(WIN)
if (m_handle->client() && !m_handle->client()->shouldCacheResponse(m_handle, cachedResponse))
return 0;
#else
CFCachedURLResponseRef newResponse = m_handle->client()->willCacheResponse(m_handle, cachedResponse);
if (newResponse != cachedResponse)
return newResponse;
#endif
CFRetain(cachedResponse);
return cachedResponse;
}
void SynchronousResourceHandleCFURLConnectionDelegate::didReceiveChallenge(CFURLAuthChallengeRef challenge)
{
LOG(Network, "CFNet - SynchronousResourceHandleCFURLConnectionDelegate::didReceiveChallenge(handle=%p (%s)", m_handle, m_handle->firstRequest().url().string().utf8().data());
m_handle->didReceiveAuthenticationChallenge(AuthenticationChallenge(challenge, m_handle));
}
void SynchronousResourceHandleCFURLConnectionDelegate::didSendBodyData(CFIndex totalBytesWritten, CFIndex totalBytesExpectedToWrite)
{
if (!m_handle || !m_handle->client())
return;
m_handle->client()->didSendData(m_handle, totalBytesWritten, totalBytesExpectedToWrite);
}
Boolean SynchronousResourceHandleCFURLConnectionDelegate::shouldUseCredentialStorage()
{
LOG(Network, "CFNet - SynchronousResourceHandleCFURLConnectionDelegate::shouldUseCredentialStorage(handle=%p) (%s)", m_handle, m_handle->firstRequest().url().string().utf8().data());
if (!m_handle)
return false;
return m_handle->shouldUseCredentialStorage();
}
#if USE(PROTECTION_SPACE_AUTH_CALLBACK)
Boolean SynchronousResourceHandleCFURLConnectionDelegate::canRespondToProtectionSpace(CFURLProtectionSpaceRef protectionSpace)
{
ASSERT(m_handle);
LOG(Network, "CFNet - SynchronousResourceHandleCFURLConnectionDelegate::canRespondToProtectionSpace(handle=%p (%s)", m_handle, m_handle->firstRequest().url().string().utf8().data());
#if PLATFORM(IOS)
ProtectionSpace coreProtectionSpace = ProtectionSpace(protectionSpace);
if (coreProtectionSpace.authenticationScheme() == ProtectionSpaceAuthenticationSchemeUnknown)
return false;
return m_handle->canAuthenticateAgainstProtectionSpace(coreProtectionSpace);
#else
return m_handle->canAuthenticateAgainstProtectionSpace(core(protectionSpace));
#endif
}
#endif // USE(PROTECTION_SPACE_AUTH_CALLBACK)
#if USE(NETWORK_CFDATA_ARRAY_CALLBACK)
void SynchronousResourceHandleCFURLConnectionDelegate::didReceiveDataArray(CFArrayRef dataArray)
{
if (!m_handle->client())
return;
LOG(Network, "CFNet - SynchronousResourceHandleCFURLConnectionDelegate::didReceiveDataArray(handle=%p, arrayLength=%ld) (%s)", m_handle, CFArrayGetCount(dataArray), m_handle->firstRequest().url().string().utf8().data());
#if USE(QUICK_LOOK)
if (m_handle->quickLookHandle() && m_handle->quickLookHandle()->didReceiveDataArray(dataArray))
return;
#endif
if (ResourceHandleClient* client = m_handle->client())
client->didReceiveBuffer(m_handle, SharedBuffer::wrapCFDataArray(dataArray), -1);
}
#endif // USE(NETWORK_CFDATA_ARRAY_CALLBACK)
void SynchronousResourceHandleCFURLConnectionDelegate::continueWillSendRequest(CFURLRequestRef)
{
ASSERT_NOT_REACHED();
}
void SynchronousResourceHandleCFURLConnectionDelegate::continueDidReceiveResponse()
{
ASSERT_NOT_REACHED();
}
void SynchronousResourceHandleCFURLConnectionDelegate::continueWillCacheResponse(CFCachedURLResponseRef)
{
ASSERT_NOT_REACHED();
}
#if USE(PROTECTION_SPACE_AUTH_CALLBACK)
void SynchronousResourceHandleCFURLConnectionDelegate::continueCanAuthenticateAgainstProtectionSpace(bool)
{
ASSERT_NOT_REACHED();
}
#endif // USE(PROTECTION_SPACE_AUTH_CALLBACK)
}
#endif