diff options
author | Ben Murdoch <benm@google.com> | 2010-10-22 13:02:20 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2010-10-26 15:21:41 +0100 |
commit | a94275402997c11dd2e778633dacf4b7e630a35d (patch) | |
tree | e66f56c67e3b01f22c9c23cd932271ee9ac558ed /WebCore/platform/network/soup/cache/soup-request-http.c | |
parent | 09e26c78506587b3f5d930d7bc72a23287ffbec0 (diff) | |
download | external_webkit-a94275402997c11dd2e778633dacf4b7e630a35d.zip external_webkit-a94275402997c11dd2e778633dacf4b7e630a35d.tar.gz external_webkit-a94275402997c11dd2e778633dacf4b7e630a35d.tar.bz2 |
Merge WebKit at r70209: Initial merge by Git
Change-Id: Id23a68efa36e9d1126bcce0b137872db00892c8e
Diffstat (limited to 'WebCore/platform/network/soup/cache/soup-request-http.c')
-rw-r--r-- | WebCore/platform/network/soup/cache/soup-request-http.c | 340 |
1 files changed, 340 insertions, 0 deletions
diff --git a/WebCore/platform/network/soup/cache/soup-request-http.c b/WebCore/platform/network/soup/cache/soup-request-http.c new file mode 100644 index 0000000..f157cfc --- /dev/null +++ b/WebCore/platform/network/soup/cache/soup-request-http.c @@ -0,0 +1,340 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-request-http.c: http: URI request object + * + * Copyright (C) 2009 Red Hat, Inc. + * Copyright (C) 2010 Igalia, S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <glib/gi18n.h> + +#include "soup-cache.h" +#include "soup-cache-private.h" +#include "soup-http-input-stream.h" +#include "soup-request-http.h" + +G_DEFINE_TYPE (WebKitSoupRequestHTTP, webkit_soup_request_http, WEBKIT_TYPE_SOUP_REQUEST) + +struct _WebKitSoupRequestHTTPPrivate { + SoupMessage *msg; +}; + +/** + * webkit_soup_request_http_get_message: + * @http: a #WebKitSoupRequestHTTP object + * + * Gets a new reference to the #SoupMessage associated to this SoupRequest + * + * Returns: a new reference to the #SoupMessage + **/ +SoupMessage * +webkit_soup_request_http_get_message (WebKitSoupRequestHTTP *http) +{ + g_return_val_if_fail (WEBKIT_IS_SOUP_REQUEST_HTTP (http), NULL); + + return g_object_ref (http->priv->msg); +} + +static void +webkit_soup_request_http_init (WebKitSoupRequestHTTP *http) +{ + http->priv = G_TYPE_INSTANCE_GET_PRIVATE (http, WEBKIT_TYPE_SOUP_REQUEST_HTTP, WebKitSoupRequestHTTPPrivate); +} + +static gboolean +webkit_soup_request_http_check_uri (WebKitSoupRequest *request, + SoupURI *uri, + GError **error) +{ + WebKitSoupRequestHTTP *http = WEBKIT_SOUP_REQUEST_HTTP (request); + + if (!SOUP_URI_VALID_FOR_HTTP (uri)) + return FALSE; + + http->priv->msg = soup_message_new_from_uri (SOUP_METHOD_GET, uri); + return TRUE; +} + +static void +webkit_soup_request_http_finalize (GObject *object) +{ + WebKitSoupRequestHTTP *http = WEBKIT_SOUP_REQUEST_HTTP (object); + + if (http->priv->msg) + g_object_unref (http->priv->msg); + + G_OBJECT_CLASS (webkit_soup_request_http_parent_class)->finalize (object); +} + +static GInputStream * +webkit_soup_request_http_send (WebKitSoupRequest *request, + GCancellable *cancellable, + GError **error) +{ + WebKitSoupHTTPInputStream *httpstream; + WebKitSoupRequestHTTP *http = WEBKIT_SOUP_REQUEST_HTTP (request); + + httpstream = webkit_soup_http_input_stream_new (webkit_soup_request_get_session (request), http->priv->msg); + if (!webkit_soup_http_input_stream_send (httpstream, cancellable, error)) { + g_object_unref (httpstream); + return NULL; + } + return (GInputStream *)httpstream; +} + + +static void +sent_async (GObject *source, GAsyncResult *result, gpointer user_data) +{ + WebKitSoupHTTPInputStream *httpstream = WEBKIT_SOUP_HTTP_INPUT_STREAM (source); + GSimpleAsyncResult *simple = user_data; + GError *error = NULL; + + if (webkit_soup_http_input_stream_send_finish (httpstream, result, &error)) { + g_simple_async_result_set_op_res_gpointer (simple, httpstream, g_object_unref); + } else { + g_simple_async_result_set_from_error (simple, error); + g_error_free (error); + g_object_unref (httpstream); + } + g_simple_async_result_complete (simple); + g_object_unref (simple); +} + + +typedef struct { + WebKitSoupRequestHTTP *req; + SoupMessage *original; + GCancellable *cancellable; + GAsyncReadyCallback callback; + gpointer user_data; +} ConditionalHelper; + + +static void +conditional_get_ready_cb (SoupSession *session, SoupMessage *msg, gpointer user_data) +{ + ConditionalHelper *helper = (ConditionalHelper *)user_data; + GSimpleAsyncResult *simple; + WebKitSoupHTTPInputStream *httpstream; + + simple = g_simple_async_result_new (G_OBJECT (helper->req), + helper->callback, helper->user_data, + conditional_get_ready_cb); + + if (msg->status_code == SOUP_STATUS_NOT_MODIFIED) { + WebKitSoupCache *cache = (WebKitSoupCache *)soup_session_get_feature (session, WEBKIT_TYPE_SOUP_CACHE); + + httpstream = (WebKitSoupHTTPInputStream *)webkit_soup_cache_send_response (cache, msg); + if (httpstream) { + const gchar *content_type; + + g_simple_async_result_set_op_res_gpointer (simple, httpstream, g_object_unref); + + soup_message_got_headers (helper->original); + content_type = soup_message_headers_get_content_type (msg->response_headers, NULL); + soup_message_content_sniffed (helper->original, content_type, NULL); + + g_simple_async_result_complete (simple); + + soup_message_finished (helper->original); + + g_object_unref (simple); + } else { + /* Ask again for the resource, somehow the cache cannot locate it */ + httpstream = webkit_soup_http_input_stream_new (session, helper->original); + webkit_soup_http_input_stream_send_async (httpstream, G_PRIORITY_DEFAULT, + helper->cancellable, sent_async, simple); + } + } else { + /* It is in the cache but it was modified remotely */ + httpstream = webkit_soup_http_input_stream_new (session, helper->original); + webkit_soup_http_input_stream_send_async (httpstream, G_PRIORITY_DEFAULT, + helper->cancellable, sent_async, simple); + } + + g_object_unref (helper->req); + g_object_unref (helper->original); + g_slice_free (ConditionalHelper, helper); +} + +typedef struct { + WebKitSoupRequestHTTP *http; + GAsyncReadyCallback callback; + gpointer user_data; +} SendAsyncHelper; + +static void webkit_soup_request_http_send_async (WebKitSoupRequest *request, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +static gboolean +send_async_cb (gpointer data) +{ + GSimpleAsyncResult *simple; + WebKitSoupHTTPInputStream *httpstream; + SoupSession *session; + WebKitSoupCache *cache; + SendAsyncHelper *helper = (SendAsyncHelper *)data; + + session = webkit_soup_request_get_session (WEBKIT_SOUP_REQUEST (helper->http)); + cache = (WebKitSoupCache *)soup_session_get_feature (session, WEBKIT_TYPE_SOUP_CACHE); + + httpstream = (WebKitSoupHTTPInputStream *)webkit_soup_cache_send_response (cache, SOUP_MESSAGE (helper->http->priv->msg)); + + if (httpstream) { + const gchar *content_type; + + simple = g_simple_async_result_new (G_OBJECT (helper->http), + helper->callback, helper->user_data, + webkit_soup_request_http_send_async); + g_simple_async_result_set_op_res_gpointer (simple, httpstream, g_object_unref); + + /* Update message status */ + soup_message_set_status (helper->http->priv->msg, SOUP_STATUS_OK); + + /* Issue signals */ + soup_message_got_headers (helper->http->priv->msg); + content_type = soup_message_headers_get_content_type (helper->http->priv->msg->response_headers, NULL); + soup_message_content_sniffed (helper->http->priv->msg, content_type, NULL); + + g_simple_async_result_complete (simple); + + soup_message_finished (helper->http->priv->msg); + + g_object_unref (simple); + } + + g_slice_free (SendAsyncHelper, helper); + + return FALSE; +} + +static void +webkit_soup_request_http_send_async (WebKitSoupRequest *request, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + WebKitSoupRequestHTTP *http = WEBKIT_SOUP_REQUEST_HTTP (request); + WebKitSoupHTTPInputStream *httpstream; + GSimpleAsyncResult *simple; + SoupSession *session; + WebKitSoupCache *cache; + + session = webkit_soup_request_get_session (request); + cache = (WebKitSoupCache *)soup_session_get_feature (session, WEBKIT_TYPE_SOUP_CACHE); + + if (cache) { + WebKitSoupCacheResponse response; + + response = webkit_soup_cache_has_response (cache, http->priv->msg); + if (response == WEBKIT_SOUP_CACHE_RESPONSE_FRESH) { + /* Do return the stream asynchronously as in + the other cases. It's not enough to use + g_simple_async_result_complete_in_idle as + the signals must be also emitted + asynchronously */ + SendAsyncHelper *helper = g_slice_new (SendAsyncHelper); + helper->http = http; + helper->callback = callback; + helper->user_data = user_data; + g_timeout_add (0, send_async_cb, helper); + return; + } else if (response == WEBKIT_SOUP_CACHE_RESPONSE_NEEDS_VALIDATION) { + SoupMessage *conditional_msg; + ConditionalHelper *helper; + + conditional_msg = webkit_soup_cache_generate_conditional_request (cache, http->priv->msg); + + helper = g_slice_new0 (ConditionalHelper); + helper->req = g_object_ref (http); + helper->original = g_object_ref (http->priv->msg); + helper->cancellable = cancellable; + helper->callback = callback; + helper->user_data = user_data; + soup_session_queue_message (session, conditional_msg, + conditional_get_ready_cb, + helper); + return; + } + } + + simple = g_simple_async_result_new (G_OBJECT (http), + callback, user_data, + webkit_soup_request_http_send_async); + httpstream = webkit_soup_http_input_stream_new (webkit_soup_request_get_session (request), + http->priv->msg); + webkit_soup_http_input_stream_send_async (httpstream, G_PRIORITY_DEFAULT, + cancellable, sent_async, simple); +} + +static GInputStream * +webkit_soup_request_http_send_finish (WebKitSoupRequest *request, + GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple; + + g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (request), webkit_soup_request_http_send_async) || g_simple_async_result_is_valid (result, G_OBJECT (request), conditional_get_ready_cb), NULL); + + simple = G_SIMPLE_ASYNC_RESULT (result); + if (g_simple_async_result_propagate_error (simple, error)) + return NULL; + return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple)); +} + +static goffset +webkit_soup_request_http_get_content_length (WebKitSoupRequest *request) +{ + WebKitSoupRequestHTTP *http = WEBKIT_SOUP_REQUEST_HTTP (request); + + return soup_message_headers_get_content_length (http->priv->msg->response_headers); +} + +static const char * +webkit_soup_request_http_get_content_type (WebKitSoupRequest *request) +{ + WebKitSoupRequestHTTP *http = WEBKIT_SOUP_REQUEST_HTTP (request); + + return soup_message_headers_get_content_type (http->priv->msg->response_headers, NULL); +} + +static void +webkit_soup_request_http_class_init (WebKitSoupRequestHTTPClass *request_http_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (request_http_class); + WebKitSoupRequestClass *request_class = + WEBKIT_SOUP_REQUEST_CLASS (request_http_class); + + g_type_class_add_private (request_http_class, sizeof (WebKitSoupRequestHTTPPrivate)); + + object_class->finalize = webkit_soup_request_http_finalize; + + request_class->check_uri = webkit_soup_request_http_check_uri; + request_class->send = webkit_soup_request_http_send; + request_class->send_async = webkit_soup_request_http_send_async; + request_class->send_finish = webkit_soup_request_http_send_finish; + request_class->get_content_length = webkit_soup_request_http_get_content_length; + request_class->get_content_type = webkit_soup_request_http_get_content_type; +} |