[epiphany/mwleeds/webapp-dbus-api: 16/17] Make web app manager work under Flatpak
- From: Phaedrus Leeds <mwleeds src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [epiphany/mwleeds/webapp-dbus-api: 16/17] Make web app manager work under Flatpak
- Date: Tue, 15 Mar 2022 22:06:44 +0000 (UTC)
commit 2b77c9491bd11dafc0958b6b7be655fcee5502ef
Author: Phaedrus Leeds <mwleeds protonmail com>
Date: Wed Feb 23 15:35:34 2022 -0800
Make web app manager work under Flatpak
Make use of the GetIcon() portal method so the app manager can work
under Flatpak.
embed/ephy-about-handler.c | 16 ++++++-
lib/ephy-web-app-utils.c | 84 ++++++++++++++++++++++++++++++++++--
lib/ephy-web-app-utils.h | 9 +++-
src/ephy-header-bar.c | 1 -
src/preferences/prefs-general-page.c | 3 +-
src/window-commands.c | 5 +--
6 files changed, 107 insertions(+), 11 deletions(-)
---
diff --git a/embed/ephy-about-handler.c b/embed/ephy-about-handler.c
index 915cfca2e..cd8b1c381 100644
--- a/embed/ephy-about-handler.c
+++ b/embed/ephy-about-handler.c
@@ -264,6 +264,7 @@ handle_applications_finished_cb (EphyAboutHandler *handler,
for (p = applications; p; p = p->next) {
EphyWebApplication *app = (EphyWebApplication *)p->data;
+ const char *icon_url;
g_autofree char *encoded_icon_url = NULL;
g_autofree char *encoded_name = NULL;
g_autofree char *encoded_url = NULL;
@@ -278,6 +279,17 @@ handle_applications_finished_cb (EphyAboutHandler *handler,
g_date_set_time_t (date, (time_t)app->install_date_uint64);
g_date_strftime (install_date, 127, "%x", date);
+ /* In the sandbox we don't have access to the host side icon file */
+ if (ephy_is_running_inside_sandbox ())
+ icon_url = app->tmp_icon_url;
+ else
+ icon_url = app->icon_url;
+
+ if (!icon_url) {
+ g_warning ("Failed to get icon url for app %s", app->id);
+ continue;
+ }
+
/* Most of these fields are at least semi-trusted. The app ID was chosen
* by ephy so it's safe. The icon URL could be changed by the user to
* something else after web app creation, though, so better not fully
@@ -285,7 +297,7 @@ handle_applications_finished_cb (EphyAboutHandler *handler,
* anything at all, so those need to be encoded for sure. Install date
* should be fine because it's constructed by Epiphany.
*/
- encoded_icon_url = ephy_encode_for_html_attribute (app->icon_url);
+ encoded_icon_url = ephy_encode_for_html_attribute (icon_url);
encoded_name = ephy_encode_for_html_entity (app->name);
encoded_url = ephy_encode_for_html_entity (app->url);
g_string_append_printf (data_str,
@@ -586,7 +598,7 @@ ephy_about_handler_handle_request (EphyAboutHandler *handler,
handled = ephy_about_handler_handle_memory (handler, request);
else if (!g_strcmp0 (path, "epiphany"))
handled = ephy_about_handler_handle_epiphany (handler, request);
- else if (!g_strcmp0 (path, "applications") && !ephy_is_running_inside_sandbox ())
+ else if (!g_strcmp0 (path, "applications"))
handled = ephy_about_handler_handle_applications (handler, request);
else if (!g_strcmp0 (path, "newtab"))
handled = ephy_about_handler_handle_newtab (handler, request);
diff --git a/lib/ephy-web-app-utils.c b/lib/ephy-web-app-utils.c
index 1b4bcb758..0f70dbfcd 100644
--- a/lib/ephy-web-app-utils.c
+++ b/lib/ephy-web-app-utils.c
@@ -36,6 +36,7 @@
#include <fcntl.h>
#include <libportal-gtk3/portal-gtk3.h>
#include <glib/gi18n.h>
+#include <gio/gunixoutputstream.h>
/* Web apps are installed in the default data dir of the user. Every
* app has its own profile directory. To create a web app, an ID needs
@@ -564,14 +565,84 @@ ephy_web_application_free (EphyWebApplication *app)
g_free (app->id);
g_free (app->name);
g_free (app->icon_url);
+ g_free (app->tmp_icon_url);
g_free (app->url);
g_free (app->desktop_file);
g_free (app->desktop_path);
g_free (app);
}
+static char *
+ephy_web_application_get_tmp_icon_path (const char *desktop_path,
+ GError **error)
+{
+ XdpPortal *portal = ephy_get_portal ();
+ g_autoptr (GVariant) icon_v = NULL;
+ g_autofree char *icon_format = NULL;
+ g_autofree char *desktop_basename = NULL;
+ g_autofree char *tmp_file_name = NULL;
+ g_autofree char *tmp_file_path = NULL;
+ g_autoptr (GIcon) icon = NULL;
+ g_autoptr (GOutputStream) stream = NULL;
+ GBytes *bytes;
+ gconstpointer bytes_data;
+ gsize bytes_len;
+ int fd;
+
+ g_return_val_if_fail (desktop_path != NULL, NULL);
+
+ /* This function is only useful inside the sandbox since the icon file on the
+ * host is inaccessible in that case.
+ */
+ g_assert (ephy_is_running_inside_sandbox ());
+
+ desktop_basename = g_path_get_basename (desktop_path);
+ icon_v = xdp_portal_dynamic_launcher_get_icon (portal, desktop_basename, &icon_format, NULL, error);
+ if (!icon_v)
+ return NULL;
+
+ tmp_file_name = ephy_file_tmp_filename (".ephy-webapp-icon-XXXXXX", icon_format);
+ tmp_file_path = g_build_filename (ephy_file_tmp_dir (), tmp_file_name, NULL);
+
+ icon = g_icon_deserialize (icon_v);
+ if (!icon) {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
+ "Icon deserialization failed");
+ return NULL;
+ }
+
+ if (!G_IS_BYTES_ICON (icon)) {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
+ "Unexpected icon type: %s", G_OBJECT_TYPE_NAME (icon));
+ return NULL;
+ }
+
+ bytes = g_bytes_icon_get_bytes (G_BYTES_ICON (icon));
+ fd = g_open (tmp_file_path, O_WRONLY | O_CREAT | O_TRUNC, 0600);
+ if (fd == -1) {
+ g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno),
+ "Failed to create tmpfile ā%sā: %s",
+ tmp_file_path, g_strerror (errno));
+ return NULL;
+ }
+
+ stream = g_unix_output_stream_new (fd, TRUE);
+ /* Use write_all() instead of write_bytes() so we don't have to worry about
+ * partial writes (https://gitlab.gnome.org/GNOME/glib/-/issues/570).
+ */
+ bytes_data = g_bytes_get_data (bytes, &bytes_len);
+ if (!g_output_stream_write_all (stream, bytes_data, bytes_len, NULL, NULL, error))
+ return NULL;
+
+ if (!g_output_stream_close (stream, NULL, error))
+ return NULL;
+
+ return g_steal_pointer (&tmp_file_path);
+}
+
EphyWebApplication *
-ephy_web_application_for_profile_directory (const char *profile_dir)
+ephy_web_application_for_profile_directory (const char *profile_dir,
+ EphyWebAppNeedTmpIcon need_tmp_icon)
{
g_autoptr (EphyWebApplication) app = NULL;
const char *id;
@@ -603,6 +674,12 @@ ephy_web_application_for_profile_directory (const char *profile_dir)
app->name = g_key_file_get_string (key_file, "Desktop Entry", "Name", NULL);
app->icon_url = g_key_file_get_string (key_file, "Desktop Entry", "Icon", NULL);
+ if (ephy_is_running_inside_sandbox () && need_tmp_icon == EPHY_WEB_APP_NEED_TMP_ICON) {
+ app->tmp_icon_url = ephy_web_application_get_tmp_icon_path (app->desktop_path, &error);
+ if (!app->tmp_icon_url)
+ g_warning ("Failed to get tmp icon path for app %s: %s", app->id, error->message);
+ }
+
exec = g_key_file_get_string (key_file, "Desktop Entry", "Exec", NULL);
if (g_shell_parse_argv (exec, &argc, &argv, NULL))
app->url = g_strdup (argv[argc - 1]);
@@ -682,7 +759,7 @@ ephy_web_application_get_application_list (void)
g_autofree char *profile_dir = NULL;
profile_dir = g_build_filename (parent_directory_path, name, NULL);
- app = ephy_web_application_for_profile_directory (profile_dir);
+ app = ephy_web_application_for_profile_directory (profile_dir, EPHY_WEB_APP_NEED_TMP_ICON);
if (app) {
g_autofree char *app_file = g_build_filename (profile_dir, ".app", NULL);
if (g_file_test (app_file, G_FILE_TEST_EXISTS))
@@ -844,7 +921,8 @@ urls_have_same_origin (const char *a_url,
gboolean
ephy_web_application_is_uri_allowed (const char *uri)
{
- g_autoptr (EphyWebApplication) webapp = ephy_web_application_for_profile_directory (ephy_profile_dir ());
+ g_autoptr (EphyWebApplication) webapp = ephy_web_application_for_profile_directory (ephy_profile_dir (),
+
EPHY_WEB_APP_NO_TMP_ICON);
const char *scheme;
g_auto (GStrv) urls = NULL;
guint i;
diff --git a/lib/ephy-web-app-utils.h b/lib/ephy-web-app-utils.h
index 5b3993fea..3870d63a8 100644
--- a/lib/ephy-web-app-utils.h
+++ b/lib/ephy-web-app-utils.h
@@ -30,6 +30,7 @@ typedef struct {
char *id;
char *name;
char *icon_url;
+ char *tmp_icon_url;
char *url;
char *desktop_file; /* only used for legacy apps */
char *desktop_path;
@@ -57,6 +58,11 @@ typedef enum {
EPHY_WEB_APP_NOT_FOUND,
} EphyWebAppFound;
+typedef enum {
+ EPHY_WEB_APP_NEED_TMP_ICON,
+ EPHY_WEB_APP_NO_TMP_ICON, /* avoid sync I/O, don't initialize app->tmp_icon_path */
+} EphyWebAppNeedTmpIcon;
+
#define EPHY_WEB_APP_ICON_NAME "app-icon.png"
char *ephy_web_application_get_app_id_from_name (const char *name);
@@ -93,7 +99,8 @@ GKeyFile *ephy_web_application_get_desktop_keyfile (const char *id,
char *ephy_web_application_get_desktop_path (const char *id);
-EphyWebApplication *ephy_web_application_for_profile_directory (const char *profile_dir);
+EphyWebApplication *ephy_web_application_for_profile_directory (const char *profile_dir,
+ EphyWebAppNeedTmpIcon need_tmp_icon);
void ephy_web_application_free (EphyWebApplication *app);
diff --git a/src/ephy-header-bar.c b/src/ephy-header-bar.c
index b03635adf..d6132ba8b 100644
--- a/src/ephy-header-bar.c
+++ b/src/ephy-header-bar.c
@@ -276,7 +276,6 @@ ephy_header_bar_constructed (GObject *object)
} else if (ephy_is_running_inside_sandbox ()) {
gtk_widget_destroy (GTK_WIDGET (gtk_builder_get_object (builder, "run-in-background-separator")));
gtk_widget_destroy (GTK_WIDGET (gtk_builder_get_object (builder, "run-in-background-button")));
- gtk_widget_destroy (GTK_WIDGET (gtk_builder_get_object (builder, "application-manager-button")));
if (is_desktop_pantheon ())
gtk_widget_destroy (GTK_WIDGET (gtk_builder_get_object (builder, "help-button")));
diff --git a/src/preferences/prefs-general-page.c b/src/preferences/prefs-general-page.c
index 6ef42f92b..297201850 100644
--- a/src/preferences/prefs-general-page.c
+++ b/src/preferences/prefs-general-page.c
@@ -1176,7 +1176,8 @@ setup_general_page (PrefsGeneralPage *general_page)
/* ======================================================================== */
if (ephy_embed_shell_get_mode (ephy_embed_shell_get_default ()) == EPHY_EMBED_SHELL_MODE_APPLICATION &&
!ephy_is_running_inside_sandbox ()) {
- general_page->webapp = ephy_web_application_for_profile_directory (ephy_profile_dir ());
+ general_page->webapp = ephy_web_application_for_profile_directory (ephy_profile_dir (),
+ EPHY_WEB_APP_NO_TMP_ICON);
g_assert (general_page->webapp);
if (!g_settings_get_boolean (EPHY_SETTINGS_WEB_APP, EPHY_PREFS_WEB_APP_SYSTEM)) {
diff --git a/src/window-commands.c b/src/window-commands.c
index 97b8175c9..11ab0d3c5 100644
--- a/src/window-commands.c
+++ b/src/window-commands.c
@@ -907,11 +907,10 @@ window_cmd_show_shortcuts (GSimpleAction *action,
builder = gtk_builder_new_from_resource ("/org/gnome/epiphany/gtk/shortcuts-dialog.ui");
shortcuts_window = GTK_WIDGET (gtk_builder_get_object (builder, "shortcuts-dialog"));
- if (!ephy_can_install_web_apps ())
+ if (!ephy_can_install_web_apps ()) {
gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (builder, "shortcuts-web-apps-group")));
-
- if (!ephy_can_install_web_apps () || ephy_is_running_inside_sandbox ())
gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (builder, "app-manager-shortcut")));
+ }
if (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL) {
GtkShortcutsShortcut *shortcut;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]