LCOV - code coverage report
Current view: top level - src/plugins/runcommand - valent-runcommand-plugin.c (source / functions) Coverage Total Hit
Test: Code Coverage Lines: 92.5 % 254 235
Test Date: 2024-04-16 07:28:14 Functions: 90.9 % 22 20
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 50.6 % 160 81

             Branch data     Line data    Source code
       1                 :             : // SPDX-License-Identifier: GPL-3.0-or-later
       2                 :             : // SPDX-FileCopyrightText: Andy Holmes <andrew.g.r.holmes@gmail.com>
       3                 :             : 
       4                 :             : #define G_LOG_DOMAIN "valent-runcommand-plugin"
       5                 :             : 
       6                 :             : #include "config.h"
       7                 :             : 
       8                 :             : #include <glib/gi18n.h>
       9                 :             : #include <json-glib/json-glib.h>
      10                 :             : #include <libportal/portal.h>
      11                 :             : #include <valent.h>
      12                 :             : 
      13                 :             : #include "valent-runcommand-plugin.h"
      14                 :             : #include "valent-runcommand-utils.h"
      15                 :             : 
      16                 :             : 
      17                 :             : struct _ValentRuncommandPlugin
      18                 :             : {
      19                 :             :   ValentDevicePlugin   parent_instance;
      20                 :             : 
      21                 :             :   GSubprocessLauncher *launcher;
      22                 :             :   GHashTable          *subprocesses;
      23                 :             : 
      24                 :             :   unsigned long        commands_changed_id;
      25                 :             : };
      26                 :             : 
      27   [ +  +  +  - ]:          30 : G_DEFINE_FINAL_TYPE (ValentRuncommandPlugin, valent_runcommand_plugin, VALENT_TYPE_DEVICE_PLUGIN)
      28                 :             : 
      29                 :             : static void valent_runcommand_plugin_execute_local_command     (ValentRuncommandPlugin *self,
      30                 :             :                                                                 const char             *key);
      31                 :             : static void valent_runcommand_plugin_execute_remote_command    (ValentRuncommandPlugin *self,
      32                 :             :                                                                 const char             *key);
      33                 :             : static void valent_runcommand_plugin_handle_command_list       (ValentRuncommandPlugin *self,
      34                 :             :                                                                 JsonObject             *command_list);
      35                 :             : static void valent_runcommand_plugin_handle_runcommand         (ValentRuncommandPlugin *self,
      36                 :             :                                                                 JsonNode               *packet);
      37                 :             : static void valent_runcommand_plugin_handle_runcommand_request (ValentRuncommandPlugin *self,
      38                 :             :                                                                 JsonNode               *packet);
      39                 :             : static void valent_runcommand_plugin_send_command_list         (ValentRuncommandPlugin *self);
      40                 :             : 
      41                 :             : 
      42                 :             : /*
      43                 :             :  * Launcher Helpers
      44                 :             :  */
      45                 :             : static void
      46                 :           1 : launcher_init (ValentRuncommandPlugin *self)
      47                 :             : {
      48                 :           1 :   ValentDevice *device;
      49                 :           1 :   GSubprocessFlags flags;
      50                 :             : 
      51         [ +  - ]:           1 :   if G_UNLIKELY (self->launcher != NULL)
      52                 :             :     return;
      53                 :             : 
      54                 :             : #ifdef VALENT_ENABLE_DEBUG
      55                 :           1 :   flags = G_SUBPROCESS_FLAGS_NONE;
      56                 :             : #else
      57                 :             :   flags = (G_SUBPROCESS_FLAGS_STDERR_SILENCE |
      58                 :             :            G_SUBPROCESS_FLAGS_STDOUT_SILENCE);
      59                 :             : #endif /* VALENT_ENABLE_DEBUG */
      60                 :             : 
      61                 :           1 :   self->launcher = g_subprocess_launcher_new (flags);
      62                 :             : 
      63                 :           1 :   device = valent_extension_get_object (VALENT_EXTENSION (self));
      64                 :           1 :   g_subprocess_launcher_setenv (self->launcher,
      65                 :             :                                 "VALENT_DEVICE_ID",
      66                 :           1 :                                 valent_device_get_id (device),
      67                 :             :                                 TRUE);
      68                 :           1 :   g_subprocess_launcher_setenv (self->launcher,
      69                 :             :                                 "VALENT_DEVICE_NAME",
      70                 :           1 :                                 valent_device_get_name (device),
      71                 :             :                                 TRUE);
      72                 :             : }
      73                 :             : 
      74                 :             : static void
      75                 :           1 : launcher_clear (ValentRuncommandPlugin *self)
      76                 :             : {
      77                 :           1 :   GHashTableIter iter;
      78                 :           1 :   gpointer subprocess;
      79                 :             : 
      80                 :           1 :   g_hash_table_iter_init (&iter, self->subprocesses);
      81                 :             : 
      82         [ -  + ]:           1 :   while (g_hash_table_iter_next (&iter, NULL, &subprocess))
      83                 :             :     {
      84                 :           0 :       g_subprocess_force_exit (G_SUBPROCESS (subprocess));
      85                 :           0 :       g_hash_table_iter_remove (&iter);
      86                 :             :     }
      87                 :             : 
      88         [ -  + ]:           1 :   g_clear_object (&self->launcher);
      89                 :           1 : }
      90                 :             : 
      91                 :             : static void
      92                 :           0 : launcher_watch (GSubprocess  *subprocess,
      93                 :             :                 GAsyncResult *result,
      94                 :             :                 GHashTable   *subprocesses)
      95                 :             : {
      96                 :           0 :   g_autoptr (GError) error = NULL;
      97                 :             : 
      98   [ #  #  #  # ]:           0 :   if (!g_subprocess_wait_finish (subprocess, result, &error) &&
      99                 :           0 :       !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
     100                 :           0 :     g_warning ("Process failed: %s", error->message);
     101                 :             : 
     102                 :           0 :   g_hash_table_remove (subprocesses, subprocess);
     103         [ #  # ]:           0 :   g_hash_table_unref (subprocesses);
     104                 :           0 : }
     105                 :             : 
     106                 :             : static gboolean
     107                 :           1 : launcher_execute (ValentRuncommandPlugin  *self,
     108                 :             :                   GVariant                *command,
     109                 :             :                   GError                 **error)
     110                 :             : {
     111                 :           2 :   g_autoptr (GSubprocess) subprocess = NULL;
     112         [ +  - ]:           1 :   g_autoptr (GString) args = NULL;
     113                 :           1 :   g_auto (GStrv) argv = NULL;
     114         [ +  - ]:           1 :   g_autofree char *command_quoted = NULL;
     115                 :           1 :   const char *command_args = "";
     116                 :             : 
     117         [ +  - ]:           1 :   g_assert (VALENT_IS_RUNCOMMAND_PLUGIN (self));
     118   [ +  -  -  + ]:           1 :   g_assert (command != NULL && g_variant_is_of_type (command, G_VARIANT_TYPE_VARDICT));
     119   [ +  -  -  + ]:           1 :   g_assert (error == NULL || *error == NULL);
     120                 :             : 
     121                 :           1 :   launcher_init (self);
     122                 :             : 
     123                 :           1 :   args = g_string_new ("");
     124                 :           1 :   g_variant_lookup (command, "command", "&s", &command_args);
     125                 :             : 
     126                 :             : 
     127                 :             :   /* When running in a Flatpak, run the command on the host if possible */
     128   [ -  +  -  - ]:           1 :   if (xdp_portal_running_under_flatpak () &&
     129                 :           0 :       valent_runcommand_can_spawn_host ())
     130         [ #  # ]:           0 :     g_string_append (args, "flatpak-spawn --host ");
     131                 :             : 
     132                 :             :   /* Quote the arguments for the shell */
     133                 :           1 :   command_quoted = g_shell_quote (command_args);
     134                 :           1 :   g_string_append_printf (args, "sh -c %s", command_quoted);
     135                 :             : 
     136         [ -  + ]:           1 :   if (!g_shell_parse_argv (args->str, NULL, &argv, error))
     137                 :             :     return FALSE;
     138                 :             : 
     139                 :           1 :   subprocess = g_subprocess_launcher_spawnv (self->launcher,
     140                 :             :                                              (const char * const *)argv,
     141                 :             :                                              error);
     142                 :             : 
     143         [ -  + ]:           1 :   if (subprocess == NULL)
     144                 :             :     return FALSE;
     145                 :             : 
     146                 :             :   /* The task holds the final reference to the GSubprocess object */
     147                 :           1 :   g_subprocess_wait_async (subprocess,
     148                 :             :                            NULL,
     149                 :             :                            (GAsyncReadyCallback)launcher_watch,
     150                 :           1 :                            g_hash_table_ref (self->subprocesses));
     151                 :           1 :   g_hash_table_add (self->subprocesses, subprocess);
     152                 :             : 
     153                 :           1 :   return TRUE;
     154                 :             : }
     155                 :             : 
     156                 :             : /*
     157                 :             :  * Local Commands
     158                 :             :  */
     159                 :             : static void
     160                 :           1 : on_commands_changed (GSettings              *settings,
     161                 :             :                      const char             *key,
     162                 :             :                      ValentRuncommandPlugin *self)
     163                 :             : {
     164                 :           1 :   ValentDevice *device;
     165                 :           1 :   ValentDeviceState state;
     166                 :             : 
     167   [ +  -  +  -  :           1 :   g_assert (G_IS_SETTINGS (settings));
             -  +  -  - ]
     168         [ -  + ]:           1 :   g_assert (key != NULL);
     169         [ -  + ]:           1 :   g_assert (VALENT_IS_RUNCOMMAND_PLUGIN (self));
     170                 :             : 
     171                 :           1 :   device = valent_extension_get_object (VALENT_EXTENSION (self));
     172                 :           1 :   state = valent_device_get_state (device);
     173                 :             : 
     174         [ +  - ]:           1 :   if ((state & VALENT_DEVICE_STATE_CONNECTED) != 0 &&
     175                 :             :       (state & VALENT_DEVICE_STATE_PAIRED) != 0)
     176                 :           1 :     valent_runcommand_plugin_send_command_list (self);
     177                 :           1 : }
     178                 :             : 
     179                 :             : static void
     180                 :           1 : valent_runcommand_plugin_execute_local_command (ValentRuncommandPlugin *self,
     181                 :             :                                                 const char             *key)
     182                 :             : {
     183                 :           1 :   GSettings *settings;
     184                 :           1 :   g_autoptr (GVariant) commands = NULL;
     185   [ +  -  -  - ]:           1 :   g_autoptr (GVariant) command = NULL;
     186   [ +  -  -  - ]:           1 :   g_autoptr (GError) error = NULL;
     187                 :             : 
     188         [ +  - ]:           1 :   g_assert (VALENT_IS_RUNCOMMAND_PLUGIN (self));
     189         [ -  + ]:           1 :   g_return_if_fail (key != NULL);
     190                 :             : 
     191                 :             :   /* Lookup the command by UUID */
     192                 :           1 :   settings = valent_extension_get_settings (VALENT_EXTENSION (self));
     193                 :           1 :   commands = g_settings_get_value (settings, "commands");
     194                 :             : 
     195         [ -  + ]:           1 :   if (!g_variant_lookup (commands, key, "@a{sv}", &command))
     196                 :           0 :     return valent_runcommand_plugin_send_command_list (self);
     197                 :             : 
     198         [ -  + ]:           1 :   if (!launcher_execute (self, command, &error))
     199                 :           0 :     g_warning ("%s(): %s", G_STRFUNC, error->message);
     200                 :             : }
     201                 :             : 
     202                 :             : static void
     203                 :           5 : valent_runcommand_plugin_send_command_list (ValentRuncommandPlugin *self)
     204                 :             : {
     205                 :           5 :   GSettings *settings;
     206                 :          10 :   g_autoptr (JsonBuilder) builder = NULL;
     207         [ -  + ]:           5 :   g_autoptr (JsonNode) packet = NULL;
     208         [ +  - ]:           5 :   g_autoptr (GVariant) commands = NULL;
     209         [ +  - ]:           5 :   g_autoptr (JsonBuilder) commands_builder = NULL;
     210         [ +  - ]:           5 :   g_autoptr (JsonNode) commands_node = NULL;
     211         [ +  - ]:           5 :   g_autofree char *commands_json = NULL;
     212                 :           5 :   GVariantIter iter;
     213                 :           5 :   char *key;
     214                 :           5 :   GVariant *value;
     215                 :             : 
     216         [ +  - ]:           5 :   g_assert (VALENT_IS_RUNCOMMAND_PLUGIN (self));
     217                 :             : 
     218                 :           5 :   settings = valent_extension_get_settings (VALENT_EXTENSION (self));
     219                 :           5 :   commands = g_settings_get_value (settings, "commands");
     220                 :             : 
     221                 :             :   /* The `commandList` dictionary is sent as a string of serialized JSON */
     222                 :           5 :   commands_builder = json_builder_new ();
     223                 :           5 :   json_builder_begin_object (commands_builder);
     224                 :             : 
     225                 :           5 :   g_variant_iter_init (&iter, commands);
     226                 :             : 
     227         [ +  + ]:           7 :   while (g_variant_iter_next (&iter, "{sv}", &key, &value))
     228                 :             :     {
     229                 :           2 :       const char *name = NULL;
     230                 :           2 :       const char *command = NULL;
     231                 :             : 
     232   [ +  -  +  - ]:           4 :       if (g_variant_lookup (value, "name", "&s", &name) &&
     233                 :           2 :           g_variant_lookup (value, "command", "&s", &command))
     234                 :             :         {
     235                 :           2 :           json_builder_set_member_name (commands_builder, key);
     236                 :           2 :           json_builder_begin_object (commands_builder);
     237                 :           2 :           json_builder_set_member_name (commands_builder, "name");
     238                 :           2 :           json_builder_add_string_value (commands_builder, name);
     239                 :           2 :           json_builder_set_member_name (commands_builder, "command");
     240                 :           2 :           json_builder_add_string_value (commands_builder, command);
     241                 :           2 :           json_builder_end_object (commands_builder);
     242                 :             :         }
     243                 :             : 
     244         [ +  - ]:           2 :       g_clear_pointer (&key, g_free);
     245         [ +  - ]:           2 :       g_clear_pointer (&value, g_variant_unref);
     246                 :             :     }
     247                 :             : 
     248                 :           5 :   json_builder_end_object (commands_builder);
     249                 :           5 :   commands_node = json_builder_get_root (commands_builder);
     250                 :           5 :   commands_json = json_to_string (commands_node, FALSE);
     251                 :             : 
     252                 :           5 :   valent_packet_init (&builder, "kdeconnect.runcommand");
     253                 :           5 :   json_builder_set_member_name (builder, "commandList");
     254                 :           5 :   json_builder_add_string_value (builder, commands_json);
     255                 :           5 :   packet = valent_packet_end (&builder);
     256                 :             : 
     257                 :           5 :   valent_device_plugin_queue_packet (VALENT_DEVICE_PLUGIN (self), packet);
     258                 :           5 : }
     259                 :             : 
     260                 :             : static void
     261                 :           2 : valent_runcommand_plugin_handle_runcommand_request (ValentRuncommandPlugin *self,
     262                 :             :                                                     JsonNode               *packet)
     263                 :             : {
     264                 :           2 :   const char *key;
     265                 :             : 
     266         [ +  - ]:           2 :   g_assert (VALENT_IS_RUNCOMMAND_PLUGIN (self));
     267         [ -  + ]:           2 :   g_assert (VALENT_IS_PACKET (packet));
     268                 :             : 
     269                 :             :   /* A request for the local command list */
     270         [ +  + ]:           2 :   if (valent_packet_check_field (packet, "requestCommandList"))
     271                 :           1 :     valent_runcommand_plugin_send_command_list (self);
     272                 :             : 
     273                 :             :   /* A request to execute a local command */
     274         [ +  + ]:           2 :   if (valent_packet_get_string (packet, "key", &key))
     275                 :           1 :     valent_runcommand_plugin_execute_local_command (self, key);
     276                 :           2 : }
     277                 :             : 
     278                 :             : /*
     279                 :             :  * Remote Commands
     280                 :             :  */
     281                 :             : static void
     282                 :           1 : valent_runcommand_plugin_execute_remote_command (ValentRuncommandPlugin *self,
     283                 :             :                                                  const char             *key)
     284                 :             : {
     285                 :           2 :   g_autoptr (JsonBuilder) builder = NULL;
     286         [ -  + ]:           1 :   g_autoptr (JsonNode) packet = NULL;
     287                 :             : 
     288         [ +  - ]:           1 :   g_assert (VALENT_IS_RUNCOMMAND_PLUGIN (self));
     289         [ -  + ]:           1 :   g_assert (key != NULL);
     290                 :             : 
     291                 :           1 :   valent_packet_init (&builder, "kdeconnect.runcommand.request");
     292                 :           1 :   json_builder_set_member_name (builder, "key");
     293                 :           1 :   json_builder_add_string_value (builder, key);
     294                 :           1 :   packet = valent_packet_end (&builder);
     295                 :             : 
     296         [ +  - ]:           1 :   valent_device_plugin_queue_packet (VALENT_DEVICE_PLUGIN (self), packet);
     297                 :           1 : }
     298                 :             : 
     299                 :             : static void
     300                 :           1 : valent_runcommand_plugin_handle_command_list (ValentRuncommandPlugin *self,
     301                 :             :                                               JsonObject             *command_list)
     302                 :             : {
     303                 :           1 :   JsonObjectIter iter;
     304                 :           1 :   const char *key;
     305                 :           1 :   JsonNode *command_node;
     306                 :           2 :   g_autoptr (GMenuItem) cmd_item = NULL;
     307         [ +  - ]:           1 :   g_autoptr (GIcon) cmd_icon = NULL;
     308         [ +  - ]:           1 :   g_autoptr (GMenu) cmd_menu = NULL;
     309                 :           1 :   GAction *commands;
     310                 :             : 
     311         [ +  - ]:           1 :   g_assert (VALENT_IS_RUNCOMMAND_PLUGIN (self));
     312         [ -  + ]:           1 :   g_assert (command_list != NULL);
     313                 :             : 
     314                 :           1 :   cmd_menu = g_menu_new ();
     315                 :             : 
     316                 :           1 :   cmd_icon = g_themed_icon_new ("system-run-symbolic");
     317                 :           1 :   cmd_item = g_menu_item_new (_("Run Command"), "device.runcommand.commands");
     318                 :           1 :   g_menu_item_set_icon (cmd_item, cmd_icon);
     319                 :           1 :   g_menu_item_set_attribute (cmd_item, "hidden-when", "s", "action-disabled");
     320                 :           1 :   g_menu_item_set_submenu (cmd_item, G_MENU_MODEL (cmd_menu));
     321                 :             : 
     322                 :             :   /* Iterate the commands */
     323                 :           1 :   json_object_iter_init (&iter, command_list);
     324                 :             : 
     325         [ +  + ]:           3 :   while (json_object_iter_next (&iter, &key, &command_node))
     326                 :             :     {
     327                 :           2 :       JsonObject *cmd;
     328                 :           2 :       const char *name;
     329                 :           2 :       const char *command;
     330                 :           2 :       g_autofree char *action = NULL;
     331                 :           2 :       g_autoptr (GMenuItem) item = NULL;
     332                 :             : 
     333                 :           2 :       cmd = json_node_get_object (command_node);
     334                 :           2 :       name = json_object_get_string_member (cmd, "name");
     335                 :           2 :       command = json_object_get_string_member (cmd, "command");
     336                 :           2 :       action = g_strdup_printf ("device.runcommand.execute::%s", key);
     337                 :             : 
     338                 :           2 :       item = g_menu_item_new (name, action);
     339                 :           2 :       g_menu_item_set_attribute (item, "command", "s", command);
     340         [ +  - ]:           2 :       g_menu_append_item (cmd_menu, item);
     341                 :             :     }
     342                 :             : 
     343                 :           1 :   commands = g_action_map_lookup_action (G_ACTION_MAP (self), "commands");
     344                 :           1 :   g_simple_action_set_enabled (G_SIMPLE_ACTION (commands),
     345                 :           1 :                                json_object_get_size (command_list) > 0);
     346         [ +  - ]:           1 :   valent_device_plugin_set_menu_item (VALENT_DEVICE_PLUGIN (self),
     347                 :             :                                       "device.runcommand.commands",
     348                 :             :                                       cmd_item);
     349                 :           1 : }
     350                 :             : 
     351                 :             : static void
     352                 :           1 : valent_runcommand_plugin_handle_runcommand (ValentRuncommandPlugin *self,
     353                 :             :                                             JsonNode               *packet)
     354                 :             : {
     355                 :           1 :   JsonObject *body;
     356                 :           1 :   g_autoptr (JsonNode) command_node = NULL;
     357                 :           1 :   const char *command_json;
     358                 :           1 :   JsonObject *command_list;
     359                 :             : 
     360         [ +  - ]:           1 :   g_assert (VALENT_IS_RUNCOMMAND_PLUGIN (self));
     361         [ -  + ]:           1 :   g_assert (VALENT_IS_PACKET (packet));
     362                 :             : 
     363                 :           1 :   body = valent_packet_get_body (packet);
     364                 :           1 :   command_json = json_object_get_string_member_with_default (body, "commandList", "{}");
     365                 :           1 :   command_node = json_from_string (command_json, NULL);
     366                 :             : 
     367   [ +  -  -  + ]:           1 :   if (command_node == NULL || !JSON_NODE_HOLDS_OBJECT (command_node))
     368                 :             :     {
     369                 :           0 :       g_warning ("%s(): malformed commandList field", G_STRFUNC);
     370         [ #  # ]:           0 :       return;
     371                 :             :     }
     372                 :             : 
     373                 :           1 :   command_list = json_node_get_object (command_node);
     374                 :           1 :   valent_runcommand_plugin_handle_command_list (self, command_list);
     375                 :             : }
     376                 :             : 
     377                 :             : /*
     378                 :             :  * GActions
     379                 :             :  */
     380                 :             : static void
     381                 :           0 : runcommand_commands_action (GSimpleAction *action,
     382                 :             :                             GVariant      *parameter,
     383                 :             :                             gpointer       user_data)
     384                 :             : {
     385                 :             :   // Mock action
     386                 :           0 : }
     387                 :             : 
     388                 :             : static void
     389                 :           1 : runcommand_execute_action (GSimpleAction *action,
     390                 :             :                            GVariant      *parameter,
     391                 :             :                            gpointer       user_data)
     392                 :             : {
     393                 :           1 :   ValentRuncommandPlugin *self = VALENT_RUNCOMMAND_PLUGIN (user_data);
     394                 :           1 :   const char *key;
     395                 :             : 
     396         [ +  - ]:           1 :   g_return_if_fail (VALENT_IS_RUNCOMMAND_PLUGIN (self));
     397                 :             : 
     398                 :           1 :   key = g_variant_get_string (parameter, NULL);
     399                 :           1 :   valent_runcommand_plugin_execute_remote_command (self, key);
     400                 :             : }
     401                 :             : 
     402                 :             : static const GActionEntry actions[] = {
     403                 :             :     {"commands", runcommand_commands_action, NULL, NULL, NULL}, // "as"
     404                 :             :     {"execute",  runcommand_execute_action,   "s", NULL, NULL}
     405                 :             : };
     406                 :             : 
     407                 :             : /**
     408                 :             :  * ValentDevicePlugin
     409                 :             :  */
     410                 :             : static void
     411                 :          10 : valent_runcommand_plugin_update_state (ValentDevicePlugin *plugin,
     412                 :             :                                        ValentDeviceState   state)
     413                 :             : {
     414                 :          10 :   ValentRuncommandPlugin *self = VALENT_RUNCOMMAND_PLUGIN (plugin);
     415                 :          10 :   GSettings *settings;
     416                 :          10 :   gboolean available;
     417                 :             : 
     418         [ +  - ]:          10 :   g_assert (VALENT_IS_RUNCOMMAND_PLUGIN (self));
     419                 :             : 
     420                 :          10 :   available = (state & VALENT_DEVICE_STATE_CONNECTED) != 0 &&
     421                 :             :               (state & VALENT_DEVICE_STATE_PAIRED) != 0;
     422                 :             : 
     423                 :          10 :   valent_extension_toggle_actions (VALENT_EXTENSION (plugin), available);
     424                 :             : 
     425                 :          10 :   settings = valent_extension_get_settings (VALENT_EXTENSION (plugin));
     426                 :             : 
     427         [ +  + ]:          10 :   if (available)
     428                 :             :     {
     429         [ +  - ]:           3 :       if (self->commands_changed_id == 0)
     430                 :             :         {
     431                 :           3 :           self->commands_changed_id =
     432                 :           3 :             g_signal_connect_object (settings,
     433                 :             :                                      "changed::commands",
     434                 :             :                                      G_CALLBACK (on_commands_changed),
     435                 :             :                                      self, 0);
     436                 :             :         }
     437                 :             : 
     438                 :           3 :       valent_runcommand_plugin_send_command_list (self);
     439                 :             :     }
     440                 :             :   else
     441                 :             :     {
     442         [ +  + ]:           7 :       g_clear_signal_handler (&self->commands_changed_id, settings);
     443                 :             :     }
     444                 :             : 
     445                 :             :   /* If the device is unpaired it is no longer trusted */
     446         [ +  + ]:          10 :   if ((state & VALENT_DEVICE_STATE_PAIRED) == 0)
     447                 :           1 :     launcher_clear (self);
     448                 :          10 : }
     449                 :             : 
     450                 :             : static void
     451                 :           3 : valent_runcommand_plugin_handle_packet (ValentDevicePlugin *plugin,
     452                 :             :                                         const char         *type,
     453                 :             :                                         JsonNode           *packet)
     454                 :             : {
     455                 :           3 :   ValentRuncommandPlugin *self = VALENT_RUNCOMMAND_PLUGIN (plugin);
     456                 :             : 
     457         [ +  - ]:           3 :   g_assert (VALENT_IS_DEVICE_PLUGIN (plugin));
     458         [ -  + ]:           3 :   g_assert (type != NULL);
     459         [ -  + ]:           3 :   g_assert (VALENT_IS_PACKET (packet));
     460                 :             : 
     461                 :             :   /* A request for the local command list or local execution */
     462         [ +  + ]:           3 :   if (g_str_equal (type, "kdeconnect.runcommand.request"))
     463                 :           2 :     valent_runcommand_plugin_handle_runcommand_request (self, packet);
     464                 :             : 
     465                 :             :   /* A response to a request for the remote command list */
     466         [ +  - ]:           1 :   else if (g_str_equal (type, "kdeconnect.runcommand"))
     467                 :           1 :     valent_runcommand_plugin_handle_runcommand (self, packet);
     468                 :             : 
     469                 :             :   else
     470                 :           0 :     g_assert_not_reached ();
     471                 :           3 : }
     472                 :             : 
     473                 :             : /*
     474                 :             :  * ValentObject
     475                 :             :  */
     476                 :             : static void
     477                 :           6 : valent_runcommand_plugin_destroy (ValentObject *object)
     478                 :             : {
     479                 :           6 :   ValentRuncommandPlugin *self = VALENT_RUNCOMMAND_PLUGIN (object);
     480                 :           6 :   ValentDevicePlugin *plugin = VALENT_DEVICE_PLUGIN (object);
     481                 :           6 :   GSettings *settings;
     482                 :             : 
     483                 :             :   /* Stop watching for command changes */
     484                 :           6 :   settings = valent_extension_get_settings (VALENT_EXTENSION (plugin));
     485         [ -  + ]:           6 :   g_clear_signal_handler (&self->commands_changed_id, settings);
     486                 :             : 
     487                 :           6 :   VALENT_OBJECT_CLASS (valent_runcommand_plugin_parent_class)->destroy (object);
     488                 :           6 : }
     489                 :             : 
     490                 :             : /*
     491                 :             :  * GObject
     492                 :             :  */
     493                 :             : static void
     494                 :           3 : valent_runcommand_plugin_constructed (GObject *object)
     495                 :             : {
     496                 :           3 :   ValentDevicePlugin *plugin = VALENT_DEVICE_PLUGIN (object);
     497                 :             : 
     498                 :           3 :   g_action_map_add_action_entries (G_ACTION_MAP (plugin),
     499                 :             :                                    actions,
     500                 :             :                                    G_N_ELEMENTS (actions),
     501                 :             :                                    plugin);
     502                 :             : 
     503                 :           3 :   G_OBJECT_CLASS (valent_runcommand_plugin_parent_class)->constructed (object);
     504                 :           3 : }
     505                 :             : 
     506                 :             : static void
     507                 :           3 : valent_runcommand_plugin_finalize (GObject *object)
     508                 :             : {
     509                 :           3 :   ValentRuncommandPlugin *self = VALENT_RUNCOMMAND_PLUGIN (object);
     510                 :             : 
     511         [ +  + ]:           3 :   g_clear_object (&self->launcher);
     512         [ +  - ]:           3 :   g_clear_pointer (&self->subprocesses, g_hash_table_unref);
     513                 :             : 
     514                 :           3 :   G_OBJECT_CLASS (valent_runcommand_plugin_parent_class)->finalize (object);
     515                 :           3 : }
     516                 :             : 
     517                 :             : static void
     518                 :           2 : valent_runcommand_plugin_class_init (ValentRuncommandPluginClass *klass)
     519                 :             : {
     520                 :           2 :   GObjectClass *object_class = G_OBJECT_CLASS (klass);
     521                 :           2 :   ValentObjectClass *vobject_class = VALENT_OBJECT_CLASS (klass);
     522                 :           2 :   ValentDevicePluginClass *plugin_class = VALENT_DEVICE_PLUGIN_CLASS (klass);
     523                 :             : 
     524                 :           2 :   object_class->constructed = valent_runcommand_plugin_constructed;
     525                 :           2 :   object_class->finalize = valent_runcommand_plugin_finalize;
     526                 :             : 
     527                 :           2 :   vobject_class->destroy = valent_runcommand_plugin_destroy;
     528                 :             : 
     529                 :           2 :   plugin_class->handle_packet = valent_runcommand_plugin_handle_packet;
     530                 :           2 :   plugin_class->update_state = valent_runcommand_plugin_update_state;
     531                 :             : }
     532                 :             : 
     533                 :             : static void
     534                 :           3 : valent_runcommand_plugin_init (ValentRuncommandPlugin *self)
     535                 :             : {
     536                 :           3 :   self->subprocesses = g_hash_table_new (NULL, NULL);
     537                 :           3 : }
     538                 :             : 
        

Generated by: LCOV version 2.0-1