[gnome-shell] St: avoid blocking IO to resolve relative urls



commit f7af96dbb2152c796c5877585e7d1e555471d6ce
Author: Giovanni Campagna <gcampagna src gnome org>
Date:   Thu Nov 22 01:13:59 2012 +0100

    St: avoid blocking IO to resolve relative urls
    
    realpath() does a series of lstat() on each path component to resolve
    symbolic links, but we just want to get an absolute path, and we don't
    really care if it is physical or not. Going through a GFile does the
    canonicalization we need, and is a lot faster.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=687881

 src/st/st-theme-node.c    |   26 +++++++++---
 src/st/st-theme-private.h |    8 ++--
 src/st/st-theme.c         |   96 ++++++++++++++-------------------------------
 3 files changed, 53 insertions(+), 77 deletions(-)
---
diff --git a/src/st/st-theme-node.c b/src/st/st-theme-node.c
index 766e073..d049ca1 100644
--- a/src/st/st-theme-node.c
+++ b/src/st/st-theme-node.c
@@ -1738,15 +1738,19 @@ _st_theme_node_ensure_background (StThemeNode *node)
               else if (term->type == TERM_URI)
                 {
                   CRStyleSheet *base_stylesheet;
+                  GFile *file;
 
                   if (decl->parent_statement != NULL)
                     base_stylesheet = decl->parent_statement->parent_sheet;
                   else
                     base_stylesheet = NULL;
 
-                  node->background_image = _st_theme_resolve_url (node->theme,
-                                                                  base_stylesheet,
-                                                                  term->content.str->stryng->str);
+                  file = _st_theme_resolve_url (node->theme,
+                                                base_stylesheet,
+                                                term->content.str->stryng->str);
+
+                  node->background_image = g_strdup (g_file_get_path (file));
+                  g_object_unref (file);
                 }
             }
         }
@@ -1843,6 +1847,7 @@ _st_theme_node_ensure_background (StThemeNode *node)
           if (decl->value->type == TERM_URI)
             {
               CRStyleSheet *base_stylesheet;
+              GFile *file;
 
               if (decl->parent_statement != NULL)
                 base_stylesheet = decl->parent_statement->parent_sheet;
@@ -1850,9 +1855,12 @@ _st_theme_node_ensure_background (StThemeNode *node)
                 base_stylesheet = NULL;
 
               g_free (node->background_image);
-              node->background_image = _st_theme_resolve_url (node->theme,
-                                                              base_stylesheet,
-                                                              decl->value->content.str->stryng->str);
+              file = _st_theme_resolve_url (node->theme,
+                                            base_stylesheet,
+                                            decl->value->content.str->stryng->str);
+
+              node->background_image = g_strdup (g_file_get_path (file));
+              g_object_unref (file);
             }
           else if (term_is_inherit (decl->value))
             {
@@ -2668,6 +2676,7 @@ st_theme_node_get_border_image (StThemeNode *node)
           int border_bottom;
           int border_left;
 
+          GFile *file;
           char *filename;
 
           /* Support border-image: none; to suppress a previously specified border image */
@@ -2746,7 +2755,10 @@ st_theme_node_get_border_image (StThemeNode *node)
           else
             base_stylesheet = NULL;
 
-          filename = _st_theme_resolve_url (node->theme, base_stylesheet, url);
+          file = _st_theme_resolve_url (node->theme, base_stylesheet, url);
+          filename = g_strdup (g_file_get_path (file));
+          g_object_unref (file);
+
           if (filename == NULL)
             goto next_property;
 
diff --git a/src/st/st-theme-private.h b/src/st/st-theme-private.h
index ecd2639..08f3a18 100644
--- a/src/st/st-theme-private.h
+++ b/src/st/st-theme-private.h
@@ -29,10 +29,10 @@ G_BEGIN_DECLS
 GPtrArray *_st_theme_get_matched_properties (StTheme       *theme,
                                              StThemeNode   *node);
 
-/* Resolve an URL from the stylesheet to a filename */
-char *_st_theme_resolve_url (StTheme      *theme,
-                             CRStyleSheet *base_stylesheet,
-                             const char   *url);
+/* Resolve an URL from the stylesheet to a file */
+GFile *_st_theme_resolve_url (StTheme      *theme,
+                              CRStyleSheet *base_stylesheet,
+                              const char   *url);
 
 CRDeclaration *_st_theme_parse_declaration_list (const char *str);
 
diff --git a/src/st/st-theme.c b/src/st/st-theme.c
index 4012ab9..601f31e 100644
--- a/src/st/st-theme.c
+++ b/src/st/st-theme.c
@@ -849,9 +849,16 @@ add_matched_properties (StTheme      *a_this,
                 char *filename = NULL;
 
                 if (import_rule->url->stryng && import_rule->url->stryng->str)
-                  filename = _st_theme_resolve_url (a_this,
-                                                    a_nodesheet,
-                                                    import_rule->url->stryng->str);
+                  {
+                    GFile *file;
+
+                    file = _st_theme_resolve_url (a_this,
+                                                  a_nodesheet,
+                                                  import_rule->url->stryng->str);
+                    filename = g_strdup (g_file_get_path (file));
+
+                    g_object_unref (file);
+                  }
 
                 if (filename)
                   import_rule->sheet = parse_stylesheet (filename, NULL);
@@ -999,84 +1006,41 @@ _st_theme_get_matched_properties (StTheme        *theme,
  * local filename, if possible. The resolution here is distinctly lame and
  * will fail on many examples.
  */
-char *
+GFile *
 _st_theme_resolve_url (StTheme      *theme,
                        CRStyleSheet *base_stylesheet,
                        const char   *url)
 {
-  const char *base_filename = NULL;
-  char *dirname;
-  char *filename;
-  char *canonicalized_path;
-
-  /* Handle absolute file:/ URLs */
-  if (g_str_has_prefix (url, "file:") ||
-      g_str_has_prefix (url, "File:") ||
-      g_str_has_prefix (url, "FILE:"))
-    {
-      GError *error = NULL;
-      char *filename;
-
-      filename = g_filename_from_uri (url, NULL, &error);
-      if (filename == NULL)
-        {
-          g_warning ("%s", error->message);
-          g_error_free (error);
-        }
-
-      return filename;
-    }
-
-  /* Guard against http:/ URLs */
+  char *scheme;
+  GFile *stylesheet, *resource;
 
-  if (g_str_has_prefix (url, "http:") ||
-      g_str_has_prefix (url, "Http:") ||
-      g_str_has_prefix (url, "HTTP:"))
+  if ((scheme = g_uri_parse_scheme (url)))
     {
-      g_warning ("Http URL '%s' in theme stylesheet is not supported", url);
-      return NULL;
+      g_free (scheme);
+      resource = g_file_new_for_uri (url);
     }
-
-  /* Assume anything else is a relative URL, and "resolve" it
-   */
-  if (url[0] == '/')
+  else if (base_stylesheet != NULL)
     {
-      canonicalized_path = realpath (url, NULL);
-      if (g_mem_is_system_malloc ())
-        {
-          filename = canonicalized_path;
-        }
-      else
-        {
-          filename = g_strdup (canonicalized_path);
-          free (canonicalized_path);
-        }
-      return filename;
-    }
+      const char *base_filename = NULL;
+      char *dirname;
 
-  base_filename = g_hash_table_lookup (theme->filenames_by_stylesheet, base_stylesheet);
+      base_filename = g_hash_table_lookup (theme->filenames_by_stylesheet, base_stylesheet);
 
-  if (base_filename == NULL)
-    {
-      g_warning ("Can't get base to resolve url '%s'", url);
-      return NULL;
-    }
+      /* This is an internal function, if we get here with
+         a bad @base_stylesheet we have a problem. */
+      g_assert (base_filename);
 
-  dirname = g_path_get_dirname (base_filename);
-  filename = g_build_filename (dirname, url, NULL);
-  canonicalized_path = realpath (filename, NULL);
-  g_free (dirname);
-  g_free (filename);
+      dirname = g_path_get_dirname (base_filename);
+      stylesheet = g_file_new_for_path (dirname);
+      resource = g_file_resolve_relative_path (stylesheet, url);
 
-  if (g_mem_is_system_malloc ())
-    {
-      filename = canonicalized_path;
+      g_object_unref (stylesheet);
+      g_free (dirname);
     }
   else
     {
-      filename = g_strdup (canonicalized_path);
-      free (canonicalized_path);
+      resource = g_file_new_for_path (url);
     }
 
-  return filename;
+  return resource;
 }



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