[gnome-software/mwleeds/pwa-plugin: 3/3] WIP: Fix epiphany self test




commit 0490e0a3cbf7fb4092a60fc0092e1479c7eea8a0
Author: Phaedrus Leeds <mwleeds protonmail com>
Date:   Fri Feb 25 20:39:52 2022 -0800

    WIP: Fix epiphany self test

 plugins/epiphany/gs-self-test.c                    | 164 ++++++++--
 plugins/epiphany/meson.build                       |  23 ++
 .../org.freedesktop.portal.DynamicLauncher.xml     | 330 +++++++++++++++++++++
 3 files changed, 495 insertions(+), 22 deletions(-)
---
diff --git a/plugins/epiphany/gs-self-test.c b/plugins/epiphany/gs-self-test.c
index e8d76d534..3c043710d 100644
--- a/plugins/epiphany/gs-self-test.c
+++ b/plugins/epiphany/gs-self-test.c
@@ -12,34 +12,139 @@
 #include "gnome-software-private.h"
 
 #include "gs-test.h"
+#include "gs-dynamic-launcher-portal-iface.h"
+#include "gs-epiphany-generated.h"
+
+#include <libglib-testing/dbus-queue.h>
+
+/* This is run in a worker thread */
+static void
+epiphany_and_portal_mock_server_cb (GtDBusQueue *queue,
+                                   gpointer     user_data)
+{
+       {
+               g_autoptr(GDBusMethodInvocation) invocation = NULL;
+               g_autoptr(GVariant) properties_variant = NULL;
+               const char *property_interface;
+               invocation = gt_dbus_queue_assert_pop_message (queue,
+                                                              "/org/gnome/Epiphany/WebAppProvider",
+                                                              "org.freedesktop.DBus.Properties",
+                                                              "GetAll", "(&s)",
+                                                              &property_interface);
+               g_assert_cmpstr (property_interface, ==, "org.gnome.Epiphany.WebAppProvider");
+               properties_variant = g_variant_ref_sink (g_variant_new_parsed ("{'Version': <@u 1>}"));
+               g_dbus_method_invocation_return_value (invocation, g_variant_new_tuple (&properties_variant, 
1));
+       }
+       {
+               g_autoptr(GDBusMethodInvocation) invocation = NULL;
+               const char *property_interface;
+               const char *property_name;
+               g_autoptr(GVariant) property_variant = NULL;
+               invocation = gt_dbus_queue_assert_pop_message (queue,
+                                                              "/org/freedesktop/portal/desktop",
+                                                              "org.freedesktop.DBus.Properties",
+                                                              "Get", "(&s&s)",
+                                                              &property_interface, &property_name);
+               g_assert_cmpstr (property_interface, ==, "org.freedesktop.portal.DynamicLauncher");
+               g_assert_cmpstr (property_name, ==, "version");
+               property_variant = g_variant_ref_sink (g_variant_new_variant (g_variant_new_uint32 (1)));
+               g_dbus_method_invocation_return_value (invocation, g_variant_new_tuple (&property_variant, 
1));
+       }
+       {
+               g_autoptr(GDBusMethodInvocation) invocation = NULL;
+               g_autoptr(GVariant) properties_variant = NULL;
+               const char *property_interface, *props_dict;
+               invocation = gt_dbus_queue_assert_pop_message (queue,
+                                                              "/org/freedesktop/portal/desktop",
+                                                              "org.freedesktop.DBus.Properties",
+                                                              "GetAll", "(&s)",
+                                                              &property_interface);
+               g_assert_cmpstr (property_interface, ==, "org.freedesktop.portal.DynamicLauncher");
+               props_dict = "{'version': <@u 1>,'SupportedLauncherTypes': <@u 3>}";
+               properties_variant = g_variant_ref_sink (g_variant_new_parsed (props_dict));
+               g_dbus_method_invocation_return_value (invocation, g_variant_new_tuple (&properties_variant, 
1));
+       }
+       {
+               g_autoptr(GDBusMethodInvocation) invocation = NULL;
+               const char *installed_apps[] = 
{"org.gnome.Epiphany.WebApp_e9d0e1e4b0a10856aa3b38d9eb4375de4070d043.desktop", NULL};
+               invocation = gt_dbus_queue_assert_pop_message (queue,
+                                                              "/org/gnome/Epiphany/WebAppProvider",
+                                                              "org.gnome.Epiphany.WebAppProvider",
+                                                              "GetInstalledApps", "()", NULL);
+               g_dbus_method_invocation_return_value (invocation, g_variant_new ("(^as)", installed_apps));
+       }
+}
+
+static GtDBusQueue *
+bus_set_up (void)
+{
+  g_autoptr(GError) local_error = NULL;
+  g_autoptr(GtDBusQueue) queue = NULL;
+
+  queue = gt_dbus_queue_new ();
+
+  gt_dbus_queue_connect (queue, &local_error);
+  g_assert_no_error (local_error);
+
+  gt_dbus_queue_own_name (queue, "org.freedesktop.portal.Desktop");
+
+  gt_dbus_queue_export_object (queue,
+                               "/org/freedesktop/portal/desktop",
+                               (GDBusInterfaceInfo *) &org_freedesktop_portal_dynamic_launcher_interface,
+                               &local_error);
+  g_assert_no_error (local_error);
+
+  gt_dbus_queue_own_name (queue, "org.gnome.Epiphany.WebAppProvider");
+
+  gt_dbus_queue_export_object (queue,
+                               "/org/gnome/Epiphany/WebAppProvider",
+                               gs_ephy_web_app_provider_interface_info (),
+                               &local_error);
+  g_assert_no_error (local_error);
+
+  gt_dbus_queue_set_server_func (queue, epiphany_and_portal_mock_server_cb,
+                                NULL);
+
+  return g_steal_pointer (&queue);
+}
 
 static void
 gs_plugins_epiphany_func (GsPluginLoader *plugin_loader)
 {
-       gboolean ret;
-       g_autoptr(GError) error = NULL;
-       g_autoptr(GsApp) app = NULL;
+       g_assert_true (gs_plugin_loader_get_enabled (plugin_loader, "epiphany"));
+}
+
+static void
+gs_plugins_epiphany_installed_func (GsPluginLoader *plugin_loader)
+{
        g_autoptr(GsPluginJob) plugin_job = NULL;
-       GsPlugin *plugin;
-
-       /* no epiphany, abort */
-       if (!gs_plugin_loader_get_enabled (plugin_loader, "epiphany"))
-               return;
-
-       /* a webapp with a local icon */
-       app = gs_app_new ("app.squoosh.webapp.desktop");
-       gs_app_set_kind (app, AS_COMPONENT_KIND_WEB_APP);
-       plugin = gs_plugin_loader_find_plugin (plugin_loader, "epiphany");
-       gs_app_set_management_plugin (app, plugin);
-       plugin_job = gs_plugin_job_refine_new_for_app (app,
-                                                      GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON);
-       ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
+       g_autoptr(GError) error = NULL;
+       g_autoptr(GIcon) icon = NULL;
+       g_autoptr(GsAppList) list = NULL;
+       GsApp *app;
+
+       plugin_job = gs_plugin_job_list_installed_apps_new (GS_PLUGIN_REFINE_FLAGS_REQUIRE_ORIGIN,
+                                                           0, GS_PLUGIN_JOB_DEDUPE_FLAGS_DEFAULT);
+       list = gs_plugin_loader_job_process (plugin_loader, plugin_job, NULL, &error);
        gs_test_flush_main_context ();
        g_assert_no_error (error);
-       g_assert_true (ret);
+       g_assert (list != NULL);
 
-       g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_AVAILABLE);
-       g_assert_nonnull (gs_app_get_icons (app));
+       g_assert_cmpint (gs_app_list_length (list), ==, 1);
+       app = gs_app_list_index (list, 0);
+       g_assert_cmpstr (gs_app_get_id (app), ==, 
"org.gnome.Epiphany.WebApp_e9d0e1e4b0a10856aa3b38d9eb4375de4070d043.desktop");
+       g_assert_cmpint (gs_app_get_kind (app), ==, AS_COMPONENT_KIND_WEB_APP);
+       g_assert_cmpint (gs_app_get_scope (app), ==, AS_COMPONENT_SCOPE_USER);
+       g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_INSTALLED);
+       g_assert_cmpstr (gs_app_get_name (app), ==, "Pinafore");
+       g_assert_cmpstr (gs_app_get_summary (app), ==, "Pinafore is a web client for Mastodon");
+       g_assert_cmpstr (gs_app_get_origin (app), ==, "gnome-web");
+       g_assert_cmpstr (gs_app_get_origin_ui (app), ==, "GNOME Web");
+       g_assert_cmpstr (gs_app_get_license (app), ==, "AGPL-3.0-only");
+       g_assert (gs_app_get_license_is_free (app));
+       icon = gs_app_get_icon_for_size (app, 128, 1, NULL);
+       g_assert_nonnull (icon);
+       g_clear_object (&icon);
 }
 
 int
@@ -50,6 +155,8 @@ main (int argc, char **argv)
        g_autofree gchar *xml = NULL;
        g_autoptr(GError) error = NULL;
        g_autoptr(GsPluginLoader) plugin_loader = NULL;
+       g_autoptr(GtDBusQueue) queue = NULL;
+       int res;
        const gchar *allowlist[] = {
                "appstream",
                "epiphany",
@@ -61,6 +168,11 @@ main (int argc, char **argv)
        g_setenv ("G_MESSAGES_DEBUG", "all", TRUE);
        g_setenv ("GS_XMLB_VERBOSE", "1", TRUE);
 
+       /* Set up mock D-Bus services for the Epiphany WebAppProvider and the
+        * DynamicLauncher portal
+        */
+       queue = bus_set_up ();
+
        /* Use an icon we already have locally */
        fn = gs_test_get_filename (TESTDATADIR, "icons/hicolor/scalable/org.gnome.Software.svg");
        g_assert (fn != NULL);
@@ -95,15 +207,23 @@ main (int argc, char **argv)
        ret = gs_plugin_loader_setup (plugin_loader,
                                      (gchar**) allowlist,
                                      NULL,
+                                     gt_dbus_queue_get_client_connection (queue),
                                      NULL,
                                      &error);
        g_assert_no_error (error);
        g_assert_true (ret);
 
+       //TODO figure out how to create a .desktop file somewhere it will be seen by g_desktop_app_info_new ()
+
        /* plugin tests go here */
-       g_test_add_data_func ("/gnome-software/plugins/epiphany",
+       g_test_add_data_func ("/gnome-software/plugins/epiphany/enabled",
                              plugin_loader,
                              (GTestDataFunc) gs_plugins_epiphany_func);
+       g_test_add_data_func ("/gnome-software/plugins/epiphany/installed",
+                             plugin_loader,
+                             (GTestDataFunc) gs_plugins_epiphany_installed_func);
 
-       return g_test_run ();
+       res = g_test_run ();
+       gt_dbus_queue_disconnect (queue, TRUE);
+       return res;
 }
diff --git a/plugins/epiphany/meson.build b/plugins/epiphany/meson.build
index d73e1d1d5..c436fb278 100644
--- a/plugins/epiphany/meson.build
+++ b/plugins/epiphany/meson.build
@@ -35,6 +35,25 @@ i18n.merge_file(
 )
 
 if get_option('tests')
+  gdbus_codegen = find_program('gdbus-codegen')
+  dynamic_launcher_portal_iface_h = custom_target(
+    'gs-dynamic-launcher-portal-iface.h',
+    input: ['org.freedesktop.portal.DynamicLauncher.xml'],
+    output: ['gs-dynamic-launcher-portal-iface.h'],
+    command: [gdbus_codegen,
+              '--interface-info-header',
+              '--output', '@OUTPUT@',
+              '@INPUT@'],
+  )
+  dynamic_launcher_portal_iface_c = custom_target(
+    'gs-dynamic-launcher-portal-iface.c',
+    input: ['org.freedesktop.portal.DynamicLauncher.xml'],
+    output: ['gs-dynamic-launcher-portal-iface.c'],
+    command: [gdbus_codegen,
+              '--interface-info-body',
+              '--output', '@OUTPUT@',
+              '@INPUT@'],
+  )
   cargs += ['-DLOCALPLUGINDIR="' + meson.current_build_dir() + '"']
   cargs += ['-DLOCALPLUGINDIR_CORE="' + meson.current_build_dir() + '/../core"']
   cargs += ['-DTESTDATADIR="' + join_paths(meson.current_source_dir(), '..', '..', 'data') + '"']
@@ -43,6 +62,9 @@ if get_option('tests')
     compiled_schemas,
     sources : [
       'gs-self-test.c',
+      dynamic_launcher_portal_iface_c,
+      dynamic_launcher_portal_iface_h,
+      epiphany_generated,
     ],
     include_directories : [
       include_directories('../..'),
@@ -50,6 +72,7 @@ if get_option('tests')
     ],
     dependencies : [
       plugin_libs,
+      dependency('glib-testing-0', fallback: ['libglib-testing', 'libglib_testing_dep']),
     ],
     link_with : [
       libgnomesoftware
diff --git a/plugins/epiphany/org.freedesktop.portal.DynamicLauncher.xml 
b/plugins/epiphany/org.freedesktop.portal.DynamicLauncher.xml
new file mode 100644
index 000000000..8a525baaf
--- /dev/null
+++ b/plugins/epiphany/org.freedesktop.portal.DynamicLauncher.xml
@@ -0,0 +1,330 @@
+<?xml version="1.0"?>
+<!--
+ Copyright (C) 2021 Matthew Leeds
+
+ This library 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/>.
+
+ Author: Matthew Leeds <mwleeds protonmail com>
+-->
+
+<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd";>
+  <!--
+      org.freedesktop.portal.DynamicLauncher:
+      @short_description: Portal for installing application launchers onto the
+        desktop
+
+      The DynamicLauncher portal allows sandboxed (or unsandboxed) applications
+      to install launchers (.desktop files) which have an icon associated with them
+      and which execute a command in the application. The desktop environment
+      would display the launcher to the user in its menu of installed applications.
+      For example this can be used by a sandboxed browser to install web app
+      launchers. The portal also allows apps to uninstall the launchers, launch
+      them, and read the desktop file and icon data for them.
+
+      The standard way to install a launcher is to use the PrepareInstall() method
+      which results in a dialog being presented to the user so they can confirm
+      they want to install the launcher. Then, the token returned by PrepareInstall()
+      would be passed to the Install() method to complete the installation.
+
+      However, in the rare circumstance that an unsandboxed process such as a
+      system component needs to install a launcher without user interaction, this
+      can be accomplished by using the RequestInstallToken() method and passing
+      the acquired token to Install().
+
+      This documentation describes version 1 of this interface.
+  -->
+  <interface name="org.freedesktop.portal.DynamicLauncher">
+    <!--
+        Install:
+        @token: Token proving authorization of the installation
+        @desktop_file_id: The .desktop file name to be used
+        @desktop_entry: The text of the Desktop Entry file to be installed, see below
+        @options: Vardict with optional further information
+
+        Installs a .desktop launcher and icon into appropriate directories to
+        allow the desktop environment to find them. Please note that this method
+        overwrites any existing launcher with the same id. If you want to
+        present the user with a confirmation dialog in that case, you can check
+        for it using the GetDesktopEntry() method and clean up any state from
+        the previous launcher if you want.
+
+        @token must be a token that was returned by a previous
+        org.freedesktop.portal.DynamicLauncher.PrepareInstall() or
+        org.freedesktop.portal.DynamicLauncher.RequestInstallToken() call.
+        The token can only be used once and is valid for up to five minutes.
+
+        The icon and name used for the launcher will be the ones from the previous
+        org.freedesktop.portal.DynamicLauncher.PrepareInstall() or
+        org.freedesktop.portal.DynamicLauncher.RequestInstallToken() call.
+
+        The @desktop_file_id must have ".desktop" as a suffix. Except in the
+        special case when the calling process has no associated app ID,
+        @desktop_file_id must have the app ID followed by a period as a prefix,
+        regardless of whether the calling process is sandboxed or unsandboxed.
+
+        The @desktop_entry should be a valid desktop entry file beginning with
+        "[Desktop Entry]", except it should not include Name= or Icon= entries
+        (if present, these will be overwritten by the portal implementation).
+        The Exec= entry will be rewritten to call the sandboxed application e.g.
+        via "flatpak run", if the application is sandboxed.
+
+        It is recommended to include a TryExec= line with either a binary name
+        or an absolute path. The launcher will be deleted if the TryExec binary
+        cannot be found on session start.
+
+        The @options vardict currently has no supported entries.
+    -->
+    <method name="Install">
+      <arg type="s" name="token" direction="in"/>
+      <arg type="s" name="desktop_file_id" direction="in"/>
+      <arg type="s" name="desktop_entry" direction="in"/>
+      <arg type="a{sv}" name="options" direction="in"/>
+    </method>
+    <!--
+        PrepareInstall:
+        @parent_window: Identifier for the application window, see <link linkend="parent_window">Common 
Conventions</link>
+        @name: The default name for the launcher
+        @icon_v: A #GBytesIcon icon as returned by g_icon_serialize(). Must be
+          a png, jpeg, or svg and no larger than 512x512
+        @options: Vardict with optional further information
+        @handle: Object path for the #org.freedesktop.portal.Request object representing this call
+
+        Presents a dialog to the user to allow them to see the icon, potentially
+        change the name, and confirm installation of the launcher.
+
+        Supported keys in the @options vardict:
+        <variablelist>
+          <varlistentry>
+            <term>handle_token s</term>
+            <listitem><para>
+              A string that will be used as the last element of the @handle. Must be a valid
+              object path element. See the #org.freedesktop.portal.Request documentation for
+              more information about the @handle.
+            </para></listitem>
+          </varlistentry>
+          <varlistentry>
+            <term>modal b</term>
+            <listitem><para>
+              Whether to make the dialog modal. Defaults to yes.
+            </para></listitem>
+          </varlistentry>
+          <varlistentry>
+            <term>launcher_type u</term>
+            <listitem><para>
+              The type of launcher being created. For supported values see the
+              SupportedLauncherTypes property. Defaults to "Application".
+            </para></listitem>
+          </varlistentry>
+          <varlistentry>
+            <term>target s</term>
+            <listitem><para>
+              For a launcher of type "Webapp", this is the URL of the web app
+              being installed. This is displayed in the user-facing dialog.
+              For other launcher types, this is not needed.
+            </para></listitem>
+          </varlistentry>
+          <varlistentry>
+            <term>editable_name b</term>
+            <listitem><para>
+              If true, the user will be able to edit the name of the launcher.
+              Defaults to true.
+            </para></listitem>
+          </varlistentry>
+          <varlistentry>
+            <term>editable_icon b</term>
+            <listitem><para>
+              If true, the user will be able to edit the icon of the launcher,
+              if the implementation supports this. Defaults to false.
+            </para></listitem>
+          </varlistentry>
+        </variablelist>
+
+        The following results get returned via the #org.freedesktop.portal.Request::Response signal:
+        <variablelist>
+          <varlistentry>
+            <term>name s</term>
+            <listitem><para>
+              The name chosen by the user for the launcher.
+            </para></listitem>
+          </varlistentry>
+          <varlistentry>
+            <term>token s</term>
+            <listitem><para>
+              Token that can be passed to a subsequent org.freedesktop.portal.DynamicLauncher.Install() call 
to
+              complete the installation without another dialog.
+            </para></listitem>
+          </varlistentry>
+        </variablelist>
+    -->
+    <method name="PrepareInstall">
+      <arg type="s" name="parent_window" direction="in"/>
+      <arg type="s" name="name" direction="in"/>
+      <arg type="v" name="icon_v" direction="in"/>
+      <arg type="a{sv}" name="options" direction="in"/>
+      <arg type="o" name="handle" direction="out"/>
+    </method>
+    <!--
+        RequestInstallToken:
+        @name: The name that will be used in the desktop file
+        @icon_v: A #GBytesIcon icon as returned by g_icon_serialize(). Must be
+          a png, jpeg, or svg and no larger than 512x512
+        @options: Vardict with optional further information
+        @token: the token to be used with the Install() method
+
+        This method is intended for use only by trusted system components and
+        will fail if used by a sandboxed process. The token returned by this
+        method can be used to avoid the need for a confirmation dialog; the
+        token can be passed to the Install() method just as if it were acquired
+        via the PrepareInstall() method.
+
+        The @options vardict currently has no supported entries.
+    -->
+    <method name="RequestInstallToken">
+      <arg type="s" name="name" direction="in"/>
+      <arg type="v" name="icon_v" direction="in"/>
+      <arg type="a{sv}" name="options" direction="in"/>
+      <arg type="s" name="token" direction="out"/>
+    </method>
+    <!--
+        Uninstall:
+        @desktop_file_id: The .desktop file name
+        @options: Vardict with optional further information
+
+        This method deletes the desktop file and corresponding icon from the
+        appropriate directories to remove the launcher referred to by
+        @desktop_file_id.
+
+        The @desktop_file_id must have ".desktop" as a suffix. Except in the
+        special case when the calling process has no associated app ID,
+        @desktop_file_id must have the app ID followed by a period as a prefix,
+        regardless of whether the calling process is sandboxed or unsandboxed.
+
+        For example, Epiphany, which has the app ID "org.gnome.Epiphany"
+        in stable builds, might use a @desktop_file_id like
+        "org.gnome.Epiphany.WebApp_e9d0e1e4b0a10856aa3b38d9eb4375de4070d043.desktop"
+        In that example the desktop file would exist at the path
+        
"~/.local/share/xdg-desktop-portal/applications/org.gnome.Epiphany.WebApp_e9d0e1e4b0a10856aa3b38d9eb4375de4070d043.desktop"
+        with a sym link in "~/.local/share/applications/".
+        The checksum at the end of the file name is an implementation detail in
+        Epiphany and not required by the portal.
+
+        This method is intended to be called by the application that created the
+        launcher, e.g. a web browser, so it can clean up associated data as part
+        of the uninstallation. Consequently, the proper way for a software center
+        to remove a launcher is by using the APIs provided by the application
+        that installed it. For example, for GNOME Software to remove web
+        launchers created by Epiphany, it would use the
+        org.gnome.Epiphany.WebAppProvider D-Bus interface.
+
+        Please note that this method call will fail if the specified launcher
+        already does not exist.
+
+        The @options vardict currently has no supported entries.
+    -->
+    <method name="Uninstall">
+      <arg type="s" name="desktop_file_id" direction="in"/>
+      <arg type="a{sv}" name="options" direction="in"/>
+    </method>
+    <!--
+        GetDesktopEntry:
+        @desktop_file_id: The .desktop file name
+        @contents: the contents of the named .desktop file
+
+        This function returns the contents of a desktop file with the name
+        @desktop_file_id in @contents.
+
+        The @desktop_file_id must have ".desktop" as a suffix. Except in the
+        special case when the calling process has no associated app ID,
+        @desktop_file_id must have the app ID followed by a period as a prefix.
+
+        This method only works for desktop files that were created by the
+        dynamic launcher portal.
+    -->
+    <method name="GetDesktopEntry">
+      <arg type="s" name="desktop_file_id" direction="in"/>
+      <arg type="s" name="contents" direction="out"/>
+    </method>
+    <!--
+        GetIcon:
+        @desktop_file_id: The .desktop file name
+        @icon_v: the icon as a serialized #GBytesIcon
+        @icon_format: one of "png", "jpeg", "svg"
+        @icon_size: the width and height in pixels of the icon
+
+        This function returns the contents of the icon specified in the "Icon"
+        key of the desktop file with the name @desktop_file_id in @icon_v. The
+        icon #GVariant can be passed to g_icon_deserialize() to reconstruct the
+        #GIcon.
+
+        The @desktop_file_id must have ".desktop" as a suffix. Except in the
+        special case when the calling process has no associated app ID,
+        @desktop_file_id must have the app ID followed by a period as a prefix.
+
+        The format and size of the icon are returned in @icon_format and
+        @icon_size. For svg icons, @icon_size is currently always set to 4096,
+        but don't depend on that as it may change in the future.
+
+        This method only works for desktop files that were created by the
+        dynamic launcher portal.
+    -->
+    <method name="GetIcon">
+      <arg type="s" name="desktop_file_id" direction="in"/>
+      <arg type="v" name="icon_v" direction="out"/>
+      <arg type="s" name="icon_format" direction="out"/>
+      <arg type="u" name="icon_size" direction="out"/>
+    </method>
+    <!--
+        Launch:
+        @desktop_file_id: The .desktop file name
+        @options: Vardict with optional further onformation
+
+        This function launches the app specified by @desktop_file_id.
+
+        The @desktop_file_id must have ".desktop" as a suffix. Except in the
+        special case when the calling process has no associated app ID,
+        @desktop_file_id must have the app ID followed by a period as a prefix.
+
+        This method only works for desktop files that were created by the
+        dynamic launcher portal.
+
+        Supported keys in the @options vardict include:
+        <variablelist>
+          <varlistentry>
+            <term>activation_token s</term>
+            <listitem><para>
+              A token that can be used to activate the chosen application.
+            </para><para>
+              The activation_token option was introduced in version 1 of the interface.
+            </para></listitem>
+          </varlistentry>
+        </variablelist>
+    -->
+    <method name="Launch">
+      <arg type="s" name="desktop_file_id" direction="in"/>
+      <arg type="a{sv}" name="options" direction="in"/>
+    </method>
+    <!--
+        SupportedLauncherTypes:
+
+        A bitmask of available launcher types. Currently defined types are:
+
+        <simplelist>
+          <member>1: Application. A launcher that represents an application.</member>
+          <member>2: Webapp. A launcher that represents a web app.</member>
+        </simplelist>
+    -->
+    <property name="SupportedLauncherTypes" type="u" access="read"/>
+    <property name="version" type="u" access="read"/>
+  </interface>
+</node>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]