cli: rework callbacks in NMPolkitListener to use one vtable structure

Instead of setting multiple callbacks, just let the user set one
vtable with callbacks. Usually, GObject would implement this via
signals. While that makes sense for public objects, for example to
work better with GIR and allow intercepting the signal, this is
overkill for our internal type. And NMPolkitListener already did
not make use of signals, for good reason.

Instead of passing multiple callbacks, must pass one structure with
callback pointers.

Also, extend the signature of the callbacks to always contain a
@self argument and a @user_data.
This commit is contained in:
Thomas Haller 2018-04-06 23:54:33 +02:00
parent 86ab96989d
commit 347118138d
4 changed files with 145 additions and 136 deletions

View file

@ -22,7 +22,8 @@
#include "nm-secret-agent-old.h"
#include "nm-meta-setting-desc.h"
#include "nm-polkit-listener.h"
struct _NMPolkitListener;
typedef char *(*NmcCompEntryFunc) (const char *, int);
@ -128,7 +129,7 @@ typedef struct _NmCli {
NMSecretAgentOld *secret_agent; /* Secret agent */
GHashTable *pwds_hash; /* Hash table with passwords in passwd-file */
NMPolkitListener *pk_listener ; /* polkit agent listener */
struct _NMPolkitListener *pk_listener; /* polkit agent listener */
int should_wait; /* Semaphore indicating whether nmcli should not end or not yet */
gboolean nowait_flag; /* '--nowait' option; used for passing to callbacks */

View file

@ -31,7 +31,8 @@
#if WITH_POLKIT_AGENT
static char *
polkit_request (const char *request,
polkit_request (NMPolkitListener *listener,
const char *request,
const char *action_id,
const char *message,
const char *icon_name,
@ -60,19 +61,25 @@ polkit_request (const char *request,
}
static void
polkit_show_info (const char *text)
polkit_show_info (NMPolkitListener *listener,
const char *text,
gpointer user_data)
{
g_print (_("Authentication message: %s\n"), text);
}
static void
polkit_show_error (const char *text)
polkit_show_error (NMPolkitListener *listener,
const char *text,
gpointer user_data)
{
g_print (_("Authentication error: %s\n"), text);
}
static void
polkit_completed (gboolean gained_authorization)
polkit_completed (NMPolkitListener *listener,
gboolean gained_authorization,
gpointer user_data)
{
/* We don't print anything here. The outcome will be evident from
* the operation result anyway. */
@ -83,7 +90,13 @@ gboolean
nmc_polkit_agent_init (NmCli* nmc, gboolean for_session, GError **error)
{
#if WITH_POLKIT_AGENT
PolkitAgentListener *listener;
static const NMPolkitListenVtable vtable = {
.on_request = polkit_request,
.on_show_info = polkit_show_info,
.on_show_error = polkit_show_error,
.on_completed = polkit_completed,
};
NMPolkitListener *listener;
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
@ -91,12 +104,9 @@ nmc_polkit_agent_init (NmCli* nmc, gboolean for_session, GError **error)
if (!listener)
return FALSE;
nm_polkit_listener_set_request_callback (NM_POLKIT_LISTENER (listener), polkit_request, nmc);
nm_polkit_listener_set_show_info_callback (NM_POLKIT_LISTENER (listener), polkit_show_info);
nm_polkit_listener_set_show_error_callback (NM_POLKIT_LISTENER (listener), polkit_show_error);
nm_polkit_listener_set_completed_callback (NM_POLKIT_LISTENER (listener), polkit_completed);
nm_polkit_listener_set_vtable (listener, &vtable, nmc);
nmc->pk_listener = NM_POLKIT_LISTENER (listener);
nmc->pk_listener = listener;
#endif
return TRUE;
}
@ -105,7 +115,10 @@ void
nmc_polkit_agent_fini (NmCli* nmc)
{
#if WITH_POLKIT_AGENT
g_clear_object (&nmc->pk_listener);
if (nmc->pk_listener) {
nm_polkit_listener_set_vtable (nmc->pk_listener, NULL, NULL);
g_clear_object (&nmc->pk_listener);
}
#endif
}

View file

@ -56,12 +56,8 @@ typedef struct {
char *icon_name;
char *identity;
/* callbacks */
NMPolkitListenerOnRequestFunc on_request_callback;
NMPolkitListenerOnShowInfoFunc on_show_info_callback;
NMPolkitListenerOnShowErrorFunc on_show_error_callback;
NMPolkitListenerOnCompletedFunc on_completed_callback;
gpointer request_callback_data;
const NMPolkitListenVtable *vtable;
gpointer vtable_user_data;
} NMPolkitListenerPrivate;
G_DEFINE_TYPE (NMPolkitListener, nm_polkit_listener, POLKIT_AGENT_TYPE_LISTENER)
@ -70,26 +66,40 @@ G_DEFINE_TYPE (NMPolkitListener, nm_polkit_listener, POLKIT_AGENT_TYPE_LISTENER)
/*****************************************************************************/
void
nm_polkit_listener_set_vtable (NMPolkitListener *self,
const NMPolkitListenVtable *vtable,
gpointer user_data)
{
NMPolkitListenerPrivate *priv = NM_POLKIT_LISTENER_GET_PRIVATE (self);
priv->vtable = vtable;
priv->vtable_user_data = user_data;
}
/*****************************************************************************/
static void
on_request (PolkitAgentSession *session,
const char *request,
gboolean echo_on,
gpointer user_data)
{
NMPolkitListenerPrivate *priv = NM_POLKIT_LISTENER_GET_PRIVATE (user_data);
char *response = NULL;
NMPolkitListener *self = NM_POLKIT_LISTENER (user_data);
NMPolkitListenerPrivate *priv = NM_POLKIT_LISTENER_GET_PRIVATE (self);
gs_free char *response = NULL;
if (priv->on_request_callback) {
response = priv->on_request_callback (request, priv->action_id,
priv->message, priv->icon_name,
priv->identity, echo_on,
priv->request_callback_data);
if (priv->vtable && priv->vtable->on_request) {
response = priv->vtable->on_request (self,
request, priv->action_id,
priv->message, priv->icon_name,
priv->identity, echo_on,
priv->vtable_user_data);
}
if (response) {
if (response)
polkit_agent_session_response (session, response);
g_free (response);
} else {
else {
//FIXME: polkit_agent_session_cancel() should emit "completed", but it doesn't work for me ???
//polkit_agent_session_cancel (session);
polkit_agent_session_response (session, "");
@ -101,10 +111,13 @@ on_show_info (PolkitAgentSession *session,
const char *text,
gpointer user_data)
{
NMPolkitListenerPrivate *priv = NM_POLKIT_LISTENER_GET_PRIVATE (user_data);
NMPolkitListener *self = NM_POLKIT_LISTENER (user_data);
NMPolkitListenerPrivate *priv = NM_POLKIT_LISTENER_GET_PRIVATE (self);
if (priv->on_show_info_callback)
priv->on_show_info_callback (text);
if (priv->vtable && priv->vtable->on_show_info) {
priv->vtable->on_show_info (self, text,
priv->vtable_user_data);
}
}
static void
@ -112,10 +125,13 @@ on_show_error (PolkitAgentSession *session,
const char *text,
gpointer user_data)
{
NMPolkitListenerPrivate *priv = NM_POLKIT_LISTENER_GET_PRIVATE (user_data);
NMPolkitListener *self = NM_POLKIT_LISTENER (user_data);
NMPolkitListenerPrivate *priv = NM_POLKIT_LISTENER_GET_PRIVATE (self);
if (priv->on_show_error_callback)
priv->on_show_error_callback (text);
if (priv->vtable && priv->vtable->on_show_error) {
priv->vtable->on_show_error (self, text,
priv->vtable_user_data);
}
}
static void
@ -123,10 +139,13 @@ on_completed (PolkitAgentSession *session,
gboolean gained_authorization,
gpointer user_data)
{
NMPolkitListenerPrivate *priv = NM_POLKIT_LISTENER_GET_PRIVATE (user_data);
NMPolkitListener *self = NM_POLKIT_LISTENER (user_data);
NMPolkitListenerPrivate *priv = NM_POLKIT_LISTENER_GET_PRIVATE (self);
if (priv->on_completed_callback)
priv->on_completed_callback (gained_authorization);
if (priv->vtable->on_completed) {
priv->vtable->on_completed (self, gained_authorization,
priv->vtable_user_data);
}
g_simple_async_result_complete_in_idle (priv->simple);
@ -150,7 +169,8 @@ on_completed (PolkitAgentSession *session,
static void
on_cancelled (GCancellable *cancellable, gpointer user_data)
{
NMPolkitListenerPrivate *priv = NM_POLKIT_LISTENER_GET_PRIVATE (user_data);
NMPolkitListener *self = NM_POLKIT_LISTENER (user_data);
NMPolkitListenerPrivate *priv = NM_POLKIT_LISTENER_GET_PRIVATE (self);
polkit_agent_session_cancel (priv->active_session);
}
@ -271,83 +291,6 @@ initiate_authentication_finish (PolkitAgentListener *listener,
/*****************************************************************************/
/**
* nm_polkit_listener_set_request_callback:
* @self: a #NMPolkitListener object
* @request_callback: callback to install for polkit requests
* @request_callback_data: usaer data passed to request_callback when it is called
*
* Set a callback for "request" signal. The callback will be invoked when polkit
* requests an authorization.
*/
void
nm_polkit_listener_set_request_callback (NMPolkitListener *self,
NMPolkitListenerOnRequestFunc request_callback,
gpointer request_callback_data)
{
NMPolkitListenerPrivate *priv;
g_return_if_fail (NM_IS_POLKIT_LISTENER (self));
priv = NM_POLKIT_LISTENER_GET_PRIVATE (self);
priv->on_request_callback = request_callback;
priv->request_callback_data = request_callback_data;
}
/**
* nm_polkit_listener_set_show_info_callback:
* @self: a #NMPolkitListener object
* @show_info_callback: callback to install for polkit show info trigger
*
* Set a callback for "show-info" signal. The callback will be invoked when polkit
* has an info text to display.
*/
void
nm_polkit_listener_set_show_info_callback (NMPolkitListener *self,
NMPolkitListenerOnShowInfoFunc show_info_callback)
{
g_return_if_fail (NM_IS_POLKIT_LISTENER (self));
NM_POLKIT_LISTENER_GET_PRIVATE (self)->on_show_info_callback = show_info_callback;
}
/**
* nm_polkit_listener_set_show_error_callback:
* @self: a #NMPolkitListener object
* @show_error_callback: callback to install for polkit show error trigger
*
* Set a callback for "show-error" signal. The callback will be invoked when polkit
* has an error text to display.
*/
void
nm_polkit_listener_set_show_error_callback (NMPolkitListener *self,
NMPolkitListenerOnShowErrorFunc show_error_callback)
{
g_return_if_fail (NM_IS_POLKIT_LISTENER (self));
NM_POLKIT_LISTENER_GET_PRIVATE (self)->on_show_error_callback = show_error_callback;
}
/**
* nm_polkit_listener_set_completed_callback:
* @self: a #NMPolkitListener object
* @completed_callback: callback to install for polkit completing authorization
*
* Set a callback for "completed" signal. The callback will be invoked when polkit
* completed the request.
*/
void
nm_polkit_listener_set_completed_callback (NMPolkitListener *self,
NMPolkitListenerOnCompletedFunc completed_callback)
{
g_return_if_fail (NM_IS_POLKIT_LISTENER (self));
NM_POLKIT_LISTENER_GET_PRIVATE (self)->on_completed_callback = completed_callback;
}
/*****************************************************************************/
static void
nm_polkit_listener_init (NMPolkitListener *agent)
{
@ -357,22 +300,26 @@ nm_polkit_listener_init (NMPolkitListener *agent)
* nm_polkit_listener_new:
* @for_session: %TRUE for registering the polkit agent for the user session,
* %FALSE for registering it for the running process
* @vtable: mandatory callbacks
* @user_data: user-data pointer for callbacks
* @error: location to store error, or %NULL
*
* Creates a new #NMPolkitListener and registers it as a polkit agent.
*
* Returns: a new #NMPolkitListener
*/
PolkitAgentListener *
nm_polkit_listener_new (gboolean for_session, GError **error)
NMPolkitListener *
nm_polkit_listener_new (gboolean for_session,
GError **error)
{
PolkitAgentListener *listener;
NMPolkitListener *listener;
PolkitSubject* session;
NMPolkitListenerPrivate *priv;
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
g_return_val_if_fail (!error || !*error, NULL);
listener = g_object_new (NM_TYPE_POLKIT_LISTENER, NULL);
priv = NM_POLKIT_LISTENER_GET_PRIVATE (listener);
if (for_session) {
@ -382,7 +329,8 @@ nm_polkit_listener_new (gboolean for_session, GError **error)
} else
session = polkit_unix_process_new_for_owner (getpid (), 0, getuid ());
priv->reg_handle = polkit_agent_listener_register (listener, POLKIT_AGENT_REGISTER_FLAGS_NONE,
priv->reg_handle = polkit_agent_listener_register (POLKIT_AGENT_LISTENER (listener),
POLKIT_AGENT_REGISTER_FLAGS_NONE,
session, NULL, NULL, error);
if (!priv->reg_handle) {
g_object_unref (listener);
@ -393,7 +341,6 @@ nm_polkit_listener_new (gboolean for_session, GError **error)
return listener;
}
static void
nm_polkit_listener_finalize (GObject *object)
{

View file

@ -19,11 +19,63 @@
#ifndef __NM_POLKIT_LISTENER_H__
#define __NM_POLKIT_LISTENER_H__
struct _NMPolkitListener;
#if WITH_POLKIT_AGENT
typedef struct _NMPolkitListener NMPolkitListener;
typedef struct _NMPolkitListenerClass NMPolkitListenerClass;
#if WITH_POLKIT_AGENT
typedef struct {
/*
* @request: the request asked by polkit agent
* @action_id: the action_id of the polkit request
* @message: the message of the polkit request
* @icon_name: the icon name of the polkit request
* @user: user name
* @echo_on: whether the response to the request should be echoed to the screen
* @user_data: user data for the callback
*
* Called as a result of a request by polkit. The function should obtain response
* to the request from user, i.e. get the password required.
*/
char *(*on_request) (NMPolkitListener *self,
const char *request,
const char *action_id,
const char *message,
const char *icon_name,
const char *user,
gboolean echo_on,
gpointer user_data);
/*
* @text: the info text from polkit
*
* Called as a result of show-info signal by polkit.
*/
void (*on_show_info) (NMPolkitListener *self,
const char *text,
gpointer user_data);
/*
* @text: the error text from polkit
*
* Called as a result of show-error signal by polkit.
*/
void (*on_show_error) (NMPolkitListener *self,
const char *text,
gpointer user_data);
/*
* @gained_authorization: whether the autorization was successful
*
* Called as a result of completed signal by polkit.
*/
void (*on_completed) (NMPolkitListener *self,
gboolean gained_authorization,
gpointer user_data);
} NMPolkitListenVtable;
/*****************************************************************************/
#define POLKIT_AGENT_I_KNOW_API_IS_SUBJECT_TO_CHANGE
#include <polkitagent/polkitagent.h>
@ -82,22 +134,18 @@ struct _NMPolkitListener {
PolkitAgentListener parent;
};
typedef struct {
struct _NMPolkitListenerClass {
PolkitAgentListenerClass parent;
} NMPolkitListenerClass;
};
GType nm_polkit_listener_get_type (void);
PolkitAgentListener* nm_polkit_listener_new (gboolean for_session, GError **error);
void nm_polkit_listener_set_request_callback (NMPolkitListener *self,
NMPolkitListenerOnRequestFunc request_callback,
gpointer request_callback_data);
void nm_polkit_listener_set_show_info_callback (NMPolkitListener *self,
NMPolkitListenerOnShowInfoFunc show_info_callback);
void nm_polkit_listener_set_show_error_callback (NMPolkitListener *self,
NMPolkitListenerOnShowErrorFunc show_error_callback);
void nm_polkit_listener_set_completed_callback (NMPolkitListener *self,
NMPolkitListenerOnCompletedFunc completed_callback);
NMPolkitListener *nm_polkit_listener_new (gboolean for_session,
GError **error);
void nm_polkit_listener_set_vtable (NMPolkitListener *self,
const NMPolkitListenVtable *vtable,
gpointer user_data);
#endif