[libsoup] SoupSession: allow features to implement "subfeatures"



commit 65d5f29c527ab6da5991696026d6bdbef903d169
Author: Dan Winship <danw gnome org>
Date:   Mon Jun 7 16:45:22 2010 -0400

    SoupSession: allow features to implement "subfeatures"
    
    Let soup_session_add_feature_by_type() (and remove()) add and remove
    "features" from existing features. Eg, to add/remove auth types or
    Content-Encodings.

 libsoup/soup-session-feature.c |   39 +++++++++++++++++++++++
 libsoup/soup-session-feature.h |   54 ++++++++++++++++++++------------
 libsoup/soup-session.c         |   66 ++++++++++++++++++++++++++++-----------
 3 files changed, 120 insertions(+), 39 deletions(-)
---
diff --git a/libsoup/soup-session-feature.c b/libsoup/soup-session-feature.c
index f5d1239..1db9c20 100644
--- a/libsoup/soup-session-feature.c
+++ b/libsoup/soup-session-feature.c
@@ -164,3 +164,42 @@ soup_session_feature_detach (SoupSessionFeature *feature,
 {
 	SOUP_SESSION_FEATURE_GET_CLASS (feature)->detach (feature, session);
 }
+
+gboolean
+soup_session_feature_add_feature (SoupSessionFeature *feature,
+				  GType               type)
+{
+	SoupSessionFeatureInterface *feature_iface =
+              SOUP_SESSION_FEATURE_GET_CLASS (feature);
+
+	if (feature_iface->add_feature)
+		return feature_iface->add_feature (feature, type);
+	else
+		return FALSE;
+}
+
+gboolean
+soup_session_feature_remove_feature (SoupSessionFeature *feature,
+				     GType               type)
+{
+	SoupSessionFeatureInterface *feature_iface =
+              SOUP_SESSION_FEATURE_GET_CLASS (feature);
+
+	if (feature_iface->remove_feature)
+		return feature_iface->remove_feature (feature, type);
+	else
+		return FALSE;
+}
+
+gboolean
+soup_session_feature_has_feature (SoupSessionFeature *feature,
+				  GType               type)
+{
+	SoupSessionFeatureInterface *feature_iface =
+              SOUP_SESSION_FEATURE_GET_CLASS (feature);
+
+	if (feature_iface->has_feature)
+		return feature_iface->has_feature (feature, type);
+	else
+		return FALSE;
+}
diff --git a/libsoup/soup-session-feature.h b/libsoup/soup-session-feature.h
index 1db776c..aa64aa0 100644
--- a/libsoup/soup-session-feature.h
+++ b/libsoup/soup-session-feature.h
@@ -21,30 +21,44 @@ typedef struct {
 	GTypeInterface parent;
 
 	/* methods */
-	void (*attach)           (SoupSessionFeature *feature,
-				  SoupSession        *session);
-	void (*detach)           (SoupSessionFeature *feature,
-				  SoupSession        *session);
-
-	void (*request_queued)   (SoupSessionFeature *feature,
-				  SoupSession        *session,
-				  SoupMessage        *msg);
-	void (*request_started)  (SoupSessionFeature *feature,
-				  SoupSession        *session,
-				  SoupMessage        *msg,
-				  SoupSocket         *socket);
-	void (*request_unqueued) (SoupSessionFeature *feature,
-				  SoupSession        *session,
-				  SoupMessage        *msg);
+	void     (*attach)           (SoupSessionFeature *feature,
+				      SoupSession        *session);
+	void     (*detach)           (SoupSessionFeature *feature,
+				      SoupSession        *session);
+
+	void     (*request_queued)   (SoupSessionFeature *feature,
+				      SoupSession        *session,
+				      SoupMessage        *msg);
+	void     (*request_started)  (SoupSessionFeature *feature,
+				      SoupSession        *session,
+				      SoupMessage        *msg,
+				      SoupSocket         *socket);
+	void     (*request_unqueued) (SoupSessionFeature *feature,
+				      SoupSession        *session,
+				      SoupMessage        *msg);
+
+	gboolean (*add_feature)      (SoupSessionFeature *feature,
+				      GType               type);
+	gboolean (*remove_feature)   (SoupSessionFeature *feature,
+				      GType               type);
+	gboolean (*has_feature)      (SoupSessionFeature *feature,
+				      GType               type);
 
 } SoupSessionFeatureInterface;
 
-GType soup_session_feature_get_type (void);
+GType    soup_session_feature_get_type       (void);
+
+void     soup_session_feature_attach         (SoupSessionFeature *feature,
+					      SoupSession        *session);
+void     soup_session_feature_detach         (SoupSessionFeature *feature,
+					      SoupSession        *session);
 
-void soup_session_feature_attach (SoupSessionFeature *feature,
-				  SoupSession        *session);
-void soup_session_feature_detach (SoupSessionFeature *feature,
-				  SoupSession        *session);
+gboolean soup_session_feature_add_feature    (SoupSessionFeature *feature,
+					      GType               type);
+gboolean soup_session_feature_remove_feature (SoupSessionFeature *feature,
+					      GType               type);
+gboolean soup_session_feature_has_feature    (SoupSessionFeature *feature,
+					      GType               type);
 
 G_END_DECLS
 
diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c
index 1dbde5a..ffefca8 100644
--- a/libsoup/soup-session.c
+++ b/libsoup/soup-session.c
@@ -186,8 +186,10 @@ soup_session_init (SoupSession *session)
 				     NULL);
 	g_signal_connect (auth_manager, "authenticate",
 			  G_CALLBACK (auth_manager_authenticate), session);
-	soup_auth_manager_add_type (auth_manager, SOUP_TYPE_AUTH_BASIC);
-	soup_auth_manager_add_type (auth_manager, SOUP_TYPE_AUTH_DIGEST);
+	soup_session_feature_add_feature (SOUP_SESSION_FEATURE (auth_manager),
+					  SOUP_TYPE_AUTH_BASIC);
+	soup_session_feature_add_feature (SOUP_SESSION_FEATURE (auth_manager),
+					  SOUP_TYPE_AUTH_DIGEST);
 	soup_session_add_feature (session, SOUP_SESSION_FEATURE (auth_manager));
 	g_object_unref (auth_manager);
 
@@ -1802,12 +1804,19 @@ soup_session_add_feature (SoupSession *session, SoupSessionFeature *feature)
 /**
  * soup_session_add_feature_by_type:
  * @session: a #SoupSession
- * @feature_type: the #GType of a class that implements #SoupSessionFeature
+ * @feature_type: a #GType
  *
- * Creates a new feature of type @feature_type and adds it to
- * @session. You can use this instead of soup_session_add_feature() in
- * the case wher you don't need to customize the new feature in any
- * way. You can also add a feature to the session at construct time by
+ * If @feature_type is the type of a class that implements
+ * #SoupSessionFeature, this creates a new feature of that type and
+ * adds it to @session as with soup_session_add_feature(). You can use
+ * this when you don't need to customize the new feature in any way.
+ *
+ * If @feature_type is not a #SoupSessionFeature type, this gives
+ * each existing feature on @session the chance to accept @feature_type
+ * as a "subfeature". This can be used to add new #SoupAuth types,
+ * for instance.
+ *
+ * You can also add a feature to the session at construct time by
  * using the %SOUP_SESSION_ADD_FEATURE_BY_TYPE property.
  *
  * Since: 2.24
@@ -1815,14 +1824,24 @@ soup_session_add_feature (SoupSession *session, SoupSessionFeature *feature)
 void
 soup_session_add_feature_by_type (SoupSession *session, GType feature_type)
 {
-	SoupSessionFeature *feature;
-
 	g_return_if_fail (SOUP_IS_SESSION (session));
-	g_return_if_fail (g_type_is_a (feature_type, SOUP_TYPE_SESSION_FEATURE));
 
-	feature = g_object_new (feature_type, NULL);
-	soup_session_add_feature (session, feature);
-	g_object_unref (feature);
+	if (g_type_is_a (feature_type, SOUP_TYPE_SESSION_FEATURE)) {
+		SoupSessionFeature *feature;
+
+		feature = g_object_new (feature_type, NULL);
+		soup_session_add_feature (session, feature);
+		g_object_unref (feature);
+	} else {
+		SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session);
+		GSList *f;
+
+		for (f = priv->features; f; f = f->next) {
+			if (soup_session_feature_add_feature (f->data, feature_type))
+				return;
+		}
+		g_warning ("No feature manager for feature of type '%s'", g_type_name (feature_type));
+	}
 }
 
 /**
@@ -1853,7 +1872,7 @@ soup_session_remove_feature (SoupSession *session, SoupSessionFeature *feature)
 /**
  * soup_session_remove_feature_by_type:
  * @session: a #SoupSession
- * @feature_type: the #GType of a class that implements #SoupSessionFeature
+ * @feature_type: a #GType
  *
  * Removes all features of type @feature_type (or any subclass of
  * @feature_type) from @session. You can also remove standard features
@@ -1871,12 +1890,21 @@ soup_session_remove_feature_by_type (SoupSession *session, GType feature_type)
 	g_return_if_fail (SOUP_IS_SESSION (session));
 
 	priv = SOUP_SESSION_GET_PRIVATE (session);
-restart:
-	for (f = priv->features; f; f = f->next) {
-		if (G_TYPE_CHECK_INSTANCE_TYPE (f->data, feature_type)) {
-			soup_session_remove_feature (session, f->data);
-			goto restart;
+
+	if (g_type_is_a (feature_type, SOUP_TYPE_SESSION_FEATURE)) {
+	restart:
+		for (f = priv->features; f; f = f->next) {
+			if (G_TYPE_CHECK_INSTANCE_TYPE (f->data, feature_type)) {
+				soup_session_remove_feature (session, f->data);
+				goto restart;
+			}
+		}
+	} else {
+		for (f = priv->features; f; f = f->next) {
+			if (soup_session_feature_remove_feature (f->data, feature_type))
+				return;
 		}
+		g_warning ("No feature manager for feature of type '%s'", g_type_name (feature_type));
 	}
 }
 



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