static CFCachedURLResponseRef willCacheResponse(CFURLConnectionRef, CFCachedURLResponseRef cachedResponse, const void* clientInfo) { ResourceHandle* handle = static_cast<ResourceHandle*>(const_cast<void*>(clientInfo)); #if PLATFORM(WIN) if (handle->client() && !handle->client()->shouldCacheResponse(handle, cachedResponse)) return 0; #else CFCachedURLResponseRef newResponse = handle->client()->willCacheResponse(handle, cachedResponse); if (newResponse != cachedResponse) return newResponse; #endif CacheStoragePolicy policy = static_cast<CacheStoragePolicy>(CFCachedURLResponseGetStoragePolicy(cachedResponse)); if (handle->client()) handle->client()->willCacheResponse(handle, policy); if (static_cast<CFURLCacheStoragePolicy>(policy) != CFCachedURLResponseGetStoragePolicy(cachedResponse)) { RetainPtr<CFArrayRef> receiverData(AdoptCF, CFCachedURLResponseCopyReceiverDataArray(cachedResponse)); cachedResponse = CFCachedURLResponseCreateWithDataArray(kCFAllocatorDefault, CFCachedURLResponseGetWrappedResponse(cachedResponse), receiverData.get(), CFCachedURLResponseGetUserInfo(cachedResponse), static_cast<CFURLCacheStoragePolicy>(policy)); } else CFRetain(cachedResponse); return cachedResponse; }
static void didSendBodyData(CFURLConnectionRef conn, CFIndex bytesWritten, CFIndex totalBytesWritten, CFIndex totalBytesExpectedToWrite, const void *clientInfo) { ResourceHandle* handle = (ResourceHandle*)clientInfo; if (!handle || !handle->client()) return; handle->client()->didSendData(handle, totalBytesWritten, totalBytesExpectedToWrite); }
static void didReceiveResponse(CFURLConnectionRef conn, CFURLResponseRef cfResponse, const void* clientInfo) { ResourceHandle* handle = static_cast<ResourceHandle*>(const_cast<void*>(clientInfo)); LOG(Network, "CFNet - didReceiveResponse(conn=%p, handle=%p) (%s)", conn, handle, handle->firstRequest().url().string().utf8().data()); if (!handle->client()) return; #if PLATFORM(MAC) // Avoid MIME type sniffing if the response comes back as 304 Not Modified. CFHTTPMessageRef msg = wkGetCFURLResponseHTTPResponse(cfResponse); int statusCode = msg ? CFHTTPMessageGetResponseStatusCode(msg) : 0; if (statusCode != 304) adjustMIMETypeIfNecessary(cfResponse); #else if (!CFURLResponseGetMIMEType(cfResponse)) { // We should never be applying the default MIMEType if we told the networking layer to do content sniffing for handle. ASSERT(!handle->shouldContentSniff()); setDefaultMIMEType(cfResponse); } #endif handle->setQuickLookHandle(QuickLookHandle::create(handle, conn, cfResponse)); if (handle->quickLookHandle()) cfResponse = handle->quickLookHandle()->cfResponse(); handle->client()->didReceiveResponse(handle, cfResponse); }
static void didReceiveResponse(CFURLConnectionRef conn, CFURLResponseRef cfResponse, const void* clientInfo) { #if LOG_DISABLED UNUSED_PARAM(conn); #endif ResourceHandle* handle = static_cast<ResourceHandle*>(const_cast<void*>(clientInfo)); LOG(Network, "CFNet - didReceiveResponse(conn=%p, handle=%p) (%s)", conn, handle, handle->firstRequest().url().string().utf8().data()); if (!handle->client()) return; #if PLATFORM(MAC) // Avoid MIME type sniffing if the response comes back as 304 Not Modified. CFHTTPMessageRef msg = wkGetCFURLResponseHTTPResponse(cfResponse); int statusCode = msg ? CFHTTPMessageGetResponseStatusCode(msg) : 0; if (statusCode != 304) adjustMIMETypeIfNecessary(cfResponse); if (_CFURLRequestCopyProtocolPropertyForKey(handle->firstRequest().cfURLRequest(), CFSTR("ForceHTMLMIMEType"))) wkSetCFURLResponseMIMEType(cfResponse, CFSTR("text/html")); #else if (!CFURLResponseGetMIMEType(cfResponse)) { // We should never be applying the default MIMEType if we told the networking layer to do content sniffing for handle. ASSERT(!handle->shouldContentSniff()); setDefaultMIMEType(cfResponse); } #endif handle->client()->didReceiveResponse(handle, cfResponse); }
static void didSendBodyData(CFURLConnectionRef, CFIndex, CFIndex totalBytesWritten, CFIndex totalBytesExpectedToWrite, const void *clientInfo) { ResourceHandle* handle = static_cast<ResourceHandle*>(const_cast<void*>(clientInfo)); if (!handle || !handle->client()) return; handle->client()->didSendData(handle, totalBytesWritten, totalBytesExpectedToWrite); }
static CFCachedURLResponseRef willCacheResponse(CFURLConnectionRef, CFCachedURLResponseRef cachedResponse, const void* clientInfo) { ResourceHandle* handle = static_cast<ResourceHandle*>(const_cast<void*>(clientInfo)); CFURLResponseRef wrappedResponse = CFCachedURLResponseGetWrappedResponse(cachedResponse); // Workaround for <rdar://problem/6300990> Caching does not respect Vary HTTP header. // FIXME: WebCore cache has issues with Vary, too (bug 58797, bug 71509). if (CFHTTPMessageRef httpResponse = CFURLResponseGetHTTPResponse(wrappedResponse)) { ASSERT(CFHTTPMessageIsHeaderComplete(httpResponse)); RetainPtr<CFStringRef> varyValue = adoptCF(CFHTTPMessageCopyHeaderFieldValue(httpResponse, CFSTR("Vary"))); if (varyValue) return 0; } #if PLATFORM(WIN) if (handle->client() && !handle->client()->shouldCacheResponse(handle, cachedResponse)) return 0; #else CFCachedURLResponseRef newResponse = handle->client()->willCacheResponse(handle, cachedResponse); if (newResponse != cachedResponse) return newResponse; #endif CFRetain(cachedResponse); return cachedResponse; }
void didReceiveResponse(CFURLConnectionRef conn, CFURLResponseRef cfResponse, const void* clientInfo) { ResourceHandle* handle = (ResourceHandle*)clientInfo; LOG(Network, "CFNet - didReceiveResponse(conn=%p, handle=%p) (%s)", conn, handle, handle->request().url().string().utf8().data()); if (handle->client()) handle->client()->didReceiveResponse(handle, cfResponse); }
void didFail(CFURLConnectionRef conn, CFErrorRef error, const void* clientInfo) { ResourceHandle* handle = (ResourceHandle*)clientInfo; LOG(Network, "CFNet - didFail(conn=%p, handle=%p, error = %p) (%s)", conn, handle, error, handle->request().url().string().utf8().data()); if (handle->client()) handle->client()->didFail(handle, ResourceError(error)); }
void didFinishLoading(CFURLConnectionRef conn, const void* clientInfo) { ResourceHandle* handle = (ResourceHandle*)clientInfo; LOG(Network, "CFNet - didFinishLoading(conn=%p, handle=%p) (%s)", conn, handle, handle->request().url().string().utf8().data()); if (handle->client()) handle->client()->didFinishLoading(handle); }
void didReceiveData(CFURLConnectionRef conn, CFDataRef data, CFIndex originalLength, const void* clientInfo) { ResourceHandle* handle = (ResourceHandle*)clientInfo; const UInt8* bytes = CFDataGetBytePtr(data); CFIndex length = CFDataGetLength(data); LOG(Network, "CFNet - didReceiveData(conn=%p, handle=%p, bytes=%d) (%s)", conn, handle, length, handle->request().url().string().utf8().data()); if (handle->client()) handle->client()->didReceiveData(handle, (const char*)bytes, length, originalLength); }
static void didFail(CFURLConnectionRef conn, CFErrorRef error, const void* clientInfo) { #if LOG_DISABLED UNUSED_PARAM(conn); #endif ResourceHandle* handle = static_cast<ResourceHandle*>(const_cast<void*>(clientInfo)); LOG(Network, "CFNet - didFail(conn=%p, handle=%p, error = %p) (%s)", conn, handle, error, handle->firstRequest().url().string().utf8().data()); if (handle->client()) handle->client()->didFail(handle, ResourceError(error)); }
static void didReceiveData(CFURLConnectionRef conn, CFDataRef data, CFIndex originalLength, const void* clientInfo) { #if LOG_DISABLED UNUSED_PARAM(conn); #endif ResourceHandle* handle = static_cast<ResourceHandle*>(const_cast<void*>(clientInfo)); const UInt8* bytes = CFDataGetBytePtr(data); CFIndex length = CFDataGetLength(data); LOG(Network, "CFNet - didReceiveData(conn=%p, handle=%p, bytes=%ld) (%s)", conn, handle, length, handle->firstRequest().url().string().utf8().data()); if (handle->client()) handle->client()->didReceiveData(handle, (const char*)bytes, length, originalLength); }
static void didFinishLoading(CFURLConnectionRef conn, const void* clientInfo) { #if LOG_DISABLED UNUSED_PARAM(conn); #endif ResourceHandle* handle = static_cast<ResourceHandle*>(const_cast<void*>(clientInfo)); LOG(Network, "CFNet - didFinishLoading(conn=%p, handle=%p) (%s)", conn, handle, handle->firstRequest().url().string().utf8().data()); if (handle->quickLookHandle() && handle->quickLookHandle()->didFinishLoading()) return; if (handle->client()) handle->client()->didFinishLoading(handle, 0); }
static void openCallback(GObject* source, GAsyncResult* res, gpointer data) { ResourceHandle* handle = static_cast<ResourceHandle*>(data); ResourceHandleInternal* d = handle->getInternal(); ResourceHandleClient* client = handle->client(); if (d->m_cancelled || !client) { cleanupGioOperation(handle); return; } GFileInputStream* in; GError *error = NULL; in = g_file_read_finish(G_FILE(source), res, &error); if (error) { cleanupGioOperation(handle); // FIXME: error client->didFinishLoading(handle); return; } d->m_input_stream = G_INPUT_STREAM(in); d->m_bufsize = 8192; d->m_buffer = static_cast<char*>(g_malloc(d->m_bufsize)); d->m_total = 0; g_input_stream_read_async(d->m_input_stream, d->m_buffer, d->m_bufsize, G_PRIORITY_DEFAULT, d->m_cancellable, readCallback, handle); }
static void readCallback(GObject* source, GAsyncResult* res, gpointer data) { ResourceHandle* handle = static_cast<ResourceHandle*>(data); ResourceHandleInternal* d = handle->getInternal(); ResourceHandleClient* client = handle->client(); if (d->m_cancelled || !client) { cleanupGioOperation(handle); return; } gssize nread; GError *error = 0; nread = g_input_stream_read_finish(d->m_input_stream, res, &error); if (error) { cleanupGioOperation(handle); // FIXME: error client->didFinishLoading(handle); return; } else if (!nread) { client->didFinishLoading(handle); g_input_stream_close_async(d->m_input_stream, G_PRIORITY_DEFAULT, NULL, closeCallback, handle); return; } d->m_total += nread; client->didReceiveData(handle, d->m_buffer, nread, d->m_total); g_input_stream_read_async(d->m_input_stream, d->m_buffer, d->m_bufsize, G_PRIORITY_DEFAULT, d->m_cancellable, readCallback, handle); }
CFCachedURLResponseRef willCacheResponse(CFURLConnectionRef conn, CFCachedURLResponseRef cachedResponse, const void* clientInfo) { ResourceHandle* handle = (ResourceHandle*)clientInfo; CacheStoragePolicy policy = static_cast<CacheStoragePolicy>(CFCachedURLResponseGetStoragePolicy(cachedResponse)); if (handle->client()) handle->client()->willCacheResponse(handle, policy); if (static_cast<CFURLCacheStoragePolicy>(policy) != CFCachedURLResponseGetStoragePolicy(cachedResponse)) cachedResponse = CFCachedURLResponseCreateWithUserInfo(kCFAllocatorDefault, CFCachedURLResponseGetWrappedResponse(cachedResponse), CFCachedURLResponseGetReceiverData(cachedResponse), CFCachedURLResponseGetUserInfo(cachedResponse), static_cast<CFURLCacheStoragePolicy>(policy)); CFRetain(cachedResponse); return cachedResponse; }
CFURLRequestRef willSendRequest(CFURLConnectionRef conn, CFURLRequestRef cfRequest, CFURLResponseRef cfRedirectResponse, const void* clientInfo) { ResourceHandle* handle = (ResourceHandle*)clientInfo; if (!cfRedirectResponse) { CFRetain(cfRequest); return cfRequest; } LOG(Network, "CFNet - willSendRequest(conn=%p, handle=%p) (%s)", conn, handle, handle->request().url().string().utf8().data()); ResourceRequest request(cfRequest); if (handle->client()) handle->client()->willSendRequest(handle, request, cfRedirectResponse); cfRequest = request.cfURLRequest(); CFRetain(cfRequest); return cfRequest; }
static CFCachedURLResponseRef willCacheResponse(CFURLConnectionRef, CFCachedURLResponseRef cachedResponse, const void* clientInfo) { ResourceHandle* handle = static_cast<ResourceHandle*>(const_cast<void*>(clientInfo)); CFURLResponseRef wrappedResponse = CFCachedURLResponseGetWrappedResponse(cachedResponse); // Workaround for <rdar://problem/6300990> Caching does not respect Vary HTTP header. // FIXME: WebCore cache has issues with Vary, too (bug 58797, bug 71509). if (CFHTTPMessageRef httpResponse = CFURLResponseGetHTTPResponse(wrappedResponse)) { ASSERT(CFHTTPMessageIsHeaderComplete(httpResponse)); RetainPtr<CFStringRef> varyValue = adoptCF(CFHTTPMessageCopyHeaderFieldValue(httpResponse, CFSTR("Vary"))); if (varyValue) return 0; } #if PLATFORM(WIN) if (handle->client() && !handle->client()->shouldCacheResponse(handle, cachedResponse)) return 0; #else CFCachedURLResponseRef newResponse = handle->client()->willCacheResponse(handle, cachedResponse); if (newResponse != cachedResponse) return newResponse; #endif CacheStoragePolicy policy = static_cast<CacheStoragePolicy>(CFCachedURLResponseGetStoragePolicy(cachedResponse)); if (handle->client()) handle->client()->willCacheResponse(handle, policy); if (static_cast<CFURLCacheStoragePolicy>(policy) != CFCachedURLResponseGetStoragePolicy(cachedResponse)) { RetainPtr<CFArrayRef> receiverData(AdoptCF, CFCachedURLResponseCopyReceiverDataArray(cachedResponse)); cachedResponse = CFCachedURLResponseCreateWithDataArray(kCFAllocatorDefault, wrappedResponse, receiverData.get(), CFCachedURLResponseGetUserInfo(cachedResponse), static_cast<CFURLCacheStoragePolicy>(policy)); } else CFRetain(cachedResponse); return cachedResponse; }
static void didReceiveDataArray(CFURLConnectionRef conn, CFArrayRef dataArray, const void* clientInfo) { #if LOG_DISABLED UNUSED_PARAM(conn); #endif ResourceHandle* handle = static_cast<ResourceHandle*>(const_cast<void*>(clientInfo)); if (!handle->client()) return; LOG(Network, "CFNet - didReceiveDataArray(conn=%p, handle=%p, arrayLength=%ld) (%s)", conn, handle, CFArrayGetCount(dataArray), handle->firstRequest().url().string().utf8().data()); handle->handleDataArray(dataArray); }
static void gotChunkCallback(SoupMessage* msg, SoupBuffer* chunk, gpointer data) { if (!SOUP_STATUS_IS_SUCCESSFUL(msg->status_code)) return; ResourceHandle* handle = static_cast<ResourceHandle*>(data); if (!handle) return; ResourceHandleInternal* d = handle->getInternal(); if (d->m_cancelled) return; ResourceHandleClient* client = handle->client(); if (!client) return; client->didReceiveData(handle, chunk->data, chunk->length, false); }
static void gotHeadersCallback(SoupMessage* msg, gpointer data) { if (!SOUP_STATUS_IS_SUCCESSFUL(msg->status_code)) return; ResourceHandle* handle = static_cast<ResourceHandle*>(data); if (!handle) return; ResourceHandleInternal* d = handle->getInternal(); if (d->m_cancelled) return; ResourceHandleClient* client = handle->client(); if (!client) return; fillResponseFromMessage(msg, &d->m_response); client->didReceiveResponse(handle, d->m_response); soup_message_set_flags(msg, SOUP_MESSAGE_OVERWRITE_CHUNKS); }
// Called at the end of the message, with all the necessary about the last informations. // Doesn't get called for redirects. static void finishedCallback(SoupSession *session, SoupMessage* msg, gpointer data) { ResourceHandle* handle = static_cast<ResourceHandle*>(data); // TODO: maybe we should run this code even if there's no client? if (!handle) return; ResourceHandleInternal* d = handle->getInternal(); // The message has been handled. d->m_msg = NULL; ResourceHandleClient* client = handle->client(); if (!client) return; if (d->m_cancelled) return; if (SOUP_STATUS_IS_TRANSPORT_ERROR(msg->status_code)) { char* uri = soup_uri_to_string(soup_message_get_uri(msg), FALSE); ResourceError error("webkit-network-error", ERROR_TRANSPORT, uri, String::fromUTF8(msg->reason_phrase)); g_free(uri); client->didFail(handle, error); return; } else if (!SOUP_STATUS_IS_SUCCESSFUL(msg->status_code)) { fillResponseFromMessage(msg, &d->m_response); client->didReceiveResponse(handle, d->m_response); // WebCore might have cancelled the job in the while if (d->m_cancelled) return; if (msg->response_body->data) client->didReceiveData(handle, msg->response_body->data, msg->response_body->length, true); } client->didFinishLoading(handle); }
static void queryInfoCallback(GObject* source, GAsyncResult* res, gpointer data) { ResourceHandle* handle = static_cast<ResourceHandle*>(data); ResourceHandleInternal* d = handle->getInternal(); ResourceHandleClient* client = handle->client(); if (d->m_cancelled) { cleanupGioOperation(handle); return; } ResourceResponse response; char* uri = g_file_get_uri(d->m_gfile); response.setUrl(KURL(uri)); g_free(uri); GError *error = NULL; GFileInfo* info = g_file_query_info_finish(d->m_gfile, res, &error); if (error) { // FIXME: to be able to handle ftp URIs properly, we must // check if the error is G_IO_ERROR_NOT_MOUNTED, and if so, // call g_file_mount_enclosing_volume() to mount the ftp // server (and then keep track of the fact that we mounted it, // and set a timeout to unmount it later after it's been idle // for a while). cleanupGioOperation(handle); if (error->domain == G_IO_ERROR && error->code == G_IO_ERROR_NOT_FOUND) response.setHTTPStatusCode(SOUP_STATUS_NOT_FOUND); else if (error->domain == G_IO_ERROR && error->code == G_IO_ERROR_PERMISSION_DENIED) response.setHTTPStatusCode(SOUP_STATUS_FORBIDDEN); else response.setHTTPStatusCode(SOUP_STATUS_BAD_REQUEST); // ? g_error_free(error); // FIXME: do we need to fake up a response body containing the // error message? client->didReceiveResponse(handle, response); client->didFinishLoading(handle); return; } if (g_file_info_get_file_type(info) != G_FILE_TYPE_REGULAR) { // FIXME: what if the URI points to a directory? Should we // generate a listing? How? What do other backends do here? cleanupGioOperation(handle); response.setHTTPStatusCode(SOUP_STATUS_FORBIDDEN); // ? client->didReceiveResponse(handle, response); client->didFinishLoading(handle); return; } response.setMimeType(g_file_info_get_content_type(info)); response.setExpectedContentLength(g_file_info_get_size(info)); response.setHTTPStatusCode(SOUP_STATUS_OK); GTimeVal tv; g_file_info_get_modification_time(info, &tv); response.setLastModifiedDate(tv.tv_sec); client->didReceiveResponse(handle, response); g_file_read_async(d->m_gfile, G_PRIORITY_DEFAULT, d->m_cancellable, openCallback, handle); }
// parseDataUrl() is taken from the CURL http backend. static gboolean parseDataUrl(gpointer callback_data) { ResourceHandle* handle = static_cast<ResourceHandle*>(callback_data); ResourceHandleClient* client = handle->client(); ResourceHandleInternal* d = handle->getInternal(); if (d->m_cancelled) return false; d->m_idleHandler = 0; ASSERT(client); if (!client) return false; String url = handle->request().url().string(); ASSERT(url.startsWith("data:", false)); int index = url.find(','); if (index == -1) { client->cannotShowURL(handle); return false; } String mediaType = url.substring(5, index - 5); String data = url.substring(index + 1); bool isBase64 = mediaType.endsWith(";base64", false); if (isBase64) mediaType = mediaType.left(mediaType.length() - 7); if (mediaType.isEmpty()) mediaType = "text/plain;charset=US-ASCII"; String mimeType = extractMIMETypeFromMediaType(mediaType); String charset = extractCharsetFromMediaType(mediaType); ResourceResponse response; response.setMimeType(mimeType); if (isBase64) { data = decodeURLEscapeSequences(data); response.setTextEncodingName(charset); client->didReceiveResponse(handle, response); if (d->m_cancelled) return false; // Use the GLib Base64, since WebCore's decoder isn't // general-purpose and fails on Acid3 test 97 (whitespace). size_t outLength = 0; char* outData = 0; outData = reinterpret_cast<char*>(g_base64_decode(data.utf8().data(), &outLength)); if (outData && outLength > 0) client->didReceiveData(handle, outData, outLength, 0); g_free(outData); } else { // We have to convert to UTF-16 early due to limitations in KURL data = decodeURLEscapeSequences(data, TextEncoding(charset)); response.setTextEncodingName("UTF-16"); client->didReceiveResponse(handle, response); if (d->m_cancelled) return false; if (data.length() > 0) client->didReceiveData(handle, reinterpret_cast<const char*>(data.characters()), data.length() * sizeof(UChar), 0); if (d->m_cancelled) return false; } client->didFinishLoading(handle); return false; }