diff options
Diffstat (limited to 'libnm-glib/nm-client.c')
| -rw-r--r-- | libnm-glib/nm-client.c | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/libnm-glib/nm-client.c b/libnm-glib/nm-client.c index 00d729a2..88fe15b5 100644 --- a/libnm-glib/nm-client.c +++ b/libnm-glib/nm-client.c @@ -58,6 +58,9 @@ typedef struct { GPtrArray *devices; GPtrArray *active_connections; + DBusGProxyCall *perm_call; + GHashTable *permissions; + gboolean have_networking_enabled; gboolean networking_enabled; gboolean wireless_enabled; @@ -84,6 +87,7 @@ enum { enum { DEVICE_ADDED, DEVICE_REMOVED, + PERMISSION_CHANGED, LAST_SIGNAL }; @@ -118,6 +122,8 @@ nm_client_init (NMClient *client) priv->state = NM_STATE_UNKNOWN; + priv->permissions = g_hash_table_new (g_direct_hash, g_direct_equal); + g_signal_connect (client, "notify::" NM_CLIENT_NETWORKING_ENABLED, G_CALLBACK (handle_net_enabled_changed), @@ -284,6 +290,130 @@ register_for_property_changed (NMClient *client) property_changed_info); } +#define NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK "org.freedesktop.NetworkManager.enable-disable-network" +#define NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI "org.freedesktop.NetworkManager.enable-disable-wifi" +#define NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN "org.freedesktop.NetworkManager.enable-disable-wwan" +#define NM_AUTH_PERMISSION_USE_USER_CONNECTIONS "org.freedesktop.NetworkManager.use-user-connections" + +static NMClientPermission +nm_permission_to_client (const char *nm) +{ + if (!strcmp (nm, NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK)) + return NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK; + else if (!strcmp (nm, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI)) + return NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI; + else if (!strcmp (nm, NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN)) + return NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN; + else if (!strcmp (nm, NM_AUTH_PERMISSION_USE_USER_CONNECTIONS)) + return NM_CLIENT_PERMISSION_USE_USER_CONNECTIONS; + return NM_CLIENT_PERMISSION_NONE; +} + +static NMClientPermissionResult +nm_permission_result_to_client (const char *nm) +{ + if (!strcmp (nm, "yes")) + return NM_CLIENT_PERMISSION_RESULT_YES; + else if (!strcmp (nm, "no")) + return NM_CLIENT_PERMISSION_RESULT_NO; + else if (!strcmp (nm, "auth")) + return NM_CLIENT_PERMISSION_RESULT_AUTH; + return NM_CLIENT_PERMISSION_RESULT_UNKNOWN; +} + +static void +update_permissions (NMClient *self, GHashTable *permissions) +{ + NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self); + GHashTableIter iter; + gpointer key, value; + NMClientPermission perm; + NMClientPermissionResult perm_result; + GList *keys, *keys_iter; + + /* get list of old permissions for change notification */ + keys = g_hash_table_get_keys (priv->permissions); + g_hash_table_remove_all (priv->permissions); + + if (permissions) { + /* Process new permissions */ + g_hash_table_iter_init (&iter, permissions); + while (g_hash_table_iter_next (&iter, &key, &value)) { + perm = nm_permission_to_client ((const char *) key); + perm_result = nm_permission_result_to_client ((const char *) value); + if (perm) { + g_hash_table_insert (priv->permissions, + GUINT_TO_POINTER (perm), + GUINT_TO_POINTER (perm_result)); + + /* Remove this permission from the list of previous permissions + * we'll be sending NM_CLIENT_PERMISSION_RESULT_UNKNOWN for + * in the change signal since it is still a known permission. + */ + keys = g_list_remove (keys, GUINT_TO_POINTER (perm)); + } + } + } + + /* Signal changes in all updated permissions */ + g_hash_table_iter_init (&iter, priv->permissions); + while (g_hash_table_iter_next (&iter, &key, &value)) { + g_signal_emit (self, signals[PERMISSION_CHANGED], 0, + GPOINTER_TO_UINT (key), + GPOINTER_TO_UINT (value)); + } + + /* And signal changes in all permissions that used to be valid but for + * some reason weren't received in the last request (if any). + */ + for (keys_iter = keys; keys_iter; keys_iter = g_list_next (keys_iter)) { + g_signal_emit (self, signals[PERMISSION_CHANGED], 0, + GPOINTER_TO_UINT (keys_iter->data), + NM_CLIENT_PERMISSION_RESULT_UNKNOWN); + } + g_list_free (keys); +} + +static void +get_permissions_sync (NMClient *self) +{ + gboolean success; + GHashTable *permissions = NULL; + + success = dbus_g_proxy_call_with_timeout (NM_CLIENT_GET_PRIVATE (self)->client_proxy, + "GetPermissions", 3000, NULL, + G_TYPE_INVALID, + DBUS_TYPE_G_MAP_OF_STRING, &permissions, G_TYPE_INVALID); + update_permissions (self, success ? permissions : NULL); + if (permissions) + g_hash_table_destroy (permissions); +} + +static void +get_permissions_reply (DBusGProxy *proxy, + GHashTable *permissions, + GError *error, + gpointer user_data) +{ + NMClient *self = NM_CLIENT (user_data); + + NM_CLIENT_GET_PRIVATE (self)->perm_call = NULL; + update_permissions (NM_CLIENT (user_data), error ? NULL : permissions); +} + +static void +client_recheck_permissions (DBusGProxy *proxy, gpointer user_data) +{ + NMClient *self = NM_CLIENT (user_data); + NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self); + + if (!priv->perm_call) { + priv->perm_call = org_freedesktop_NetworkManager_get_permissions_async (NM_CLIENT_GET_PRIVATE (self)->client_proxy, + get_permissions_reply, + self); + } +} + static GObject* constructor (GType type, guint n_construct_params, @@ -324,6 +454,15 @@ constructor (GType type, object, NULL); + /* Permissions */ + dbus_g_proxy_add_signal (priv->client_proxy, "CheckPermissions", G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->client_proxy, + "CheckPermissions", + G_CALLBACK (client_recheck_permissions), + object, + NULL); + get_permissions_sync (NM_CLIENT (object)); + priv->bus_proxy = dbus_g_proxy_new_for_name (connection, "org.freedesktop.DBus", "/org/freedesktop/DBus", @@ -381,12 +520,17 @@ dispose (GObject *object) return; } + if (priv->perm_call) + dbus_g_proxy_cancel_call (priv->client_proxy, priv->perm_call); + g_object_unref (priv->client_proxy); g_object_unref (priv->bus_proxy); free_object_array (&priv->devices); free_object_array (&priv->active_connections); + g_hash_table_destroy (priv->permissions); + G_OBJECT_CLASS (nm_client_parent_class)->dispose (object); } @@ -626,6 +770,22 @@ nm_client_class_init (NMClientClass *client_class) g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT); + + /** + * NMClient::permission-changed: + * @widget: the client that received the signal + * @permission: a permission from #NMClientPermission + * @result: the permission's result, one of #NMClientPermissionResult + * + * Notifies that a permission has changed + **/ + signals[PERMISSION_CHANGED] = + g_signal_new ("permission-changed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, + _nm_marshal_VOID__UINT_UINT, + G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); } /** @@ -1158,3 +1318,25 @@ nm_client_get_manager_running (NMClient *client) return NM_CLIENT_GET_PRIVATE (client)->manager_running; } +/** + * nm_client_get_permission_result: + * @client: a #NMClient + * @permission: the permission for which to return the result, one of #NMClientPermission + * + * Requests the result of a specific permission, which indicates whether the + * client can or cannot perform the action the permission represents + * + * Returns: the permission's result, one of #NMClientPermissionResult + **/ +NMClientPermissionResult +nm_client_get_permission_result (NMClient *client, NMClientPermission permission) +{ + gpointer result; + + g_return_val_if_fail (NM_IS_CLIENT (client), NM_CLIENT_PERMISSION_RESULT_UNKNOWN); + + result = g_hash_table_lookup (NM_CLIENT_GET_PRIVATE (client)->permissions, + GUINT_TO_POINTER (permission)); + return GPOINTER_TO_UINT (result); +} + |