[epiphany/wip/tingping/profile-migration: 1/4] Migrate web app profiles into their own toplevel directories



commit bde2ff0d730ebce04765a4c4e9eca315abd4dddb
Author: Patrick Griffis <pgriffis igalia com>
Date:   Tue Dec 18 09:24:08 2018 -0500

    Migrate web app profiles into their own toplevel directories
    
    This layout better reflects how the sandbox expects with the top
    level XDG directories containing prgname matching directories.

 lib/ephy-file-helpers.c                      |  7 +--
 lib/ephy-profile-utils.h                     |  2 +-
 lib/ephy-settings.c                          | 25 ++++----
 lib/ephy-web-app-utils.c                     | 85 ++++++++++++++++++++--------
 lib/ephy-web-app-utils.h                     |  5 +-
 src/profile-migrator/ephy-profile-migrator.c | 62 +++++++++++++++++++-
 6 files changed, 141 insertions(+), 45 deletions(-)
---
diff --git a/lib/ephy-file-helpers.c b/lib/ephy-file-helpers.c
index 62efb1299..65758b01d 100644
--- a/lib/ephy-file-helpers.c
+++ b/lib/ephy-file-helpers.c
@@ -309,8 +309,6 @@ ephy_file_helpers_init (const char          *profile_dir,
   steal_data_from_profile = flags & EPHY_FILE_HELPERS_STEAL_DATA;
 
   if (profile_dir != NULL && !steal_data_from_profile) {
-    char *basename;
-
     if (g_path_is_absolute (profile_dir)) {
       dot_dir = g_strdup (profile_dir);
     } else {
@@ -319,10 +317,9 @@ ephy_file_helpers_init (const char          *profile_dir,
       g_object_unref (file);
     }
 
-    basename = g_path_get_basename (dot_dir);
-    if (g_str_has_prefix (basename, EPHY_WEB_APP_PREFIX))
+    g_autofree char *app_file = g_build_filename (profile_dir, ".app", NULL);
+    if (g_file_test (app_file, G_FILE_TEST_EXISTS))
       dot_dir_type = EPHY_PROFILE_DIR_WEB_APP;
-    g_free (basename);
   } else if (private_profile) {
     if (ephy_file_tmp_dir () == NULL) {
       g_set_error (error,
diff --git a/lib/ephy-profile-utils.h b/lib/ephy-profile-utils.h
index c5432e11b..0ed11f65e 100644
--- a/lib/ephy-profile-utils.h
+++ b/lib/ephy-profile-utils.h
@@ -24,7 +24,7 @@
 
 G_BEGIN_DECLS
 
-#define EPHY_PROFILE_MIGRATION_VERSION 28
+#define EPHY_PROFILE_MIGRATION_VERSION 29
 #define EPHY_INSECURE_PASSWORDS_MIGRATION_VERSION 11
 #define EPHY_SETTINGS_MIGRATION_VERSION 16
 #define EPHY_FIREFOX_SYNC_PASSWORDS_MIGRATION_VERSION 19
diff --git a/lib/ephy-settings.c b/lib/ephy-settings.c
index 82f172efa..8a66cb979 100644
--- a/lib/ephy-settings.c
+++ b/lib/ephy-settings.c
@@ -37,7 +37,6 @@ static void
 ephy_settings_init (void)
 {
   const char *profile_directory;
-  const char *web_app_name;
   char *base_path;
 
   if (settings != NULL)
@@ -51,16 +50,17 @@ ephy_settings_init (void)
                                     g_str_equal, g_free,
                                     g_object_unref);
 
-  web_app_name = strstr (profile_directory, EPHY_WEB_APP_PREFIX);
-  if (web_app_name)
+  if (ephy_dot_dir_is_web_application ()) {
+    const char *web_app_name = ephy_web_application_get_program_name_from_profile_directory 
(profile_directory);
     base_path = g_build_path ("/", "/org/gnome/epiphany/web-apps/", web_app_name, NULL);
-  else
+  } else {
     base_path = g_strdup ("/org/gnome/epiphany/");
+  }
 
   for (guint i = 0; i < G_N_ELEMENTS (ephy_prefs_relocatable_schemas); i++) {
     char *path;
 
-    if (!web_app_name && ephy_prefs_relocatable_schemas[i].is_webapp_only)
+    if (!ephy_dot_dir_is_web_application () && ephy_prefs_relocatable_schemas[i].is_webapp_only)
       continue;
 
     path = g_build_path ("/", base_path, ephy_prefs_relocatable_schemas[i].path, NULL);
@@ -142,9 +142,17 @@ sync_settings (GSettings *original,
 static char *
 get_relocatable_path (const char *schema)
 {
+  g_autofree char *base_path = NULL;
+
+  if (ephy_dot_dir_is_web_application ()) {
+    const char *web_app_name = ephy_web_application_get_program_name_from_profile_directory (ephy_dot_dir 
());
+    base_path = g_build_path ("/", "/org/gnome/epiphany/web-apps/", web_app_name, NULL);
+  } else
+    base_path = g_strdup ("/org/gnome/epiphany/");
+
   for (size_t i = 0; i < G_N_ELEMENTS (ephy_prefs_relocatable_schemas); i++) {
     if (g_strcmp0 (ephy_prefs_relocatable_schemas[i].schema, schema) == 0)
-      return g_build_path ("/", "/org/gnome/epiphany/", ephy_prefs_relocatable_schemas[i].path, NULL);
+      return g_build_path ("/", base_path, ephy_prefs_relocatable_schemas[i].path, NULL);
   }
   return NULL;
 }
@@ -170,11 +178,6 @@ ephy_settings_get_for_web_extension (const char *schema)
 
   ephy_settings_init ();
 
-  // Web apps can't work with the sandbox anyway
-  const char *web_app_name = strstr (ephy_dot_dir (), EPHY_WEB_APP_PREFIX);
-  if (web_app_name != NULL)
-    return ephy_settings_get (schema);
-
   key_name = g_strdup_printf ("keyfile-%s", schema);
   gsettings = g_hash_table_lookup (settings, key_name);
 
diff --git a/lib/ephy-web-app-utils.c b/lib/ephy-web-app-utils.c
index 5352bed0f..38d5964b8 100644
--- a/lib/ephy-web-app-utils.c
+++ b/lib/ephy-web-app-utils.c
@@ -39,7 +39,7 @@
  *
  * The id is used to uniquely identify the app.
  *  - Program name: epiphany-<id>
- *  - Profile directory: app-<program-name>
+ *  - Profile directory: <program-name>
  *  - Desktop file: <profile-dir>/<program-name>.desktop
  *
  * System web applications have a profile dir without a desktop file.
@@ -89,7 +89,7 @@ get_app_profile_directory_name (const char *id)
   char *profile_dir;
   char *encoded;
 
-  profile_dir = g_strconcat (EPHY_WEB_APP_PREFIX, EPHY_WEB_APP_PROGRAM_NAME_PREFIX, id, NULL);
+  profile_dir = g_strconcat (EPHY_WEB_APP_PROGRAM_NAME_PREFIX, id, NULL);
   encoded = get_encoded_path (profile_dir);
   g_free (profile_dir);
 
@@ -109,18 +109,18 @@ get_app_desktop_filename (const char *id)
   return encoded;
 }
 
-static const char *
-get_program_name_from_profile_directory (const char *profile_dir)
+const char *
+ephy_web_application_get_program_name_from_profile_directory (const char *profile_dir)
 {
   const char *name;
 
-  name = strstr (profile_dir, EPHY_WEB_APP_PREFIX);
+  name = strstr (profile_dir, EPHY_WEB_APP_PROGRAM_NAME_PREFIX);
   if (!name) {
-    g_warning ("Profile directory %s does not begin with required web app prefix %s", profile_dir, 
EPHY_WEB_APP_PREFIX);
+    g_warning ("Profile directory %s does not begin with required web app prefix %s", profile_dir, 
EPHY_WEB_APP_PROGRAM_NAME_PREFIX);
     return NULL;
   }
 
-  return name + strlen (EPHY_WEB_APP_PREFIX);
+  return name;
 }
 
 static const char *
@@ -139,7 +139,7 @@ get_app_id_from_profile_directory (const char *profile_dir)
 {
   const char *program_name;
 
-  program_name = get_program_name_from_profile_directory (profile_dir);
+  program_name = ephy_web_application_get_program_name_from_profile_directory (profile_dir);
   return program_name ? get_app_id_from_program_name (program_name) : NULL;
 }
 
@@ -161,7 +161,7 @@ ephy_web_application_get_profile_directory (const char *id)
     return NULL;
 
   dot_dir = !ephy_dot_dir_is_default () ? ephy_default_dot_dir () : NULL;
-  profile_dir = g_build_filename (dot_dir ? dot_dir : ephy_dot_dir (), app_dir, NULL);
+  profile_dir = g_build_filename (dot_dir ? dot_dir : g_get_user_config_dir (), app_dir, NULL);
   g_free (app_dir);
   g_free (dot_dir);
 
@@ -391,7 +391,7 @@ ephy_web_application_setup_from_profile_directory (const char *profile_directory
 
   g_assert (profile_directory != NULL);
 
-  program_name = get_program_name_from_profile_directory (profile_directory);
+  program_name = ephy_web_application_get_program_name_from_profile_directory (profile_directory);
   if (!program_name)
     exit (1);
 
@@ -534,17 +534,8 @@ ephy_web_application_for_profile_directory (const char *profile_dir)
   return app;
 }
 
-/**
- * ephy_web_application_get_application_list:
- *
- * Gets a list of the currently installed web applications.
- * Free the returned GList with
- * ephy_web_application_free_application_list.
- *
- * Returns: (transfer-full): a #GList of #EphyWebApplication objects
- **/
-GList *
-ephy_web_application_get_application_list (void)
+static GList *
+ephy_web_application_get_application_list_internal (gboolean only_legacy)
 {
   GFileEnumerator *children = NULL;
   GFileInfo *info;
@@ -553,7 +544,7 @@ ephy_web_application_get_application_list (void)
   char *default_dot_dir;
 
   default_dot_dir = !ephy_dot_dir_is_default () ? ephy_default_dot_dir () : NULL;
-  dot_dir = g_file_new_for_path (default_dot_dir ? default_dot_dir : ephy_dot_dir ());
+  dot_dir = g_file_new_for_path (default_dot_dir ? default_dot_dir : only_legacy ? ephy_dot_dir () : 
g_get_user_config_dir ());
   children = g_file_enumerate_children (dot_dir,
                                         "standard::name",
                                         0, NULL, NULL);
@@ -564,14 +555,24 @@ ephy_web_application_get_application_list (void)
     const char *name;
 
     name = g_file_info_get_name (info);
-    if (g_str_has_prefix (name, EPHY_WEB_APP_PREFIX)) {
+    if ((only_legacy && g_str_has_prefix (name, "app-")) ||
+        (!only_legacy && g_str_has_prefix (name, EPHY_WEB_APP_PROGRAM_NAME_PREFIX))) {
       EphyWebApplication *app;
       char *profile_dir;
 
       profile_dir = g_build_filename (default_dot_dir ? default_dot_dir : ephy_dot_dir (), name, NULL);
       app = ephy_web_application_for_profile_directory (profile_dir);
-      if (app)
-        applications = g_list_prepend (applications, app);
+      if (app) {
+        if (!only_legacy) {
+          g_autofree char *app_file = g_build_filename (profile_dir, ".app", NULL);
+          if (g_file_test (app_file, G_FILE_TEST_EXISTS))
+            applications = g_list_prepend (applications, app);
+          else
+            g_object_unref (app);
+        } else
+          applications = g_list_prepend (applications, app);
+      }
+
       g_free (profile_dir);
     }
 
@@ -586,6 +587,40 @@ ephy_web_application_get_application_list (void)
   return g_list_reverse (applications);
 }
 
+/**
+ * ephy_web_application_get_application_list:
+ *
+ * Gets a list of the currently installed web applications.
+ * Free the returned GList with
+ * ephy_web_application_free_application_list.
+ *
+ * Returns: (transfer-full): a #GList of #EphyWebApplication objects
+ **/
+GList *
+ephy_web_application_get_application_list (void)
+{
+  return ephy_web_application_get_application_list_internal (FALSE);
+}
+
+/**
+ * ephy_web_application_get_legacy_application_list:
+ *
+ * Gets a list of the currently installed web applications.
+ * This is only used for the profile migrator as it gets
+ * applications in the legacy directory.
+ *
+ * Free the returned GList with
+ * ephy_web_application_free_application_list.
+ *
+ * Returns: (transfer-full): a #GList of #EphyWebApplication objects
+ **/
+GList *
+ephy_web_application_get_legacy_application_list (void)
+{
+  return ephy_web_application_get_application_list_internal (TRUE);
+}
+
+
 /**
  * ephy_web_application_free_application_list:
  * @list: an #EphyWebApplication GList
diff --git a/lib/ephy-web-app-utils.h b/lib/ephy-web-app-utils.h
index c13d553b7..18cba3939 100644
--- a/lib/ephy-web-app-utils.h
+++ b/lib/ephy-web-app-utils.h
@@ -35,11 +35,12 @@ typedef struct {
   char install_date[128];
 } EphyWebApplication;
 
-#define EPHY_WEB_APP_PREFIX "app-"
 #define EPHY_WEB_APP_ICON_NAME "app-icon.png"
 
 char               *ephy_web_application_get_app_id_from_name (const char *name);
 
+const char         *ephy_web_application_get_program_name_from_profile_directory (const char *profile_dir);
+
 char               *ephy_web_application_create (const char *id, const char *address, const char *name, 
GdkPixbuf *icon);
 
 char               *ephy_web_application_ensure_for_app_info (GAppInfo *app_info);
@@ -60,6 +61,8 @@ gboolean            ephy_web_application_exists (const char *id);
 
 GList              *ephy_web_application_get_application_list (void);
 
+GList              *ephy_web_application_get_legacy_application_list (void);
+
 void                ephy_web_application_free_application_list (GList *list);
 
 void                ephy_web_application_initialize_settings (const char *profile_directory);
diff --git a/src/profile-migrator/ephy-profile-migrator.c b/src/profile-migrator/ephy-profile-migrator.c
index 14b276946..ccc9aa5b5 100644
--- a/src/profile-migrator/ephy-profile-migrator.c
+++ b/src/profile-migrator/ephy-profile-migrator.c
@@ -76,7 +76,7 @@ migrate_app_desktop_file_categories (void)
 {
   GList *web_apps, *l;
 
-  web_apps = ephy_web_application_get_application_list ();
+  web_apps = ephy_web_application_get_legacy_application_list ();
 
   for (l = web_apps; l; l = l->next) {
     EphyWebApplication *app = (EphyWebApplication *)l->data;
@@ -1215,6 +1215,63 @@ migrate_annoyance_list (void)
   g_strfreev (modified_filters);
 }
 
+static void
+migrate_app_profile_directories (void)
+{
+  GList *web_apps, *l;
+
+  /* Web app profiles moved from config to data dirs */
+  web_apps = ephy_web_application_get_legacy_application_list ();
+  for (l = web_apps; l; l = l->next) {
+    EphyWebApplication *app = (EphyWebApplication *)l->data;
+    g_autoptr(GError) error = NULL;
+
+    g_autofree char *old_name = g_strconcat ("app-epiphany-", app->id, NULL);
+    g_autofree char *old_path = g_build_filename (ephy_default_dot_dir (), old_name, NULL);
+    g_autoptr(GFile) old_directory = g_file_new_for_path (old_path);
+    g_autofree char *app_path = ephy_web_application_get_profile_directory (app->id);
+    g_autoptr(GFile) new_directory = g_file_new_for_path (app_path);
+
+    if (!g_file_move (old_directory, new_directory, G_FILE_COPY_NONE, NULL, NULL, NULL, &error)) {
+      LOG ("Failed to move directory %s to %s: %s", old_path, app_path, error->message);
+      continue;
+    }
+
+    // Create an empty file to indicate it's an app
+    g_autofree char *app_file = g_build_filename (app_path, ".app", NULL);
+    int fd = g_open (app_file, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+    if (fd < 0)
+      LOG ("Failed to create .app file: %s", g_strerror (errno));
+    else
+      close (fd);
+
+    g_autoptr(GKeyFile) file = g_key_file_new ();
+    g_autofree char *desktop_file_path = g_build_filename (app_path, app->desktop_file, NULL);
+    g_key_file_load_from_file (file, desktop_file_path, G_KEY_FILE_NONE, NULL);
+    g_autofree char *exec = g_key_file_get_string (file, G_KEY_FILE_DESKTOP_GROUP, 
G_KEY_FILE_DESKTOP_KEY_EXEC, &error);
+    if (exec == NULL) {
+      LOG ("Failed to get Exec key from %s: %s", desktop_file_path, error->message);
+      continue;
+    }
+
+    g_autoptr(GRegex) re = g_regex_new ("epiphany/app-epiphany-", 0, 0, NULL);
+    g_autofree char *new_exec = g_regex_replace (re, exec, -1, 0, "/epiphany-", 0, &error);
+
+    if (error != NULL) {
+      LOG ("Failed to replace Exec line %s: %s", exec, error->message);
+      g_clear_error (&error);
+    }
+
+    LOG ("migrate_app_profile_directories: setting Exec to %s", new_exec);
+    g_key_file_set_string (file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_EXEC, new_exec);
+
+    if (!g_key_file_save_to_file (file, desktop_file_path, &error))
+      LOG ("Failed to save desktop file %s", error->message);
+  }
+
+  ephy_web_application_free_application_list (web_apps);
+}
+
 static void
 migrate_nothing (void)
 {
@@ -1256,7 +1313,8 @@ const EphyProfileMigrator migrators[] = {
   /* 25 */ migrate_passwords_timestamp,
   /* 26 */ migrate_nothing,
   /* 27 */ migrate_search_engines,
-  /* 28 */ migrate_annoyance_list
+  /* 28 */ migrate_annoyance_list,
+  /* 29 */ migrate_app_profile_directories,
 };
 
 static gboolean


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