コード例 #1
0
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;
}
コード例 #2
0
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);
}
コード例 #3
0
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);
}
コード例 #4
0
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);
}
コード例 #5
0
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);
}
コード例 #6
0
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;
}
コード例 #7
0
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);
}
コード例 #8
0
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));
}
コード例 #9
0
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);
}
コード例 #10
0
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);
}
コード例 #11
0
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));
}
コード例 #12
0
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);
}
コード例 #13
0
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);
}
コード例 #14
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);
}
コード例 #15
0
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);
}
コード例 #16
0
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;
}
コード例 #17
0
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;
}
コード例 #18
0
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;
}
コード例 #19
0
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);
}
コード例 #20
0
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);
}
コード例 #21
0
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);
}
コード例 #22
0
// 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);
}
コード例 #23
0
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);
}
コード例 #24
0
// 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;
}