summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Winship <danw@gnome.org>2010-12-08 12:52:54 +0100
committerDan Winship <danw@gnome.org>2010-12-09 12:09:40 +0100
commit54743d8b595f4aa17b0bccb0848c99b17d0488ed (patch)
treed591b3828b9a0d8e1c0308e6d99ad4e94a0ac010
parentf8494ad794438280c8772e29d1dd178af7ccd257 (diff)
downloadlibsoup-54743d8b595f4aa17b0bccb0848c99b17d0488ed.tar.gz
Make SoupRequester a SoupSessionFeature and the request types sub-features
WebKit already exposes the SoupSession to its users, so this change will automatically give them access to the SoupRequest infrastructure as well.
-rw-r--r--libsoup/soup-request-data.c4
-rw-r--r--libsoup/soup-request-file.c4
-rw-r--r--libsoup/soup-request-http.c4
-rw-r--r--libsoup/soup-request.h2
-rw-r--r--libsoup/soup-requester.c191
-rw-r--r--libsoup/soup-requester.h9
6 files changed, 133 insertions, 81 deletions
diff --git a/libsoup/soup-request-data.c b/libsoup/soup-request-data.c
index 8449813a..188a0cb3 100644
--- a/libsoup/soup-request-data.c
+++ b/libsoup/soup-request-data.c
@@ -151,6 +151,8 @@ soup_request_data_get_content_type (SoupRequest *request)
return data->priv->content_type;
}
+static const char *data_schemes[] = { "data", NULL };
+
static void
soup_request_data_class_init (SoupRequestDataClass *request_data_class)
{
@@ -160,6 +162,8 @@ soup_request_data_class_init (SoupRequestDataClass *request_data_class)
g_type_class_add_private (request_data_class, sizeof (SoupRequestDataPrivate));
+ request_class->schemes = data_schemes;
+
object_class->finalize = soup_request_data_finalize;
request_class->check_uri = soup_request_data_check_uri;
diff --git a/libsoup/soup-request-file.c b/libsoup/soup-request-file.c
index 7de35261..a57331ef 100644
--- a/libsoup/soup-request-file.c
+++ b/libsoup/soup-request-file.c
@@ -227,6 +227,8 @@ soup_request_file_get_content_type (SoupRequest *request)
return file->priv->mime_type;
}
+static const char *file_schemes[] = { "file", NULL };
+
static void
soup_request_file_class_init (SoupRequestFileClass *request_file_class)
{
@@ -236,6 +238,8 @@ soup_request_file_class_init (SoupRequestFileClass *request_file_class)
g_type_class_add_private (request_file_class, sizeof (SoupRequestFilePrivate));
+ request_class->schemes = file_schemes;
+
object_class->finalize = soup_request_file_finalize;
request_class->check_uri = soup_request_file_check_uri;
diff --git a/libsoup/soup-request-http.c b/libsoup/soup-request-http.c
index 3b195ab9..81e59df1 100644
--- a/libsoup/soup-request-http.c
+++ b/libsoup/soup-request-http.c
@@ -312,6 +312,8 @@ soup_request_http_get_content_type (SoupRequest *request)
return soup_message_headers_get_content_type (http->priv->msg->response_headers, NULL);
}
+static const char *http_schemes[] = { "http", "https", NULL };
+
static void
soup_request_http_class_init (SoupRequestHTTPClass *request_http_class)
{
@@ -321,6 +323,8 @@ soup_request_http_class_init (SoupRequestHTTPClass *request_http_class)
g_type_class_add_private (request_http_class, sizeof (SoupRequestHTTPPrivate));
+ request_class->schemes = http_schemes;
+
object_class->finalize = soup_request_http_finalize;
request_class->check_uri = soup_request_http_check_uri;
diff --git a/libsoup/soup-request.h b/libsoup/soup-request.h
index 5b4fcd29..a48e9174 100644
--- a/libsoup/soup-request.h
+++ b/libsoup/soup-request.h
@@ -50,6 +50,8 @@ struct _SoupRequest {
struct _SoupRequestClass {
GObjectClass parent;
+ const char **schemes;
+
gboolean (*check_uri) (SoupRequest *req_base,
SoupURI *uri,
GError **error);
diff --git a/libsoup/soup-requester.c b/libsoup/soup-requester.c
index 072b8be9..3375a7a2 100644
--- a/libsoup/soup-requester.c
+++ b/libsoup/soup-requester.c
@@ -30,33 +30,37 @@
#include "soup-request-data.h"
#include "soup-request-file.h"
#include "soup-request-http.h"
+#include "soup-session-feature.h"
#include "soup-uri.h"
+static SoupSessionFeatureInterface *soup_requester_default_feature_interface;
+static void soup_requester_session_feature_init (SoupSessionFeatureInterface *feature_interface, gpointer interface_data);
+
struct _SoupRequesterPrivate {
+ SoupSession *session;
GHashTable *request_types;
};
-G_DEFINE_TYPE (SoupRequester, soup_requester, G_TYPE_OBJECT)
+G_DEFINE_TYPE_WITH_CODE (SoupRequester, soup_requester, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (SOUP_TYPE_SESSION_FEATURE,
+ soup_requester_session_feature_init))
static void
soup_requester_init (SoupRequester *requester)
{
+ SoupSessionFeature *feature;
+
requester->priv = G_TYPE_INSTANCE_GET_PRIVATE (requester,
SOUP_TYPE_REQUESTER,
SoupRequesterPrivate);
- requester->priv->request_types =
- g_hash_table_new_full (soup_str_case_hash,
- soup_str_case_equal,
- g_free, NULL);
- g_hash_table_insert (requester->priv->request_types, g_strdup ("file"),
- GSIZE_TO_POINTER (SOUP_TYPE_REQUEST_FILE));
- g_hash_table_insert (requester->priv->request_types, g_strdup ("data"),
- GSIZE_TO_POINTER (SOUP_TYPE_REQUEST_DATA));
- g_hash_table_insert (requester->priv->request_types, g_strdup ("http"),
- GSIZE_TO_POINTER (SOUP_TYPE_REQUEST_HTTP));
- g_hash_table_insert (requester->priv->request_types, g_strdup ("https"),
- GSIZE_TO_POINTER (SOUP_TYPE_REQUEST_HTTP));
+ requester->priv->request_types = g_hash_table_new (soup_str_case_hash,
+ soup_str_case_equal);
+
+ feature = SOUP_SESSION_FEATURE (requester);
+ soup_session_feature_add_feature (feature, SOUP_TYPE_REQUEST_HTTP);
+ soup_session_feature_add_feature (feature, SOUP_TYPE_REQUEST_FILE);
+ soup_session_feature_add_feature (feature, SOUP_TYPE_REQUEST_DATA);
}
static void
@@ -64,8 +68,7 @@ finalize (GObject *object)
{
SoupRequester *requester = SOUP_REQUESTER (object);
- if (requester->priv->request_types)
- g_hash_table_destroy (requester->priv->request_types);
+ g_hash_table_destroy (requester->priv->request_types);
G_OBJECT_CLASS (soup_requester_parent_class)->finalize (object);
}
@@ -81,6 +84,100 @@ soup_requester_class_init (SoupRequesterClass *requester_class)
object_class->finalize = finalize;
}
+static void
+attach (SoupSessionFeature *feature, SoupSession *session)
+{
+ SoupRequester *requester = SOUP_REQUESTER (feature);
+
+ requester->priv->session = session;
+
+ soup_requester_default_feature_interface->attach (feature, session);
+}
+
+static void
+detach (SoupSessionFeature *feature, SoupSession *session)
+{
+ SoupRequester *requester = SOUP_REQUESTER (feature);
+
+ requester->priv->session = NULL;
+
+ soup_requester_default_feature_interface->detach (feature, session);
+}
+
+static gboolean
+add_feature (SoupSessionFeature *feature, GType type)
+{
+ SoupRequester *requester = SOUP_REQUESTER (feature);
+ SoupRequestClass *request_class;
+ int i;
+
+ if (!g_type_is_a (type, SOUP_TYPE_REQUEST))
+ return FALSE;
+
+ request_class = g_type_class_ref (type);
+ for (i = 0; request_class->schemes[i]; i++) {
+ g_hash_table_insert (requester->priv->request_types,
+ (char *)request_class->schemes[i],
+ GSIZE_TO_POINTER (type));
+ }
+ return TRUE;
+}
+
+static gboolean
+remove_feature (SoupSessionFeature *feature, GType type)
+{
+ SoupRequester *requester = SOUP_REQUESTER (feature);
+ SoupRequestClass *request_class;
+ int i, orig_size;
+
+ if (!g_type_is_a (type, SOUP_TYPE_REQUEST))
+ return FALSE;
+
+ request_class = g_type_class_peek (type);
+ if (!request_class)
+ return FALSE;
+
+ orig_size = g_hash_table_size (requester->priv->request_types);
+ for (i = 0; request_class->schemes[i]; i++) {
+ g_hash_table_remove (requester->priv->request_types,
+ request_class->schemes[i]);
+ }
+
+ return g_hash_table_size (requester->priv->request_types) != orig_size;
+}
+
+static gboolean
+has_feature (SoupSessionFeature *feature, GType type)
+{
+ SoupRequester *requester = SOUP_REQUESTER (feature);
+ GHashTableIter iter;
+ gpointer key, value;
+
+ if (!g_type_is_a (type, SOUP_TYPE_REQUEST))
+ return FALSE;
+
+ g_hash_table_iter_init (&iter, requester->priv->request_types);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ if (value == GSIZE_TO_POINTER (type))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void
+soup_requester_session_feature_init (SoupSessionFeatureInterface *feature_interface,
+ gpointer interface_data)
+{
+ soup_requester_default_feature_interface =
+ g_type_default_interface_peek (SOUP_TYPE_SESSION_FEATURE);
+
+ feature_interface->attach = attach;
+ feature_interface->detach = detach;
+ feature_interface->add_feature = add_feature;
+ feature_interface->remove_feature = remove_feature;
+ feature_interface->has_feature = has_feature;
+}
+
SoupRequester *
soup_requester_new (void)
{
@@ -89,7 +186,7 @@ soup_requester_new (void)
SoupRequest *
soup_requester_request (SoupRequester *requester, const char *uri_string,
- SoupSession *session, GError **error)
+ GError **error)
{
SoupURI *uri;
SoupRequest *req;
@@ -101,14 +198,14 @@ soup_requester_request (SoupRequester *requester, const char *uri_string,
return NULL;
}
- req = soup_requester_request_uri (requester, uri, session, error);
+ req = soup_requester_request_uri (requester, uri, error);
soup_uri_free (uri);
return req;
}
SoupRequest *
soup_requester_request_uri (SoupRequester *requester, SoupURI *uri,
- SoupSession *session, GError **error)
+ GError **error)
{
GType request_type;
@@ -122,60 +219,10 @@ soup_requester_request_uri (SoupRequester *requester, SoupURI *uri,
return NULL;
}
- if (g_type_is_a (request_type, G_TYPE_INITABLE)) {
- return g_initable_new (request_type, NULL, error,
- "uri", uri,
- "session", session,
- NULL);
- } else {
- return g_object_new (request_type,
- "uri", uri,
- "session", session,
- NULL);
- }
-}
-
-/* RFC 2396, 3.1 */
-static gboolean
-soup_scheme_is_valid (const char *scheme)
-{
- if (scheme == NULL ||
- !g_ascii_isalpha (*scheme))
- return FALSE;
-
- scheme++;
- while (*scheme) {
- if (!g_ascii_isalpha (*scheme) &&
- !g_ascii_isdigit (*scheme) &&
- *scheme != '+' &&
- *scheme != '-' &&
- *scheme != '.')
- return FALSE;
- scheme++;
- }
- return TRUE;
-}
-
-void
-soup_requester_add_protocol (SoupRequester *requester,
- const char *scheme,
- GType request_type)
-{
- g_return_if_fail (SOUP_IS_REQUESTER (requester));
- g_return_if_fail (soup_scheme_is_valid (scheme));
-
- g_hash_table_insert (requester->priv->request_types, g_strdup (scheme),
- GSIZE_TO_POINTER (request_type));
-}
-
-void
-soup_requester_remove_protocol (SoupRequester *requester,
- const char *scheme)
-{
- g_return_if_fail (SOUP_IS_REQUESTER (requester));
- g_return_if_fail (soup_scheme_is_valid (scheme));
-
- g_hash_table_remove (requester->priv->request_types, scheme);
+ return g_initable_new (request_type, NULL, error,
+ "uri", uri,
+ "session", requester->priv->session,
+ NULL);
}
GQuark
diff --git a/libsoup/soup-requester.h b/libsoup/soup-requester.h
index 68b4cd7b..a10f1e55 100644
--- a/libsoup/soup-requester.h
+++ b/libsoup/soup-requester.h
@@ -54,21 +54,12 @@ SoupRequester *soup_requester_new (void);
SoupRequest *soup_requester_request (SoupRequester *requester,
const char *uri_string,
- SoupSession *session,
GError **error);
SoupRequest *soup_requester_request_uri (SoupRequester *requester,
SoupURI *uri,
- SoupSession *session,
GError **error);
-void soup_requester_add_protocol (SoupRequester *requester,
- const char *scheme,
- GType request_type);
-
-void soup_requester_remove_protocol (SoupRequester *requester,
- const char *scheme);
-
GQuark soup_requester_error_quark (void);
#define SOUP_REQUESTER_ERROR soup_requester_error_quark ()