[libsoup] Make SoupRequester a SoupSessionFeature and the request types sub-features



commit 54743d8b595f4aa17b0bccb0848c99b17d0488ed
Author: Dan Winship <danw gnome org>
Date:   Wed Dec 8 12:52:54 2010 +0100

    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.

 libsoup/soup-request-data.c |    4 +
 libsoup/soup-request-file.c |    4 +
 libsoup/soup-request-http.c |    4 +
 libsoup/soup-request.h      |    2 +
 libsoup/soup-requester.c    |  191 +++++++++++++++++++++++++++----------------
 libsoup/soup-requester.h    |    9 --
 6 files changed, 133 insertions(+), 81 deletions(-)
---
diff --git a/libsoup/soup-request-data.c b/libsoup/soup-request-data.c
index 8449813..188a0cb 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 7de3526..a57331e 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 3b195ab..81e59df 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 5b4fcd2..a48e917 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 072b8be..3375a7a 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 68b4cd7..a10f1e5 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 ()
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]