[yelp/yelp-3-0] [libyelp] Look up resources (e.g. images) from URI search path
- From: Shaun McCance <shaunm src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [yelp/yelp-3-0] [libyelp] Look up resources (e.g. images) from URI search path
- Date: Wed, 21 Oct 2009 22:18:00 +0000 (UTC)
commit ddc7de372fa2865b34ec08168a5e3087b79861fb
Author: Shaun McCance <shaunm gnome org>
Date: Wed Oct 21 17:15:15 2009 -0500
[libyelp] Look up resources (e.g. images) from URI search path
Especially for Mallard documents, the files included in a document can be
placed anywhere within a search path. With this change, not only can pages
come from the search path, but also images or other resources.
FIXME: We should make XInclude work on the path as well.
libyelp/yelp-uri.c | 50 +++++++++++++++++++++++++++---
libyelp/yelp-uri.h | 3 ++
libyelp/yelp-view.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++----
3 files changed, 125 insertions(+), 11 deletions(-)
---
diff --git a/libyelp/yelp-uri.c b/libyelp/yelp-uri.c
index 3edd748..a81a459 100644
--- a/libyelp/yelp-uri.c
+++ b/libyelp/yelp-uri.c
@@ -405,6 +405,34 @@ yelp_uri_get_frag_id (YelpUri *uri)
/******************************************************************************/
+gchar *
+yelp_uri_locate_file_uri (YelpUri *uri,
+ const gchar *filename)
+{
+ YelpUriPrivate *priv = GET_PRIV (uri);
+ GFile *gfile;
+ gchar *fullpath;
+ gchar *returi = NULL;
+ gint i;
+ for (i = 0; priv->search_path[i] != NULL; i++) {
+ fullpath = g_strconcat (priv->search_path[i],
+ G_DIR_SEPARATOR_S,
+ filename,
+ NULL);
+ if (g_file_test (fullpath, G_FILE_TEST_EXISTS)) {
+ gfile = g_file_new_for_path (fullpath);
+ returi = g_file_get_uri (gfile);
+ g_object_unref (gfile);
+ }
+ g_free (fullpath);
+ if (returi)
+ break;
+ }
+ return returi;
+}
+
+/******************************************************************************/
+
static void
resolve_file_uri (YelpUri *uri)
{
@@ -467,14 +495,21 @@ resolve_data_dirs (YelpUri *ret,
const gchar *docid,
const gchar *pageid)
{
- YelpUriPrivate *priv = GET_PRIV (ret);
- const gchar * const *datadirs = g_get_system_data_dirs ();
+ const gchar * const *sdatadirs = g_get_system_data_dirs ();
const gchar * const *langs = g_get_language_names ();
+ /* The strings are still owned by GLib; we just own the array. */
+ const gchar **datadirs;
+ YelpUriPrivate *priv = GET_PRIV (ret);
gchar *filename = NULL;
gchar **searchpath = NULL;
gint searchi, searchmax;
gint datadir_i, subdir_i, lang_i;
+ datadirs = g_new0 (gchar *, g_strv_length (sdatadirs) + 2);
+ datadirs[0] = g_get_user_data_dir ();
+ for (datadir_i = 0; sdatadirs[datadir_i]; datadir_i++)
+ datadirs[datadir_i + 1] = sdatadirs[datadir_i];
+
searchi = 0;
searchmax = 10;
searchpath = g_new0 (gchar *, 10);
@@ -482,8 +517,12 @@ resolve_data_dirs (YelpUri *ret,
for (datadir_i = 0; datadirs[datadir_i]; datadir_i++) {
for (subdir_i = 0; subdirs[subdir_i]; subdir_i++) {
for (lang_i = 0; langs[lang_i]; lang_i++) {
- gchar *helpdir = g_strdup_printf ("%s%s/%s/%s",
- datadirs[datadir_i], subdirs[subdir_i], docid, langs[lang_i]);
+ gchar *helpdir = g_strdup_printf ("%s%s%s/%s/%s",
+ datadirs[datadir_i],
+ (datadirs[datadir_i][strlen(datadirs[datadir_i]) - 1] == '/' ? "" : "/"),
+ subdirs[subdir_i],
+ docid,
+ langs[lang_i]);
if (!g_file_test (helpdir, G_FILE_TEST_IS_DIR)) {
g_free (helpdir);
continue;
@@ -526,6 +565,7 @@ resolve_data_dirs (YelpUri *ret,
} /* end for subdirs */
} /* end for datadirs */
+ g_free (datadirs);
if (priv->tmptype == YELP_URI_DOCUMENT_TYPE_UNRESOLVED) {
g_strfreev (searchpath);
priv->tmptype = YELP_URI_DOCUMENT_TYPE_NOT_FOUND;
@@ -793,7 +833,7 @@ resolve_xref_uri (YelpUri *uri)
priv->search_path = g_strdupv (base_priv->search_path);
priv->docuri = g_strdup (base_priv->docuri);
- if (arg == '#') {
+ if (arg[0] == '#') {
priv->page_id = g_strdup (base_priv->page_id);
priv->frag_id = g_strdup (arg + 1);
}
diff --git a/libyelp/yelp-uri.h b/libyelp/yelp-uri.h
index 09bf40d..8161261 100644
--- a/libyelp/yelp-uri.h
+++ b/libyelp/yelp-uri.h
@@ -82,6 +82,9 @@ gchar ** yelp_uri_get_search_path (YelpUri *uri);
gchar * yelp_uri_get_page_id (YelpUri *uri);
gchar * yelp_uri_get_frag_id (YelpUri *uri);
+gchar * yelp_uri_locate_file_uri (YelpUri *uri,
+ const gchar *filename);
+
G_END_DECLS
#endif /* __YELP_URI_H__ */
diff --git a/libyelp/yelp-view.c b/libyelp/yelp-view.c
index 1410cc7..98ccba9 100644
--- a/libyelp/yelp-view.c
+++ b/libyelp/yelp-view.c
@@ -28,12 +28,16 @@
#include <gio/gio.h>
#include <gtk/gtk.h>
#include <webkit/webkit.h>
+#include <webkit/webkitwebresource.h>
#include "yelp-debug.h"
#include "yelp-error.h"
#include "yelp-types.h"
#include "yelp-view.h"
+#define BOGUS_URI "file:///bogus/"
+#define BOGUS_URI_LEN 14
+
static void yelp_view_init (YelpView *view);
static void yelp_view_class_init (YelpViewClass *klass);
static void yelp_view_dispose (GObject *object);
@@ -53,6 +57,12 @@ static gboolean view_navigation_requested (WebKitWebView *vi
WebKitWebNavigationAction *action,
WebKitWebPolicyDecision *decision,
gpointer user_data);
+static void view_resource_request (WebKitWebView *view,
+ WebKitWebFrame *frame,
+ WebKitWebResource *resource,
+ WebKitNetworkRequest *request,
+ WebKitNetworkResponse *response,
+ gpointer user_data);
static void view_clear_load (YelpView *view);
static void view_load_page (YelpView *view);
@@ -84,10 +94,13 @@ typedef struct _YelpViewPrivate YelpViewPrivate;
struct _YelpViewPrivate {
YelpUri *uri;
gulong uri_resolved;
+ gchar *bogus_uri;
YelpDocument *document;
GCancellable *cancellable;
YelpViewState state;
+
+ gint navigation_requested;
};
#define TARGET_TYPE_URI_LIST "text/uri-list"
@@ -104,8 +117,11 @@ yelp_view_init (YelpView *view)
priv->state = YELP_VIEW_STATE_BLANK;
- g_signal_connect (view, "navigation-policy-decision-requested",
- G_CALLBACK (view_navigation_requested), NULL);
+ priv->navigation_requested =
+ g_signal_connect (view, "navigation-policy-decision-requested",
+ G_CALLBACK (view_navigation_requested), NULL);
+ g_signal_connect (view, "resource-request-starting",
+ G_CALLBACK (view_resource_request), NULL);
}
static void
@@ -135,6 +151,10 @@ yelp_view_dispose (GObject *object)
static void
yelp_view_finalize (GObject *object)
{
+ YelpViewPrivate *priv = GET_PRIV (object);
+
+ g_free (priv->bogus_uri);
+
G_OBJECT_CLASS (yelp_view_parent_class)->finalize (object);
}
@@ -292,6 +312,39 @@ view_navigation_requested (WebKitWebView *view,
}
static void
+view_resource_request (WebKitWebView *view,
+ WebKitWebFrame *frame,
+ WebKitWebResource *resource,
+ WebKitNetworkRequest *request,
+ WebKitNetworkResponse *response,
+ gpointer user_data)
+{
+ YelpViewPrivate *priv = GET_PRIV (view);
+ const gchar *requri = webkit_network_request_get_uri (request);
+ gchar last;
+ gchar *newpath;
+
+ debug_print (DB_FUNCTION, "entering\n");
+ debug_print (DB_ARG, " uri=\"%s\"\n", requri);
+
+ if (!g_str_has_prefix (requri, BOGUS_URI))
+ return;
+
+ /* We get this signal for the page itself. Ignore. */
+ if (g_str_equal (requri, priv->bogus_uri))
+ return;
+
+ newpath = yelp_uri_locate_file_uri (priv->uri, requri + BOGUS_URI_LEN);
+ if (newpath != NULL) {
+ webkit_network_request_set_uri (request, newpath);
+ g_free (newpath);
+ }
+ else {
+ webkit_network_request_set_uri (request, "about:blank");
+ }
+}
+
+static void
view_clear_load (YelpView *view)
{
YelpViewPrivate *priv = GET_PRIV (view);
@@ -356,6 +409,7 @@ static void
view_show_error_page (YelpView *view,
GError *error)
{
+ YelpViewPrivate *priv = GET_PRIV (view);
static const gchar *errorpage =
"<html><head>"
"<style type='text/css'>"
@@ -393,11 +447,13 @@ view_show_error_page (YelpView *view,
title = _("Unknown Error");
page = g_strdup_printf (errorpage, title, error->message);
g_object_set (view, "state", YELP_VIEW_STATE_ERROR, NULL);
+ g_signal_handler_block (view, priv->navigation_requested);
webkit_web_view_load_string (WEBKIT_WEB_VIEW (view),
page,
"text/html",
"UTF-8",
"about:error");
+ g_signal_handler_unblock (view, priv->navigation_requested);
g_error_free (error);
g_free (page);
}
@@ -436,21 +492,36 @@ document_callback (YelpDocument *document,
}
else if (signal == YELP_DOCUMENT_SIGNAL_CONTENTS) {
const gchar *contents;
- gchar *real_uri, *mime_type, *page_id;
- real_uri = yelp_uri_get_canonical_uri (priv->uri);
+ gchar *mime_type, *page_id, *frag_id;
page_id = yelp_uri_get_page_id (priv->uri);
debug_print (DB_ARG, " document.uri.page_id=\"%s\"\n", page_id);
mime_type = yelp_document_get_mime_type (document, page_id);
contents = yelp_document_read_contents (document, page_id);
+ frag_id = yelp_uri_get_frag_id (priv->uri);
+ g_free (priv->bogus_uri);
+ /* We have to give WebKit a URI in a scheme it understands, otherwise we
+ won't get the resource-request-starting signal. So we can't use the
+ canonical URI, because it might be something like ghelp. We also have
+ to give it something unique, because WebKit ignores our load_string
+ call if the URI isn't different. We could try to construct something
+ based on actual file locations, but in fact it doesn't matter. So
+ we just make a bogus URI that's easy to process later.
+ */
+ if (frag_id != NULL)
+ priv->bogus_uri = g_strdup_printf ("%s%p#%s", BOGUS_URI, priv->uri, frag_id);
+ else
+ priv->bogus_uri = g_strdup_printf ("%s%p", BOGUS_URI, priv->uri);
+ g_signal_handler_block (view, priv->navigation_requested);
webkit_web_view_load_string (WEBKIT_WEB_VIEW (view),
contents,
mime_type,
"UTF-8",
- real_uri);
+ priv->bogus_uri);
+ g_signal_handler_unblock (view, priv->navigation_requested);
g_object_set (view, "state", YELP_VIEW_STATE_LOADED, NULL);
+ g_free (frag_id);
g_free (page_id);
g_free (mime_type);
- g_free (real_uri);
yelp_document_finish_read (document, contents);
}
else if (signal == YELP_DOCUMENT_SIGNAL_ERROR) {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]