diff --git a/doc/libportal-sections.txt b/doc/libportal-sections.txt index eca56151..ef54373f 100644 --- a/doc/libportal-sections.txt +++ b/doc/libportal-sections.txt @@ -184,6 +184,8 @@ xdp_portal_update_monitor_stop XdpUpdateInstallFlags xdp_portal_update_install xdp_portal_update_install_finish +xdp_portal_update_install_ref +xdp_portal_update_install_ref_finish
diff --git a/libportal/updates.c b/libportal/updates.c index c5f5855f..5424f9dd 100644 --- a/libportal/updates.c +++ b/libportal/updates.c @@ -108,7 +108,6 @@ update_progress_received (GDBusConnection *bus, g_variant_lookup (info, "error", "&s", &error); g_variant_lookup (info, "error_message", "&s", &error_message); } -g_print ("update progress received %u/%u %u%% %d\n", op, n_ops, progress, status); g_signal_emit_by_name (portal, "update-progress", n_ops, @@ -310,6 +309,7 @@ typedef struct { XdpParent *parent; char *parent_handle; GTask *task; + char *ref; } InstallUpdateCall; static void @@ -324,6 +324,7 @@ install_update_call_free (InstallUpdateCall *call) g_object_unref (call->portal); g_object_unref (call->task); + g_free (call->ref); g_free (call); } @@ -380,15 +381,27 @@ install_update (InstallUpdateCall *call) cancellable = g_task_get_cancellable (call->task); g_variant_builder_init (&options, G_VARIANT_TYPE_VARDICT); - g_dbus_connection_call (call->portal->bus, - FLATPAK_PORTAL_BUS_NAME, - call->portal->update_monitor_handle, - UPDATE_MONITOR_INTERFACE, - "Update", - g_variant_new ("(sa{sv})", - call->parent_handle, - &options), - NULL, 0, -1, cancellable, update_started, call); + if (call->ref) + g_dbus_connection_call (call->portal->bus, + FLATPAK_PORTAL_BUS_NAME, + call->portal->update_monitor_handle, + UPDATE_MONITOR_INTERFACE, + "Install", + g_variant_new ("(ssa{sv})", + call->parent_handle, + call->ref, + &options), + NULL, 0, -1, cancellable, update_started, call); + else + g_dbus_connection_call (call->portal->bus, + FLATPAK_PORTAL_BUS_NAME, + call->portal->update_monitor_handle, + UPDATE_MONITOR_INTERFACE, + "Update", + g_variant_new ("(sa{sv})", + call->parent_handle, + &options), + NULL, 0, -1, cancellable, update_started, call); } /** @@ -458,3 +471,74 @@ xdp_portal_update_install_finish (XdpPortal *portal, return g_task_propagate_boolean (G_TASK (result), error); } + +/** + * xdp_portal_update_install_ref: + * @portal: a #XdpPortal + * @parent: a #XdpParent + * @ref: the ref to install + * @flags: options for this call + * @cancellable: (nullable): optional #GCancellable + * @callback: (scope async): a callback to call when the request is done + * @data: (closure): data to pass to @callback + * + * Installs an available application or runtime extension of the + * app making this call. + * + * During the installation, the #XdpPortal::update-progress + * signal will be emitted to provide progress information. + */ +void +xdp_portal_update_install_ref (XdpPortal *portal, + XdpParent *parent, + const char *ref, + XdpUpdateInstallFlags flags, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer data) +{ + InstallUpdateCall *call; + + g_return_if_fail (XDP_IS_PORTAL (portal)); + g_return_if_fail (flags == XDP_UPDATE_INSTALL_FLAG_NONE); + + call = g_new (InstallUpdateCall, 1); + call->portal = g_object_ref (portal); + if (parent) + call->parent = _xdp_parent_copy (parent); + else + call->parent_handle = g_strdup (""); + call->ref = g_strdup (ref); + call->task = g_task_new (portal, cancellable, callback, data); + g_task_set_source_tag (call->task, xdp_portal_update_install_ref); + + install_update (call); +} + +/** + * xdp_portal_update_install_ref_finish: + * @portal: a #XdpPortal + * @result: a #GAsyncResult + * @error: return location for an error + * + * Finishes an installation request, and returns + * the result in the form of boolean. + * + * Note that the install may not be completed + * by the time this function is called. You need to + * listen to the #XdpPortal::update-progress signal + * to learn when it is complete. + * + * Returns: %TRUE if the installation was started + */ +gboolean +xdp_portal_update_install_ref_finish (XdpPortal *portal, + GAsyncResult *result, + GError **error) +{ + g_return_val_if_fail (XDP_IS_PORTAL (portal), FALSE); + g_return_val_if_fail (g_task_is_valid (result, portal), FALSE); + g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == xdp_portal_update_install_ref, FALSE); + + return g_task_propagate_boolean (G_TASK (result), error); +} diff --git a/libportal/updates.h b/libportal/updates.h index e1d4b15f..2cc3cb3f 100644 --- a/libportal/updates.h +++ b/libportal/updates.h @@ -77,4 +77,18 @@ gboolean xdp_portal_update_install_finish (XdpPortal *porta GAsyncResult *result, GError **error); +XDP_PUBLIC +void xdp_portal_update_install_ref (XdpPortal *portal, + XdpParent *parent, + const char *ref, + XdpUpdateInstallFlags flags, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer data); + +XDP_PUBLIC +gboolean xdp_portal_update_install_ref_finish (XdpPortal *portal, + GAsyncResult *result, + GError **error); + G_END_DECLS diff --git a/portal-test/portal-test-win.c b/portal-test/portal-test-win.c index 69540e4e..72bd4df1 100644 --- a/portal-test/portal-test-win.c +++ b/portal-test/portal-test-win.c @@ -1073,6 +1073,77 @@ set_wallpaper (PortalTestWin *win) xdp_parent_free (parent); } +static void +install_debuginfo_called (GObject *source, + GAsyncResult *result, + gpointer data) +{ + XdpPortal *portal = XDP_PORTAL (source); + g_autoptr(GError) error = NULL; + gboolean ret; + + g_print ("install debuginfo called\n"); + ret = xdp_portal_update_install_ref_finish (portal, result, &error); + if (!ret) + { + g_warning ("Install request failed: %s", error ? error->message : "Unknown error"); + return; + } + + g_message ("Install request successful!"); +} + +static void +update_progress (XdpPortal *portal, + guint n_ops, + guint op, + guint progress, + XdpUpdateStatus status, + const char *error, + const char *error_message, + gpointer data) +{ + g_message ("Installation progress %u/%u %u%%\n", op, n_ops, progress); + if (status != 0) + g_warning ("Installation failed: %s", error_message); + + if (progress == 100 && status == 0) + g_message ("Installation completed successfully"); + + if (status != 0 || progress == 100) + { + g_print ("Stopping the update monitor\n"); + g_signal_handlers_disconnect_by_func (portal, update_progress, NULL); + xdp_portal_update_monitor_stop (portal); + } +} + +static void +monitor_started_cb (GObject *source, + GAsyncResult *result, + gpointer data) +{ + XdpPortal *portal = XDP_PORTAL (source); + g_autoptr(GError) error = NULL; + const char *ref = "runtime/org.gnome.PortalTest.Debug/x86_64/master"; + + if (!xdp_portal_update_monitor_start_finish (portal, result, &error)) + { + g_warning ("Failed to start update monitor: %s", error->message); + return; + } + + g_signal_connect (portal, "update-progress", G_CALLBACK (update_progress), NULL); + + xdp_portal_update_install_ref (portal, NULL, ref, 0, NULL, install_debuginfo_called, NULL); +} + +static void +install_debuginfo (PortalTestWin *win) +{ + xdp_portal_update_monitor_start (win->portal, 0, NULL, monitor_started_cb, NULL); +} + static void portal_test_win_class_init (PortalTestWinClass *class) { @@ -1093,6 +1164,7 @@ portal_test_win_class_init (PortalTestWinClass *class) gtk_widget_class_bind_template_callback (widget_class, compose_email); gtk_widget_class_bind_template_callback (widget_class, request_background); gtk_widget_class_bind_template_callback (widget_class, set_wallpaper); + gtk_widget_class_bind_template_callback (widget_class, install_debuginfo); gtk_widget_class_bind_template_child (widget_class, PortalTestWin, sandbox_status); gtk_widget_class_bind_template_child (widget_class, PortalTestWin, network_status); gtk_widget_class_bind_template_child (widget_class, PortalTestWin, monitor_name); diff --git a/portal-test/portal-test-win.ui b/portal-test/portal-test-win.ui index 78fb682c..d61850d2 100644 --- a/portal-test/portal-test-win.ui +++ b/portal-test/portal-test-win.ui @@ -654,6 +654,29 @@ 18 + + + 1 + end + Extensions + + + 0 + 19 + + + + + 1 + 0 + Install + + + + 1 + 19 + +