/* Representation of a channel request as presented to plugins. This is * deliberately a "smaller" API than McdChannel or McdRequest. * * Copyright © 2009 Nokia Corporation. * Copyright © 2009-2010 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include "plugin-request.h" #include #include "mission-control-plugins/implementation.h" #include "mcd-channel-priv.h" #include "mcd-debug.h" enum { PROP_0, PROP_ACCOUNT, PROP_REAL_REQUEST }; struct _McdPluginRequest { GObject parent; McdAccount *account; McdRequest *real_request; }; struct _McdPluginRequestClass { GObjectClass parent; }; static void plugin_iface_init (McpRequestIface *iface, gpointer unused G_GNUC_UNUSED); G_DEFINE_TYPE_WITH_CODE (McdPluginRequest, _mcd_plugin_request, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (MCP_TYPE_REQUEST, plugin_iface_init)) static void _mcd_plugin_request_init (McdPluginRequest *self) { DEBUG ("%p", self); } static void plugin_req_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { McdPluginRequest *self = (McdPluginRequest *) object; switch (prop_id) { case PROP_REAL_REQUEST: g_assert (self->real_request == NULL); /* construct-only */ self->real_request = g_value_dup_object (value); break; case PROP_ACCOUNT: g_assert (self->account == NULL); /* construct-only */ self->account = g_value_dup_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void plugin_req_dispose (GObject *object) { McdPluginRequest *self = (McdPluginRequest *) object; GObjectFinalizeFunc dispose = G_OBJECT_CLASS (_mcd_plugin_request_parent_class)->dispose; DEBUG ("%p", object); tp_clear_object (&self->account); tp_clear_object (&self->real_request); if (dispose != NULL) dispose (object); } static void _mcd_plugin_request_class_init ( McdPluginRequestClass *cls) { GObjectClass *object_class = (GObjectClass *) cls; object_class->set_property = plugin_req_set_property; object_class->dispose = plugin_req_dispose; g_object_class_install_property (object_class, PROP_REAL_REQUEST, g_param_spec_object ("real-request", "Real channel request", "The underlying McdRequest", MCD_TYPE_REQUEST, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_ACCOUNT, g_param_spec_object ("account", "Account", "The underlying McdAccount", MCD_TYPE_ACCOUNT, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); } McdPluginRequest * _mcd_plugin_request_new (McdAccount *account, McdRequest *real_request) { McdPluginRequest *self; self = g_object_new (MCD_TYPE_PLUGIN_REQUEST, "account", account, "real-request", real_request, NULL); DEBUG ("%p (for %p, %p)", self, account, real_request); return self; } static const gchar * plugin_req_get_account_path (McpRequest *obj) { McdPluginRequest *self = MCD_PLUGIN_REQUEST (obj); g_return_val_if_fail (self != NULL, NULL); return mcd_account_get_object_path (self->account); } static const gchar * plugin_req_get_protocol (McpRequest *obj) { McdPluginRequest *self = MCD_PLUGIN_REQUEST (obj); g_return_val_if_fail (self != NULL, NULL); return mcd_account_get_protocol_name (self->account); } static const gchar * plugin_req_get_cm_name (McpRequest *obj) { McdPluginRequest *self = MCD_PLUGIN_REQUEST (obj); g_return_val_if_fail (self != NULL, NULL); return mcd_account_get_manager_name (self->account); } static gint64 plugin_req_get_user_action_time (McpRequest *obj) { McdPluginRequest *self = MCD_PLUGIN_REQUEST (obj); g_return_val_if_fail (self != NULL, 0); return _mcd_request_get_user_action_time (self->real_request); } static guint plugin_req_get_n_requests (McpRequest *obj) { McdPluginRequest *self = MCD_PLUGIN_REQUEST (obj); g_return_val_if_fail (self != NULL, 0); /* We only know how to request one channel at a time */ return 1; } static GHashTable * plugin_req_ref_nth_request (McpRequest *obj, guint n) { McdPluginRequest *self = MCD_PLUGIN_REQUEST (obj); GHashTable *requested_properties; g_return_val_if_fail (self != NULL, NULL); if (n > 0) { /* not an error, for easy iteration */ return NULL; } requested_properties = _mcd_request_get_properties ( self->real_request); g_return_val_if_fail (requested_properties != NULL, NULL); return g_hash_table_ref (requested_properties); } static void plugin_req_deny (McpRequest *obj, GQuark domain, gint code, const gchar *message) { McdPluginRequest *self = MCD_PLUGIN_REQUEST (obj); g_return_if_fail (self != NULL); _mcd_request_set_failure (self->real_request, domain, code, message); } /* an arbitrary constant, to detect use-after-free or wrong pointers */ #define DELAY_MAGIC 0xC953 typedef struct { gsize magic; McdPluginRequest *self; } RealDelay; static McpRequestDelay * plugin_req_start_delay (McpRequest *obj) { McdPluginRequest *self = MCD_PLUGIN_REQUEST (obj); RealDelay *delay; DEBUG ("%p", self); g_return_val_if_fail (self != NULL, NULL); delay = g_slice_new (RealDelay); delay->magic = DELAY_MAGIC; delay->self = g_object_ref (obj); _mcd_request_start_delay (self->real_request); return (McpRequestDelay *) delay; } static void plugin_req_end_delay (McpRequest *obj, McpRequestDelay *delay) { McdPluginRequest *self = MCD_PLUGIN_REQUEST (obj); RealDelay *real_delay = (RealDelay *) delay; DEBUG ("%p", self); g_return_if_fail (self != NULL); g_return_if_fail (real_delay->self == self); g_return_if_fail (real_delay->magic == DELAY_MAGIC); real_delay->magic = ~(DELAY_MAGIC); real_delay->self = NULL; _mcd_request_end_delay (self->real_request); g_object_unref (self); } static void plugin_iface_init (McpRequestIface *iface, gpointer unused G_GNUC_UNUSED) { DEBUG ("called"); iface->get_account_path = plugin_req_get_account_path; iface->get_protocol = plugin_req_get_protocol; iface->get_cm_name = plugin_req_get_cm_name; iface->get_user_action_time = plugin_req_get_user_action_time; iface->get_n_requests = plugin_req_get_n_requests; iface->ref_nth_request = plugin_req_ref_nth_request; iface->deny = plugin_req_deny; iface->start_delay = plugin_req_start_delay; iface->end_delay = plugin_req_end_delay; }