[epiphany] web-app: Add support for system-wide installed web apps



commit 8748d405e7b7d5e63114b6eaed17b01f710ed07f
Author: Carlos Garcia Campos <cgarcia igalia com>
Date:   Tue Nov 10 14:15:56 2015 +0100

    web-app: Add support for system-wide installed web apps
    
    Any desktop file running ephy with --application-mode command line
    options should work. It doesn't need to provide the profile directory, it
    will be built from the desktop file info, and created on first run.

 lib/ephy-web-app-utils.c |  125 ++++++++++++++++++++++++++++++++++++++++++++--
 lib/ephy-web-app-utils.h |    7 +++
 src/ephy-main.c          |   49 ++++++++----------
 3 files changed, 150 insertions(+), 31 deletions(-)
---
diff --git a/lib/ephy-web-app-utils.c b/lib/ephy-web-app-utils.c
index 9fefa4e..3d19d7d 100644
--- a/lib/ephy-web-app-utils.c
+++ b/lib/ephy-web-app-utils.c
@@ -25,8 +25,11 @@
 #include "ephy-debug.h"
 #include "ephy-file-helpers.h"
 
+#include <errno.h>
+#include <gio/gio.h>
 #include <glib/gstdio.h>
 #include <libsoup/soup.h>
+#include <string.h>
 #include <webkit2/webkit2.h>
 
 #define EPHY_WEB_APP_DESKTOP_FILE_PREFIX "epiphany-"
@@ -147,12 +150,14 @@ ephy_web_application_delete (const char *name)
   g_free (wm_class);
   if (!desktop_file)
     goto out;
-  desktop_path = g_build_filename (g_get_user_data_dir (), "applications", desktop_file, NULL);
-  launcher = g_file_new_for_path (desktop_path);
-  if (!g_file_delete (launcher, NULL, NULL))
-    goto out;
-  LOG ("Deleted application launcher.\n");
 
+  desktop_path = g_build_filename (g_get_user_data_dir (), "applications", desktop_file, NULL);
+  if (g_file_test (desktop_path, G_FILE_TEST_IS_DIR)) {
+    launcher = g_file_new_for_path (desktop_path);
+    if (!g_file_delete (launcher, NULL, NULL))
+      goto out;
+    LOG ("Deleted application launcher.\n");
+  }
   return_value = TRUE;
 
 out:
@@ -359,6 +364,116 @@ out:
   return desktop_file_path;
 }
 
+char *
+ephy_web_application_ensure_for_app_info (GAppInfo *app_info)
+{
+  char *profile_dir;
+  const char *cmd;
+  char *address;
+
+  profile_dir = ephy_web_application_get_profile_directory (g_app_info_get_name (app_info));
+  if (g_mkdir (profile_dir, 488) == -1) {
+    if (errno == EEXIST)
+      return profile_dir;
+
+    g_free (profile_dir);
+    return NULL;
+  }
+
+  /* The address should be the last command line argument in the desktop file */
+  cmd = g_app_info_get_commandline (app_info);
+  if (!cmd) {
+    g_free (profile_dir);
+    return NULL;
+  }
+
+  address = g_strrstr (cmd, " ");
+  if (!address) {
+    g_free (profile_dir);
+    return NULL;
+  }
+
+  address++;
+  if (*address == '\0') {
+    g_free (profile_dir);
+    return NULL;
+  }
+
+  create_cookie_jar_for_domain (address, profile_dir);
+
+  return profile_dir;
+}
+
+void
+ephy_web_application_setup_from_profile_directory (const char *profile_directory)
+{
+  char *app_name;
+  char *app_icon;
+
+  g_return_if_fail (profile_directory != NULL);
+
+  app_name = g_strrstr (profile_directory, EPHY_WEB_APP_PREFIX);
+  if (!app_name)
+    return;
+
+  /* Skip the 'app-' part */
+  app_name += strlen (EPHY_WEB_APP_PREFIX);
+  g_set_prgname (app_name);
+  g_set_application_name (app_name);
+
+  app_icon = g_build_filename (profile_directory, EPHY_WEB_APP_ICON_NAME, NULL);
+  gtk_window_set_default_icon_from_file (app_icon, NULL);
+  g_free (app_icon);
+
+  /* We need to re-set this because we have already parsed the
+   * options, which inits GTK+ and sets this as a side effect.
+   */
+  gdk_set_program_class (app_name);
+}
+
+void
+ephy_web_application_setup_from_desktop_file (GDesktopAppInfo *desktop_info)
+{
+  GAppInfo *app_info;
+  const char *app_name;
+  const char *wm_class;
+  GIcon *icon;
+
+  g_return_if_fail (G_IS_DESKTOP_APP_INFO (desktop_info));
+
+  app_info = G_APP_INFO (desktop_info);
+  app_name = g_app_info_get_name (app_info);
+  if (!app_name)
+    return;
+
+  g_set_prgname (app_name);
+  g_set_application_name (app_name);
+
+  icon = g_app_info_get_icon (app_info);
+  if (G_IS_FILE_ICON (icon)) {
+    GFile *file = g_file_icon_get_file (G_FILE_ICON (icon));
+    char *path = file ? g_file_get_path (file) : NULL;
+
+    if (path) {
+      gtk_window_set_default_icon_from_file (path, NULL);
+      g_free (path);
+    }
+    g_clear_object (&file);
+  } else if (G_IS_THEMED_ICON (icon)) {
+    const char *const *names = g_themed_icon_get_names (G_THEMED_ICON (icon));
+    if (names)
+      gtk_window_set_default_icon_name (names[0]);
+  }
+  g_clear_object (&icon);
+
+  /* We need to re-set this because we have already parsed the
+   * options, which inits GTK+ and sets this as a side effect.
+   */
+  wm_class = g_desktop_app_info_get_startup_wm_class (desktop_info);
+  if (wm_class)
+    gdk_set_program_class (wm_class);
+}
+
 /**
  * ephy_web_application_get_application_list:
  *
diff --git a/lib/ephy-web-app-utils.h b/lib/ephy-web-app-utils.h
index 39157fd..2c93187 100644
--- a/lib/ephy-web-app-utils.h
+++ b/lib/ephy-web-app-utils.h
@@ -24,6 +24,7 @@
 #ifndef EPHY_WEB_APP_UTILS_H
 #define EPHY_WEB_APP_UTILS_H
 
+#include <gio/gdesktopappinfo.h>
 #include <glib.h>
 #include <gtk/gtk.h>
 #include <webkit2/webkit2.h>
@@ -43,8 +44,14 @@ typedef struct {
 
 char    *ephy_web_application_create (const char *address, const char *name, GdkPixbuf *icon);
 
+char    *ephy_web_application_ensure_for_app_info (GAppInfo *app_info);
+
 gboolean ephy_web_application_delete (const char *name);
 
+void     ephy_web_application_setup_from_profile_directory (const char *profile_directory);
+
+void     ephy_web_application_setup_from_desktop_file (GDesktopAppInfo *desktop_info);
+
 char    *ephy_web_application_get_profile_directory (const char *name);
 
 GList   *ephy_web_application_get_application_list (void);
diff --git a/src/ephy-main.c b/src/ephy-main.c
index 02a02ef..bb7b9dc 100644
--- a/src/ephy-main.c
+++ b/src/ephy-main.c
@@ -237,6 +237,7 @@ main (int argc,
   EphyShell *ephy_shell;
   int status;
   EphyFileHelpersFlags flags;
+  GDesktopAppInfo *desktop_info = NULL;
 
   /* Initialize the i18n stuff */
   bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
@@ -341,21 +342,32 @@ main (int argc,
     exit (1);
   }
 
+  if (application_mode && profile_directory && !g_file_test (profile_directory, G_FILE_TEST_IS_DIR)) {
+      g_print ("--profile must be an existing directory when --application-mode is requested\n");
+      exit (1);
+  }
+
+  if (application_mode && !profile_directory) {
+    const char *desktop_file_path = g_getenv ("GIO_LAUNCHED_DESKTOP_FILE");
+
+    if (desktop_file_path) {
+      desktop_info = g_desktop_app_info_new_from_filename (desktop_file_path);
+
+      if (desktop_info)
+        profile_directory = ephy_web_application_ensure_for_app_info (G_APP_INFO (desktop_info));
+    }
+  }
+
   if (application_mode && profile_directory == NULL) {
     g_print ("--profile must be used when --application-mode is requested\n");
     exit (1);
   }
 
-  if (application_mode && !g_file_test (profile_directory, G_FILE_TEST_IS_DIR)) {
-      g_print ("--profile must be an existing directory when --application-mode is requested\n");
-      exit (1);
-  }
-
   if (incognito_mode && profile_directory == NULL)
     profile_directory = g_strdup (ephy_dot_dir ());
 
   /* Start our services */
-  flags = EPHY_FILE_HELPERS_ENSURE_EXISTS;
+  flags = !application_mode ? EPHY_FILE_HELPERS_ENSURE_EXISTS : 0;
 
   if (incognito_mode || private_instance || application_mode)
     flags |= EPHY_FILE_HELPERS_PRIVATE_PROFILE;
@@ -432,29 +444,14 @@ main (int argc,
   } else if (incognito_mode) {
     mode = EPHY_EMBED_SHELL_MODE_INCOGNITO;
   } else if (application_mode) {
-    char *app_name;
-    char *app_icon;
-
     mode = EPHY_EMBED_SHELL_MODE_APPLICATION;
 
-    app_name = g_strrstr (profile_directory, EPHY_WEB_APP_PREFIX);
-    app_icon = g_build_filename (profile_directory, EPHY_WEB_APP_ICON_NAME, NULL);
-
-    if (app_name) {
-      /* Skip the 'app-' part */
-      app_name += strlen (EPHY_WEB_APP_PREFIX);
-
-      g_set_prgname (app_name);
-      g_set_application_name (app_name);
-
-      gtk_window_set_default_icon_from_file (app_icon, NULL);
-
-      /* We need to re-set this because we have already parsed the
-       * options, which inits GTK+ and sets this as a side effect. */
-      gdk_set_program_class (app_name);
+    if (desktop_info) {
+      ephy_web_application_setup_from_desktop_file (desktop_info);
+      g_object_unref (desktop_info);
+    } else {
+      ephy_web_application_setup_from_profile_directory (profile_directory);
     }
-
-    g_free (app_icon);
   } else if (profile_directory) {
     /* This mode exists purely for letting EphyShell know it should
      * not consider this instance part of the unique application


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