[gnome-software] Add gs_plugin_download_rewrite_resource()



commit d2f7e62fa22e22f025527a1c9a152243e3518f1f
Author: Richard Hughes <richard hughsie com>
Date:   Fri May 5 21:18:34 2017 +0100

    Add gs_plugin_download_rewrite_resource()
    
    This allows us to rewrite a resource with remote URIs to instead have cached
    local URIs.

 lib/gs-plugin.c    |  103 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/gs-plugin.h    |    5 +++
 lib/gs-self-test.c |   29 +++++++++++++++
 3 files changed, 137 insertions(+), 0 deletions(-)
---
diff --git a/lib/gs-plugin.c b/lib/gs-plugin.c
index f46dbd1..f8f6f12 100644
--- a/lib/gs-plugin.c
+++ b/lib/gs-plugin.c
@@ -46,6 +46,7 @@
 
 #include <gio/gdesktopappinfo.h>
 #include <gdk/gdk.h>
+#include <string.h>
 
 #ifdef USE_VALGRIND
 #include <valgrind.h>
@@ -1330,6 +1331,108 @@ gs_plugin_download_file (GsPlugin *plugin,
        return TRUE;
 }
 
+static gchar *
+gs_plugin_download_rewrite_resource_uri (GsPlugin *plugin,
+                                        const gchar *uri,
+                                        GCancellable *cancellable,
+                                        GError **error)
+{
+       g_autofree gchar *cachefn = NULL;
+
+       /* local files */
+       if (g_str_has_prefix (uri, "/"))
+               return g_strdup (uri);
+       if (g_str_has_prefix (uri, "file://"))
+               return g_strdup (uri + 7);
+
+       /* get cache location */
+       cachefn = gs_utils_get_cache_filename ("cssresource", uri,
+                                              GS_UTILS_CACHE_FLAG_WRITEABLE |
+                                              GS_UTILS_CACHE_FLAG_USE_HASH,
+                                              error);
+       if (cachefn == NULL)
+               return NULL;
+
+       /* already exists */
+       if (g_file_test (cachefn, G_FILE_TEST_EXISTS))
+               return g_steal_pointer (&cachefn);
+
+       /* download */
+       if (!gs_plugin_download_file (plugin,
+                                     NULL, /* GsApp */
+                                     uri,
+                                     cachefn,
+                                     cancellable,
+                                     error)) {
+               return NULL;
+       }
+       return g_steal_pointer (&cachefn);
+}
+
+/**
+ * gs_plugin_download_rewrite_resource:
+ * @plugin: a #GsPlugin
+ * @resource: the CSS resource
+ * @cancellable: a #GCancellable, or %NULL
+ * @error: a #GError, or %NULL
+ *
+ * Downloads remote assets and rewrites a CSS resource to use cached local URIs.
+ *
+ * Returns: %TRUE for success
+ *
+ * Since: 3.26
+ **/
+gchar *
+gs_plugin_download_rewrite_resource (GsPlugin *plugin,
+                                    const gchar *resource,
+                                    GCancellable *cancellable,
+                                    GError **error)
+{
+       guint start = 0;
+       g_autoptr(GString) str = g_string_new (NULL);
+
+       g_return_val_if_fail (GS_IS_PLUGIN (plugin), NULL);
+       g_return_val_if_fail (resource != NULL, NULL);
+       g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+       /* look in string for any url() links */
+       for (guint i = 0; resource[i] != '\0'; i++) {
+               if (i > 4 && strncmp (resource + i - 4, "url(", 4) == 0) {
+                       start = i;
+                       continue;
+               }
+               if (start == 0) {
+                       g_string_append_c (str, resource[i]);
+                       continue;
+               }
+               if (resource[i] == ')') {
+                       guint len;
+                       g_autofree gchar *cachefn = NULL;
+                       g_autofree gchar *uri = NULL;
+
+                       /* remove optional single quotes */
+                       if (resource[start] == '\'' || resource[start] == '"')
+                               start++;
+                       len = i - start;
+                       if (i > 0 && (resource[i - 1] == '\'' || resource[i - 1] == '"'))
+                               len--;
+                       uri = g_strndup (resource + start, len);
+
+                       /* download them to per-user cache */
+                       cachefn = gs_plugin_download_rewrite_resource_uri (plugin,
+                                                                          uri,
+                                                                          cancellable,
+                                                                          error);
+                       if (cachefn == NULL)
+                               return NULL;
+                       g_string_append_printf (str, "'%s'", cachefn);
+                       g_string_append_c (str, resource[i]);
+                       start = 0;
+               }
+       }
+       return g_strdup (str->str);
+}
+
 /**
  * gs_plugin_cache_lookup:
  * @plugin: a #GsPlugin
diff --git a/lib/gs-plugin.h b/lib/gs-plugin.h
index a2f0608..67b86f2 100644
--- a/lib/gs-plugin.h
+++ b/lib/gs-plugin.h
@@ -105,6 +105,11 @@ gboolean    gs_plugin_download_file                (GsPlugin       *plugin,
                                                         const gchar    *filename,
                                                         GCancellable   *cancellable,
                                                         GError         **error);
+gchar          *gs_plugin_download_rewrite_resource    (GsPlugin       *plugin,
+                                                        const gchar    *resource,
+                                                        GCancellable   *cancellable,
+                                                        GError         **error);
+
 gboolean        gs_plugin_check_distro_id              (GsPlugin       *plugin,
                                                         const gchar    *distro_id);
 GsApp          *gs_plugin_cache_lookup                 (GsPlugin       *plugin,
diff --git a/lib/gs-self-test.c b/lib/gs-self-test.c
index af8a13b..434ec6f 100644
--- a/lib/gs-self-test.c
+++ b/lib/gs-self-test.c
@@ -138,6 +138,34 @@ gs_utils_error_func (void)
 }
 
 static void
+gs_plugin_download_rewrite_func (void)
+{
+       g_autofree gchar *css = NULL;
+       g_autoptr(GError) error = NULL;
+       g_autoptr(GsPlugin) plugin = NULL;
+       const gchar *resource = "background:\n"
+                               " url('file://" DATADIR "/gnome-software/featured-maps.png')\n"
+                               " url('file://" DATADIR "/gnome-software/featured-maps-bg.png')\n"
+                               " bottom center / contain no-repeat;\n";
+
+       /* only when installed */
+       if (!g_file_test (DATADIR "/gnome-software/featured-maps.png", G_FILE_TEST_EXISTS)) {
+               g_test_skip ("not installed");
+               return;
+       }
+
+       /* test rewrite */
+       plugin = gs_plugin_new ();
+       gs_plugin_set_name (plugin, "self-test");
+       css = gs_plugin_download_rewrite_resource (plugin,
+                                                  resource,
+                                                  NULL,
+                                                  &error);
+       g_assert_no_error (error);
+       g_assert (css != NULL);
+}
+
+static void
 gs_plugin_global_cache_func (void)
 {
        const gchar *unique_id;
@@ -586,6 +614,7 @@ main (int argc, char **argv)
        g_test_add_func ("/gnome-software/lib/app{unique-id}", gs_app_unique_id_func);
        g_test_add_func ("/gnome-software/lib/app{thread}", gs_app_thread_func);
        g_test_add_func ("/gnome-software/lib/plugin", gs_plugin_func);
+       g_test_add_func ("/gnome-software/lib/plugin{download-rewrite}", gs_plugin_download_rewrite_func);
        g_test_add_func ("/gnome-software/lib/plugin{global-cache}", gs_plugin_global_cache_func);
        g_test_add_func ("/gnome-software/lib/auth{secret}", gs_auth_secret_func);
 


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