diff options
| author | William Jon McCann <mccann@jhu.edu> | 2007-02-15 15:28:27 -0500 | 
|---|---|---|
| committer | William Jon McCann <mccann@jhu.edu> | 2007-02-15 15:28:27 -0500 | 
| commit | cbe9b9ba1ca59d25365593fdc1a66f9ffd3183ca (patch) | |
| tree | 513550d8e7b24e7b5321eefaad491e8b2bfa1cb2 /src | |
| parent | 66c740f30d36bac8f7b56261f0bd595b297d3dd2 (diff) | |
implement get/set idle methods
Add the GetIdle and SetIdle methods, and the IdleChanged signal.
SetIdle is restricted to the uid of the session in question.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ck-session.c | 166 | ||||
| -rw-r--r-- | src/ck-session.h | 7 | ||||
| -rw-r--r-- | src/ck-session.xml | 11 | 
3 files changed, 173 insertions, 11 deletions
diff --git a/src/ck-session.c b/src/ck-session.c index ca1fed5..5f44bac 100644 --- a/src/ck-session.c +++ b/src/ck-session.c @@ -58,7 +58,10 @@ struct CkSessionPrivate          gboolean         active;          gboolean         is_local; +        gboolean         idle; +          DBusGConnection *connection; +        DBusGProxy      *bus_proxy;  };  enum { @@ -66,6 +69,7 @@ enum {          LOCK,          UNLOCK,          ACTIVE_CHANGED, +        IDLE_CHANGED,          LAST_SIGNAL  }; @@ -80,6 +84,7 @@ enum {          PROP_HOST_NAME,          PROP_IS_LOCAL,          PROP_ACTIVE, +        PROP_IDLE,  };  static guint signals [LAST_SIGNAL] = { 0, }; @@ -116,6 +121,11 @@ register_session (CkSession *session)                  return FALSE;          } +        session->priv->bus_proxy = dbus_g_proxy_new_for_name (session->priv->connection, +                                                              DBUS_SERVICE_DBUS, +                                                              DBUS_PATH_DBUS, +                                                              DBUS_INTERFACE_DBUS); +          dbus_g_connection_register_g_object (session->priv->connection, session->priv->id, G_OBJECT (session));          return TRUE; @@ -136,7 +146,7 @@ ck_session_lock (CkSession             *session,          ck_debug ("Emitting lock for session %s", session->priv->id);          g_signal_emit (session, signals [LOCK], 0); -        dbus_g_method_return (context, TRUE); +        dbus_g_method_return (context);          return TRUE;  } @@ -150,12 +160,129 @@ ck_session_unlock (CkSession             *session,          ck_debug ("Emitting unlock for session %s", session->priv->id);          g_signal_emit (session, signals [UNLOCK], 0); -        dbus_g_method_return (context, TRUE); +        dbus_g_method_return (context); + +        return TRUE; +} + +/* adapted from PolicyKit */ +static gboolean +get_caller_info (CkSession   *session, +                 const char  *sender, +                 uid_t       *calling_uid, +                 pid_t       *calling_pid) +{ +        gboolean res; +        GError  *error = NULL; + +        res = FALSE; + +        if (sender == NULL) { +                goto out; +        } + +        if (! dbus_g_proxy_call (session->priv->bus_proxy, "GetConnectionUnixUser", &error, +                                 G_TYPE_STRING, sender, +                                 G_TYPE_INVALID, +                                 G_TYPE_UINT, calling_uid, +                                 G_TYPE_INVALID)) { +                g_warning ("GetConnectionUnixUser() failed: %s", error->message); +                g_error_free (error); +                goto out; +        } + +        if (! dbus_g_proxy_call (session->priv->bus_proxy, "GetConnectionUnixProcessID", &error, +                                 G_TYPE_STRING, sender, +                                 G_TYPE_INVALID, +                                 G_TYPE_UINT, calling_pid, +                                 G_TYPE_INVALID)) { +                g_warning ("GetConnectionUnixProcessID() failed: %s", error->message); +                g_error_free (error); +                goto out; +        } + +        res = TRUE; + +        ck_debug ("uid = %d", *calling_uid); +        ck_debug ("pid = %d", *calling_pid); + +out: +        return res; +} + +static gboolean +session_set_idle_internal (CkSession      *session, +                           gboolean        idle) +{ +        if (session->priv->idle != idle) { +                session->priv->idle = idle; +                ck_debug ("Emitting idle-changed for session %s", session->priv->id); +                g_signal_emit (session, signals [IDLE_CHANGED], 0); +        }          return TRUE;  }  gboolean +ck_session_set_idle (CkSession             *session, +                     gboolean               idle, +                     DBusGMethodInvocation *context) +{ +        char       *sender; +        uid_t       calling_uid; +        pid_t       calling_pid; +        gboolean    res; + +        g_return_val_if_fail (CK_IS_SESSION (session), FALSE); + +        sender = dbus_g_method_get_sender (context); + +        res = get_caller_info (session, +                               sender, +                               &calling_uid, +                               &calling_pid); +        g_free (sender); + +        if (! res) { +                GError *error; +                error = g_error_new (CK_SESSION_ERROR, +                                     CK_SESSION_ERROR_GENERAL, +                                     _("Unable to lookup information about calling process '%d'"), +                                     calling_pid); +                g_warning ("stat on pid %d failed", calling_pid); +                dbus_g_method_return_error (context, error); +                g_error_free (error); +                return FALSE; +        } + +        /* only restrict this by UID for now */ +        if (session->priv->uid != calling_uid) { +                GError *error; +                error = g_error_new (CK_SESSION_ERROR, +                                     CK_SESSION_ERROR_GENERAL, +                                     _("Only session owner may set idle state")); +                dbus_g_method_return_error (context, error); +                g_error_free (error); +                return FALSE; +        } + +        session_set_idle_internal (session, idle); +        dbus_g_method_return (context); + +        return TRUE; +} + +gboolean +ck_session_get_idle (CkSession             *session, +                     DBusGMethodInvocation *context) +{ +        g_return_val_if_fail (CK_IS_SESSION (session), FALSE); + +        dbus_g_method_return (context, session->priv->idle); +        return TRUE; +} + +gboolean  ck_session_activate (CkSession             *session,                       DBusGMethodInvocation *context)  { @@ -480,6 +607,9 @@ ck_session_set_property (GObject            *object,          case PROP_HOST_NAME:                  ck_session_set_host_name (self, g_value_get_string (value), NULL);                  break; +        case PROP_IDLE: +                session_set_idle_internal (self, g_value_get_boolean (value)); +                break;          default:                  G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);                  break; @@ -524,6 +654,9 @@ ck_session_get_property (GObject    *object,          case PROP_HOST_NAME:                  g_value_set_string (value, self->priv->host_name);                  break; +        case PROP_IDLE: +                g_value_set_boolean (value, self->priv->idle); +                break;          default:                  G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);                  break; @@ -579,6 +712,16 @@ ck_session_class_init (CkSessionClass *klass)                                g_cclosure_marshal_VOID__VOID,                                G_TYPE_NONE,                                0); +        signals [IDLE_CHANGED] = +                g_signal_new ("idle-changed", +                              G_TYPE_FROM_CLASS (object_class), +                              G_SIGNAL_RUN_LAST, +                              G_STRUCT_OFFSET (CkSessionClass, idle_changed), +                              NULL, +                              NULL, +                              g_cclosure_marshal_VOID__BOOLEAN, +                              G_TYPE_NONE, +                              1, G_TYPE_BOOLEAN);          g_object_class_install_property (object_class,                                           PROP_ACTIVE, @@ -641,12 +784,19 @@ ck_session_class_init (CkSessionClass *klass)          g_object_class_install_property (object_class,                                           PROP_USER,                                           g_param_spec_uint ("user", -                                                           "User Id", -                                                           "User Id", -                                                           0, -                                                           G_MAXINT, -                                                           0, -                                                           G_PARAM_READWRITE)); +                                                            "User Id", +                                                            "User Id", +                                                            0, +                                                            G_MAXINT, +                                                            0, +                                                            G_PARAM_READWRITE)); +        g_object_class_install_property (object_class, +                                         PROP_ACTIVE, +                                         g_param_spec_boolean ("idle", +                                                               NULL, +                                                               NULL, +                                                               FALSE, +                                                               G_PARAM_READWRITE));          g_type_class_add_private (klass, sizeof (CkSessionPrivate)); diff --git a/src/ck-session.h b/src/ck-session.h index 761edc9..e2f68bf 100644 --- a/src/ck-session.h +++ b/src/ck-session.h @@ -55,6 +55,8 @@ typedef struct          void          (* unlock)         (CkSession *session);          void          (* active_changed) (CkSession *session,                                            gboolean   active); +        void          (* idle_changed)   (CkSession *session, +                                          gboolean   idle);  } CkSessionClass;  typedef enum @@ -136,11 +138,10 @@ gboolean            ck_session_get_host_name       (CkSession             *sessi  /* Non-authoritative properties */  gboolean            ck_session_get_idle            (CkSession             *session, -                                                    gboolean              *idle, -                                                    GError               **error); +                                                    DBusGMethodInvocation *context);  gboolean            ck_session_set_idle            (CkSession             *session,                                                      gboolean               idle, -                                                    GError               **error); +                                                    DBusGMethodInvocation *context);  /* Privileged actions */  gboolean            ck_session_activate            (CkSession             *session, diff --git a/src/ck-session.xml b/src/ck-session.xml index 668d1b2..f3faae1 100644 --- a/src/ck-session.xml +++ b/src/ck-session.xml @@ -41,9 +41,20 @@        <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>      </method> +    <method name="GetIdle"> +      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> +      <arg name="idle" type="b" direction="out"/> +    </method> +    <method name="SetIdle"> +      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> +      <arg name="idle" type="b" direction="in"/> +    </method> +      <signal name="ActiveChanged"/>      <signal name="Lock"/>      <signal name="Unlock"/> +    <signal name="IdleChanged"/> +    </interface>  </node>  | 
