<commit_before>/*
 * Copyright © 2021 Igalia S.L.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
 *
 * Authors:
 *       <NAME> <<EMAIL>>
 */

#include "config.h"

#include <string.h>
#include <gio/gio.h>

#include "realtime.h"
#include "request.h"
#include "xdp-dbus.h"
#include "xdp-utils.h"

typedef struct _Realtime Realtime;
typedef struct _RealtimeClass RealtimeClass;

struct _Realtime
{
  XdpRealtimeSkeleton parent_instance;
  GDBusProxy *rtkit_proxy;
};

struct _RealtimeClass
{
  XdpRealtimeSkeletonClass parent_class;
};

static Realtime *realtime;

GType realtime_get_type (void) G_GNUC_CONST;
static void realtime_iface_init (XdpRealtimeIface *iface);

G_DEFINE_TYPE_WITH_CODE (Realtime, realtime, XDP_TYPE_REALTIME_SKELETON,
                         G_IMPLEMENT_INTERFACE (XDP_TYPE_REALTIME, realtime_iface_init));

static gboolean
map_pid_if_needed (XdpAppInfo *app_info, pid_t *pid, GError **error)
{
  if (!xdp_app_info_is_host (app_info))
  {
    if (!xdg_app_info_map_pids (app_info, pid, 1, error))
    {
      g_prefix_error (error, "Could not map pid: ");
      g_warning ("Realtime error: %s", (*error)->message);
      return FALSE;
    }
  }

  return TRUE;
}

static void
on_call_ready (GObject      *source_object,
               GAsyncResult *result,
               gpointer      user_data)
{
  g_autoptr(GError) error = NULL;
  g_autoptr(GDBusMethodInvocation) invocation = g_steal_pointer (&user_data);
  g_autoptr(GVariant) response = NULL;

  response = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
                                       result,
                                       &error);

  if (error)
    g_dbus_method_invocation_return_gerror (invocation, error);
  else
    g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
}

static gboolean
handle_make_thread_realtime_with_pid (XdpRealtime           *object,
                                      GDBusMethodInvocation *invocation,
                                      guint64                process,
                                      guint64                thread,
                                      guint32                priority)
{
  g_autoptr (GError) error = NULL;
  Request *request = request_from_invocation (invocation);
  pid_t pids[1] = { process };

  if (!realtime->rtkit_proxy)
    {
      g_dbus_method_invocation_return_error (invocation,
                                             XDG_DESKTOP_PORTAL_ERROR,
                                             XDG_DESKTOP_PORTAL_ERROR_FAILED,
                                             "RealtimeKit was not found");
      return TRUE;
    }

  if (!map_pid_if_needed (request->app_info, pids, &error))
    {
      g_dbus_method_invocation_return_gerror (invocation, error);
      return TRUE;
    }

  g_dbus_proxy_call (G_DBUS_PROXY (realtime->rtkit_proxy),
                     "MakeThreadRealtimeWithPID",
                     g_variant_new ("(ttu)", pids[0], thread, priority),
                     G_DBUS_CALL_FLAGS_NONE,
                     -1,
                     NULL,
                     on_call_ready,
                     g_object_ref (invocation));

  return TRUE;
}

static gboolean
handle_make_thread_high_priority_with_pid (XdpRealtime           *object,
                                           GDBusMethodInvocation *invocation,
                                           guint64                process,
                                           guint64                thread,
                                           gint32                 priority)
{
  g_autoptr (GError) error = NULL;
  Request *request = request_from_invocation (invocation);
  pid_t pids[1] = { process };

  if (!realtime->rtkit_proxy)
    {
      g_dbus_method_invocation_return_error (invocation,
                                             XDG_DESKTOP_PORTAL_ERROR,
                                             XDG_DESKTOP_PORTAL_ERROR_FAILED,
                                             "RealtimeKit was not found");
      return TRUE;
    }
<commit_msg>realtime: Add ability to deny realtime permission It defaults to allowed unless specifically configured<commit_after>/*
 * Copyright © 2021 Igalia S.L.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
 *
 * Authors:
 *       <NAME> <<EMAIL>>
 */

#include "config.h"

#include <string.h>
#include <gio/gio.h>

#include "realtime.h"
#include "request.h"
#include "permissions.h"
#include "xdp-dbus.h"
#include "xdp-utils.h"

#define PERMISSION_TABLE "realtime"
#define PERMISSION_ID "realtime"

typedef struct _Realtime Realtime;
typedef struct _RealtimeClass RealtimeClass;

struct _Realtime
{
  XdpRealtimeSkeleton parent_instance;
  GDBusProxy *rtkit_proxy;
};

struct _RealtimeClass
{
  XdpRealtimeSkeletonClass parent_class;
};

static Realtime *realtime;

GType realtime_get_type (void) G_GNUC_CONST;
static void realtime_iface_init (XdpRealtimeIface *iface);

G_DEFINE_TYPE_WITH_CODE (Realtime, realtime, XDP_TYPE_REALTIME_SKELETON,
                         G_IMPLEMENT_INTERFACE (XDP_TYPE_REALTIME, realtime_iface_init));

static gboolean
map_pid_if_needed (XdpAppInfo *app_info, pid_t *pid, GError **error)
{
  if (!xdp_app_info_is_host (app_info))
  {
    if (!xdg_app_info_map_pids (app_info, pid, 1, error))
    {
      g_prefix_error (error, "Could not map pid: ");
      g_warning ("Realtime error: %s", (*error)->message);
      return FALSE;
    }
  }

  return TRUE;
}

static void
on_call_ready (GObject      *source_object,
               GAsyncResult *result,
               gpointer      user_data)
{
  g_autoptr(GError) error = NULL;
  g_autoptr(GDBusMethodInvocation) invocation = g_steal_pointer (&user_data);
  g_autoptr(GVariant) response = NULL;

  response = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
                                       result,
                                       &error);

  if (error)
    g_dbus_method_invocation_return_gerror (invocation, error);
  else
    g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
}

static gboolean
handle_make_thread_realtime_with_pid (XdpRealtime           *object,
                                      GDBusMethodInvocation *invocation,
                                      guint64                process,
                                      guint64                thread,
                                      guint32                priority)
{
  g_autoptr (GError) error = NULL;
  Request *request = request_from_invocation (invocation);
  pid_t pids[1] = { process };
  const char *app_id = xdp_app_info_get_id (request->app_info);
  Permission permission;

  if (!realtime->rtkit_proxy)
    {
      g_dbus_method_invocation_return_error (invocation,
                                             XDG_DESKTOP_PORTAL_ERROR,
                                             XDG_DESKTOP_PORTAL_ERROR_FAILED,
                                             "RealtimeKit was not found");
    }

  permission = get_permission_sync (app_id, PERMISSION_TABLE, PERMISSION_ID);
  if (permission == PERMISSION_NO)
    {
      g_dbus_method_invocation_return_error (invocation,
                                             XDG_DESKTOP_PORTAL_ERROR,
                                             XDG_DESKTOP_PORTAL_ERROR_NOT_ALLOWED,
                                             "Permission denied");
      return TRUE;
    }

  if (!map_pid_if_needed (request->app_info, pids, &error))
    {
      g_dbus_method_invocation_return_gerror (invocation, error);
      return TRUE;
    }

  g_dbus_proxy_call (G_DBUS_PROXY (realtime->rtkit_proxy),
                     "MakeThreadRealtimeWithPID",
                     g_variant_new ("(ttu)", pids[0], thread, priority),
                     G_DBUS_CALL_FLAGS_NONE,
                     -1,
                     NULL,
                     on_call_ready,
                     g_object_ref (invocation));

  return TRUE;
}

static gboolean
handle_make_thread_high_priority_with_pid (XdpRealtime           *object,
                                           GDBusMethodInvocation *invocation,
                                           guint64                process,
                                           guint64                thread,
                                           gint32                 priority)
{
  g_autoptr (GError) error = NULL;
  Request *request = request_from_invocation (invocation);
  pid_t pids[1] = { process };
  const char *app_id = xdp_app_info_get_id (request->app_info);
  Permission permission;

  if (!realtime->rtkit_proxy)
    {
      g_dbus_method_invocation_return_error (invocation,
                                             XDG_DESKTOP_PORTAL_ERROR,
                                             XDG_DESKTOP_PORTAL_ERROR_FAILED,
                                             "RealtimeKit was not found");
    }

  permission = get_permission_sync (app_id, PERMISSION_TABLE, PERMISSION_ID);
  if (permission == PERMISSION_NO)
    {
      g_dbus_method_invocation_return_error (invocation,
                                             XDG_DESKTOP_PORTAL_ERROR,
                                             XDG_DESKTOP_PORTAL_ERROR_NOT_ALLOWED,
                                             "Permission denied");
      return TRUE;
    }

{'fraction_non_alphanumeric': 0.07167948352795975, 'fraction_numerical': 0.0041773473844108995, 'mean_word_length': 1.9277376320177877, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 64, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5473160', 'n_tokens_mistral': 3079, 'n_tokens_neox': 2972, 'n_words': 719}