(root)/
glib-2.79.0/
gio/
gpermission.c
       1  /*
       2   * Copyright © 2010 Codethink Limited
       3   *
       4   * SPDX-License-Identifier: LGPL-2.1-or-later
       5   *
       6   * This library is free software; you can redistribute it and/or
       7   * modify it under the terms of the GNU Lesser General Public
       8   * License as published by the Free Software Foundation; either
       9   * version 2.1 of the License, or (at your option) any later version.
      10   *
      11   * This library is distributed in the hope that it will be useful,
      12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14   * Lesser General Public License for more details.
      15   *
      16   * You should have received a copy of the GNU Lesser General Public
      17   * License along with this library; if not, see <http://www.gnu.org/licenses/>.
      18   *
      19   * Author: Ryan Lortie <desrt@desrt.ca>
      20   */
      21  
      22  #include "config.h"
      23  
      24  #include "gpermission.h"
      25  
      26  #include "gioerror.h"
      27  #include "gioenums.h"
      28  #include "gasyncresult.h"
      29  #include "gtask.h"
      30  #include "glibintl.h"
      31  
      32  
      33  /**
      34   * GPermission:
      35   *
      36   * A `GPermission` represents the status of the caller’s permission to
      37   * perform a certain action.
      38   *
      39   * You can query if the action is currently allowed and if it is
      40   * possible to acquire the permission so that the action will be allowed
      41   * in the future.
      42   *
      43   * There is also an API to actually acquire the permission and one to
      44   * release it.
      45   *
      46   * As an example, a `GPermission` might represent the ability for the
      47   * user to write to a [class@Gio.Settings] object.  This `GPermission` object
      48   * could then be used to decide if it is appropriate to show a “Click here to
      49   * unlock” button in a dialog and to provide the mechanism to invoke
      50   * when that button is clicked.
      51   **/
      52  
      53  struct _GPermissionPrivate
      54  {
      55    gboolean allowed;
      56    gboolean can_acquire;
      57    gboolean can_release;
      58  };
      59  
      60  enum  {
      61    PROP_NONE,
      62    PROP_ALLOWED,
      63    PROP_CAN_ACQUIRE,
      64    PROP_CAN_RELEASE
      65  };
      66  
      67  G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GPermission, g_permission, G_TYPE_OBJECT)
      68  
      69  /**
      70   * g_permission_acquire:
      71   * @permission: a #GPermission instance
      72   * @cancellable: (nullable): a #GCancellable, or %NULL
      73   * @error: a pointer to a %NULL #GError, or %NULL
      74   *
      75   * Attempts to acquire the permission represented by @permission.
      76   *
      77   * The precise method by which this happens depends on the permission
      78   * and the underlying authentication mechanism.  A simple example is
      79   * that a dialog may appear asking the user to enter their password.
      80   *
      81   * You should check with g_permission_get_can_acquire() before calling
      82   * this function.
      83   *
      84   * If the permission is acquired then %TRUE is returned.  Otherwise,
      85   * %FALSE is returned and @error is set appropriately.
      86   *
      87   * This call is blocking, likely for a very long time (in the case that
      88   * user interaction is required).  See g_permission_acquire_async() for
      89   * the non-blocking version.
      90   *
      91   * Returns: %TRUE if the permission was successfully acquired
      92   *
      93   * Since: 2.26
      94   */
      95  gboolean
      96  g_permission_acquire (GPermission   *permission,
      97                        GCancellable  *cancellable,
      98                        GError       **error)
      99  {
     100    g_return_val_if_fail (G_IS_PERMISSION (permission), FALSE);
     101    return G_PERMISSION_GET_CLASS (permission)
     102      ->acquire (permission, cancellable, error);
     103  }
     104  
     105  /**
     106   * g_permission_acquire_async:
     107   * @permission: a #GPermission instance
     108   * @cancellable: (nullable): a #GCancellable, or %NULL
     109   * @callback: the #GAsyncReadyCallback to call when done
     110   * @user_data: the user data to pass to @callback
     111   *
     112   * Attempts to acquire the permission represented by @permission.
     113   *
     114   * This is the first half of the asynchronous version of
     115   * g_permission_acquire().
     116   *
     117   * Since: 2.26
     118   **/
     119  void
     120  g_permission_acquire_async (GPermission         *permission,
     121                              GCancellable        *cancellable,
     122                              GAsyncReadyCallback  callback,
     123                              gpointer             user_data)
     124  {
     125    g_return_if_fail (G_IS_PERMISSION (permission));
     126    G_PERMISSION_GET_CLASS (permission)
     127      ->acquire_async (permission, cancellable, callback, user_data);
     128  }
     129  
     130  /**
     131   * g_permission_acquire_finish:
     132   * @permission: a #GPermission instance
     133   * @result: the #GAsyncResult given to the #GAsyncReadyCallback
     134   * @error: a pointer to a %NULL #GError, or %NULL
     135   *
     136   * Collects the result of attempting to acquire the permission
     137   * represented by @permission.
     138   *
     139   * This is the second half of the asynchronous version of
     140   * g_permission_acquire().
     141   *
     142   * Returns: %TRUE if the permission was successfully acquired
     143   *
     144   * Since: 2.26
     145   **/
     146  gboolean
     147  g_permission_acquire_finish (GPermission   *permission,
     148                               GAsyncResult  *result,
     149                               GError       **error)
     150  {
     151    g_return_val_if_fail (G_IS_PERMISSION (permission), FALSE);
     152    return G_PERMISSION_GET_CLASS (permission)
     153      ->acquire_finish (permission, result, error);
     154  }
     155  
     156  /**
     157   * g_permission_release:
     158   * @permission: a #GPermission instance
     159   * @cancellable: (nullable): a #GCancellable, or %NULL
     160   * @error: a pointer to a %NULL #GError, or %NULL
     161   *
     162   * Attempts to release the permission represented by @permission.
     163   *
     164   * The precise method by which this happens depends on the permission
     165   * and the underlying authentication mechanism.  In most cases the
     166   * permission will be dropped immediately without further action.
     167   *
     168   * You should check with g_permission_get_can_release() before calling
     169   * this function.
     170   *
     171   * If the permission is released then %TRUE is returned.  Otherwise,
     172   * %FALSE is returned and @error is set appropriately.
     173   *
     174   * This call is blocking, likely for a very long time (in the case that
     175   * user interaction is required).  See g_permission_release_async() for
     176   * the non-blocking version.
     177   *
     178   * Returns: %TRUE if the permission was successfully released
     179   *
     180   * Since: 2.26
     181   **/
     182  gboolean
     183  g_permission_release (GPermission   *permission,
     184                        GCancellable  *cancellable,
     185                        GError       **error)
     186  {
     187    g_return_val_if_fail (G_IS_PERMISSION (permission), FALSE);
     188    return G_PERMISSION_GET_CLASS (permission)
     189      ->release (permission, cancellable, error);
     190  }
     191  
     192  /**
     193   * g_permission_release_async:
     194   * @permission: a #GPermission instance
     195   * @cancellable: (nullable): a #GCancellable, or %NULL
     196   * @callback: the #GAsyncReadyCallback to call when done
     197   * @user_data: the user data to pass to @callback
     198   *
     199   * Attempts to release the permission represented by @permission.
     200   *
     201   * This is the first half of the asynchronous version of
     202   * g_permission_release().
     203   *
     204   * Since: 2.26
     205   **/
     206  void
     207  g_permission_release_async (GPermission         *permission,
     208                              GCancellable        *cancellable,
     209                              GAsyncReadyCallback  callback,
     210                              gpointer             user_data)
     211  {
     212    g_return_if_fail (G_IS_PERMISSION (permission));
     213    G_PERMISSION_GET_CLASS (permission)
     214      ->release_async (permission, cancellable, callback, user_data);
     215  }
     216  
     217  /**
     218   * g_permission_release_finish:
     219   * @permission: a #GPermission instance
     220   * @result: the #GAsyncResult given to the #GAsyncReadyCallback
     221   * @error: a pointer to a %NULL #GError, or %NULL
     222   *
     223   * Collects the result of attempting to release the permission
     224   * represented by @permission.
     225   *
     226   * This is the second half of the asynchronous version of
     227   * g_permission_release().
     228   *
     229   * Returns: %TRUE if the permission was successfully released
     230   *
     231   * Since: 2.26
     232   **/
     233  gboolean
     234  g_permission_release_finish (GPermission   *permission,
     235                               GAsyncResult  *result,
     236                               GError       **error)
     237  {
     238    g_return_val_if_fail (G_IS_PERMISSION (permission), FALSE);
     239    return G_PERMISSION_GET_CLASS (permission)
     240      ->release_finish (permission, result, error);
     241  }
     242  
     243  /**
     244   * g_permission_get_allowed:
     245   * @permission: a #GPermission instance
     246   *
     247   * Gets the value of the 'allowed' property.  This property is %TRUE if
     248   * the caller currently has permission to perform the action that
     249   * @permission represents the permission to perform.
     250   *
     251   * Returns: the value of the 'allowed' property
     252   *
     253   * Since: 2.26
     254   **/
     255  gboolean
     256  g_permission_get_allowed (GPermission *permission)
     257  {
     258    g_return_val_if_fail (G_IS_PERMISSION (permission), FALSE);
     259    return permission->priv->allowed;
     260  }
     261  
     262  /**
     263   * g_permission_get_can_acquire:
     264   * @permission: a #GPermission instance
     265   *
     266   * Gets the value of the 'can-acquire' property.  This property is %TRUE
     267   * if it is generally possible to acquire the permission by calling
     268   * g_permission_acquire().
     269   *
     270   * Returns: the value of the 'can-acquire' property
     271   *
     272   * Since: 2.26
     273   **/
     274  gboolean
     275  g_permission_get_can_acquire (GPermission *permission)
     276  {
     277    g_return_val_if_fail (G_IS_PERMISSION (permission), FALSE);
     278    return permission->priv->can_acquire;
     279  }
     280  
     281  /**
     282   * g_permission_get_can_release:
     283   * @permission: a #GPermission instance
     284   *
     285   * Gets the value of the 'can-release' property.  This property is %TRUE
     286   * if it is generally possible to release the permission by calling
     287   * g_permission_release().
     288   *
     289   * Returns: the value of the 'can-release' property
     290   *
     291   * Since: 2.26
     292   **/
     293  gboolean
     294  g_permission_get_can_release (GPermission *permission)
     295  {
     296    g_return_val_if_fail (G_IS_PERMISSION (permission), FALSE);
     297    return permission->priv->can_release;
     298  }
     299  
     300  /**
     301   * g_permission_impl_update:
     302   * @permission: a #GPermission instance
     303   * @allowed: the new value for the 'allowed' property
     304   * @can_acquire: the new value for the 'can-acquire' property
     305   * @can_release: the new value for the 'can-release' property
     306   *
     307   * This function is called by the #GPermission implementation to update
     308   * the properties of the permission.  You should never call this
     309   * function except from a #GPermission implementation.
     310   *
     311   * GObject notify signals are generated, as appropriate.
     312   *
     313   * Since: 2.26
     314   **/
     315  void
     316  g_permission_impl_update (GPermission *permission,
     317                            gboolean     allowed,
     318                            gboolean     can_acquire,
     319                            gboolean     can_release)
     320  {
     321    GObject *object;
     322  
     323    g_return_if_fail (G_IS_PERMISSION (permission));
     324  
     325    object = G_OBJECT (permission);
     326    g_object_freeze_notify (object);
     327  
     328    allowed = allowed != FALSE;
     329    if (allowed != permission->priv->allowed)
     330      {
     331        permission->priv->allowed = allowed;
     332        g_object_notify (object, "allowed");
     333      }
     334  
     335    can_acquire = can_acquire != FALSE;
     336    if (can_acquire != permission->priv->can_acquire)
     337      {
     338        permission->priv->can_acquire = can_acquire;
     339        g_object_notify (object, "can-acquire");
     340      }
     341  
     342    can_release = can_release != FALSE;
     343    if (can_release != permission->priv->can_release)
     344      {
     345        permission->priv->can_release = can_release;
     346        g_object_notify (object, "can-release");
     347      }
     348  
     349    g_object_thaw_notify (object);
     350  }
     351  
     352  static void
     353  g_permission_get_property (GObject *object, guint prop_id,
     354                             GValue *value, GParamSpec *pspec)
     355  {
     356    GPermission *permission = G_PERMISSION (object);
     357  
     358    switch (prop_id)
     359      {
     360      case PROP_ALLOWED:
     361        g_value_set_boolean (value, permission->priv->allowed);
     362        break;
     363  
     364      case PROP_CAN_ACQUIRE:
     365        g_value_set_boolean (value, permission->priv->can_acquire);
     366        break;
     367  
     368      case PROP_CAN_RELEASE:
     369        g_value_set_boolean (value, permission->priv->can_release);
     370        break;
     371  
     372      default:
     373        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     374    }
     375  }
     376  
     377  static void
     378  g_permission_init (GPermission *permission)
     379  {
     380    permission->priv = g_permission_get_instance_private (permission);
     381  }
     382  
     383  static gboolean
     384  acquire_or_release (GPermission   *permission,
     385                      GCancellable  *cancellable,
     386                      GError       **error)
     387  {
     388    g_set_error_literal  (error,
     389                          G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
     390                          "Can't acquire or release permission");
     391    return FALSE;
     392  }
     393  
     394  static void
     395  acquire_or_release_async (GPermission         *permission,
     396                            GCancellable        *cancellable,
     397                            GAsyncReadyCallback  callback,
     398                            gpointer             user_data)
     399  {
     400    g_task_report_new_error (permission,
     401                             callback, user_data,
     402                             NULL,
     403                             G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
     404                             "Can't acquire or release permission");
     405  }
     406  
     407  static gboolean
     408  acquire_or_release_finish (GPermission   *permission,
     409                             GAsyncResult  *result,
     410                             GError       **error)
     411  {
     412    return g_task_propagate_boolean (G_TASK (result), error);
     413  }
     414  
     415  static void
     416  g_permission_class_init (GPermissionClass *class)
     417  {
     418    GObjectClass *object_class = G_OBJECT_CLASS (class);
     419  
     420    object_class->get_property = g_permission_get_property;
     421  
     422    class->acquire = acquire_or_release;
     423    class->release = acquire_or_release;
     424    class->acquire_async = acquire_or_release_async;
     425    class->release_async = acquire_or_release_async;
     426    class->acquire_finish = acquire_or_release_finish;
     427    class->release_finish = acquire_or_release_finish;
     428  
     429    /**
     430     * GPermission:allowed:
     431     *
     432     * %TRUE if the caller currently has permission to perform the action that
     433     * @permission represents the permission to perform.
     434     */
     435     g_object_class_install_property (object_class, PROP_ALLOWED,
     436       g_param_spec_boolean ("allowed", NULL, NULL,
     437                             FALSE,
     438                             G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
     439  
     440    /**
     441     * GPermission:can-acquire:
     442     *
     443     * %TRUE if it is generally possible to acquire the permission by calling
     444     * g_permission_acquire().
     445     */
     446     g_object_class_install_property (object_class, PROP_CAN_ACQUIRE,
     447       g_param_spec_boolean ("can-acquire", NULL, NULL,
     448                             FALSE,
     449                             G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
     450  
     451    /**
     452     * GPermission:can-release:
     453     *
     454     * %TRUE if it is generally possible to release the permission by calling
     455     * g_permission_release().
     456     */
     457     g_object_class_install_property (object_class, PROP_CAN_RELEASE,
     458       g_param_spec_boolean ("can-release", NULL, NULL,
     459                             FALSE,
     460                             G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
     461  }