diff options
author | Dan Winship <danw@gnome.org> | 2010-06-07 16:45:22 -0400 |
---|---|---|
committer | Dan Winship <danw@gnome.org> | 2010-12-09 12:04:51 +0100 |
commit | 65d5f29c527ab6da5991696026d6bdbef903d169 (patch) | |
tree | 0d7eeb16b8f63688b757ecb2323d653e8a40c053 | |
parent | f5a0053364adfa24014f0c595c3a2890d10e437c (diff) | |
download | libsoup-65d5f29c527ab6da5991696026d6bdbef903d169.tar.gz |
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.
-rw-r--r-- | libsoup/soup-session-feature.c | 39 | ||||
-rw-r--r-- | libsoup/soup-session-feature.h | 54 | ||||
-rw-r--r-- | 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 f5d12393..1db9c204 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 1db776ce..aa64aa0f 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 1dbde5a8..ffefca8a 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)); } } |