Blob Blame Raw
From c66cee942242a731082f0fac649f3f9569ae99a3 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Wed, 8 Aug 2018 16:11:56 -0400
Subject: [PATCH 1/2] user: add new Session/SessionType properties to replace
 XSession

Having a property called XSession in the API makes little
sense when wayland has taken the world by storm.

This commit adds new "Session" property without the "X" in the name,
and an additional property "SessionType" that can be either
"wayland" or "x11".
---
 data/org.freedesktop.Accounts.User.xml | 103 +++++++++++++++++++++
 src/libaccountsservice/act-user.c      |  93 +++++++++++++++++++
 src/libaccountsservice/act-user.h      |   6 ++
 src/user.c                             | 121 +++++++++++++++++++++++++
 4 files changed, 323 insertions(+)

diff --git a/data/org.freedesktop.Accounts.User.xml b/data/org.freedesktop.Accounts.User.xml
index 4ab989a..7fc3c61 100644
--- a/data/org.freedesktop.Accounts.User.xml
+++ b/data/org.freedesktop.Accounts.User.xml
@@ -141,60 +141,143 @@
             <doc:term>org.freedesktop.accounts.user-administration</doc:term>
             <doc:definition>To change the language of another user</doc:definition>
           </doc:item>
         </doc:list>
       </doc:permission>
       <doc:errors>
         <doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
         <doc:error name="org.freedesktop.Accounts.Error.Failed">if the operation failed</doc:error>
       </doc:errors>
     </doc:doc>
   </method>
 
   <method name="SetXSession">
     <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
     <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="user_set_x_session"/>
     <arg name="x_session" direction="in" type="s">
       <doc:doc>
         <doc:summary>
           The new xsession to start (e.g. "gnome")
         </doc:summary>
       </doc:doc>
     </arg>
     <doc:doc>
       <doc:description>
         <doc:para>
           Sets the users x session.
         </doc:para>
         <doc:para>
           The expectation is that display managers will log the user in to this
           specified session, if available.
+
+          Note this call is deprecated and has been superceded by SetSession since
+          not all graphical sessions use X as the display server.
+        </doc:para>
+      </doc:description>
+      <doc:permission>
+        The caller needs one of the following PolicyKit authorizations:
+        <doc:list>
+          <doc:item>
+            <doc:term>org.freedesktop.accounts.change-own-user-data</doc:term>
+            <doc:definition>To change his own language</doc:definition>
+          </doc:item>
+          <doc:item>
+            <doc:term>org.freedesktop.accounts.user-administration</doc:term>
+            <doc:definition>To change the language of another user</doc:definition>
+          </doc:item>
+        </doc:list>
+      </doc:permission>
+      <doc:errors>
+        <doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
+        <doc:error name="org.freedesktop.Accounts.Error.Failed">if the operation failed</doc:error>
+      </doc:errors>
+   </doc:doc>
+  </method>
+
+  <method name="SetSession">
+    <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+    <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="user_set_session"/>
+    <arg name="session" direction="in" type="s">
+      <doc:doc>
+        <doc:summary>
+          The new session to start (e.g. "gnome-xorg")
+        </doc:summary>
+      </doc:doc>
+    </arg>
+    <doc:doc>
+      <doc:description>
+        <doc:para>
+          Sets the users wayland or x session.
+        </doc:para>
+        <doc:para>
+          The expectation is that display managers will log the user in to this
+          specified session, if available.
+        </doc:para>
+      </doc:description>
+      <doc:permission>
+        The caller needs one of the following PolicyKit authorizations:
+        <doc:list>
+          <doc:item>
+            <doc:term>org.freedesktop.accounts.change-own-user-data</doc:term>
+            <doc:definition>To change his own language</doc:definition>
+          </doc:item>
+          <doc:item>
+            <doc:term>org.freedesktop.accounts.user-administration</doc:term>
+            <doc:definition>To change the language of another user</doc:definition>
+          </doc:item>
+        </doc:list>
+      </doc:permission>
+      <doc:errors>
+        <doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
+        <doc:error name="org.freedesktop.Accounts.Error.Failed">if the operation failed</doc:error>
+      </doc:errors>
+   </doc:doc>
+  </method>
+
+  <method name="SetSessionType">
+    <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+    <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="user_set_session_type"/>
+    <arg name="session_type" direction="in" type="s">
+      <doc:doc>
+        <doc:summary>
+          The type of the new session to start (e.g. "wayland" or "x11")
+        </doc:summary>
+      </doc:doc>
+    </arg>
+    <doc:doc>
+      <doc:description>
+        <doc:para>
+          Sets the session type of the users session.
+        </doc:para>
+        <doc:para>
+          Display managers may use this property to decide what type of display server to use when
+          loading the session
         </doc:para>
       </doc:description>
       <doc:permission>
         The caller needs one of the following PolicyKit authorizations:
         <doc:list>
           <doc:item>
             <doc:term>org.freedesktop.accounts.change-own-user-data</doc:term>
             <doc:definition>To change his own language</doc:definition>
           </doc:item>
           <doc:item>
             <doc:term>org.freedesktop.accounts.user-administration</doc:term>
             <doc:definition>To change the language of another user</doc:definition>
           </doc:item>
         </doc:list>
       </doc:permission>
       <doc:errors>
         <doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
         <doc:error name="org.freedesktop.Accounts.Error.Failed">if the operation failed</doc:error>
       </doc:errors>
    </doc:doc>
   </method>
 
   <method name="SetLocation">
     <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
     <arg name="location" direction="in" type="s">
       <doc:doc>
         <doc:summary>
           The new location as a freeform string.
         </doc:summary>
       </doc:doc>
@@ -641,60 +724,80 @@
   <property name="Shell" type="s" access="read">
     <doc:doc>
       <doc:description>
         <doc:para>
           The users shell.
         </doc:para>
       </doc:description>
     </doc:doc>
   </property>
 
   <property name="Email" type="s" access="read">
     <doc:doc>
       <doc:description>
         <doc:para>
           The email address.
         </doc:para>
       </doc:description>
     </doc:doc>
   </property>
 
   <property name="Language" type="s" access="read">
     <doc:doc>
       <doc:description>
         <doc:para>
           The users language, as a locale specification like "de_DE.UTF-8".
         </doc:para>
       </doc:description>
     </doc:doc>
   </property>
 
+  <property name="Session" type="s" access="read">
+    <doc:doc>
+      <doc:description>
+        <doc:para>
+          The users Wayland or X session.
+        </doc:para>
+      </doc:description>
+    </doc:doc>
+  </property>
+
+  <property name="SessionType" type="s" access="read">
+    <doc:doc>
+      <doc:description>
+        <doc:para>
+          The type of session the user should use (e.g. "wayland" or "x11")
+        </doc:para>
+      </doc:description>
+    </doc:doc>
+  </property>
+
   <property name="XSession" type="s" access="read">
     <doc:doc>
       <doc:description>
         <doc:para>
           The users x session.
         </doc:para>
       </doc:description>
     </doc:doc>
   </property>
 
   <property name="Location" type="s" access="read">
     <doc:doc>
       <doc:description>
         <doc:para>
           The users location.
         </doc:para>
       </doc:description>
     </doc:doc>
   </property>
 
   <property name="LoginFrequency" type="t" access="read">
     <doc:doc>
       <doc:description>
         <doc:para>
           How often the user has logged in.
         </doc:para>
       </doc:description>
     </doc:doc>
   </property>
 
diff --git a/src/libaccountsservice/act-user.c b/src/libaccountsservice/act-user.c
index 7162221..dd8f81b 100644
--- a/src/libaccountsservice/act-user.c
+++ b/src/libaccountsservice/act-user.c
@@ -999,60 +999,98 @@ act_user_get_icon_file (ActUser *user)
 const char *
 act_user_get_language (ActUser *user)
 {
         g_return_val_if_fail (ACT_IS_USER (user), NULL);
 
         if (user->accounts_proxy == NULL)
                 return NULL;
 
         return accounts_user_get_language (user->accounts_proxy);
 }
 
 /**
  * act_user_get_x_session:
  * @user: a #ActUser
  *
  * Returns the path to the configured X session for @user.
  *
  * Returns: (transfer none): a path to an icon
  */
 const char *
 act_user_get_x_session (ActUser *user)
 {
         g_return_val_if_fail (ACT_IS_USER (user), NULL);
 
         if (user->accounts_proxy == NULL)
                 return NULL;
 
         return accounts_user_get_xsession (user->accounts_proxy);
 }
 
+/**
+ * act_user_get_session:
+ * @user: a #ActUser
+ *
+ * Returns the path to the configured session for @user.
+ *
+ * Returns: (transfer none): a path to an icon
+ */
+const char *
+act_user_get_session (ActUser *user)
+{
+        g_return_val_if_fail (ACT_IS_USER (user), NULL);
+
+        if (user->accounts_proxy == NULL)
+                return NULL;
+
+        return accounts_user_get_session (user->accounts_proxy);
+}
+
+/**
+ * act_user_get_session_type:
+ * @user: a #ActUser
+ *
+ * Returns the type of the configured session for @user.
+ *
+ * Returns: (transfer none): a path to an icon
+ */
+const char *
+act_user_get_session_type (ActUser *user)
+{
+        g_return_val_if_fail (ACT_IS_USER (user), NULL);
+
+        if (user->accounts_proxy == NULL)
+                return NULL;
+
+        return accounts_user_get_session_type (user->accounts_proxy);
+}
+
 /**
  * act_user_get_object_path:
  * @user: a #ActUser
  *
  * Returns the user accounts service object path of @user,
  * or %NULL if @user doesn't have an object path associated
  * with it.
  *
  * Returns: (transfer none): the object path of the user
  */
 const char *
 act_user_get_object_path (ActUser *user)
 {
         g_return_val_if_fail (ACT_IS_USER (user), NULL);
 
         if (user->accounts_proxy == NULL)
                 return NULL;
 
         return g_dbus_proxy_get_object_path (G_DBUS_PROXY (user->accounts_proxy));
 }
 
 /**
  * act_user_get_primary_session_id:
  * @user: a #ActUser
  *
  * Returns the id of the primary session of @user, or %NULL if @user
  * has no primary session.  The primary session will always be
  * graphical and will be chosen from the sessions on the same seat as
  * the seat of the session of the calling process.
  *
@@ -1310,60 +1348,115 @@ act_user_set_language (ActUser    *user,
 }
 
 /**
  * act_user_set_x_session:
  * @user: the user object to alter.
  * @x_session: an x session (e.g. gnome)
  *
  * Assigns a new x session for @user.
  *
  * Note this function is synchronous and ignores errors.
  **/
 void
 act_user_set_x_session (ActUser    *user,
                         const char *x_session)
 {
         g_autoptr(GError) error = NULL;
 
         g_return_if_fail (ACT_IS_USER (user));
         g_return_if_fail (x_session != NULL);
         g_return_if_fail (ACCOUNTS_IS_USER (user->accounts_proxy));
 
         if (!accounts_user_call_set_xsession_sync (user->accounts_proxy,
                                                    x_session,
                                                    NULL,
                                                    &error)) {
                 g_warning ("SetXSession call failed: %s", error->message);
                 return;
         }
 }
 
+/**
+ * act_user_set_session:
+ * @user: the user object to alter.
+ * @session: a session (e.g. gnome)
+ *
+ * Assigns a new session for @user.
+ *
+ * Note this function is synchronous and ignores errors.
+ **/
+void
+act_user_set_session (ActUser    *user,
+                      const char *session)
+{
+        g_autoptr(GError) error = NULL;
+
+        g_return_if_fail (ACT_IS_USER (user));
+        g_return_if_fail (session != NULL);
+        g_return_if_fail (ACCOUNTS_IS_USER (user->accounts_proxy));
+
+        if (!accounts_user_call_set_session_sync (user->accounts_proxy,
+                                                  session,
+                                                  NULL,
+                                                  &error)) {
+                g_warning ("SetSession call failed: %s", error->message);
+                return;
+        }
+}
+
+/**
+ * act_user_set_session_type:
+ * @user: the user object to alter.
+ * @session_type: a type of session (e.g. "wayland" or "x11")
+ *
+ * Assigns a type to the session for @user.
+ *
+ * Note this function is synchronous and ignores errors.
+ **/
+void
+act_user_set_session_type (ActUser    *user,
+                           const char *session_type)
+{
+        g_autoptr(GError) error = NULL;
+
+        g_return_if_fail (ACT_IS_USER (user));
+        g_return_if_fail (session_type != NULL);
+        g_return_if_fail (ACCOUNTS_IS_USER (user->accounts_proxy));
+
+        if (!accounts_user_call_set_session_type_sync (user->accounts_proxy,
+                                                       session_type,
+                                                       NULL,
+                                                       &error)) {
+                g_warning ("SetSessionType call failed: %s", error->message);
+                return;
+        }
+}
 
 /**
  * act_user_set_location:
  * @user: the user object to alter.
  * @location: a location
  *
  * Assigns a new location for @user.
  *
  * Note this function is synchronous and ignores errors.
  **/
 void
 act_user_set_location (ActUser    *user,
                        const char *location)
 {
         g_autoptr(GError) error = NULL;
 
         g_return_if_fail (ACT_IS_USER (user));
         g_return_if_fail (location != NULL);
         g_return_if_fail (ACCOUNTS_IS_USER (user->accounts_proxy));
 
         if (!accounts_user_call_set_location_sync (user->accounts_proxy,
                                                    location,
                                                    NULL,
                                                    &error)) {
                 g_warning ("SetLocation call failed: %s", error->message);
                 return;
         }
 }
 
 /**
diff --git a/src/libaccountsservice/act-user.h b/src/libaccountsservice/act-user.h
index c685fcc..2ef13b1 100644
--- a/src/libaccountsservice/act-user.h
+++ b/src/libaccountsservice/act-user.h
@@ -51,79 +51,85 @@ typedef struct _ActUserClass ActUserClass;
 
 GType          act_user_get_type                  (void) G_GNUC_CONST;
 
 const char    *act_user_get_object_path           (ActUser *user);
 
 uid_t          act_user_get_uid                   (ActUser   *user);
 const char    *act_user_get_user_name             (ActUser   *user);
 const char    *act_user_get_real_name             (ActUser   *user);
 ActUserAccountType act_user_get_account_type      (ActUser   *user);
 ActUserPasswordMode act_user_get_password_mode    (ActUser   *user);
 const char    *act_user_get_password_hint         (ActUser   *user);
 const char    *act_user_get_home_dir              (ActUser   *user);
 const char    *act_user_get_shell                 (ActUser   *user);
 const char    *act_user_get_email                 (ActUser   *user);
 const char    *act_user_get_location              (ActUser   *user);
 guint          act_user_get_num_sessions          (ActUser   *user);
 guint          act_user_get_num_sessions_anywhere (ActUser   *user);
 gboolean       act_user_is_logged_in              (ActUser   *user);
 gboolean       act_user_is_logged_in_anywhere     (ActUser   *user);
 int            act_user_get_login_frequency       (ActUser   *user);
 gint64         act_user_get_login_time            (ActUser   *user);
 const GVariant*act_user_get_login_history         (ActUser   *user);
 gboolean       act_user_get_locked                (ActUser   *user);
 gboolean       act_user_get_automatic_login       (ActUser   *user);
 gboolean       act_user_is_system_account         (ActUser   *user);
 gboolean       act_user_is_local_account          (ActUser   *user);
 gboolean       act_user_is_nonexistent            (ActUser   *user);
 const char    *act_user_get_icon_file             (ActUser   *user);
 const char    *act_user_get_language              (ActUser   *user);
 const char    *act_user_get_x_session             (ActUser   *user);
+const char    *act_user_get_session               (ActUser   *user);
+const char    *act_user_get_session_type          (ActUser   *user);
 const char    *act_user_get_primary_session_id    (ActUser   *user);
 
 gint           act_user_collate                   (ActUser   *user1,
                                                    ActUser   *user2);
 gboolean       act_user_is_loaded                 (ActUser   *user);
 
 void           act_user_get_password_expiration_policy (ActUser   *user,
                                                         gint64    *expiration_time,
                                                         gint64    *last_change_time,
                                                         gint64    *min_days_between_changes,
                                                         gint64    *max_days_between_changes,
                                                         gint64    *days_to_warn,
                                                         gint64    *days_after_expiration_until_lock);
 
 void           act_user_set_email                 (ActUser    *user,
                                                    const char *email);
 void           act_user_set_language              (ActUser    *user,
                                                    const char *language);
 void           act_user_set_x_session             (ActUser    *user,
                                                    const char *x_session);
+void           act_user_set_session               (ActUser    *user,
+                                                   const char *session);
+void           act_user_set_session_type          (ActUser    *user,
+                                                   const char *session_type);
 void           act_user_set_location              (ActUser    *user,
                                                    const char *location);
 void           act_user_set_user_name             (ActUser    *user,
                                                    const char  *user_name);
 void           act_user_set_real_name             (ActUser    *user,
                                                    const char *real_name);
 void           act_user_set_icon_file             (ActUser    *user,
                                                    const char *icon_file);
 void           act_user_set_account_type          (ActUser    *user,
                                                    ActUserAccountType account_type);
 void           act_user_set_password              (ActUser     *user,
                                                    const gchar *password,
                                                    const gchar *hint);
 void           act_user_set_password_hint         (ActUser             *user,
                                                    const gchar *hint);
 void           act_user_set_password_mode         (ActUser             *user,
                                                    ActUserPasswordMode  password_mode);
 void           act_user_set_locked                (ActUser    *user,
                                                    gboolean    locked);
 void           act_user_set_automatic_login       (ActUser   *user,
                                                    gboolean  enabled);
 
 #if GLIB_CHECK_VERSION(2, 44, 0)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (ActUser, g_object_unref)
 #endif
 
 G_END_DECLS
 
 #endif /* __ACT_USER_H__ */
diff --git a/src/user.c b/src/user.c
index 174530f..94c0244 100644
--- a/src/user.c
+++ b/src/user.c
@@ -232,60 +232,75 @@ user_update_from_pwent (User          *user,
                 user->account_expiration_policy_known = TRUE;
         }
 
         accounts_user_set_password_mode (ACCOUNTS_USER (user), mode);
         is_system_account = !user_classify_is_human (accounts_user_get_uid (ACCOUNTS_USER (user)),
                                                      accounts_user_get_user_name (ACCOUNTS_USER (user)),
                                                      accounts_user_get_shell (ACCOUNTS_USER (user)),
                                                      passwd);
         accounts_user_set_system_account (ACCOUNTS_USER (user), is_system_account);
 
         g_object_thaw_notify (G_OBJECT (user));
 }
 
 void
 user_update_from_keyfile (User     *user,
                           GKeyFile *keyfile)
 {
         gchar *s;
 
         g_object_freeze_notify (G_OBJECT (user));
 
         s = g_key_file_get_string (keyfile, "User", "Language", NULL);
         if (s != NULL) {
                 accounts_user_set_language (ACCOUNTS_USER (user), s);
                 g_clear_pointer (&s, g_free);
         }
 
         s = g_key_file_get_string (keyfile, "User", "XSession", NULL);
         if (s != NULL) {
                 accounts_user_set_xsession (ACCOUNTS_USER (user), s);
+
+                /* for backward compat */
+                accounts_user_set_session (ACCOUNTS_USER (user), s);
+                g_clear_pointer (&s, g_free);
+        }
+
+        s = g_key_file_get_string (keyfile, "User", "Session", NULL);
+        if (s != NULL) {
+                accounts_user_set_session (ACCOUNTS_USER (user), s);
+                g_clear_pointer (&s, g_free);
+        }
+
+        s = g_key_file_get_string (keyfile, "User", "SessionType", NULL);
+        if (s != NULL) {
+                accounts_user_set_session_type (ACCOUNTS_USER (user), s);
                 g_clear_pointer (&s, g_free);
         }
 
         s = g_key_file_get_string (keyfile, "User", "Email", NULL);
         if (s != NULL) {
                 accounts_user_set_email (ACCOUNTS_USER (user), s);
                 g_clear_pointer (&s, g_free);
         }
 
         s = g_key_file_get_string (keyfile, "User", "Location", NULL);
         if (s != NULL) {
                 accounts_user_set_location (ACCOUNTS_USER (user), s);
                 g_clear_pointer (&s, g_free);
         }
 
         s = g_key_file_get_string (keyfile, "User", "PasswordHint", NULL);
         if (s != NULL) {
                 accounts_user_set_password_hint (ACCOUNTS_USER (user), s);
                 g_clear_pointer (&s, g_free);
         }
 
         s = g_key_file_get_string (keyfile, "User", "Icon", NULL);
         if (s != NULL) {
                 accounts_user_set_icon_file (ACCOUNTS_USER (user), s);
                 g_clear_pointer (&s, g_free);
         }
 
         if (g_key_file_has_key (keyfile, "User", "SystemAccount", NULL)) {
             gboolean system_account;
 
@@ -299,60 +314,66 @@ user_update_from_keyfile (User     *user,
 
         g_object_thaw_notify (G_OBJECT (user));
 }
 
 void
 user_update_local_account_property (User          *user,
                                     gboolean       local)
 {
         accounts_user_set_local_account (ACCOUNTS_USER (user), local);
 }
 
 void
 user_update_system_account_property (User          *user,
                                      gboolean       system)
 {
         accounts_user_set_system_account (ACCOUNTS_USER (user), system);
 }
 
 static void
 user_save_to_keyfile (User     *user,
                       GKeyFile *keyfile)
 {
         g_key_file_remove_group (keyfile, "User", NULL);
 
         if (accounts_user_get_email (ACCOUNTS_USER (user)))
                 g_key_file_set_string (keyfile, "User", "Email", accounts_user_get_email (ACCOUNTS_USER (user)));
 
         if (accounts_user_get_language (ACCOUNTS_USER (user)))
                 g_key_file_set_string (keyfile, "User", "Language", accounts_user_get_language (ACCOUNTS_USER (user)));
 
+        if (accounts_user_get_session (ACCOUNTS_USER (user)))
+                g_key_file_set_string (keyfile, "User", "Session", accounts_user_get_session (ACCOUNTS_USER (user)));
+
+        if (accounts_user_get_session_type (ACCOUNTS_USER (user)))
+                g_key_file_set_string (keyfile, "User", "SessionType", accounts_user_get_session_type (ACCOUNTS_USER (user)));
+
         if (accounts_user_get_xsession (ACCOUNTS_USER (user)))
                 g_key_file_set_string (keyfile, "User", "XSession", accounts_user_get_xsession (ACCOUNTS_USER (user)));
 
         if (accounts_user_get_location (ACCOUNTS_USER (user)))
                 g_key_file_set_string (keyfile, "User", "Location", accounts_user_get_location (ACCOUNTS_USER (user)));
 
         if (accounts_user_get_password_hint (ACCOUNTS_USER (user)))
                 g_key_file_set_string (keyfile, "User", "PasswordHint", accounts_user_get_password_hint (ACCOUNTS_USER (user)));
 
         if (accounts_user_get_icon_file (ACCOUNTS_USER (user)))
                 g_key_file_set_string (keyfile, "User", "Icon", accounts_user_get_icon_file (ACCOUNTS_USER (user)));
 
         g_key_file_set_boolean (keyfile, "User", "SystemAccount", accounts_user_get_system_account (ACCOUNTS_USER (user)));
 
         user_set_cached (user, TRUE);
 }
 
 static void
 save_extra_data (User *user)
 {
         g_autofree gchar *data = NULL;
         g_autofree gchar *filename = NULL;
         g_autoptr(GError) error = NULL;
 
         user_save_to_keyfile (user, user->keyfile);
 
         data = g_key_file_to_data (user->keyfile, NULL, &error);
         if (data == NULL) {
                 g_warning ("Saving data for user %s failed: %s",
                            accounts_user_get_user_name (ACCOUNTS_USER (user)), error->message);
@@ -996,60 +1017,158 @@ static gboolean
 user_set_language (AccountsUser          *auser,
                    GDBusMethodInvocation *context,
                    const gchar           *language)
 {
         User *user = (User*)auser;
         int uid;
         const gchar *action_id;
 
         if (!get_caller_uid (context, &uid)) {
                 throw_error (context, ERROR_FAILED, "identifying caller failed");
                 return FALSE;
         }
 
         if (accounts_user_get_uid (ACCOUNTS_USER (user)) == (uid_t) uid)
                 action_id = "org.freedesktop.accounts.change-own-user-data";
         else
                 action_id = "org.freedesktop.accounts.user-administration";
 
         daemon_local_check_auth (user->daemon,
                                  user,
                                  action_id,
                                  TRUE,
                                  user_change_language_authorized_cb,
                                  context,
                                  g_strdup (language),
                                  (GDestroyNotify)g_free);
 
         return TRUE;
 }
 
+static void
+user_change_session_authorized_cb (Daemon                *daemon,
+                                   User                  *user,
+                                   GDBusMethodInvocation *context,
+                                   gpointer               user_data)
+
+{
+        const gchar *session = user_data;
+
+        if (g_strcmp0 (accounts_user_get_session (ACCOUNTS_USER (user)), session) != 0) {
+                accounts_user_set_session (ACCOUNTS_USER (user), session);
+
+                save_extra_data (user);
+        }
+
+        accounts_user_complete_set_session (ACCOUNTS_USER (user), context);
+}
+
+static gboolean
+user_set_session (AccountsUser          *auser,
+                  GDBusMethodInvocation *context,
+                  const gchar           *session)
+{
+        User *user = (User*)auser;
+        int uid;
+        const gchar *action_id;
+
+        if (!get_caller_uid (context, &uid)) {
+                throw_error (context, ERROR_FAILED, "identifying caller failed");
+                return FALSE;
+        }
+
+        if (accounts_user_get_uid (ACCOUNTS_USER (user)) == (uid_t) uid)
+                action_id = "org.freedesktop.accounts.change-own-user-data";
+        else
+                action_id = "org.freedesktop.accounts.user-administration";
+
+        daemon_local_check_auth (user->daemon,
+                                 user,
+                                 action_id,
+                                 TRUE,
+                                 user_change_session_authorized_cb,
+                                 context,
+                                 g_strdup (session),
+                                 (GDestroyNotify) g_free);
+
+        return TRUE;
+}
+
+static void
+user_change_session_type_authorized_cb (Daemon                *daemon,
+                                        User                  *user,
+                                        GDBusMethodInvocation *context,
+                                        gpointer               user_data)
+
+{
+        const gchar *session_type = user_data;
+
+        if (g_strcmp0 (accounts_user_get_session_type (ACCOUNTS_USER (user)), session_type) != 0) {
+                accounts_user_set_session_type (ACCOUNTS_USER (user), session_type);
+
+                save_extra_data (user);
+        }
+
+        accounts_user_complete_set_session_type (ACCOUNTS_USER (user), context);
+}
+
+static gboolean
+user_set_session_type (AccountsUser          *auser,
+                       GDBusMethodInvocation *context,
+                       const gchar           *session_type)
+{
+        User *user = (User*)auser;
+        int uid;
+        const gchar *action_id;
+
+        if (!get_caller_uid (context, &uid)) {
+                throw_error (context, ERROR_FAILED, "identifying caller failed");
+                return FALSE;
+        }
+
+        if (accounts_user_get_uid (ACCOUNTS_USER (user)) == (uid_t) uid)
+                action_id = "org.freedesktop.accounts.change-own-user-data";
+        else
+                action_id = "org.freedesktop.accounts.user-administration";
+
+        daemon_local_check_auth (user->daemon,
+                                 user,
+                                 action_id,
+                                 TRUE,
+                                 user_change_session_type_authorized_cb,
+                                 context,
+                                 g_strdup (session_type),
+                                 (GDestroyNotify) g_free);
+
+        return TRUE;
+}
+
 static void
 user_change_x_session_authorized_cb (Daemon                *daemon,
                                      User                  *user,
                                      GDBusMethodInvocation *context,
                                      gpointer               data)
 
 {
         gchar *x_session = data;
 
         if (g_strcmp0 (accounts_user_get_xsession (ACCOUNTS_USER (user)), x_session) != 0) {
                 accounts_user_set_xsession (ACCOUNTS_USER (user), x_session);
 
                 save_extra_data (user);
         }
 
         accounts_user_complete_set_xsession (ACCOUNTS_USER (user), context);
 }
 
 static gboolean
 user_set_x_session (AccountsUser          *auser,
                     GDBusMethodInvocation *context,
                     const gchar           *x_session)
 {
         User *user = (User*)auser;
         int uid;
         const gchar *action_id;
 
         if (!get_caller_uid (context, &uid)) {
                 throw_error (context, ERROR_FAILED, "identifying caller failed");
                 return FALSE;
@@ -1966,41 +2085,43 @@ user_finalize (GObject *object)
 }
 
 static void
 user_class_init (UserClass *class)
 {
         GObjectClass *gobject_class;
 
         gobject_class = G_OBJECT_CLASS (class);
 
         gobject_class->finalize = user_finalize;
 }
 
 static void
 user_accounts_user_iface_init (AccountsUserIface *iface)
 {
         iface->handle_set_account_type = user_set_account_type;
         iface->handle_set_automatic_login = user_set_automatic_login;
         iface->handle_set_email = user_set_email;
         iface->handle_set_home_directory = user_set_home_directory;
         iface->handle_set_icon_file = user_set_icon_file;
         iface->handle_set_language = user_set_language;
         iface->handle_set_location = user_set_location;
         iface->handle_set_locked = user_set_locked;
         iface->handle_set_password = user_set_password;
         iface->handle_set_password_mode = user_set_password_mode;
         iface->handle_set_password_hint = user_set_password_hint;
         iface->handle_set_real_name = user_set_real_name;
         iface->handle_set_shell = user_set_shell;
         iface->handle_set_user_name = user_set_user_name;
         iface->handle_set_xsession = user_set_x_session;
+        iface->handle_set_session = user_set_session;
+        iface->handle_set_session_type = user_set_session_type;
         iface->handle_get_password_expiration_policy = user_get_password_expiration_policy;
 }
 
 static void
 user_init (User *user)
 {
         user->system_bus_connection = NULL;
         user->default_icon_file = NULL;
         user->login_history = NULL;
         user->keyfile = g_key_file_new ();
 }
-- 
2.17.1