1642 lines
62 KiB
Diff
1642 lines
62 KiB
Diff
From e625a214d531635db1e48b2dc51ed0e09ef8005b Mon Sep 17 00:00:00 2001
|
|
From: Ray Strode <rstrode@redhat.com>
|
|
Date: Tue, 14 Aug 2018 14:52:41 -0400
|
|
Subject: [PATCH 2/4] session: support new accountsservice Session and
|
|
SessionType props
|
|
|
|
At the moment the user's session is stored in a property called
|
|
"XSession". This is pretty weird if the user is using wayland.
|
|
|
|
AccountService now supports a more generic property "Session" and
|
|
a related "SessionType" property to replace "XSession".
|
|
|
|
This commit switches GDM over to use the new properties.
|
|
---
|
|
daemon/gdm-session-settings.c | 61 ++++++++++++++++++++++++---
|
|
daemon/gdm-session-settings.h | 3 ++
|
|
daemon/gdm-session-worker.c | 28 +++++++++++++
|
|
daemon/gdm-session-worker.xml | 3 ++
|
|
daemon/gdm-session.c | 78 ++++++++++++++++++++++++++---------
|
|
5 files changed, 148 insertions(+), 25 deletions(-)
|
|
|
|
diff --git a/daemon/gdm-session-settings.c b/daemon/gdm-session-settings.c
|
|
index 933f095bc..8463fad32 100644
|
|
--- a/daemon/gdm-session-settings.c
|
|
+++ b/daemon/gdm-session-settings.c
|
|
@@ -12,114 +12,121 @@
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
* 02110-1301, USA.
|
|
*
|
|
* Written by: Ray Strode <rstrode@redhat.com>
|
|
*/
|
|
#include "config.h"
|
|
#include "gdm-session-settings.h"
|
|
|
|
#include <errno.h>
|
|
#include <pwd.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <unistd.h>
|
|
|
|
#include <glib.h>
|
|
#include <glib-object.h>
|
|
#include <glib/gi18n.h>
|
|
|
|
#include <act/act-user-manager.h>
|
|
|
|
struct _GdmSessionSettingsPrivate
|
|
{
|
|
ActUserManager *user_manager;
|
|
ActUser *user;
|
|
char *session_name;
|
|
+ char *session_type;
|
|
char *language_name;
|
|
};
|
|
|
|
static void gdm_session_settings_finalize (GObject *object);
|
|
static void gdm_session_settings_class_install_properties (GdmSessionSettingsClass *
|
|
settings_class);
|
|
|
|
static void gdm_session_settings_set_property (GObject *object,
|
|
guint prop_id,
|
|
const GValue *value,
|
|
GParamSpec *pspec);
|
|
static void gdm_session_settings_get_property (GObject *object,
|
|
guint prop_id,
|
|
GValue *value,
|
|
GParamSpec *pspec);
|
|
|
|
enum {
|
|
PROP_0 = 0,
|
|
PROP_SESSION_NAME,
|
|
+ PROP_SESSION_TYPE,
|
|
PROP_LANGUAGE_NAME,
|
|
PROP_IS_LOADED
|
|
};
|
|
|
|
G_DEFINE_TYPE (GdmSessionSettings, gdm_session_settings, G_TYPE_OBJECT)
|
|
|
|
static void
|
|
gdm_session_settings_class_init (GdmSessionSettingsClass *settings_class)
|
|
{
|
|
GObjectClass *object_class;
|
|
|
|
object_class = G_OBJECT_CLASS (settings_class);
|
|
|
|
object_class->finalize = gdm_session_settings_finalize;
|
|
|
|
gdm_session_settings_class_install_properties (settings_class);
|
|
|
|
g_type_class_add_private (settings_class, sizeof (GdmSessionSettingsPrivate));
|
|
}
|
|
|
|
static void
|
|
gdm_session_settings_class_install_properties (GdmSessionSettingsClass *settings_class)
|
|
{
|
|
GObjectClass *object_class;
|
|
GParamSpec *param_spec;
|
|
|
|
object_class = G_OBJECT_CLASS (settings_class);
|
|
object_class->set_property = gdm_session_settings_set_property;
|
|
object_class->get_property = gdm_session_settings_get_property;
|
|
|
|
param_spec = g_param_spec_string ("session-name", "Session Name",
|
|
"The name of the session",
|
|
NULL, G_PARAM_READWRITE);
|
|
g_object_class_install_property (object_class, PROP_SESSION_NAME, param_spec);
|
|
|
|
+ param_spec = g_param_spec_string ("session-type", "Session Type",
|
|
+ "The type of the session",
|
|
+ NULL, G_PARAM_READWRITE);
|
|
+ g_object_class_install_property (object_class, PROP_SESSION_TYPE, param_spec);
|
|
+
|
|
param_spec = g_param_spec_string ("language-name", "Language Name",
|
|
"The name of the language",
|
|
NULL,
|
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
|
g_object_class_install_property (object_class, PROP_LANGUAGE_NAME, param_spec);
|
|
|
|
param_spec = g_param_spec_boolean ("is-loaded", NULL, NULL,
|
|
FALSE, G_PARAM_READABLE);
|
|
g_object_class_install_property (object_class, PROP_IS_LOADED, param_spec);
|
|
}
|
|
|
|
static void
|
|
gdm_session_settings_init (GdmSessionSettings *settings)
|
|
{
|
|
settings->priv = G_TYPE_INSTANCE_GET_PRIVATE (settings,
|
|
GDM_TYPE_SESSION_SETTINGS,
|
|
GdmSessionSettingsPrivate);
|
|
|
|
settings->priv->user_manager = act_user_manager_get_default ();
|
|
|
|
}
|
|
|
|
static void
|
|
gdm_session_settings_finalize (GObject *object)
|
|
{
|
|
GdmSessionSettings *settings;
|
|
GObjectClass *parent_class;
|
|
|
|
settings = GDM_SESSION_SETTINGS (object);
|
|
|
|
@@ -136,172 +143,212 @@ gdm_session_settings_finalize (GObject *object)
|
|
parent_class->finalize (object);
|
|
}
|
|
}
|
|
|
|
void
|
|
gdm_session_settings_set_language_name (GdmSessionSettings *settings,
|
|
const char *language_name)
|
|
{
|
|
g_return_if_fail (GDM_IS_SESSION_SETTINGS (settings));
|
|
|
|
if (settings->priv->language_name == NULL ||
|
|
strcmp (settings->priv->language_name, language_name) != 0) {
|
|
settings->priv->language_name = g_strdup (language_name);
|
|
g_object_notify (G_OBJECT (settings), "language-name");
|
|
}
|
|
}
|
|
|
|
void
|
|
gdm_session_settings_set_session_name (GdmSessionSettings *settings,
|
|
const char *session_name)
|
|
{
|
|
g_return_if_fail (GDM_IS_SESSION_SETTINGS (settings));
|
|
|
|
if (settings->priv->session_name == NULL ||
|
|
strcmp (settings->priv->session_name, session_name) != 0) {
|
|
settings->priv->session_name = g_strdup (session_name);
|
|
g_object_notify (G_OBJECT (settings), "session-name");
|
|
}
|
|
}
|
|
|
|
+void
|
|
+gdm_session_settings_set_session_type (GdmSessionSettings *settings,
|
|
+ const char *session_type)
|
|
+{
|
|
+ g_return_if_fail (GDM_IS_SESSION_SETTINGS (settings));
|
|
+
|
|
+ if (settings->priv->session_type == NULL ||
|
|
+ g_strcmp0 (settings->priv->session_type, session_type) != 0) {
|
|
+ settings->priv->session_type = g_strdup (session_type);
|
|
+ g_object_notify (G_OBJECT (settings), "session-type");
|
|
+ }
|
|
+}
|
|
+
|
|
char *
|
|
gdm_session_settings_get_language_name (GdmSessionSettings *settings)
|
|
{
|
|
g_return_val_if_fail (GDM_IS_SESSION_SETTINGS (settings), NULL);
|
|
return g_strdup (settings->priv->language_name);
|
|
}
|
|
|
|
char *
|
|
gdm_session_settings_get_session_name (GdmSessionSettings *settings)
|
|
{
|
|
g_return_val_if_fail (GDM_IS_SESSION_SETTINGS (settings), NULL);
|
|
return g_strdup (settings->priv->session_name);
|
|
}
|
|
|
|
+char *
|
|
+gdm_session_settings_get_session_type (GdmSessionSettings *settings)
|
|
+{
|
|
+ g_return_val_if_fail (GDM_IS_SESSION_SETTINGS (settings), NULL);
|
|
+ return g_strdup (settings->priv->session_type);
|
|
+}
|
|
+
|
|
static void
|
|
gdm_session_settings_set_property (GObject *object,
|
|
guint prop_id,
|
|
const GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
GdmSessionSettings *settings;
|
|
|
|
settings = GDM_SESSION_SETTINGS (object);
|
|
|
|
switch (prop_id) {
|
|
case PROP_LANGUAGE_NAME:
|
|
gdm_session_settings_set_language_name (settings, g_value_get_string (value));
|
|
break;
|
|
|
|
case PROP_SESSION_NAME:
|
|
gdm_session_settings_set_session_name (settings, g_value_get_string (value));
|
|
break;
|
|
|
|
+ case PROP_SESSION_TYPE:
|
|
+ gdm_session_settings_set_session_type (settings, g_value_get_string (value));
|
|
+ break;
|
|
+
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
}
|
|
}
|
|
|
|
static void
|
|
gdm_session_settings_get_property (GObject *object,
|
|
guint prop_id,
|
|
GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
GdmSessionSettings *settings;
|
|
|
|
settings = GDM_SESSION_SETTINGS (object);
|
|
|
|
switch (prop_id) {
|
|
case PROP_SESSION_NAME:
|
|
g_value_set_string (value, settings->priv->session_name);
|
|
break;
|
|
|
|
+ case PROP_SESSION_TYPE:
|
|
+ g_value_set_string (value, settings->priv->session_type);
|
|
+ break;
|
|
+
|
|
case PROP_LANGUAGE_NAME:
|
|
g_value_set_string (value, settings->priv->language_name);
|
|
break;
|
|
|
|
case PROP_IS_LOADED:
|
|
g_value_set_boolean (value, gdm_session_settings_is_loaded (settings));
|
|
break;
|
|
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
}
|
|
}
|
|
|
|
GdmSessionSettings *
|
|
gdm_session_settings_new (void)
|
|
{
|
|
GdmSessionSettings *settings;
|
|
|
|
settings = g_object_new (GDM_TYPE_SESSION_SETTINGS,
|
|
NULL);
|
|
|
|
return settings;
|
|
}
|
|
|
|
gboolean
|
|
gdm_session_settings_is_loaded (GdmSessionSettings *settings)
|
|
{
|
|
if (settings->priv->user == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
return act_user_is_loaded (settings->priv->user);
|
|
}
|
|
|
|
static void
|
|
load_settings_from_user (GdmSessionSettings *settings)
|
|
{
|
|
const char *session_name;
|
|
+ const char *session_type;
|
|
const char *language_name;
|
|
|
|
if (!act_user_is_loaded (settings->priv->user)) {
|
|
g_warning ("GdmSessionSettings: trying to load user settings from unloaded user");
|
|
return;
|
|
}
|
|
|
|
- session_name = act_user_get_x_session (settings->priv->user);
|
|
- g_debug ("GdmSessionSettings: saved session is %s", session_name);
|
|
+ /* if the user doesn't have saved state, they don't have any settings worth reading */
|
|
+ if (!act_user_get_saved (settings->priv->user))
|
|
+ goto out;
|
|
+
|
|
+ session_type = act_user_get_session_type (settings->priv->user);
|
|
+ session_name = act_user_get_session (settings->priv->user);
|
|
|
|
- if (session_name != NULL) {
|
|
+ g_debug ("GdmSessionSettings: saved session is %s (type %s)", session_name, session_type);
|
|
+
|
|
+ if (session_type != NULL && session_type[0] != '\0') {
|
|
+ gdm_session_settings_set_session_type (settings, session_type);
|
|
+ }
|
|
+
|
|
+ if (session_name != NULL && session_name[0] != '\0') {
|
|
gdm_session_settings_set_session_name (settings, session_name);
|
|
}
|
|
|
|
language_name = act_user_get_language (settings->priv->user);
|
|
|
|
g_debug ("GdmSessionSettings: saved language is %s", language_name);
|
|
- if (language_name != NULL) {
|
|
+ if (language_name != NULL && language_name[0] != '\0') {
|
|
gdm_session_settings_set_language_name (settings, language_name);
|
|
}
|
|
|
|
+out:
|
|
g_object_notify (G_OBJECT (settings), "is-loaded");
|
|
}
|
|
|
|
static void
|
|
on_user_is_loaded_changed (ActUser *user,
|
|
GParamSpec *pspec,
|
|
GdmSessionSettings *settings)
|
|
{
|
|
if (act_user_is_loaded (settings->priv->user)) {
|
|
load_settings_from_user (settings);
|
|
g_signal_handlers_disconnect_by_func (G_OBJECT (settings->priv->user),
|
|
G_CALLBACK (on_user_is_loaded_changed),
|
|
settings);
|
|
}
|
|
}
|
|
|
|
gboolean
|
|
gdm_session_settings_load (GdmSessionSettings *settings,
|
|
const char *username)
|
|
{
|
|
ActUser *old_user;
|
|
|
|
g_return_val_if_fail (settings != NULL, FALSE);
|
|
g_return_val_if_fail (username != NULL, FALSE);
|
|
g_return_val_if_fail (!gdm_session_settings_is_loaded (settings), FALSE);
|
|
|
|
if (settings->priv->user != NULL) {
|
|
old_user = settings->priv->user;
|
|
|
|
g_signal_handlers_disconnect_by_func (G_OBJECT (settings->priv->user),
|
|
@@ -322,40 +369,44 @@ gdm_session_settings_load (GdmSessionSettings *settings,
|
|
G_CALLBACK (on_user_is_loaded_changed),
|
|
settings);
|
|
return FALSE;
|
|
}
|
|
|
|
load_settings_from_user (settings);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
gboolean
|
|
gdm_session_settings_save (GdmSessionSettings *settings,
|
|
const char *username)
|
|
{
|
|
ActUser *user;
|
|
|
|
g_return_val_if_fail (GDM_IS_SESSION_SETTINGS (settings), FALSE);
|
|
g_return_val_if_fail (username != NULL, FALSE);
|
|
g_return_val_if_fail (gdm_session_settings_is_loaded (settings), FALSE);
|
|
|
|
user = act_user_manager_get_user (settings->priv->user_manager,
|
|
username);
|
|
|
|
|
|
if (!act_user_is_loaded (user)) {
|
|
g_object_unref (user);
|
|
return FALSE;
|
|
}
|
|
|
|
if (settings->priv->session_name != NULL) {
|
|
- act_user_set_x_session (user, settings->priv->session_name);
|
|
+ act_user_set_session (user, settings->priv->session_name);
|
|
+ }
|
|
+
|
|
+ if (settings->priv->session_type != NULL) {
|
|
+ act_user_set_session_type (user, settings->priv->session_type);
|
|
}
|
|
|
|
if (settings->priv->language_name != NULL) {
|
|
act_user_set_language (user, settings->priv->language_name);
|
|
}
|
|
g_object_unref (user);
|
|
|
|
return TRUE;
|
|
}
|
|
diff --git a/daemon/gdm-session-settings.h b/daemon/gdm-session-settings.h
|
|
index 20946bff1..db38ffc72 100644
|
|
--- a/daemon/gdm-session-settings.h
|
|
+++ b/daemon/gdm-session-settings.h
|
|
@@ -33,37 +33,40 @@ G_BEGIN_DECLS
|
|
#define GDM_IS_SESSION_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDM_TYPE_SESSION_SETTINGS))
|
|
#define GDM_SESSION_SETTINGS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GDM_TYPE_SESSION_SETTINGS, GdmSessionSettingsClass))
|
|
#define GDM_SESSION_SETTINGS_ERROR (gdm_session_settings_error_quark ())
|
|
typedef struct _GdmSessionSettings GdmSessionSettings;
|
|
typedef struct _GdmSessionSettingsClass GdmSessionSettingsClass;
|
|
typedef struct _GdmSessionSettingsPrivate GdmSessionSettingsPrivate;
|
|
|
|
struct _GdmSessionSettings
|
|
{
|
|
GObject parent;
|
|
|
|
/*< private > */
|
|
GdmSessionSettingsPrivate *priv;
|
|
};
|
|
|
|
struct _GdmSessionSettingsClass
|
|
{
|
|
GObjectClass parent_class;
|
|
};
|
|
|
|
GType gdm_session_settings_get_type (void);
|
|
GdmSessionSettings *gdm_session_settings_new (void);
|
|
|
|
gboolean gdm_session_settings_load (GdmSessionSettings *settings,
|
|
const char *username);
|
|
gboolean gdm_session_settings_save (GdmSessionSettings *settings,
|
|
const char *username);
|
|
gboolean gdm_session_settings_is_loaded (GdmSessionSettings *settings);
|
|
char *gdm_session_settings_get_language_name (GdmSessionSettings *settings);
|
|
char *gdm_session_settings_get_session_name (GdmSessionSettings *settings);
|
|
+char *gdm_session_settings_get_session_type (GdmSessionSettings *settings);
|
|
void gdm_session_settings_set_language_name (GdmSessionSettings *settings,
|
|
const char *language_name);
|
|
void gdm_session_settings_set_session_name (GdmSessionSettings *settings,
|
|
const char *session_name);
|
|
+void gdm_session_settings_set_session_type (GdmSessionSettings *settings,
|
|
+ const char *session_type);
|
|
|
|
G_END_DECLS
|
|
#endif /* GDM_SESSION_SETTINGS_H */
|
|
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
|
|
index e79073996..ae86d28ac 100644
|
|
--- a/daemon/gdm-session-worker.c
|
|
+++ b/daemon/gdm-session-worker.c
|
|
@@ -2539,60 +2539,74 @@ gdm_session_worker_handle_set_language_name (GdmDBusWorker *object,
|
|
gdm_dbus_worker_complete_set_language_name (object, invocation);
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
on_saved_language_name_read (GdmSessionWorker *worker)
|
|
{
|
|
char *language_name;
|
|
|
|
language_name = gdm_session_settings_get_language_name (worker->priv->user_settings);
|
|
|
|
g_debug ("GdmSessionWorker: Saved language is %s", language_name);
|
|
gdm_dbus_worker_emit_saved_language_name_read (GDM_DBUS_WORKER (worker),
|
|
language_name);
|
|
g_free (language_name);
|
|
}
|
|
|
|
static void
|
|
on_saved_session_name_read (GdmSessionWorker *worker)
|
|
{
|
|
char *session_name;
|
|
|
|
session_name = gdm_session_settings_get_session_name (worker->priv->user_settings);
|
|
|
|
g_debug ("GdmSessionWorker: Saved session is %s", session_name);
|
|
gdm_dbus_worker_emit_saved_session_name_read (GDM_DBUS_WORKER (worker),
|
|
session_name);
|
|
g_free (session_name);
|
|
}
|
|
|
|
+static void
|
|
+on_saved_session_type_read (GdmSessionWorker *worker)
|
|
+{
|
|
+ char *session_type;
|
|
+
|
|
+ session_type = gdm_session_settings_get_session_type (worker->priv->user_settings);
|
|
+
|
|
+ g_debug ("GdmSessionWorker: Saved session type is %s", session_type);
|
|
+ gdm_dbus_worker_emit_saved_session_type_read (GDM_DBUS_WORKER (worker),
|
|
+ session_type);
|
|
+ g_free (session_type);
|
|
+}
|
|
+
|
|
+
|
|
static void
|
|
do_setup (GdmSessionWorker *worker)
|
|
{
|
|
GError *error;
|
|
gboolean res;
|
|
|
|
error = NULL;
|
|
res = gdm_session_worker_initialize_pam (worker,
|
|
worker->priv->service,
|
|
(const char **) worker->priv->extensions,
|
|
worker->priv->username,
|
|
worker->priv->hostname,
|
|
worker->priv->display_is_local,
|
|
worker->priv->x11_display_name,
|
|
worker->priv->x11_authority_file,
|
|
worker->priv->display_device,
|
|
worker->priv->display_seat_id,
|
|
&error);
|
|
|
|
if (res) {
|
|
g_dbus_method_invocation_return_value (worker->priv->pending_invocation, NULL);
|
|
} else {
|
|
g_dbus_method_invocation_take_error (worker->priv->pending_invocation, error);
|
|
}
|
|
worker->priv->pending_invocation = NULL;
|
|
}
|
|
|
|
static void
|
|
do_authenticate (GdmSessionWorker *worker)
|
|
{
|
|
@@ -3001,158 +3015,172 @@ gdm_session_worker_handle_initialize (GdmDBusWorker *object,
|
|
} else if (g_strcmp0 (key, "x11-authority-file") == 0) {
|
|
worker->priv->x11_authority_file = g_variant_dup_string (value, NULL);
|
|
} else if (g_strcmp0 (key, "console") == 0) {
|
|
worker->priv->display_device = g_variant_dup_string (value, NULL);
|
|
} else if (g_strcmp0 (key, "seat-id") == 0) {
|
|
worker->priv->display_seat_id = g_variant_dup_string (value, NULL);
|
|
} else if (g_strcmp0 (key, "hostname") == 0) {
|
|
worker->priv->hostname = g_variant_dup_string (value, NULL);
|
|
} else if (g_strcmp0 (key, "display-is-local") == 0) {
|
|
worker->priv->display_is_local = g_variant_get_boolean (value);
|
|
} else if (g_strcmp0 (key, "display-is-initial") == 0) {
|
|
worker->priv->display_is_initial = g_variant_get_boolean (value);
|
|
}
|
|
}
|
|
|
|
worker->priv->pending_invocation = invocation;
|
|
|
|
if (!worker->priv->is_program_session) {
|
|
worker->priv->user_settings = gdm_session_settings_new ();
|
|
|
|
g_signal_connect_swapped (worker->priv->user_settings,
|
|
"notify::language-name",
|
|
G_CALLBACK (on_saved_language_name_read),
|
|
worker);
|
|
|
|
g_signal_connect_swapped (worker->priv->user_settings,
|
|
"notify::session-name",
|
|
G_CALLBACK (on_saved_session_name_read),
|
|
worker);
|
|
|
|
+ g_signal_connect_swapped (worker->priv->user_settings,
|
|
+ "notify::session-type",
|
|
+ G_CALLBACK (on_saved_session_type_read),
|
|
+ worker);
|
|
+
|
|
if (worker->priv->username) {
|
|
wait_for_settings = !gdm_session_settings_load (worker->priv->user_settings,
|
|
worker->priv->username);
|
|
}
|
|
}
|
|
|
|
if (wait_for_settings) {
|
|
/* Load settings from accounts daemon before continuing
|
|
*/
|
|
g_signal_connect (G_OBJECT (worker->priv->user_settings),
|
|
"notify::is-loaded",
|
|
G_CALLBACK (on_settings_is_loaded_changed),
|
|
worker);
|
|
} else {
|
|
queue_state_change (worker);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
gdm_session_worker_handle_setup (GdmDBusWorker *object,
|
|
GDBusMethodInvocation *invocation,
|
|
const char *service,
|
|
const char *x11_display_name,
|
|
const char *x11_authority_file,
|
|
const char *console,
|
|
const char *seat_id,
|
|
const char *hostname,
|
|
gboolean display_is_local,
|
|
gboolean display_is_initial)
|
|
{
|
|
GdmSessionWorker *worker = GDM_SESSION_WORKER (object);
|
|
validate_and_queue_state_change (worker, invocation, GDM_SESSION_WORKER_STATE_SETUP_COMPLETE);
|
|
|
|
worker->priv->service = g_strdup (service);
|
|
worker->priv->x11_display_name = g_strdup (x11_display_name);
|
|
worker->priv->x11_authority_file = g_strdup (x11_authority_file);
|
|
worker->priv->display_device = g_strdup (console);
|
|
worker->priv->display_seat_id = g_strdup (seat_id);
|
|
worker->priv->hostname = g_strdup (hostname);
|
|
worker->priv->display_is_local = display_is_local;
|
|
worker->priv->display_is_initial = display_is_initial;
|
|
worker->priv->username = NULL;
|
|
|
|
worker->priv->user_settings = gdm_session_settings_new ();
|
|
|
|
g_signal_connect_swapped (worker->priv->user_settings,
|
|
"notify::language-name",
|
|
G_CALLBACK (on_saved_language_name_read),
|
|
worker);
|
|
|
|
g_signal_connect_swapped (worker->priv->user_settings,
|
|
"notify::session-name",
|
|
G_CALLBACK (on_saved_session_name_read),
|
|
worker);
|
|
+ g_signal_connect_swapped (worker->priv->user_settings,
|
|
+ "notify::session-type",
|
|
+ G_CALLBACK (on_saved_session_type_read),
|
|
+ worker);
|
|
+
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
gdm_session_worker_handle_setup_for_user (GdmDBusWorker *object,
|
|
GDBusMethodInvocation *invocation,
|
|
const char *service,
|
|
const char *username,
|
|
const char *x11_display_name,
|
|
const char *x11_authority_file,
|
|
const char *console,
|
|
const char *seat_id,
|
|
const char *hostname,
|
|
gboolean display_is_local,
|
|
gboolean display_is_initial)
|
|
{
|
|
GdmSessionWorker *worker = GDM_SESSION_WORKER (object);
|
|
|
|
if (!validate_state_change (worker, invocation, GDM_SESSION_WORKER_STATE_SETUP_COMPLETE))
|
|
return TRUE;
|
|
|
|
worker->priv->service = g_strdup (service);
|
|
worker->priv->x11_display_name = g_strdup (x11_display_name);
|
|
worker->priv->x11_authority_file = g_strdup (x11_authority_file);
|
|
worker->priv->display_device = g_strdup (console);
|
|
worker->priv->display_seat_id = g_strdup (seat_id);
|
|
worker->priv->hostname = g_strdup (hostname);
|
|
worker->priv->display_is_local = display_is_local;
|
|
worker->priv->display_is_initial = display_is_initial;
|
|
worker->priv->username = g_strdup (username);
|
|
|
|
worker->priv->user_settings = gdm_session_settings_new ();
|
|
|
|
g_signal_connect_swapped (worker->priv->user_settings,
|
|
"notify::language-name",
|
|
G_CALLBACK (on_saved_language_name_read),
|
|
worker);
|
|
|
|
g_signal_connect_swapped (worker->priv->user_settings,
|
|
"notify::session-name",
|
|
G_CALLBACK (on_saved_session_name_read),
|
|
worker);
|
|
+ g_signal_connect_swapped (worker->priv->user_settings,
|
|
+ "notify::session-type",
|
|
+ G_CALLBACK (on_saved_session_type_read),
|
|
+ worker);
|
|
|
|
/* Load settings from accounts daemon before continuing
|
|
*/
|
|
worker->priv->pending_invocation = invocation;
|
|
if (gdm_session_settings_load (worker->priv->user_settings, username)) {
|
|
queue_state_change (worker);
|
|
} else {
|
|
g_signal_connect (G_OBJECT (worker->priv->user_settings),
|
|
"notify::is-loaded",
|
|
G_CALLBACK (on_settings_is_loaded_changed),
|
|
worker);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
gdm_session_worker_handle_setup_for_program (GdmDBusWorker *object,
|
|
GDBusMethodInvocation *invocation,
|
|
const char *service,
|
|
const char *username,
|
|
const char *x11_display_name,
|
|
const char *x11_authority_file,
|
|
const char *console,
|
|
const char *seat_id,
|
|
const char *hostname,
|
|
gboolean display_is_local,
|
|
gboolean display_is_initial,
|
|
const char *log_file)
|
|
{
|
|
diff --git a/daemon/gdm-session-worker.xml b/daemon/gdm-session-worker.xml
|
|
index 4280fe095..a215779c8 100644
|
|
--- a/daemon/gdm-session-worker.xml
|
|
+++ b/daemon/gdm-session-worker.xml
|
|
@@ -51,40 +51,43 @@
|
|
<method name="SetupForProgram">
|
|
<arg name="service_name" direction="in" type="s"/>
|
|
<arg name="user_name" direction="in" type="s"/>
|
|
<arg name="x11_display_name" direction="in" type="s"/>
|
|
<arg name="x11_authority_file" direction="in" type="s"/>
|
|
<arg name="display_device" direction="in" type="s"/>
|
|
<arg name="display_seat" direction="in" type="s"/>
|
|
<arg name="hostname" direction="in" type="s"/>
|
|
<arg name="display_is_local" direction="in" type="b"/>
|
|
<arg name="display_is_initial" direction="in" type="b"/>
|
|
<arg name="log_file" direction="in" type="s"/>
|
|
</method>
|
|
<method name="StartReauthentication">
|
|
<arg name="pid_of_caller" direction="in" type="i"/>
|
|
<arg name="uid_of_caller" direction="in" type="i"/>
|
|
<arg name="address" direction="out" type="s"/>
|
|
</method>
|
|
|
|
<signal name="SessionExited">
|
|
<arg name="service_name" type="s" />
|
|
<!-- This is a combination of exit code and exit
|
|
signal. Use macros in sys/wait.h to handle it. -->
|
|
<arg name="status" type="i" />
|
|
</signal>
|
|
<signal name="SavedLanguageNameRead">
|
|
<arg name="language_name" type="s"/>
|
|
</signal>
|
|
<signal name="SavedSessionNameRead">
|
|
<arg name="session_name" type="s"/>
|
|
</signal>
|
|
+ <signal name="SavedSessionTypeRead">
|
|
+ <arg name="session_type" type="s"/>
|
|
+ </signal>
|
|
<signal name="UsernameChanged">
|
|
<arg name="new_username" type="s"/>
|
|
</signal>
|
|
<signal name="Reauthenticated">
|
|
<arg name="service_name" type="s"/>
|
|
</signal>
|
|
<signal name="CancelPendingQuery">
|
|
</signal>
|
|
</interface>
|
|
</node>
|
|
diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c
|
|
index 19d26c92e..e6640aac7 100644
|
|
--- a/daemon/gdm-session.c
|
|
+++ b/daemon/gdm-session.c
|
|
@@ -59,60 +59,61 @@
|
|
|
|
#define GDM_SESSION_DBUS_ERROR_CANCEL "org.gnome.DisplayManager.Session.Error.Cancel"
|
|
#define GDM_SESSION_DBUS_OBJECT_PATH "/org/gnome/DisplayManager/Session"
|
|
|
|
#define GDM_WORKER_DBUS_PATH "/org/gnome/DisplayManager/Worker"
|
|
|
|
typedef struct
|
|
{
|
|
GdmSession *session;
|
|
GdmSessionWorkerJob *job;
|
|
GPid worker_pid;
|
|
char *service_name;
|
|
GDBusMethodInvocation *starting_invocation;
|
|
char *starting_username;
|
|
GDBusMethodInvocation *pending_invocation;
|
|
GdmDBusWorkerManager *worker_manager_interface;
|
|
GdmDBusWorker *worker_proxy;
|
|
GCancellable *worker_cancellable;
|
|
char *session_id;
|
|
guint32 is_stopping : 1;
|
|
|
|
GPid reauth_pid_of_caller;
|
|
} GdmSessionConversation;
|
|
|
|
struct _GdmSessionPrivate
|
|
{
|
|
/* per open scope */
|
|
char *selected_program;
|
|
char *selected_session;
|
|
char *saved_session;
|
|
+ char *saved_session_type;
|
|
char *saved_language;
|
|
char *selected_user;
|
|
char *user_x11_authority_file;
|
|
|
|
char *timed_login_username;
|
|
int timed_login_delay;
|
|
GList *pending_timed_login_invocations;
|
|
|
|
GHashTable *conversations;
|
|
|
|
GdmSessionConversation *session_conversation;
|
|
|
|
char **conversation_environment;
|
|
|
|
GdmDBusUserVerifier *user_verifier_interface;
|
|
GHashTable *user_verifier_extensions;
|
|
GdmDBusGreeter *greeter_interface;
|
|
GdmDBusRemoteGreeter *remote_greeter_interface;
|
|
GdmDBusChooser *chooser_interface;
|
|
|
|
GList *pending_worker_connections;
|
|
GList *outside_connections;
|
|
|
|
GPid session_pid;
|
|
|
|
/* object lifetime scope */
|
|
char *session_type;
|
|
char *display_name;
|
|
char *display_hostname;
|
|
char *display_device;
|
|
@@ -312,295 +313,310 @@ on_establish_credentials_cb (GdmDBusWorker *proxy,
|
|
return;
|
|
|
|
self = g_object_ref (conversation->session);
|
|
service_name = g_strdup (conversation->service_name);
|
|
|
|
if (worked) {
|
|
if (self->priv->user_verifier_interface != NULL) {
|
|
gdm_dbus_user_verifier_emit_verification_complete (self->priv->user_verifier_interface,
|
|
service_name);
|
|
g_signal_emit (self, signals[VERIFICATION_COMPLETE], 0, service_name);
|
|
}
|
|
|
|
switch (self->priv->verification_mode) {
|
|
case GDM_SESSION_VERIFICATION_MODE_LOGIN:
|
|
case GDM_SESSION_VERIFICATION_MODE_CHOOSER:
|
|
gdm_session_open_session (self, service_name);
|
|
break;
|
|
case GDM_SESSION_VERIFICATION_MODE_REAUTHENTICATE:
|
|
default:
|
|
break;
|
|
}
|
|
} else {
|
|
report_and_stop_conversation (self, service_name, error);
|
|
}
|
|
|
|
g_free (service_name);
|
|
g_object_unref (self);
|
|
}
|
|
|
|
static char **
|
|
-get_system_session_dirs (GdmSession *self)
|
|
+get_system_session_dirs (GdmSession *self,
|
|
+ const char *type)
|
|
{
|
|
GArray *search_array = NULL;
|
|
char **search_dirs;
|
|
|
|
static const char *x_search_dirs[] = {
|
|
"/etc/X11/sessions/",
|
|
DMCONFDIR "/Sessions/",
|
|
DATADIR "/gdm/BuiltInSessions/",
|
|
DATADIR "/xsessions/",
|
|
};
|
|
|
|
static const char *wayland_search_dir = DATADIR "/wayland-sessions/";
|
|
|
|
search_array = g_array_new (TRUE, TRUE, sizeof (char *));
|
|
|
|
- g_array_append_vals (search_array, x_search_dirs, G_N_ELEMENTS (x_search_dirs));
|
|
+ if (type == NULL || strcmp (type, "x11") == 0)
|
|
+ g_array_append_vals (search_array, x_search_dirs, G_N_ELEMENTS (x_search_dirs));
|
|
|
|
#ifdef ENABLE_WAYLAND_SUPPORT
|
|
- if (!self->priv->ignore_wayland) {
|
|
+ if ((!self->priv->ignore_wayland && type == NULL) || g_strcmp0 (type, "wayland") == 0) {
|
|
#ifdef ENABLE_USER_DISPLAY_SERVER
|
|
g_array_prepend_val (search_array, wayland_search_dir);
|
|
#else
|
|
g_array_append_val (search_array, wayland_search_dir);
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
search_dirs = g_strdupv ((char **) search_array->data);
|
|
|
|
g_array_free (search_array, TRUE);
|
|
|
|
return search_dirs;
|
|
}
|
|
|
|
static gboolean
|
|
is_prog_in_path (const char *prog)
|
|
{
|
|
char *f;
|
|
gboolean ret;
|
|
|
|
f = g_find_program_in_path (prog);
|
|
ret = (f != NULL);
|
|
g_free (f);
|
|
return ret;
|
|
}
|
|
|
|
static GKeyFile *
|
|
load_key_file_for_file (GdmSession *self,
|
|
const char *file,
|
|
+ const char *type,
|
|
char **full_path)
|
|
{
|
|
GKeyFile *key_file;
|
|
- GError *error;
|
|
+ GError *error = NULL;
|
|
gboolean res;
|
|
char **search_dirs;
|
|
|
|
key_file = g_key_file_new ();
|
|
|
|
- search_dirs = get_system_session_dirs (self),
|
|
+ search_dirs = get_system_session_dirs (self, type);
|
|
+
|
|
error = NULL;
|
|
res = g_key_file_load_from_dirs (key_file,
|
|
file,
|
|
(const char **) search_dirs,
|
|
full_path,
|
|
G_KEY_FILE_NONE,
|
|
&error);
|
|
if (! res) {
|
|
- g_debug ("GdmSession: File '%s' not found: %s", file, error->message);
|
|
- g_error_free (error);
|
|
+ g_debug ("GdmSession: File '%s' not found in search dirs", file);
|
|
+ if (error != NULL) {
|
|
+ g_debug ("GdmSession: %s", error->message);
|
|
+ g_error_free (error);
|
|
+ }
|
|
g_key_file_free (key_file);
|
|
key_file = NULL;
|
|
}
|
|
|
|
g_strfreev (search_dirs);
|
|
|
|
return key_file;
|
|
}
|
|
|
|
static gboolean
|
|
get_session_command_for_file (GdmSession *self,
|
|
const char *file,
|
|
+ const char *type,
|
|
char **command)
|
|
{
|
|
GKeyFile *key_file;
|
|
GError *error;
|
|
char *exec;
|
|
gboolean ret;
|
|
gboolean res;
|
|
|
|
exec = NULL;
|
|
ret = FALSE;
|
|
if (command != NULL) {
|
|
*command = NULL;
|
|
}
|
|
|
|
+ if (self->priv->ignore_wayland && g_strcmp0 (type, "wayland") == 0) {
|
|
+ g_debug ("GdmSession: ignoring wayland session command request for file '%s'",
|
|
+ file);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
g_debug ("GdmSession: getting session command for file '%s'", file);
|
|
- key_file = load_key_file_for_file (self, file, NULL);
|
|
+ key_file = load_key_file_for_file (self, file, type, NULL);
|
|
if (key_file == NULL) {
|
|
goto out;
|
|
}
|
|
|
|
error = NULL;
|
|
res = g_key_file_get_boolean (key_file,
|
|
G_KEY_FILE_DESKTOP_GROUP,
|
|
G_KEY_FILE_DESKTOP_KEY_HIDDEN,
|
|
&error);
|
|
if (error == NULL && res) {
|
|
g_debug ("GdmSession: Session %s is marked as hidden", file);
|
|
goto out;
|
|
}
|
|
|
|
exec = g_key_file_get_string (key_file,
|
|
G_KEY_FILE_DESKTOP_GROUP,
|
|
G_KEY_FILE_DESKTOP_KEY_TRY_EXEC,
|
|
NULL);
|
|
if (exec != NULL) {
|
|
res = is_prog_in_path (exec);
|
|
g_free (exec);
|
|
exec = NULL;
|
|
|
|
if (! res) {
|
|
g_debug ("GdmSession: Command not found: %s",
|
|
G_KEY_FILE_DESKTOP_KEY_TRY_EXEC);
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
error = NULL;
|
|
exec = g_key_file_get_string (key_file,
|
|
G_KEY_FILE_DESKTOP_GROUP,
|
|
G_KEY_FILE_DESKTOP_KEY_EXEC,
|
|
&error);
|
|
if (error != NULL) {
|
|
g_debug ("GdmSession: %s key not found: %s",
|
|
G_KEY_FILE_DESKTOP_KEY_EXEC,
|
|
error->message);
|
|
g_error_free (error);
|
|
goto out;
|
|
}
|
|
|
|
if (command != NULL) {
|
|
*command = g_strdup (exec);
|
|
}
|
|
ret = TRUE;
|
|
|
|
out:
|
|
g_free (exec);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static gboolean
|
|
get_session_command_for_name (GdmSession *self,
|
|
const char *name,
|
|
+ const char *type,
|
|
char **command)
|
|
{
|
|
gboolean res;
|
|
char *filename;
|
|
|
|
filename = g_strdup_printf ("%s.desktop", name);
|
|
- res = get_session_command_for_file (self, filename, command);
|
|
+ res = get_session_command_for_file (self, filename, type, command);
|
|
g_free (filename);
|
|
|
|
return res;
|
|
}
|
|
|
|
static const char *
|
|
get_default_language_name (GdmSession *self)
|
|
{
|
|
const char *default_language;
|
|
|
|
if (self->priv->saved_language != NULL) {
|
|
return self->priv->saved_language;
|
|
}
|
|
|
|
default_language = g_hash_table_lookup (self->priv->environment,
|
|
"LANG");
|
|
|
|
if (default_language != NULL) {
|
|
return default_language;
|
|
}
|
|
|
|
return setlocale (LC_MESSAGES, NULL);
|
|
}
|
|
|
|
static const char *
|
|
get_fallback_session_name (GdmSession *self)
|
|
{
|
|
char **search_dirs;
|
|
int i;
|
|
char *name;
|
|
GSequence *sessions;
|
|
GSequenceIter *session;
|
|
|
|
if (self->priv->fallback_session_name != NULL) {
|
|
/* verify that the cached version still exists */
|
|
- if (get_session_command_for_name (self, self->priv->fallback_session_name, NULL)) {
|
|
+ if (get_session_command_for_name (self, self->priv->fallback_session_name, NULL, NULL)) {
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
name = g_strdup ("gnome");
|
|
- if (get_session_command_for_name (self, name, NULL)) {
|
|
+ if (get_session_command_for_name (self, name, NULL, NULL)) {
|
|
g_free (self->priv->fallback_session_name);
|
|
self->priv->fallback_session_name = name;
|
|
goto out;
|
|
}
|
|
g_free (name);
|
|
|
|
sessions = g_sequence_new (g_free);
|
|
|
|
- search_dirs = get_system_session_dirs (self);
|
|
+ search_dirs = get_system_session_dirs (self, NULL);
|
|
for (i = 0; search_dirs[i] != NULL; i++) {
|
|
GDir *dir;
|
|
const char *base_name;
|
|
|
|
dir = g_dir_open (search_dirs[i], 0, NULL);
|
|
|
|
if (dir == NULL) {
|
|
continue;
|
|
}
|
|
|
|
do {
|
|
base_name = g_dir_read_name (dir);
|
|
|
|
if (base_name == NULL) {
|
|
break;
|
|
}
|
|
|
|
if (!g_str_has_suffix (base_name, ".desktop")) {
|
|
continue;
|
|
}
|
|
|
|
- if (get_session_command_for_file (self, base_name, NULL)) {
|
|
+ if (get_session_command_for_file (self, base_name, NULL, NULL)) {
|
|
name = g_strndup (base_name, strlen (base_name) - strlen (".desktop"));
|
|
g_sequence_insert_sorted (sessions, name, (GCompareDataFunc) g_strcmp0, NULL);
|
|
}
|
|
} while (base_name != NULL);
|
|
|
|
g_dir_close (dir);
|
|
}
|
|
g_strfreev (search_dirs);
|
|
|
|
name = NULL;
|
|
session = g_sequence_get_begin_iter (sessions);
|
|
|
|
if (g_sequence_iter_is_end (session))
|
|
g_error ("GdmSession: no session desktop files installed, aborting...");
|
|
|
|
do {
|
|
name = g_sequence_get (session);
|
|
if (name) {
|
|
break;
|
|
}
|
|
session = g_sequence_iter_next (session);
|
|
} while (!g_sequence_iter_is_end (session));
|
|
|
|
g_free (self->priv->fallback_session_name);
|
|
self->priv->fallback_session_name = g_strdup (name);
|
|
|
|
g_sequence_free (sessions);
|
|
|
|
out:
|
|
return self->priv->fallback_session_name;
|
|
@@ -616,60 +632,63 @@ get_default_session_name (GdmSession *self)
|
|
return get_fallback_session_name (self);
|
|
}
|
|
|
|
static void
|
|
gdm_session_defaults_changed (GdmSession *self)
|
|
{
|
|
|
|
update_session_type (self);
|
|
|
|
if (self->priv->greeter_interface != NULL) {
|
|
gdm_dbus_greeter_emit_default_language_name_changed (self->priv->greeter_interface,
|
|
get_default_language_name (self));
|
|
gdm_dbus_greeter_emit_default_session_name_changed (self->priv->greeter_interface,
|
|
get_default_session_name (self));
|
|
}
|
|
}
|
|
|
|
void
|
|
gdm_session_select_user (GdmSession *self,
|
|
const char *text)
|
|
{
|
|
|
|
g_debug ("GdmSession: Setting user: '%s'", text);
|
|
|
|
g_free (self->priv->selected_user);
|
|
self->priv->selected_user = g_strdup (text);
|
|
|
|
g_free (self->priv->saved_session);
|
|
self->priv->saved_session = NULL;
|
|
|
|
+ g_free (self->priv->saved_session_type);
|
|
+ self->priv->saved_session_type = NULL;
|
|
+
|
|
g_free (self->priv->saved_language);
|
|
self->priv->saved_language = NULL;
|
|
}
|
|
|
|
static void
|
|
cancel_pending_query (GdmSessionConversation *conversation)
|
|
{
|
|
if (conversation->pending_invocation == NULL) {
|
|
return;
|
|
}
|
|
|
|
g_debug ("GdmSession: Cancelling pending query");
|
|
|
|
g_dbus_method_invocation_return_dbus_error (conversation->pending_invocation,
|
|
GDM_SESSION_DBUS_ERROR_CANCEL,
|
|
"Operation cancelled");
|
|
conversation->pending_invocation = NULL;
|
|
}
|
|
|
|
static void
|
|
answer_pending_query (GdmSessionConversation *conversation,
|
|
const char *answer)
|
|
{
|
|
g_dbus_method_invocation_return_value (conversation->pending_invocation,
|
|
g_variant_new ("(s)", answer));
|
|
conversation->pending_invocation = NULL;
|
|
}
|
|
|
|
static void
|
|
set_pending_query (GdmSessionConversation *conversation,
|
|
@@ -936,80 +955,91 @@ worker_on_reauthenticated (GdmDBusWorker *worker,
|
|
GdmSession *self = conversation->session;
|
|
g_debug ("GdmSession: Emitting 'reauthenticated' signal ");
|
|
g_signal_emit (self, signals[REAUTHENTICATED], 0, service_name);
|
|
}
|
|
|
|
static void
|
|
worker_on_saved_language_name_read (GdmDBusWorker *worker,
|
|
const char *language_name,
|
|
GdmSessionConversation *conversation)
|
|
{
|
|
GdmSession *self = conversation->session;
|
|
|
|
if (strlen (language_name) > 0) {
|
|
g_free (self->priv->saved_language);
|
|
self->priv->saved_language = g_strdup (language_name);
|
|
|
|
if (self->priv->greeter_interface != NULL) {
|
|
gdm_dbus_greeter_emit_default_language_name_changed (self->priv->greeter_interface,
|
|
language_name);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
worker_on_saved_session_name_read (GdmDBusWorker *worker,
|
|
const char *session_name,
|
|
GdmSessionConversation *conversation)
|
|
{
|
|
GdmSession *self = conversation->session;
|
|
|
|
- if (! get_session_command_for_name (self, session_name, NULL)) {
|
|
+ if (! get_session_command_for_name (self, session_name, self->priv->saved_session_type, NULL)) {
|
|
/* ignore sessions that don't exist */
|
|
g_debug ("GdmSession: not using invalid .dmrc session: %s", session_name);
|
|
g_free (self->priv->saved_session);
|
|
self->priv->saved_session = NULL;
|
|
} else if (strcmp (session_name,
|
|
get_default_session_name (self)) != 0) {
|
|
g_free (self->priv->saved_session);
|
|
self->priv->saved_session = g_strdup (session_name);
|
|
|
|
if (self->priv->greeter_interface != NULL) {
|
|
gdm_dbus_greeter_emit_default_session_name_changed (self->priv->greeter_interface,
|
|
session_name);
|
|
}
|
|
}
|
|
|
|
update_session_type (self);
|
|
|
|
}
|
|
|
|
+static void
|
|
+worker_on_saved_session_type_read (GdmDBusWorker *worker,
|
|
+ const char *session_type,
|
|
+ GdmSessionConversation *conversation)
|
|
+{
|
|
+ GdmSession *self = conversation->session;
|
|
+
|
|
+ g_free (self->priv->saved_session_type);
|
|
+ self->priv->saved_session_type = g_strdup (session_type);
|
|
+}
|
|
+
|
|
static GdmSessionConversation *
|
|
find_conversation_by_pid (GdmSession *self,
|
|
GPid pid)
|
|
{
|
|
GHashTableIter iter;
|
|
gpointer key, value;
|
|
|
|
g_hash_table_iter_init (&iter, self->priv->conversations);
|
|
while (g_hash_table_iter_next (&iter, &key, &value)) {
|
|
GdmSessionConversation *conversation;
|
|
|
|
conversation = (GdmSessionConversation *) value;
|
|
|
|
if (conversation->worker_pid == pid) {
|
|
return conversation;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static gboolean
|
|
allow_worker_function (GDBusAuthObserver *observer,
|
|
GIOStream *stream,
|
|
GCredentials *credentials,
|
|
GdmSession *self)
|
|
{
|
|
uid_t connecting_user;
|
|
|
|
connecting_user = g_credentials_get_unix_user (credentials, NULL);
|
|
@@ -1089,60 +1119,63 @@ register_worker (GdmDBusWorkerManager *worker_manager_interface,
|
|
g_dbus_method_invocation_return_value (invocation, NULL);
|
|
|
|
conversation->worker_proxy = gdm_dbus_worker_proxy_new_sync (connection,
|
|
G_DBUS_PROXY_FLAGS_NONE,
|
|
NULL,
|
|
GDM_WORKER_DBUS_PATH,
|
|
NULL, NULL);
|
|
/* drop the reference we stole from the pending connections list
|
|
* since the proxy owns the connection now */
|
|
g_object_unref (connection);
|
|
|
|
g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (conversation->worker_proxy), G_MAXINT);
|
|
|
|
conversation->worker_cancellable = g_cancellable_new ();
|
|
|
|
g_signal_connect (conversation->worker_proxy,
|
|
"username-changed",
|
|
G_CALLBACK (worker_on_username_changed), conversation);
|
|
g_signal_connect (conversation->worker_proxy,
|
|
"session-exited",
|
|
G_CALLBACK (worker_on_session_exited), conversation);
|
|
g_signal_connect (conversation->worker_proxy,
|
|
"reauthenticated",
|
|
G_CALLBACK (worker_on_reauthenticated), conversation);
|
|
g_signal_connect (conversation->worker_proxy,
|
|
"saved-language-name-read",
|
|
G_CALLBACK (worker_on_saved_language_name_read), conversation);
|
|
g_signal_connect (conversation->worker_proxy,
|
|
"saved-session-name-read",
|
|
G_CALLBACK (worker_on_saved_session_name_read), conversation);
|
|
+ g_signal_connect (conversation->worker_proxy,
|
|
+ "saved-session-type-read",
|
|
+ G_CALLBACK (worker_on_saved_session_type_read), conversation);
|
|
g_signal_connect (conversation->worker_proxy,
|
|
"cancel-pending-query",
|
|
G_CALLBACK (worker_on_cancel_pending_query), conversation);
|
|
|
|
conversation->worker_manager_interface = g_object_ref (worker_manager_interface);
|
|
g_debug ("GdmSession: worker connection is %p", connection);
|
|
|
|
g_debug ("GdmSession: Emitting conversation-started signal");
|
|
g_signal_emit (self, signals[CONVERSATION_STARTED], 0, conversation->service_name);
|
|
|
|
if (self->priv->user_verifier_interface != NULL) {
|
|
gdm_dbus_user_verifier_emit_conversation_started (self->priv->user_verifier_interface,
|
|
conversation->service_name);
|
|
}
|
|
|
|
if (conversation->starting_invocation != NULL) {
|
|
if (conversation->starting_username != NULL) {
|
|
gdm_session_setup_for_user (self, conversation->service_name, conversation->starting_username);
|
|
|
|
g_clear_pointer (&conversation->starting_username,
|
|
(GDestroyNotify)
|
|
g_free);
|
|
} else {
|
|
gdm_session_setup (self, conversation->service_name);
|
|
}
|
|
}
|
|
|
|
g_debug ("GdmSession: Conversation started");
|
|
|
|
return TRUE;
|
|
@@ -1804,60 +1837,63 @@ static void
|
|
free_conversation (GdmSessionConversation *conversation)
|
|
{
|
|
if (conversation->job != NULL) {
|
|
g_warning ("Freeing conversation '%s' with active job", conversation->service_name);
|
|
}
|
|
|
|
g_free (conversation->service_name);
|
|
g_free (conversation->starting_username);
|
|
g_free (conversation->session_id);
|
|
g_clear_object (&conversation->worker_manager_interface);
|
|
|
|
g_cancellable_cancel (conversation->worker_cancellable);
|
|
g_clear_object (&conversation->worker_cancellable);
|
|
|
|
if (conversation->worker_proxy != NULL) {
|
|
g_signal_handlers_disconnect_by_func (conversation->worker_proxy,
|
|
G_CALLBACK (worker_on_username_changed),
|
|
conversation);
|
|
g_signal_handlers_disconnect_by_func (conversation->worker_proxy,
|
|
G_CALLBACK (worker_on_session_exited),
|
|
conversation);
|
|
g_signal_handlers_disconnect_by_func (conversation->worker_proxy,
|
|
G_CALLBACK (worker_on_reauthenticated),
|
|
conversation);
|
|
g_signal_handlers_disconnect_by_func (conversation->worker_proxy,
|
|
G_CALLBACK (worker_on_saved_language_name_read),
|
|
conversation);
|
|
g_signal_handlers_disconnect_by_func (conversation->worker_proxy,
|
|
G_CALLBACK (worker_on_saved_session_name_read),
|
|
conversation);
|
|
+ g_signal_handlers_disconnect_by_func (conversation->worker_proxy,
|
|
+ G_CALLBACK (worker_on_saved_session_type_read),
|
|
+ conversation);
|
|
g_signal_handlers_disconnect_by_func (conversation->worker_proxy,
|
|
G_CALLBACK (worker_on_cancel_pending_query),
|
|
conversation);
|
|
g_clear_object (&conversation->worker_proxy);
|
|
}
|
|
g_clear_object (&conversation->session);
|
|
g_free (conversation);
|
|
}
|
|
|
|
static void
|
|
load_lang_config_file (GdmSession *self)
|
|
{
|
|
static const char *config_file = LANG_CONFIG_FILE;
|
|
gchar *contents = NULL;
|
|
gchar *p;
|
|
gchar *key;
|
|
gchar *value;
|
|
gsize length;
|
|
GError *error;
|
|
GString *line;
|
|
GRegex *re;
|
|
|
|
if (!g_file_test (config_file, G_FILE_TEST_EXISTS)) {
|
|
g_debug ("Cannot access '%s'", config_file);
|
|
return;
|
|
}
|
|
|
|
error = NULL;
|
|
if (!g_file_get_contents (config_file, &contents, &length, &error)) {
|
|
g_debug ("Failed to parse '%s': %s",
|
|
@@ -2412,83 +2448,83 @@ gdm_session_send_environment (GdmSession *self,
|
|
g_return_if_fail (GDM_IS_SESSION (self));
|
|
|
|
conversation = find_conversation_by_name (self, service_name);
|
|
if (conversation != NULL) {
|
|
send_environment (self, conversation);
|
|
}
|
|
}
|
|
|
|
static const char *
|
|
get_session_name (GdmSession *self)
|
|
{
|
|
/* FIXME: test the session names before we use them? */
|
|
|
|
if (self->priv->selected_session != NULL) {
|
|
return self->priv->selected_session;
|
|
}
|
|
|
|
return get_default_session_name (self);
|
|
}
|
|
|
|
static char *
|
|
get_session_command (GdmSession *self)
|
|
{
|
|
gboolean res;
|
|
char *command;
|
|
const char *session_name;
|
|
|
|
session_name = get_session_name (self);
|
|
|
|
command = NULL;
|
|
- res = get_session_command_for_name (self, session_name, &command);
|
|
+ res = get_session_command_for_name (self, session_name, NULL, &command);
|
|
if (! res) {
|
|
g_critical ("Cannot find a command for specified session: %s", session_name);
|
|
exit (EXIT_FAILURE);
|
|
}
|
|
|
|
return command;
|
|
}
|
|
|
|
static gchar *
|
|
get_session_desktop_names (GdmSession *self)
|
|
{
|
|
gchar *filename;
|
|
GKeyFile *keyfile;
|
|
gchar *desktop_names = NULL;
|
|
|
|
if (self->priv->selected_program != NULL) {
|
|
return g_strdup ("GNOME-Greeter:GNOME");
|
|
}
|
|
|
|
filename = g_strdup_printf ("%s.desktop", get_session_name (self));
|
|
g_debug ("GdmSession: getting desktop names for file '%s'", filename);
|
|
- keyfile = load_key_file_for_file (self, filename, NULL);
|
|
+ keyfile = load_key_file_for_file (self, filename, NULL, NULL);
|
|
if (keyfile != NULL) {
|
|
gchar **names;
|
|
|
|
names = g_key_file_get_string_list (keyfile, G_KEY_FILE_DESKTOP_GROUP,
|
|
"DesktopNames", NULL, NULL);
|
|
if (names != NULL) {
|
|
desktop_names = g_strjoinv (":", names);
|
|
|
|
g_strfreev (names);
|
|
}
|
|
}
|
|
|
|
g_key_file_free (keyfile);
|
|
g_free (filename);
|
|
return desktop_names;
|
|
}
|
|
|
|
void
|
|
gdm_session_set_environment_variable (GdmSession *self,
|
|
const char *key,
|
|
const char *value)
|
|
{
|
|
g_return_if_fail (key != NULL);
|
|
g_return_if_fail (value != NULL);
|
|
|
|
g_hash_table_replace (self->priv->environment,
|
|
g_strdup (key),
|
|
g_strdup (value));
|
|
}
|
|
|
|
@@ -3008,115 +3044,117 @@ gdm_session_get_conversation_session_id (GdmSession *self,
|
|
|
|
conversation = find_conversation_by_name (self, service_name);
|
|
|
|
if (conversation == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
return conversation->session_id;
|
|
}
|
|
|
|
static char *
|
|
get_session_filename (GdmSession *self)
|
|
{
|
|
return g_strdup_printf ("%s.desktop", get_session_name (self));
|
|
}
|
|
|
|
#ifdef ENABLE_WAYLAND_SUPPORT
|
|
static gboolean
|
|
gdm_session_is_wayland_session (GdmSession *self)
|
|
{
|
|
GKeyFile *key_file;
|
|
gboolean is_wayland_session = FALSE;
|
|
char *filename;
|
|
char *full_path = NULL;
|
|
|
|
g_return_val_if_fail (self != NULL, FALSE);
|
|
g_return_val_if_fail (GDM_IS_SESSION (self), FALSE);
|
|
|
|
filename = get_session_filename (self);
|
|
|
|
- key_file = load_key_file_for_file (self, filename, &full_path);
|
|
+ key_file = load_key_file_for_file (self, filename, "wayland", &full_path);
|
|
|
|
if (key_file == NULL) {
|
|
goto out;
|
|
}
|
|
|
|
if (full_path != NULL && strstr (full_path, "/wayland-sessions/") != NULL) {
|
|
is_wayland_session = TRUE;
|
|
}
|
|
g_debug ("GdmSession: checking if file '%s' is wayland session: %s", filename, is_wayland_session? "yes" : "no");
|
|
|
|
out:
|
|
g_clear_pointer (&key_file, (GDestroyNotify) g_key_file_free);
|
|
g_free (filename);
|
|
return is_wayland_session;
|
|
}
|
|
#endif
|
|
|
|
static void
|
|
update_session_type (GdmSession *self)
|
|
{
|
|
#ifdef ENABLE_WAYLAND_SUPPORT
|
|
- gboolean is_wayland_session;
|
|
+ gboolean is_wayland_session = FALSE;
|
|
+
|
|
+ if (!self->priv->ignore_wayland)
|
|
+ is_wayland_session = gdm_session_is_wayland_session (self);
|
|
|
|
- is_wayland_session = gdm_session_is_wayland_session (self);
|
|
if (is_wayland_session) {
|
|
set_session_type (self, "wayland");
|
|
} else {
|
|
set_session_type (self, NULL);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
gboolean
|
|
gdm_session_bypasses_xsession (GdmSession *self)
|
|
{
|
|
GError *error;
|
|
GKeyFile *key_file;
|
|
gboolean res;
|
|
gboolean bypasses_xsession = FALSE;
|
|
char *filename = NULL;
|
|
|
|
g_return_val_if_fail (self != NULL, FALSE);
|
|
g_return_val_if_fail (GDM_IS_SESSION (self), FALSE);
|
|
|
|
#ifdef ENABLE_WAYLAND_SUPPORT
|
|
if (gdm_session_is_wayland_session (self)) {
|
|
bypasses_xsession = TRUE;
|
|
goto out;
|
|
}
|
|
#endif
|
|
|
|
filename = get_session_filename (self);
|
|
|
|
- key_file = load_key_file_for_file (self, filename, NULL);
|
|
+ key_file = load_key_file_for_file (self, filename, "x11", NULL);
|
|
|
|
error = NULL;
|
|
res = g_key_file_has_key (key_file, G_KEY_FILE_DESKTOP_GROUP, "X-GDM-BypassXsession", NULL);
|
|
if (!res) {
|
|
goto out;
|
|
} else {
|
|
bypasses_xsession = g_key_file_get_boolean (key_file, G_KEY_FILE_DESKTOP_GROUP, "X-GDM-BypassXsession", &error);
|
|
if (error) {
|
|
bypasses_xsession = FALSE;
|
|
g_error_free (error);
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
out:
|
|
if (bypasses_xsession) {
|
|
g_debug ("GdmSession: Session %s bypasses Xsession wrapper script", filename);
|
|
}
|
|
g_free (filename);
|
|
return bypasses_xsession;
|
|
}
|
|
|
|
GdmSessionDisplayMode
|
|
gdm_session_get_display_mode (GdmSession *self)
|
|
{
|
|
g_debug ("GdmSession: type %s, program? %s, seat %s",
|
|
self->priv->session_type,
|
|
self->priv->is_program_session? "yes" : "no",
|
|
self->priv->display_seat_id);
|
|
|
|
--
|
|
2.17.1
|
|
|